Module Declarations prealables¶
Objectif¶
Le module Declarations prealables gere des demandes administratives structurees par type. Chaque type definit :
- les documents attendus ;
- les questions a renseigner ;
- les champs obligatoires ;
- l'icone et le libelle affiches.
Une societe cree une demande en brouillon ou la depose pour examen. Les administrateurs suivent ensuite la demande, changent son statut, archivent/suppriment et recoivent/envoient des notifications.
Carte technique¶
flowchart TD
Router["app/core/Router.php"] --> Controller["DeclarationPrealableController"]
Router --> TypeController["admin/DeclarationPrealableTypeController"]
Controller --> Model["DeclarationPrealableModel"]
TypeController --> TypeModel["DeclarationPrealableTypeModel"]
Model --> Tables["dp_instances / dp_instance_*"]
TypeModel --> TypeTables["dp_types / dp_type_*"]
Model --> Notifications["DeclarationPrealableNotificationService"]
NoteModel["NoteModel"] --> Notifications
Notifications --> Mailer["MailerService"]
Cron["app/cron/dp_notifications_cron.php"] --> Notifications
View["declarations-prealables.php"] --> Details["declaration-prealable-details.php"]
AdminView["admin/declaration-prealable-types.php"] --> TypeModal["ajouter-modifier-pour-declaration-prealable-type.php"]
Fichiers a connaitre¶
| Role | Fichiers |
|---|---|
| Routes | app/core/Router.php |
| Controleur demandes | app/controllers/DeclarationPrealableController.php |
| Modele demandes | app/models/DeclarationPrealableModel.php |
| Controleur types admin | app/controllers/admin/DeclarationPrealableTypeController.php |
| Modele types admin | app/models/admin/DeclarationPrealableTypeModel.php |
| Notifications | app/services/DeclarationPrealableNotificationService.php, app/cron/dp_notifications_cron.php |
| Notes liees | app/models/NoteModel.php |
| Vues | app/views/declarations-prealables.php, app/views/partials/details/declaration-prealable-details.php |
| Admin types | app/views/admin/declaration-prealable-types.php, app/views/partials/modals/ajouter-modifier-pour-declaration-prealable-type.php |
| SQL | app/bd/declarations-prealables.sql |
Routes demandes¶
| Route | Methode | Acces routeur | Controleur | Usage |
|---|---|---|---|---|
declarations-prealables |
GET | FEATURE_GERER_DECLARATION_PREALABLE |
index() |
Liste et page principale. |
declaration-prealable/get |
POST | FEATURE_GERER_DECLARATION_PREALABLE |
get() |
Detail complet d'une demande. |
declaration-prealable/save |
POST | FEATURE_GERER_DECLARATION_PREALABLE |
save() |
Brouillon ou depot. |
declaration-prealable/change-status |
POST | admin | changeStatus() |
Changement de statut. |
declaration-prealable/archive |
POST | admin | archive() |
Archivage logique. |
declaration-prealable/unarchive |
POST | admin | unarchive() |
Desarchivage. |
declaration-prealable/delete |
POST | admin | delete() |
Suppression logique. |
Routes admin des types¶
| Route | Methode | Acces | Controleur | Usage |
|---|---|---|---|---|
declaration-prealable-types |
GET | admin | index() |
Liste des types. |
declaration-prealable-type/add |
POST | admin | add() |
Creation d'un type. |
declaration-prealable-type/update |
POST | admin | update() |
Modification d'un type. |
declaration-prealable-type/delete |
POST | admin | delete() |
Suppression d'un type. |
Droits et plans¶
Le routeur controle la feature FEATURE_GERER_DECLARATION_PREALABLE.
Le modele refait un controle via checkFeatureAccess(), puis un controle de plan via checkRequestActionAccess() pour les actions de creation/modification.
Plan minimal pour creer ou modifier une demande :
MINIMUM_REQUIRED_PLAN_NAME = TPE;- admins : rang force a
999, donc bypass de plan ; GRATUITest insuffisant.
Permissions utilisees :
- liste/detail :
PermissionMiddleware::require('déclarations préalable', 'view_all'); - creation :
déclarations préalable/create; - edition :
déclarations préalable/edit.
Les constantes de permissions contiennent le module déclarations préalable.
Schema de donnees¶
dp_types¶
Types administrables :
nameunique ;icon;- timestamps.
dp_type_documents¶
Documents attendus par type :
dp_type_id;label;required;sort_order.
Suppression en cascade quand le type est supprime.
dp_type_questions¶
Questions attendues par type :
dp_type_id;label;required;sort_order.
Suppression en cascade quand le type est supprime.
dp_instances¶
Demande concrete d'une societe.
Champs principaux :
dp_type_id;societe_id;created_by_membre_id;reference;status;submitted_at;reviewed_at;reviewed_by_membre_id;review_reason;- timestamps.
Statuts exacts dans l'enum SQL :
incomplète;en cours;déposée;non réalisable;terminée.
Colonnes de cycle de vie ajoutees au runtime par ensureLifecycleColumns() si absentes :
archived_at;archived_by_membre_id;deleted_at;deleted_by_membre_id.
dp_instance_documents¶
Documents d'une demande :
dp_instance_id;dp_type_document_id;label;required;file_path;original_name;mime_type;file_size;uploaded_at.
dp_instance_answers¶
Reponses d'une demande :
dp_instance_id;dp_type_question_id;label;answer.
Le detail general de la demande est stocke comme une reponse avec le libelle Description générale.
Flux : liste et visibilite¶
getPaginatedDeclarations() applique toujours deleted_at IS NULL.
En contexte admin :
- seules les demandes deposees sont visibles (
submitted_at IS NOT NULL) ; - filtre optionnel par
societe_id.
En contexte societe :
- filtre obligatoire sur
societe_id = active_societe_id; - les brouillons de la societe restent visibles.
Filtres supportes :
search: reference, nom du type, reponseDescription générale;statut;created_by;societe_idpour admin ;date_debut;date_fin;- tri autorise :
id,reference,status,created_at.
Une demande est editable cote societe seulement si :
- l'utilisateur n'est pas admin ;
- permission
editpresente ; - pas archivee ;
- statut
incomplèteouen cours.
Flux : brouillon et depot¶
save() recoit :
declaration_id;type_id;reference;detail_demande;accepted_cgu;save_mode;documents;answers;- fichiers
$_FILES.
save_mode = draft :
- statut
incomplète; - documents/reponses obligatoires peuvent manquer ;
submitted_atreste nul.
Depot :
- statut
en cours; referenceobligatoire ;detail_demandeobligatoire ;- tous les documents obligatoires doivent etre presents ou deja existants ;
- toutes les questions obligatoires doivent avoir une reponse ;
submitted_atest pose a la premiere soumission.
Notification admin :
- envoyee seulement si la demande n'est pas un brouillon ;
- et si c'est une nouvelle demande deposee ou une demande qui n'avait pas encore
submitted_at.
Flux : documents uploades¶
Constantes :
- module upload :
dp; - type de document :
attachments; - taille max :
5 Mo.
prepareInstanceDocument() :
- conserve le fichier existant si aucun nouvel upload n'arrive ;
- upload avec
BaseModel::uploadFile($file, 'dp', 'attachments', 5242880, false); - stocke
file_pathsousattachments/<fichier>; - calcule
mime_typeviamime_content_type(); - stocke
original_name,file_size,uploaded_at.
URL de lecture :
Donc un fichier stocke en base comme attachments/x.pdf est servi via uploads/dp/attachments/x.pdf.
Flux : changement de statut¶
updateStatus() est reserve admin.
Statuts autorises par le modele :
en cours;incomplète;déposée;non réalisable;terminée.
Regles :
- statut inconnu refuse ;
- demande introuvable refusee ;
- demande archivee refusee ;
- demande deja
terminéeverrouillee ; - si le statut ne change pas, retour success sans notification ;
- sinon mise a jour de
status,reviewed_at,reviewed_by_membre_id,review_reason,updated_at; - notification de changement de statut ensuite.
Archivage et suppression¶
Actions admin :
archive()renseignearchived_atetarchived_by_membre_id;unarchive()remet ces champs aNULL;delete()renseignedeleted_atetdeleted_by_membre_id.
La suppression est logique. Les listes excluent les lignes avec deleted_at.
Administration des types¶
DeclarationPrealableTypeModel::saveType() cree ou modifie un type et ses enfants dans une transaction.
Regles utiles :
- nom obligatoire ;
- documents et questions sont remplaces par les valeurs postees ;
- chaque enfant porte
label,required,sort_order; - la suppression d'un type supprime d'abord documents/questions puis
dp_types.
Attention : dp_instances.dp_type_id a une contrainte ON DELETE RESTRICT. Supprimer un type utilise par une demande peut donc echouer selon l'etat des donnees.
Notifications¶
DeclarationPrealableNotificationService cree dynamiquement la table dp_notifications :
dp_instance_id;societe_id;source_type;payload_json;status:pending,processing,sent,failed;retry_count;next_retry_at;last_error;sent_at;- timestamps.
Retries :
MAX_RETRIES = 3;- delai entre retries :
300secondes ; processPendingNotifications($limit)borne la limite entre 1 et 100.
Sources verifiees :
new_request: nouvelle demande deposee, notification aux admins ;status_changed: changement de statut, notification a la societe ;note_from_societe: note ajoutee par la societe, notification aux admins ;note_from_admin: note ajoutee par un admin, notification a la societe.
queueNotification() envoie les sources new_request et note_from_societe vers queueAdminNotifications(), donc potentiellement plusieurs lignes de notification.
Le modele tente l'envoi immediat apres mise en file via sendNotificationById(). Le cron sert de rattrapage pour les notifications pending.
Cron :
Integration Notes¶
NoteModel appelle dispatchDeclarationNoteNotification() quand resource_type === 'dp'.
Le payload de note contient :
source_type:note_from_adminounote_from_societeselon la session ;dp_instance_id;societe_id;reference;type_name;societe_name;detail_demande;- nom de la personne ayant ajoute la note ;
note_content;redirect_path.
Particularites runtime¶
Deux schemas sont crees/alteres au runtime :
DeclarationPrealableModel::__construct()appelleensureLifecycleColumns()pour ajouter les colonnes archive/suppression ;DeclarationPrealableNotificationService::__construct()appelleensureStorageSchema()pour creerdp_notifications.
Impact :
- l'utilisateur SQL applicatif doit pouvoir
ALTER TABLEetCREATE TABLE; - un environnement avec droits limites peut echouer tardivement ;
- ces changements devraient idealement etre appliques par migration avant usage.
Points de vigilance¶
- Utiliser les statuts exacts avec accents. Une variante comme
incompleteoutermineene correspond pas a l'enum. - Les admins ne voient que les demandes deposees (
submitted_at IS NOT NULL). Les brouillons restent cote societe. - Une demande
terminée,non réalisable, archivee ou supprimee ne doit pas etre modifiable cote societe. - Le champ
accepted_cguest recu par le controleur mais aucune colonne equivalente n'a ete identifiee dans le schema inspecte. - La creation de
dp_notificationsest dans le service, pas dansdeclarations-prealables.sql. - La suppression de type peut etre bloquee par
dp_instancesviaON DELETE RESTRICT. - Les documents obligatoires sont verifies deux fois dans
save(): avant preparation, puis apres preparation. Garder ce double verrou si la logique upload evolue.
Verification conseillee¶
- Creer un type avec un document obligatoire et une question obligatoire.
- En societe TPE ou plus, creer un brouillon : statut
incomplète,submitted_atnul. - Tenter le depot sans document obligatoire : refus attendu.
- Ajouter les pieces et reponses, deposer : statut
en cours,submitted_atrenseigne, notificationnew_request. - En admin, verifier que la demande apparait dans la liste.
- Changer le statut vers
déposée, puis verifierreviewed_at,reviewed_by_membre_id,review_reasonet notificationstatus_changed. - Ajouter une note cote societe et cote admin ; verifier les sources
note_from_societeetnote_from_admin. - Lancer
php app/cron/dp_notifications_cron.phppour traiter les notifications restantes.
Questions ouvertes¶
- Aucun test automatise dedie aux Declarations prealables n'a ete trouve dans les fichiers inspectes.
accepted_cgusemble capture au POST mais n'est pas persiste dans les tables inspectees.- Les migrations runtime devraient etre clarifiees avant durcissement des droits SQL de production.