Compare commits
7 Commits
fa0c288e07
...
91549f1a05
| Author | SHA1 | Date | |
|---|---|---|---|
| 91549f1a05 | |||
| 3909e3e369 | |||
| 0c248b7e84 | |||
| 16ce1cb096 | |||
| f796f2c658 | |||
| de5e81fe22 | |||
| 94a5794bab |
20
.env.example
20
.env.example
@@ -1,4 +1,4 @@
|
|||||||
APP_NAME="Le Retzien Libre"
|
APP_NAME="Roxane - Le Retzien Libre"
|
||||||
APP_ENV=local
|
APP_ENV=local
|
||||||
APP_KEY=
|
APP_KEY=
|
||||||
APP_DEBUG=true
|
APP_DEBUG=true
|
||||||
@@ -63,3 +63,21 @@ AWS_BUCKET=
|
|||||||
AWS_USE_PATH_STYLE_ENDPOINT=false
|
AWS_USE_PATH_STYLE_ENDPOINT=false
|
||||||
|
|
||||||
VITE_APP_NAME="${APP_NAME}"
|
VITE_APP_NAME="${APP_NAME}"
|
||||||
|
|
||||||
|
DOLIBARR_URL=
|
||||||
|
LIBARR_USERNAME=
|
||||||
|
DOLIBARR_PWD=
|
||||||
|
|
||||||
|
MAIL_ISPAPI_URL=
|
||||||
|
MAIL_ISPAPI_USERNAME=
|
||||||
|
MAIL_ISPAPI_PWD=
|
||||||
|
|
||||||
|
HOSTING_ISPAPI_URL=
|
||||||
|
HOSTING_ISPAPI_USERNAME=
|
||||||
|
HOSTING_ISPAPI_PWD=
|
||||||
|
|
||||||
|
#NEXTCLOUD_API_ID=
|
||||||
|
#NEXCLOUD_API_PWD=
|
||||||
|
|
||||||
|
#SYMPA_API_ID=
|
||||||
|
#SYMPA_API_PWD=
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
name: lrl-app
|
name: roxane-app
|
||||||
recipe: laravel
|
recipe: laravel
|
||||||
config:
|
config:
|
||||||
php: '8.3'
|
php: '8.3'
|
||||||
@@ -11,11 +11,11 @@ config:
|
|||||||
|
|
||||||
proxy:
|
proxy:
|
||||||
appserver:
|
appserver:
|
||||||
- lrl-app.lndo.site
|
- roxane.lndo.site
|
||||||
mailhog:
|
mailhog:
|
||||||
- mail.lrl-app.lndo.site
|
- mail.roxane.lndo.site
|
||||||
pma:
|
pma:
|
||||||
- pma.lrl-app.lndo.site
|
- pma.roxane.lndo.site
|
||||||
|
|
||||||
services:
|
services:
|
||||||
pma:
|
pma:
|
||||||
|
|||||||
13
README.md
13
README.md
@@ -1,15 +1,16 @@
|
|||||||
# LRL APP - Centralized Portal with Laravel, React & Keycloak SSO
|
# ROXANE - Centralized Portal with Laravel, React & Keycloak SSO
|
||||||
|
|
||||||
This project is a **centralized portal application** built with **Laravel 12 & React19**, designed to provide a seamless and secure entry point for both **end users** and **administrators**.
|
This project is a **centralized portal application & web hosting association ERP** built with **Laravel 12 & React19**, designed to provide a seamless and secure entry point for both **end users** and **administrators**.
|
||||||
|
|
||||||
- **Front Office (Users)**
|
- **Front Office (Users)**
|
||||||
- Build on React19
|
- Build on React19
|
||||||
- (V2) Authentication via **Keycloak SSO (OIDC)**
|
- (V2) Authentication via **Keycloak SSO (OIDC)**
|
||||||
- Unified dashboard to access external applications (cloud storage, mailing tools, file sharing, etc.)
|
- Unified dashboard to access external applications (cloud storage, mailing tools, file sharing, etc.)
|
||||||
- Role-based access control synced from Keycloak
|
- Role-based access control synced from Keycloak
|
||||||
|
- Connected with : ISP Config for web hosting and mailbox management, NextCloud, Sympa for mailing list and more...
|
||||||
- **Back Office (Admins)**
|
- **Back Office (Admins)**
|
||||||
- Authentication handled **locally in Laravel** (separate from Keycloak)
|
- Authentication handled **locally in Laravel** (separate from Keycloak)
|
||||||
- Built with **FilamentPHP** for a modern and intuitive admin panel
|
- Built with **FilamentPHP**
|
||||||
- Advanced admin features: app configuration, user activity logs, monitoring
|
- Advanced admin features: app configuration, user activity logs, monitoring
|
||||||
- **Security & API**
|
- **Security & API**
|
||||||
- JWT validation for user-facing APIs (via Keycloak)
|
- JWT validation for user-facing APIs (via Keycloak)
|
||||||
@@ -20,10 +21,10 @@ This project is a **centralized portal application** built with **Laravel 12 & R
|
|||||||
- Blade + Livewire (back office UI)
|
- Blade + Livewire (back office UI)
|
||||||
- React19 (front office UI)
|
- React19 (front office UI)
|
||||||
- TailwindCSS (UI framework)
|
- TailwindCSS (UI framework)
|
||||||
- Keycloak SSO (OIDC)
|
- Keycloak SSO (OIDC) (V2)
|
||||||
- FilamentPHP (admin panel)
|
- FilamentPHP (admin panel)
|
||||||
- Redis (cache, sessions, queues)
|
- Redis (cache, sessions, queues)
|
||||||
- MySQL (PostgreSQL coming soon)
|
- Maria DB
|
||||||
- Docker-ready + CI/CD support (coming soon)
|
- Docker-ready + CI/CD support and automated deploy
|
||||||
|
|
||||||
This architecture allows associations to **centralize authentication and app access** while keeping the **admin back office independent and highly secure**.
|
This architecture allows associations to **centralize authentication and app access** while keeping the **admin back office independent and highly secure**.
|
||||||
|
|||||||
150
app/Console/Commands/SyncDolibarrMembers.php
Normal file
150
app/Console/Commands/SyncDolibarrMembers.php
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use App\Models\Member;
|
||||||
|
use App\Models\Membership;
|
||||||
|
use App\Services\DolibarrService;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Illuminate\Http\Client\ConnectionException;
|
||||||
|
use function Laravel\Prompts\progress;
|
||||||
|
|
||||||
|
class SyncDolibarrMembers extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string */
|
||||||
|
protected $signature = 'sync:dolibarr-members';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description. *
|
||||||
|
*
|
||||||
|
* @var string */
|
||||||
|
protected $description = 'Retrieve members data from Dolibarr';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
* @throws ConnectionException
|
||||||
|
*/
|
||||||
|
public function handle(): void
|
||||||
|
{
|
||||||
|
$this->info('Starting Dolibarr members import...');
|
||||||
|
|
||||||
|
$client = new DolibarrService;
|
||||||
|
|
||||||
|
// $doliMembers = collect($client->getAllMembers())->take(10); // For test
|
||||||
|
$doliMembers = collect($client->getAllMembers());
|
||||||
|
|
||||||
|
$progressBar = progress(label: 'Dolibarr Members import', steps: $doliMembers->count());
|
||||||
|
$progressBar->start();
|
||||||
|
|
||||||
|
// Stats trackers
|
||||||
|
$createdMembers = 0;
|
||||||
|
$updatedMembers = 0;
|
||||||
|
$createdMemberships = 0;
|
||||||
|
$updatedMemberships = 0;
|
||||||
|
|
||||||
|
// Status mapping from Dolibarr
|
||||||
|
$memberStatuses = [
|
||||||
|
'-2' => 'excluded',
|
||||||
|
'0' => 'cancelled',
|
||||||
|
'1' => 'valid'
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($doliMembers as $member) {
|
||||||
|
|
||||||
|
// CREATE or UPDATE MEMBER
|
||||||
|
$newMember = Member::updateOrCreate(
|
||||||
|
['dolibarr_id' => $member['id']],
|
||||||
|
[
|
||||||
|
'status' => $memberStatuses[$member['status']] ?? 'draft',
|
||||||
|
'nature' => 'physical',
|
||||||
|
'member_type' => $member['type'],
|
||||||
|
'group_id' => null,
|
||||||
|
'lastname' => $member['firstname'],
|
||||||
|
'firstname' => $member['lastname'],
|
||||||
|
'email' => $member['email'] ?: null,
|
||||||
|
'retzien_email' => '',
|
||||||
|
'company' => $member['societe'],
|
||||||
|
'website_url' => $member['url'],
|
||||||
|
'address' => $member['address'],
|
||||||
|
'zipcode' => $member['zip'],
|
||||||
|
'city' => $member['town'],
|
||||||
|
'country' => '',
|
||||||
|
'phone1' => $member['phone'],
|
||||||
|
'phone2' => $member['phone_mobile'],
|
||||||
|
'public_membership' => 0,
|
||||||
|
'created_at' => $this->toDate($member['date_creation']),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Count member creation/update
|
||||||
|
if ($newMember->wasRecentlyCreated) {
|
||||||
|
$createdMembers++;
|
||||||
|
} else {
|
||||||
|
$updatedMembers++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get subscriptions for memeber
|
||||||
|
$memberships = collect($client->getMemberSubscriptions($member['id']));
|
||||||
|
|
||||||
|
foreach ($memberships as $membership) {
|
||||||
|
|
||||||
|
$membershipStatus = $membership['datef'] < now()->timestamp ? 'expired' : 'active';
|
||||||
|
|
||||||
|
$newMembership = Membership::updateOrCreate(
|
||||||
|
['dolibarr_id' => $membership['id']],
|
||||||
|
[
|
||||||
|
'member_id' => $newMember->id,
|
||||||
|
'admin_id' => 1,
|
||||||
|
'package_id' => 2, // annual subscription
|
||||||
|
'start_date' => $this->toDate($membership['dateh']),
|
||||||
|
'end_date' => $this->toDate($membership['datef']),
|
||||||
|
'status' => $membershipStatus,
|
||||||
|
'validation_date' => $this->toDate($membership['datem']),
|
||||||
|
'payment_method' => null,
|
||||||
|
'amount' => number_format($membership['amount'], 2),
|
||||||
|
'payment_status' => 'paid',
|
||||||
|
'note_public' => $membership['note_public'],
|
||||||
|
'note_private' => $membership['note_private'],
|
||||||
|
'dolibarr_user_id' => $member['id']
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Count membership creation/update
|
||||||
|
if ($newMembership->wasRecentlyCreated) {
|
||||||
|
$createdMemberships++;
|
||||||
|
} else {
|
||||||
|
$updatedMemberships++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$progressBar->advance();
|
||||||
|
}
|
||||||
|
|
||||||
|
$progressBar->finish();
|
||||||
|
|
||||||
|
// Report
|
||||||
|
$this->info('');
|
||||||
|
$this->info('===== IMPORT SUMMARY =====');
|
||||||
|
$this->info("Members created : $createdMembers");
|
||||||
|
$this->info("Members updated : $updatedMembers");
|
||||||
|
$this->info("Memberships created : $createdMemberships");
|
||||||
|
$this->info("Memberships updated : $updatedMemberships");
|
||||||
|
$this->info('===========================');
|
||||||
|
$this->info('Import completed successfully.');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert timestamp to date format safely
|
||||||
|
* @todo: export this in a service or repo
|
||||||
|
*/
|
||||||
|
private function toDate($timestamp): ?string
|
||||||
|
{
|
||||||
|
return $timestamp
|
||||||
|
? Carbon::createFromTimestamp($timestamp)->format('Y-m-d H:i:s')
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,13 +11,16 @@ use Illuminate\Notifications\Notifiable;
|
|||||||
/**
|
/**
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property int|null $user_id
|
* @property int|null $user_id
|
||||||
|
* @property string|null $dolibarr_id
|
||||||
* @property string|null $keycloak_id
|
* @property string|null $keycloak_id
|
||||||
* @property string $status
|
* @property string $status
|
||||||
* @property string $nature
|
* @property string $nature
|
||||||
|
* @property int|null $type_id
|
||||||
* @property int|null $group_id
|
* @property int|null $group_id
|
||||||
* @property string|null $lastname
|
* @property string|null $lastname
|
||||||
* @property string|null $firstname
|
* @property string|null $firstname
|
||||||
* @property string $email
|
* @property string $email
|
||||||
|
* @property string|null $retzien_email
|
||||||
* @property string|null $company
|
* @property string|null $company
|
||||||
* @property string|null $date_of_birth
|
* @property string|null $date_of_birth
|
||||||
* @property string|null $address
|
* @property string|null $address
|
||||||
@@ -27,6 +30,7 @@ use Illuminate\Notifications\Notifiable;
|
|||||||
* @property string|null $phone1
|
* @property string|null $phone1
|
||||||
* @property string|null $phone2
|
* @property string|null $phone2
|
||||||
* @property int $public_membership
|
* @property int $public_membership
|
||||||
|
* @property string|null $website_url
|
||||||
* @property \Illuminate\Support\Carbon|null $created_at
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
* @property string|null $deleted_at
|
* @property string|null $deleted_at
|
||||||
@@ -34,6 +38,8 @@ use Illuminate\Notifications\Notifiable;
|
|||||||
* @property-read \App\Models\MemberGroup|null $group
|
* @property-read \App\Models\MemberGroup|null $group
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Membership> $memberships
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Membership> $memberships
|
||||||
* @property-read int|null $memberships_count
|
* @property-read int|null $memberships_count
|
||||||
|
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection<int, \Illuminate\Notifications\DatabaseNotification> $notifications
|
||||||
|
* @property-read int|null $notifications_count
|
||||||
* @property-read \App\Models\User|null $user
|
* @property-read \App\Models\User|null $user
|
||||||
* @method static \Database\Factories\MemberFactory factory($count = null, $state = [])
|
* @method static \Database\Factories\MemberFactory factory($count = null, $state = [])
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member newModelQuery()
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member newModelQuery()
|
||||||
@@ -46,6 +52,7 @@ use Illuminate\Notifications\Notifiable;
|
|||||||
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member whereCreatedAt($value)
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member whereCreatedAt($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member whereDateOfBirth($value)
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member whereDateOfBirth($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member whereDeletedAt($value)
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member whereDeletedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member whereDolibarrId($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member whereEmail($value)
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member whereEmail($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member whereFirstname($value)
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member whereFirstname($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member whereGroupId($value)
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member whereGroupId($value)
|
||||||
@@ -56,9 +63,12 @@ use Illuminate\Notifications\Notifiable;
|
|||||||
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member wherePhone1($value)
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member wherePhone1($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member wherePhone2($value)
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member wherePhone2($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member wherePublicMembership($value)
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member wherePublicMembership($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member whereRetzienEmail($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member whereStatus($value)
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member whereStatus($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member whereTypeId($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member whereUpdatedAt($value)
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member whereUpdatedAt($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member whereUserId($value)
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member whereUserId($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member whereWebsiteUrl($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member whereZipcode($value)
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Member whereZipcode($value)
|
||||||
* @mixin \Eloquent
|
* @mixin \Eloquent
|
||||||
*/
|
*/
|
||||||
@@ -67,9 +77,11 @@ class Member extends Model
|
|||||||
use HasFactory, Notifiable;
|
use HasFactory, Notifiable;
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'user_id',
|
'user_id',
|
||||||
|
'dolibarr_id',
|
||||||
'keycloak_id',
|
'keycloak_id',
|
||||||
'status',
|
'status',
|
||||||
'nature',
|
'nature',
|
||||||
|
'type_id',
|
||||||
'group_id',
|
'group_id',
|
||||||
'lastname',
|
'lastname',
|
||||||
'firstname',
|
'firstname',
|
||||||
@@ -83,9 +95,7 @@ class Member extends Model
|
|||||||
'phone1',
|
'phone1',
|
||||||
'phone2',
|
'phone2',
|
||||||
'public_membership',
|
'public_membership',
|
||||||
'package_id',
|
'website_url'
|
||||||
'amount',
|
|
||||||
'payment_status'
|
|
||||||
];
|
];
|
||||||
|
|
||||||
public static function getAttributeLabel(string $attribute): string
|
public static function getAttributeLabel(string $attribute): string
|
||||||
|
|||||||
@@ -13,11 +13,17 @@ use Illuminate\Database\Eloquent\Relations\HasOne;
|
|||||||
* @property int $member_id
|
* @property int $member_id
|
||||||
* @property int|null $admin_id
|
* @property int|null $admin_id
|
||||||
* @property int $package_id
|
* @property int $package_id
|
||||||
* @property string $start_date
|
* @property string|null $start_date
|
||||||
* @property string|null $end_date
|
* @property string|null $end_date
|
||||||
* @property string $status
|
* @property string $status
|
||||||
|
* @property string|null $validation_date
|
||||||
|
* @property string|null $payment_method
|
||||||
* @property string $amount
|
* @property string $amount
|
||||||
* @property string $payment_status
|
* @property string $payment_status
|
||||||
|
* @property string|null $note_public
|
||||||
|
* @property string|null $note_private
|
||||||
|
* @property string|null $dolibarr_id
|
||||||
|
* @property string|null $dolibarr_user_id
|
||||||
* @property \Illuminate\Support\Carbon|null $created_at
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
* @property string|null $deleted_at
|
* @property string|null $deleted_at
|
||||||
@@ -33,14 +39,20 @@ use Illuminate\Database\Eloquent\Relations\HasOne;
|
|||||||
* @method static \Illuminate\Database\Eloquent\Builder<static>|Membership whereAmount($value)
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Membership whereAmount($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder<static>|Membership whereCreatedAt($value)
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Membership whereCreatedAt($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder<static>|Membership whereDeletedAt($value)
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Membership whereDeletedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Membership whereDolibarrId($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Membership whereDolibarrUserId($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder<static>|Membership whereEndDate($value)
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Membership whereEndDate($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder<static>|Membership whereId($value)
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Membership whereId($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder<static>|Membership whereMemberId($value)
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Membership whereMemberId($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Membership whereNotePrivate($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Membership whereNotePublic($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder<static>|Membership wherePackageId($value)
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Membership wherePackageId($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Membership wherePaymentMethod($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder<static>|Membership wherePaymentStatus($value)
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Membership wherePaymentStatus($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder<static>|Membership whereStartDate($value)
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Membership whereStartDate($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder<static>|Membership whereStatus($value)
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Membership whereStatus($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder<static>|Membership whereUpdatedAt($value)
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Membership whereUpdatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Membership whereValidationDate($value)
|
||||||
* @mixin \Eloquent
|
* @mixin \Eloquent
|
||||||
*/
|
*/
|
||||||
class Membership extends Model
|
class Membership extends Model
|
||||||
@@ -52,8 +64,14 @@ class Membership extends Model
|
|||||||
'start_date',
|
'start_date',
|
||||||
'end_date',
|
'end_date',
|
||||||
'status',
|
'status',
|
||||||
|
'validation_date',
|
||||||
|
'payment_method',
|
||||||
'amount',
|
'amount',
|
||||||
'payment_status',
|
'payment_status',
|
||||||
|
'note_public',
|
||||||
|
'note_private',
|
||||||
|
'dolibarr_id',
|
||||||
|
'dolibarr_user_id'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
61
app/Services/DolibarrService.php
Normal file
61
app/Services/DolibarrService.php
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services;
|
||||||
|
|
||||||
|
use Illuminate\Http\Client\ConnectionException;
|
||||||
|
use Illuminate\Http\Client\PendingRequest;
|
||||||
|
use Illuminate\Support\Facades\Http;
|
||||||
|
|
||||||
|
class DolibarrService
|
||||||
|
{
|
||||||
|
protected string $baseUrl;
|
||||||
|
protected string $username;
|
||||||
|
protected string $password;
|
||||||
|
protected string $apiKey;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->baseUrl = config('services.dolibarr.base_url');
|
||||||
|
$this->username = config('services.dolibarr.username');
|
||||||
|
$this->password = config('services.dolibarr.password');
|
||||||
|
$this->apiKey = config('services.dolibarr.api_key');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an authenticated HTTP client for Dolibarr
|
||||||
|
*/
|
||||||
|
protected function client(): PendingRequest
|
||||||
|
{
|
||||||
|
return Http::withBasicAuth($this->username, $this->password)
|
||||||
|
->withHeaders([
|
||||||
|
'Accept' => 'application/json',
|
||||||
|
'DOLAPIKEY' => $this->apiKey,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all members
|
||||||
|
* @throws ConnectionException
|
||||||
|
*/
|
||||||
|
public function getAllMembers(int $limit = 400, string $sortField = 't.rowid', string $sortOrder = 'ASC'): array
|
||||||
|
{
|
||||||
|
$response = $this->client()->get($this->baseUrl . '/members', [
|
||||||
|
'sortfield' => $sortField,
|
||||||
|
'sortorder' => $sortOrder,
|
||||||
|
'limit' => $limit,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $response->json();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get member subscriptions
|
||||||
|
* @throws ConnectionException
|
||||||
|
*/
|
||||||
|
public function getMemberSubscriptions(int|string $id): array
|
||||||
|
{
|
||||||
|
$response = $this->client()->get($this->baseUrl . '/members/'. $id . '/subscriptions');
|
||||||
|
|
||||||
|
return $response->json();
|
||||||
|
}
|
||||||
|
}
|
||||||
89
app/Services/ISPConfigService.php
Normal file
89
app/Services/ISPConfigService.php
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use SoapClient;
|
||||||
|
use SoapFault;
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class ISPConfigService
|
||||||
|
{
|
||||||
|
protected ?SoapClient $client = null;
|
||||||
|
protected ?string $sessionId = null;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ISPConfig Login
|
||||||
|
*/
|
||||||
|
public function connect(string $type): void
|
||||||
|
{
|
||||||
|
// Type = 'hosting' or 'mailbox'
|
||||||
|
$username = $username ?? config('services.ispconfig'.$type.'.username');
|
||||||
|
$password = $password ?? config('services.ispconfig'.$type.'.password');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->client = new SoapClient(null, [
|
||||||
|
'location' => config('services.ispconfig' . $type . '.base_url'),
|
||||||
|
'trace' => true,
|
||||||
|
'exceptions' => true,
|
||||||
|
'stream_context' => stream_context_create([
|
||||||
|
'ssl' => [
|
||||||
|
'verify_peer' => false,
|
||||||
|
'verify_peer_name' => false,
|
||||||
|
'allow_self_signed' => true,
|
||||||
|
],
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->sessionId = $this->client->login($username, $password);
|
||||||
|
} catch (SoapFault $e) {
|
||||||
|
throw new Exception("An error occurred : " . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all clients
|
||||||
|
*/
|
||||||
|
public function getAllClients(string $username = null, string $password = null): array
|
||||||
|
{
|
||||||
|
if (!$this->sessionId) {
|
||||||
|
$this->connect($username, $password);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$clientIds = $this->client->client_get_all($this->sessionId);
|
||||||
|
$clients = [];
|
||||||
|
|
||||||
|
foreach ($clientIds as $id) {
|
||||||
|
$details = $this->client->client_get($this->sessionId, (int)$id);
|
||||||
|
if (!empty($details)) {
|
||||||
|
$clients[] = (array) $details;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $clients;
|
||||||
|
} catch (SoapFault $e) {
|
||||||
|
throw new Exception("An error occurred : " . $e->getMessage());
|
||||||
|
} finally {
|
||||||
|
$this->disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logout
|
||||||
|
*/
|
||||||
|
public function disconnect(): void
|
||||||
|
{
|
||||||
|
if ($this->client && $this->sessionId) {
|
||||||
|
try {
|
||||||
|
$this->client->logout($this->sessionId);
|
||||||
|
} catch (SoapFault $e) {
|
||||||
|
Log::info('ISP Config logout succeeded');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,13 +8,15 @@
|
|||||||
"require": {
|
"require": {
|
||||||
"php": "^8.3",
|
"php": "^8.3",
|
||||||
"andreia/filament-nord-theme": "^2.0",
|
"andreia/filament-nord-theme": "^2.0",
|
||||||
|
"deployer/deployer": "^7.5",
|
||||||
"filament/filament": "^4.0",
|
"filament/filament": "^4.0",
|
||||||
"inertiajs/inertia-laravel": "^2.0",
|
"inertiajs/inertia-laravel": "^2.0",
|
||||||
"laravel/fortify": "^1.31",
|
"laravel/fortify": "^1.31",
|
||||||
"laravel/framework": "^12.0",
|
"laravel/framework": "^12.0",
|
||||||
"laravel/tinker": "^2.10",
|
"laravel/tinker": "^2.10",
|
||||||
"laravel/wayfinder": "^0.1.9",
|
"laravel/wayfinder": "^0.1.9",
|
||||||
"spatie/laravel-permission": "^6.21"
|
"spatie/laravel-permission": "^6.21",
|
||||||
|
"ext-soap": "*"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"barryvdh/laravel-debugbar": "^3.16",
|
"barryvdh/laravel-debugbar": "^3.16",
|
||||||
|
|||||||
56
composer.lock
generated
56
composer.lock
generated
@@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "2dad60120da5595265fa9bae98361025",
|
"content-hash": "8575e8552839730222fc96c1b3864d9f",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "andreia/filament-nord-theme",
|
"name": "andreia/filament-nord-theme",
|
||||||
@@ -799,6 +799,60 @@
|
|||||||
},
|
},
|
||||||
"time": "2025-09-16T12:23:56+00:00"
|
"time": "2025-09-16T12:23:56+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "deployer/deployer",
|
||||||
|
"version": "v7.5.12",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/deployphp/deployer.git",
|
||||||
|
"reference": "efc71dac9ccc86b3f9946e75d50cb106b775aae2"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/deployphp/deployer/zipball/efc71dac9ccc86b3f9946e75d50cb106b775aae2",
|
||||||
|
"reference": "efc71dac9ccc86b3f9946e75d50cb106b775aae2",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-json": "*",
|
||||||
|
"php": "^8.0|^7.3"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"friendsofphp/php-cs-fixer": "^3.64",
|
||||||
|
"pestphp/pest": "^3.3",
|
||||||
|
"phpstan/phpstan": "^1.4",
|
||||||
|
"phpunit/php-code-coverage": "^11.0",
|
||||||
|
"phpunit/phpunit": "^11.4"
|
||||||
|
},
|
||||||
|
"bin": [
|
||||||
|
"bin/dep"
|
||||||
|
],
|
||||||
|
"type": "library",
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Anton Medvedev",
|
||||||
|
"email": "anton@medv.io"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Deployment Tool",
|
||||||
|
"homepage": "https://deployer.org",
|
||||||
|
"support": {
|
||||||
|
"docs": "https://deployer.org/docs",
|
||||||
|
"issues": "https://github.com/deployphp/deployer/issues",
|
||||||
|
"source": "https://github.com/deployphp/deployer"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://github.com/sponsors/antonmedv",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2025-02-19T16:45:27+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "dflydev/dot-access-data",
|
"name": "dflydev/dot-access-data",
|
||||||
"version": "v3.0.3",
|
"version": "v3.0.3",
|
||||||
|
|||||||
@@ -35,4 +35,24 @@ return [
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
|
'dolibarr' => [
|
||||||
|
'base_url' => env('DOLIBARR_URL'),
|
||||||
|
'username' => env('DOLIBARR_USERNAME'),
|
||||||
|
'password' => env('DOLIBARR_PWD'),
|
||||||
|
'api_key' => env('DOLIBARR_APIKEY')
|
||||||
|
],
|
||||||
|
|
||||||
|
'ispconfig' => [
|
||||||
|
'hosting' => [
|
||||||
|
'base_url' => env('HOSTING_ISPAPI_URL'),
|
||||||
|
'username' => env('HOSTING_ISPAPI_USERNAME'),
|
||||||
|
'password' => env('HOSTING_ISPAPI_PWD'),
|
||||||
|
],
|
||||||
|
'mailbox' => [
|
||||||
|
'base_url' => env('MAIL_ISPAPI_URL'),
|
||||||
|
'username' => env('MAIL_ISPAPI_USERNAME'),
|
||||||
|
'password' => env('MAIL_ISPAPI_PWD'),
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: Schéma de Base de Données - Le Retzien Libre
|
title: Schéma de Base de Données - Roxane - Le Retzien Libre
|
||||||
---
|
---
|
||||||
erDiagram
|
erDiagram
|
||||||
users ||--o{ members : "a"
|
users ||--o{ members : "a"
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('member_types', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('identifier')->unique();
|
||||||
|
$table->string('name');
|
||||||
|
$table->string('description')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
$table->softDeletes();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('member_types');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -18,6 +18,8 @@ return new class extends Migration
|
|||||||
// User
|
// User
|
||||||
$table->foreignId('user_id')->nullable()->constrained('users')->onDelete('set null');
|
$table->foreignId('user_id')->nullable()->constrained('users')->onDelete('set null');
|
||||||
|
|
||||||
|
$table->string('dolibarr_id')->nullable();
|
||||||
|
|
||||||
// Keycloak
|
// Keycloak
|
||||||
$table->string('keycloak_id')->nullable();
|
$table->string('keycloak_id')->nullable();
|
||||||
|
|
||||||
@@ -33,6 +35,9 @@ return new class extends Migration
|
|||||||
// Nature
|
// Nature
|
||||||
$table->enum('nature', ['physical', 'legal'])->default('physical');
|
$table->enum('nature', ['physical', 'legal'])->default('physical');
|
||||||
|
|
||||||
|
// Type
|
||||||
|
$table->unsignedBigInteger('type_id')->nullable();
|
||||||
|
|
||||||
// Group
|
// Group
|
||||||
$table->unsignedBigInteger('group_id')->nullable();
|
$table->unsignedBigInteger('group_id')->nullable();
|
||||||
|
|
||||||
@@ -40,6 +45,7 @@ return new class extends Migration
|
|||||||
$table->string('lastname')->nullable();
|
$table->string('lastname')->nullable();
|
||||||
$table->string('firstname')->nullable();
|
$table->string('firstname')->nullable();
|
||||||
$table->string('email');
|
$table->string('email');
|
||||||
|
$table->string('retzien_email')->nullable();
|
||||||
$table->string('company')->nullable();
|
$table->string('company')->nullable();
|
||||||
$table->date('date_of_birth')->nullable();
|
$table->date('date_of_birth')->nullable();
|
||||||
|
|
||||||
@@ -54,6 +60,9 @@ return new class extends Migration
|
|||||||
// Membership type
|
// Membership type
|
||||||
$table->boolean('public_membership')->default(false);
|
$table->boolean('public_membership')->default(false);
|
||||||
|
|
||||||
|
// Others
|
||||||
|
$table->string('website_url')->nullable();
|
||||||
|
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
$table->softDeletes();
|
$table->softDeletes();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -19,8 +19,14 @@ return new class extends Migration
|
|||||||
$table->date('start_date')->nullable();
|
$table->date('start_date')->nullable();
|
||||||
$table->date('end_date')->nullable();
|
$table->date('end_date')->nullable();
|
||||||
$table->enum('status', ['active', 'expired', 'pending'])->default('pending');
|
$table->enum('status', ['active', 'expired', 'pending'])->default('pending');
|
||||||
|
$table->date('validation_date')->nullable();
|
||||||
|
$table->string('payment_method')->nullable();
|
||||||
$table->decimal('amount', 10, 2)->default(0);
|
$table->decimal('amount', 10, 2)->default(0);
|
||||||
$table->enum('payment_status', ['paid', 'unpaid', 'partial'])->default('unpaid');
|
$table->enum('payment_status', ['paid', 'unpaid', 'partial'])->default('unpaid');
|
||||||
|
$table->longText('note_public')->nullable();
|
||||||
|
$table->longText('note_private')->nullable();
|
||||||
|
$table->string('dolibarr_id')->nullable();
|
||||||
|
$table->string('dolibarr_user_id')->nullable();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
$table->softDeletes();
|
$table->softDeletes();
|
||||||
});
|
});
|
||||||
|
|||||||
71
deploy.php
Normal file
71
deploy.php
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
namespace Deployer;
|
||||||
|
|
||||||
|
require 'recipe/laravel.php';
|
||||||
|
require 'contrib/rsync.php';
|
||||||
|
|
||||||
|
// Environment
|
||||||
|
$env = $_SERVER['CI_COMMIT_REF_NAME'] === 'master' ? 'PROD' : 'STAGING';
|
||||||
|
|
||||||
|
$envConfig = [
|
||||||
|
'host' => $_SERVER[$env . '_SSH_HOST'],
|
||||||
|
'port' => $_SERVER[$env . '_SSH_PORT'] ?? 22,
|
||||||
|
'user' => $_SERVER[$env . '_SSH_USER'],
|
||||||
|
'path' => $_SERVER[$env . '_SSH_PATH'],
|
||||||
|
'repository' => $_SERVER['CI_REPOSITORY_URL'],
|
||||||
|
];
|
||||||
|
|
||||||
|
// GLOBAL
|
||||||
|
set('repository', $envConfig['repository']);
|
||||||
|
set('keep_releases', 3);
|
||||||
|
set('bin/php', '/usr/bin/php8.3');
|
||||||
|
set('bin/composer', '{{bin/php}} /usr/local/bin/composer');
|
||||||
|
set('composer_options', '--no-dev --optimize-autoloader --no-interaction --prefer-dist');
|
||||||
|
set('rsync_src', __DIR__);
|
||||||
|
set('rsync_dest', '{{release_path}}');
|
||||||
|
set('rsync', [
|
||||||
|
'exclude' => [
|
||||||
|
'.git',
|
||||||
|
'node_modules',
|
||||||
|
'vendor',
|
||||||
|
'.env',
|
||||||
|
'.gitlab-ci.yml',
|
||||||
|
'deploy.php',
|
||||||
|
],
|
||||||
|
'flags' => 'rz',
|
||||||
|
'options' => ['delete'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
// HOSTS
|
||||||
|
host($envConfig['host'])
|
||||||
|
->setPort($envConfig['port'])
|
||||||
|
->set('remote_user', $envConfig['user'])
|
||||||
|
->set('deploy_path', $envConfig['path']);
|
||||||
|
|
||||||
|
// TASKS
|
||||||
|
task('deploy:vendors', function () {
|
||||||
|
run('cd {{release_path}} && {{bin/composer}} install {{composer_options}}');
|
||||||
|
});
|
||||||
|
|
||||||
|
task('build:assets', function () {
|
||||||
|
run('cd {{release_path}} && npm ci && npm run build');
|
||||||
|
});
|
||||||
|
|
||||||
|
task('artisan:storage:link', artisan('storage:link'));
|
||||||
|
task('artisan:cache:clear', artisan('cache:clear'));
|
||||||
|
task('artisan:config:clear', artisan('config:clear'));
|
||||||
|
task('artisan:migrate', artisan('migrate --force'));
|
||||||
|
|
||||||
|
task('deploy', [
|
||||||
|
'deploy:prepare',
|
||||||
|
'deploy:vendors',
|
||||||
|
'build:assets',
|
||||||
|
'artisan:storage:link',
|
||||||
|
'artisan:config:clear',
|
||||||
|
'artisan:cache:clear',
|
||||||
|
'artisan:migrate',
|
||||||
|
'deploy:publish',
|
||||||
|
'deploy:publish',
|
||||||
|
]);
|
||||||
|
|
||||||
|
after('deploy:failed', 'deploy:unlock');
|
||||||
67
gitlab-ci.yml
Normal file
67
gitlab-ci.yml
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
image: nebulaed/php83-node22:latest
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- preparation
|
||||||
|
- build
|
||||||
|
- test
|
||||||
|
- deploy
|
||||||
|
|
||||||
|
variables:
|
||||||
|
DEPLOY_PATH: /var/www/roxane
|
||||||
|
GIT_SUBMODULE_STRATEGY: recursive
|
||||||
|
NODE_ENV: production
|
||||||
|
|
||||||
|
# Dependencies installation
|
||||||
|
prepare:
|
||||||
|
stage: preparation
|
||||||
|
before_script:
|
||||||
|
- apt-get update -y
|
||||||
|
- apt-get install -y php8.3 php8.3-cli php8.3-mbstring php8.3-xml php8.3-bcmath php8.3-curl unzip git curl mariadb-client
|
||||||
|
- curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||||
|
script:
|
||||||
|
- php -v
|
||||||
|
- composer -V
|
||||||
|
- node -v
|
||||||
|
- npm ci
|
||||||
|
- composer install --no-dev --no-interaction --prefer-dist
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- vendor/
|
||||||
|
- node_modules/
|
||||||
|
expire_in: 1h
|
||||||
|
|
||||||
|
# Front compilation with vite
|
||||||
|
build:
|
||||||
|
stage: build
|
||||||
|
script:
|
||||||
|
- npm run build
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- public/build/
|
||||||
|
- public/assets/
|
||||||
|
- public/css/
|
||||||
|
- public/js/
|
||||||
|
- public/images/
|
||||||
|
expire_in: 1h
|
||||||
|
|
||||||
|
# Tests Laravel
|
||||||
|
test:
|
||||||
|
stage: test
|
||||||
|
script:
|
||||||
|
- php artisan test --without-tty
|
||||||
|
|
||||||
|
# Deploy
|
||||||
|
deploy:
|
||||||
|
stage: deploy
|
||||||
|
rules:
|
||||||
|
- if: '$CI_COMMIT_REF_NAME == "release" || $CI_COMMIT_REF_NAME == "master"'
|
||||||
|
before_script:
|
||||||
|
- apt-get update -y && apt-get install -y ssh
|
||||||
|
- mkdir -p ~/.ssh
|
||||||
|
- echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
|
||||||
|
- chmod 600 ~/.ssh/id_rsa
|
||||||
|
- echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config
|
||||||
|
script:
|
||||||
|
- composer global require deployer/deployer
|
||||||
|
- ~/.composer/vendor/bin/dep deploy -vvv
|
||||||
|
# Laravel pint ?
|
||||||
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "app",
|
"name": "roxane",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
|
|||||||
@@ -526,3 +526,77 @@ membershipForm.head = (options?: RouteQueryOptions): RouteFormDefinition<'get'>
|
|||||||
})
|
})
|
||||||
|
|
||||||
membership.form = membershipForm
|
membership.form = membershipForm
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see routes/dev-routes.php:5
|
||||||
|
* @route '/call-dolibarr'
|
||||||
|
*/
|
||||||
|
export const callDolibarr = (options?: RouteQueryOptions): RouteDefinition<'get'> => ({
|
||||||
|
url: callDolibarr.url(options),
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
|
||||||
|
callDolibarr.definition = {
|
||||||
|
methods: ["get","head"],
|
||||||
|
url: '/call-dolibarr',
|
||||||
|
} satisfies RouteDefinition<["get","head"]>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see routes/dev-routes.php:5
|
||||||
|
* @route '/call-dolibarr'
|
||||||
|
*/
|
||||||
|
callDolibarr.url = (options?: RouteQueryOptions) => {
|
||||||
|
return callDolibarr.definition.url + queryParams(options)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see routes/dev-routes.php:5
|
||||||
|
* @route '/call-dolibarr'
|
||||||
|
*/
|
||||||
|
callDolibarr.get = (options?: RouteQueryOptions): RouteDefinition<'get'> => ({
|
||||||
|
url: callDolibarr.url(options),
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see routes/dev-routes.php:5
|
||||||
|
* @route '/call-dolibarr'
|
||||||
|
*/
|
||||||
|
callDolibarr.head = (options?: RouteQueryOptions): RouteDefinition<'head'> => ({
|
||||||
|
url: callDolibarr.url(options),
|
||||||
|
method: 'head',
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see routes/dev-routes.php:5
|
||||||
|
* @route '/call-dolibarr'
|
||||||
|
*/
|
||||||
|
const callDolibarrForm = (options?: RouteQueryOptions): RouteFormDefinition<'get'> => ({
|
||||||
|
action: callDolibarr.url(options),
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see routes/dev-routes.php:5
|
||||||
|
* @route '/call-dolibarr'
|
||||||
|
*/
|
||||||
|
callDolibarrForm.get = (options?: RouteQueryOptions): RouteFormDefinition<'get'> => ({
|
||||||
|
action: callDolibarr.url(options),
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see routes/dev-routes.php:5
|
||||||
|
* @route '/call-dolibarr'
|
||||||
|
*/
|
||||||
|
callDolibarrForm.head = (options?: RouteQueryOptions): RouteFormDefinition<'get'> => ({
|
||||||
|
action: callDolibarr.url({
|
||||||
|
[options?.mergeQuery ? 'mergeQuery' : 'query']: {
|
||||||
|
_method: 'HEAD',
|
||||||
|
...(options?.query ?? options?.mergeQuery ?? {}),
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
|
||||||
|
callDolibarr.form = callDolibarrForm
|
||||||
|
|||||||
21
routes/dev-routes.php
Normal file
21
routes/dev-routes.php
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
|
Route::get('/call-dolibarr', function () {
|
||||||
|
$call = new App\Services\DolibarrService;
|
||||||
|
$members = $call->getAllMembers();
|
||||||
|
// find specific
|
||||||
|
$userData = collect($members)->firstWhere('id', 124); // Isabelle AK
|
||||||
|
|
||||||
|
//dd($userData);
|
||||||
|
$subscriptions = collect($call->getMemberSubscriptions(124))->firstWhere('id', 324);
|
||||||
|
dd($subscriptions);
|
||||||
|
$date1 = \Carbon\Carbon::createFromTimestamp($subscriptions['datec'])->format('d/m/Y');
|
||||||
|
$date2 = \Carbon\Carbon::createFromTimestamp($subscriptions['datem'])->format('d/m/Y');
|
||||||
|
$date3 = \Carbon\Carbon::createFromTimestamp($subscriptions['dateh'])->format('d/m/Y');
|
||||||
|
$date4 = \Carbon\Carbon::createFromTimestamp($subscriptions['datef'])->format('d/m/Y');
|
||||||
|
|
||||||
|
dd($date1, $date2, $date3, $date4);
|
||||||
|
|
||||||
|
})->name('call-dolibarr');
|
||||||
@@ -17,3 +17,4 @@ Route::middleware(['auth', 'verified'])->group(function () {
|
|||||||
require __DIR__.'/settings.php';
|
require __DIR__.'/settings.php';
|
||||||
require __DIR__.'/auth.php';
|
require __DIR__.'/auth.php';
|
||||||
require __DIR__.'/forms.php';
|
require __DIR__.'/forms.php';
|
||||||
|
require __DIR__.'/dev-routes.php';
|
||||||
|
|||||||
Reference in New Issue
Block a user