2026-02-09 18:40:44 +01:00
|
|
|
# Roxane - Structure du projet
|
|
|
|
|
|
|
|
|
|
Roxane est une application de gestion d'adhésions pour **Le Retzien Libre**, une association libre/open source.
|
|
|
|
|
Elle gère les membres, les cotisations, et s'intègre avec des services tiers (Dolibarr, ISPConfig, Nextcloud).
|
|
|
|
|
|
|
|
|
|
## Stack technique
|
|
|
|
|
|
|
|
|
|
| Couche | Technologies |
|
|
|
|
|
| --------- | ------------------------------------------------- |
|
|
|
|
|
| Backend | Laravel 12, PHP 8.4, MySQL |
|
|
|
|
|
| Admin | Filament v4, Livewire 3 |
|
|
|
|
|
| Frontend | React 19, Inertia v2, Tailwind CSS v4 |
|
|
|
|
|
| Auth | Laravel Fortify, 2FA, Spatie Permissions + Shield |
|
|
|
|
|
| Tests | PHPUnit 11 |
|
|
|
|
|
| DevTools | Pint, ESLint, Prettier, Sail, Wayfinder |
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Modeles Eloquent
|
|
|
|
|
|
|
|
|
|
### User
|
2026-02-20 15:36:48 +01:00
|
|
|
- **Traits** : HasRoles, TwoFactorAuthenticatable
|
2026-02-09 18:40:44 +01:00
|
|
|
- **Relations** : `members()` hasMany(Member)
|
2026-02-20 15:36:48 +01:00
|
|
|
- **Role** : Implemente `FilamentUser` pour l'acces admin.
|
2026-02-09 18:40:44 +01:00
|
|
|
|
|
|
|
|
### Member
|
|
|
|
|
- **Table** : `members` (soft deletes)
|
|
|
|
|
- **Statuts** : draft, valid, pending, cancelled, excluded
|
|
|
|
|
- **Natures** : physical, legal
|
|
|
|
|
- **Relations** :
|
|
|
|
|
- `user()` belongsTo(User)
|
|
|
|
|
- `group()` belongsTo(MemberGroup)
|
|
|
|
|
- `memberships()` hasMany(Membership)
|
|
|
|
|
- `ispconfigs()` hasMany(IspconfigMember)
|
|
|
|
|
- `nextcloudAccounts()` hasMany(NextCloudMember)
|
|
|
|
|
- **Accessors** : `full_name`, `retzien_email`
|
|
|
|
|
- **Methodes** : `lastMembership()`, `hasService()`, `isExpired()`
|
|
|
|
|
|
|
|
|
|
### Membership
|
|
|
|
|
- **Table** : `memberships` (soft deletes)
|
|
|
|
|
- **Statuts** : active, expired, pending
|
|
|
|
|
- **Statuts paiement** : paid, unpaid, partial
|
|
|
|
|
- **Relations** :
|
|
|
|
|
- `member()` belongsTo(Member)
|
|
|
|
|
- `author()` belongsTo(User, 'admin_id')
|
|
|
|
|
- `package()` belongsTo(Package)
|
|
|
|
|
- `services()` belongsToMany(Service) via `services_memberships`
|
|
|
|
|
|
|
|
|
|
### Package
|
|
|
|
|
- **Table** : `packages`
|
|
|
|
|
- **Donnees** : custom (1EUR), one-year (12EUR), two-years (24EUR)
|
|
|
|
|
|
|
|
|
|
### Service
|
|
|
|
|
- **Table** : `services`
|
|
|
|
|
- **Relations** : `memberships()` belongsToMany(Membership)
|
2026-02-20 15:36:48 +01:00
|
|
|
- **Donnees** : mail (RoundCube), file2link, nextcloud, sympa, webhosting
|
2026-02-09 18:40:44 +01:00
|
|
|
|
|
|
|
|
### MemberGroup
|
|
|
|
|
- **Table** : `member_groups`
|
|
|
|
|
- **Relations** : `members()` hasMany(Member)
|
|
|
|
|
- **Donnees** : admin-interface, website
|
|
|
|
|
|
|
|
|
|
### Contact
|
|
|
|
|
- **Table** : `contacts`
|
|
|
|
|
|
|
|
|
|
### IspconfigMember
|
|
|
|
|
- **Table** : `ispconfigs_members`
|
|
|
|
|
- **Cast** : `type` vers IspconfigType enum, `data` vers array
|
|
|
|
|
|
|
|
|
|
### NextCloudMember
|
|
|
|
|
- **Table** : `nextclouds_members`
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Enums
|
|
|
|
|
|
2026-02-20 15:36:48 +01:00
|
|
|
| Enum | Valeurs |
|
|
|
|
|
| ------------- | ----------------------------------------------------- |
|
|
|
|
|
| IspconfigType | MAIL ("Email"), WEB ("Hebergement"), OTHER ("Autre") |
|
2026-02-09 18:40:44 +01:00
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Services (couche metier)
|
|
|
|
|
|
2026-02-20 15:36:48 +01:00
|
|
|
| Service | Responsabilite |
|
|
|
|
|
| ---------------------- | ----------------------------------------------------------- |
|
|
|
|
|
| ContactService | Creation de demandes de contact |
|
|
|
|
|
| MemberService | Inscription et desactivation de membres |
|
|
|
|
|
| DolibarrService | Integration ERP via API REST |
|
|
|
|
|
| ISPConfigMailService | Gestion comptes mail via SOAP |
|
|
|
|
|
| ISPConfigWebService | Gestion hebergement web via SOAP (avec cache) |
|
|
|
|
|
| NextcloudService | Gestion comptes Nextcloud via OCS (avec cache 7 jours) |
|
2026-02-09 18:40:44 +01:00
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Commandes Artisan (synchronisation)
|
|
|
|
|
|
2026-02-20 15:36:48 +01:00
|
|
|
| Commande | Description |
|
|
|
|
|
| ------------------------------- | ------------------------------------------------------------------------------ |
|
|
|
|
|
| `sync:dolibarr-members` | Importe les membres et cotisations depuis Dolibarr |
|
|
|
|
|
| `members:cleanup-expired` | Desactive les membres expires (Dolibarr + ISPConfig + Nextcloud). `--dry-run` |
|
|
|
|
|
| `sync:ispconfig-mail-members` | Lie les membres a leurs comptes mail ISPConfig (@retzien.fr) |
|
|
|
|
|
| `sync:ispconfig-web-members` | Lie les membres a leurs comptes d'hebergement web |
|
|
|
|
|
| `sync:nextcloud-members` | Lie les membres a leurs comptes Nextcloud |
|
|
|
|
|
| `sync:services-members` | Synchronise les services associes aux membres |
|
2026-02-09 18:40:44 +01:00
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Panel Admin (Filament v4)
|
|
|
|
|
|
2026-02-20 15:36:48 +01:00
|
|
|
### Structure des ressources
|
2026-02-09 18:40:44 +01:00
|
|
|
|
|
|
|
|
```
|
|
|
|
|
app/Filament/Resources/<Nom>/
|
2026-02-20 15:36:48 +01:00
|
|
|
├── <Nom>Resource.php
|
|
|
|
|
├── Schemas/<Nom>Form.php
|
|
|
|
|
├── Tables/<Nom>sTable.php
|
|
|
|
|
├── Pages/ (List, Create, Edit)
|
|
|
|
|
├── Widgets/ (optionnel)
|
|
|
|
|
└── RelationManagers/ (optionnel)
|
2026-02-09 18:40:44 +01:00
|
|
|
```
|
|
|
|
|
|
2026-02-20 15:36:48 +01:00
|
|
|
**Ressources** : MemberResource, MembershipResource, PackageResource, ServiceResource, MemberGroupResource, UserResource
|
|
|
|
|
|
|
|
|
|
**Pages custom** : Synchronisations (groupe "Paramètres" — lancement manuel des commandes Artisan)
|
2026-02-09 18:40:44 +01:00
|
|
|
|
|
|
|
|
**Widgets** : MemberCount, MembershipsChart
|
|
|
|
|
|
|
|
|
|
**Actions custom** : ServiceToggleAction
|
|
|
|
|
|
|
|
|
|
### Permissions (Spatie + Shield)
|
|
|
|
|
|
|
|
|
|
Format : `Action:Modele` en PascalCase (ex: `ViewAny:Member`, `Create:Membership`)
|
|
|
|
|
|
|
|
|
|
Roles :
|
|
|
|
|
- `super_admin` : acces complet
|
|
|
|
|
- `panel_user` : acces au panel avec permissions specifiques
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Frontend (React + Inertia v2)
|
|
|
|
|
|
|
|
|
|
### Pages
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
resources/js/pages/
|
2026-02-20 15:36:48 +01:00
|
|
|
├── welcome.tsx / maintenance.tsx / dashboard.tsx
|
|
|
|
|
├── auth/ (login, register, forgot-password, reset-password, verify-email, two-factor-challenge)
|
|
|
|
|
├── forms/ (contact.tsx, membership.tsx)
|
|
|
|
|
└── settings/ (profile, password, two-factor, appearance)
|
2026-02-09 18:40:44 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Composants principaux
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
resources/js/components/
|
2026-02-20 15:36:48 +01:00
|
|
|
├── app-shell.tsx / app-header.tsx / app-sidebar.tsx
|
2026-02-09 18:40:44 +01:00
|
|
|
├── nav-main.tsx / nav-user.tsx / nav-footer.tsx
|
2026-02-20 15:36:48 +01:00
|
|
|
├── breadcrumbs.tsx / flash-message.tsx
|
|
|
|
|
├── two-factor-setup-modal.tsx / appearance-tabs.tsx
|
|
|
|
|
└── ui/ (Shadcn/ui)
|
2026-02-09 18:40:44 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Notifications
|
|
|
|
|
|
2026-02-20 15:36:48 +01:00
|
|
|
| Classe | Canal | Description |
|
|
|
|
|
| ------------------------- | ----- | --------------------------------------------- |
|
|
|
|
|
| SubscriptionExpiredPhase1 | Email | Notification d'expiration d'adhesion (queued) |
|
2026-02-09 18:40:44 +01:00
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Localisation
|
|
|
|
|
|
2026-02-20 15:36:48 +01:00
|
|
|
Langues : **fr**, **en** — fichiers dans `lang/{locale}/` : contacts, members, memberships, packages, services, users, member_groups.
|
2026-02-09 18:40:44 +01:00
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## TODOs identifies dans le code
|
|
|
|
|
|
2026-02-20 15:36:48 +01:00
|
|
|
| Fichier | TODO |
|
|
|
|
|
|---------------------------|----------------------------------------------------------------------------|
|
|
|
|
|
| ContactService | Envoyer un email a l'administrateur |
|
|
|
|
|
| MemberService | Envoyer des emails au membre + admin a la desactivation |
|
|
|
|
|
| SubscriptionExpiredPhase1 | Creer un template generique + UI backend pour le contenu |
|
|
|
|
|
| User.php | Restreindre l'acces admin en prod aux emails @retzien.fr |
|
|
|
|
|
| SyncDolibarrMembers | Exporter la methode toDate() dans un service/helper |
|
|
|
|
|
| SyncISPConfigMailMembers | Gerer plusieurs emails par membre |
|
|
|
|
|
| SyncISPConfigMailMembers | Ajouter le suivi ispconfig_client_id |
|
|
|
|
|
| Global | Refactoriser pour rendre générique le projet Roxane (ERP pour association) |
|
|
|
|
|
| Traduction | Crawler le prrojet pour retrouver toutes les clés manquantes |
|
|
|
|
|
| Global | PHPstan niveau 8 |
|