Commit Graph

5 Commits

Author SHA1 Message Date
Serreau Jovann
95d33a9a6d feat: gestion complete Devis + Avis de paiement + DocuSeal signature + mails
Devis :
- Entity DevisLine (pos, title, description, priceHt) liee a Devis (OneToMany cascade/orphanRemoval)
- Champs ajoutes sur Devis : customer (ManyToOne), submissionId, state machine (created/send/accepted/refused/cancel), raisonMessage, totaux HT/TVA/TTC, updatedAt, setUpdatedAt public
- Relation Devis <-> Advert changee de ManyToOne a OneToOne nullable
- Vich Attribute (migration Annotation -> Attribute) pour unsignedPdf/signedPdf/auditPdf
- DevisController CRUD complet : create (form repeater lignes + boutons rapides TarificationService), edit, cancel (libere OrderNumber), generate-pdf, send, resend, create-advert, events
- DevisPdf (FPDF/FPDI) : header legacy (logo, num, date, client), body lignes, summary totaux, footer SITECONSEIL + pagination, champ signature DocuSeal sur page devis + derniere page CGV
- OrderNumberService : preview() et generate() reutilisent les OrderNumber non utilises (isUsed=false) en priorite
- OrderNumber::markAsUnused() ajoute

DocuSeal integration devis :
- DocuSealService : sendDevisForSignature (avec completed_redirect_url), resendDevisSignature (archive ancienne submission), getSubmitterSlug, downloadSignedDevis (sauvegarde via Vich UploadedFile test=true)
- WebhookDocuSealController : dispatch par doc_type devis/attestation, handleDevisEvent (form.completed -> STATE_ACCEPTED + download PDF signe/audit, form.declined -> STATE_REFUSED + raison)
- DocusealEvent entity pour tracer form.viewed/started/completed/declined en temps reel
- Page evenements admin /admin/devis/{id}/events avec badges et payload JSON

Signature client :
- DevisProcessController : page publique /devis/process/{id}/{hmac} securisee par HMAC, boutons Signer (redirect DocuSeal) / Refuser (motif optionnel)
- Pages confirmation : signed.html.twig (merci + recap) et refused.html.twig (confirmation refus + motif)
- Nelmio whitelist : signature.esy-web.dev + signature.siteconseil.fr

Avis de paiement :
- Entity AdvertLine (pos, title, description, priceHt) liee a Advert
- Advert refactorise : customer, state, totaux, raisonMessage, submissionId, advertFile (Vich mapping advert_pdf), lines collection, updatedAt
- AdvertController : generate-pdf, send (mail + PJ + lien paiement), resend (rappel), cancel (delie devis, libere OrderNumber), search Meilisearch
- AdvertPdf (FPDF/FPDI) : QR code Endroid pointant vers /order/{numOrder}, texte "Scannez pour payer"
- OrderPaymentController : page publique /order/{numOrder} avec detail prestations, totaux, options paiement (placeholder)
- Creation auto depuis devis signe : copie client, totaux, lignes, meme OrderNumber

Meilisearch :
- Index customer_devis et customer_advert avec searchable (numOrder, customerName, customerEmail, state) et filterable (customerId, state)
- CRUD indexation sur chaque action (create, edit, send, cancel, create-advert)
- Recherche AJAX dans tabs Devis et Avis avec debounce + dropdown glassmorphism
- Sync admin : boutons syncDevis / syncAdverts + compteurs dans /admin/sync

Emails :
- MailerService : VCF auto (fiche contact SARL SITECONSEIL) en PJ sur tous les mails, bloc HTML pieces jointes injecte automatiquement (exclut .asc/.p7z/smime) avec icone trombone + taille fichier
- Templates : devis_to_sign, devis_signed_client/admin (PJ signed+audit), devis_refused_client/admin, advert_send (PJ + bouton paiement), ndd_expiration
- TestMailCommand : option --force-dsn pour envoyer via un DSN SMTP specifique (test prod depuis dev)

Commande NDD :
- app:ndd:check : verifie expiration domaines <= 30j, envoie mail groupe a monitor@siteconseil.fr
- Cron quotidien 8h (docker + ansible)

Divers :
- Titles templates : CRM SITECONSEIL -> SARL SITECONSEIL (52 fichiers)
- VAULT_URL dev = https://kms.esy-web.dev (comme prod)
- app.js : initDevisLines (repeater + drag & drop), initTabSearch, toggle refus devis
- app.scss : styles drag & drop
- setasign/fpdi-fpdf installe pour fusion PDF
- 5 migrations Doctrine

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 09:44:35 +02:00
Serreau Jovann
1c82da99f3 fix: utiliser /uploads/devis comme URL pour les PDFs de devis
src/Controller/DevisPdfController.php:
- Route changee de /devis/pdf/{id}/{type} vers /uploads/devis/{id}/{type}
  pour garder une URL coherente avec le dossier uploads

config/packages/vich_uploader.yaml:
- uri_prefix change de /devis/pdf vers /uploads/devis

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 22:35:11 +02:00
Serreau Jovann
88053611a4 feat: controller securise pour servir les PDFs de devis + stockage prive
src/Controller/DevisPdfController.php (nouveau):
- Route /devis/pdf/{id}/{type} avec type = unsigned|signed|audit
- Requiert ROLE_USER minimum
- checkAccess(): les ROLE_EMPLOYE ont toujours acces,
  pour les clients un TODO est prepare pour verifier que le
  client connecte est bien lie au devis (a implementer quand
  la relation Customer sera ajoutee sur Devis)
- Sert le fichier via BinaryFileResponse en inline (affichage
  dans le navigateur) avec nom de telechargement propre
  (ex: signed-04-2026-00001.pdf)

config/packages/vich_uploader.yaml:
- Mapping devis_pdf: stockage deplace de public/uploads/devis
  vers var/uploads/devis (hors du dossier public, inaccessible
  directement par URL)
- uri_prefix change en /devis/pdf (pointe vers le controller)

config/packages/security.yaml:
- Suppression de la regle access_control sur /uploads/devis
  (remplacee par le controller avec verification plus fine)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 22:34:54 +02:00
Serreau Jovann
09148b5b33 feat: ajout champs submitter + PDFs Vich sur Devis + protection uploads
src/Entity/Devis.php:
- submitterSiteconseilId (int nullable): ID du soumetteur cote SITECONSEIL
  dans DocuSeal apres signature
- submitterCustomerId (int nullable): ID du soumetteur cote client
  dans DocuSeal apres signature
- unsignedPdf (string nullable) + unsignedPdfFile (Vich): PDF non signe
- signedPdf (string nullable) + signedPdfFile (Vich): PDF signe
- auditPdf (string nullable) + auditPdfFile (Vich): certificat d'audit
- updatedAt (DateTimeImmutable nullable): mis a jour automatiquement
  a chaque upload de fichier via les setters *File()
- Annotation #[Vich\Uploadable] sur la classe
- Les 3 champs fichier utilisent le mapping 'devis_pdf'

config/packages/vich_uploader.yaml:
- Nouveau mapping devis_pdf: stockage dans public/uploads/devis
  avec SmartUniqueNamer pour eviter les collisions de noms

config/packages/security.yaml:
- Nouvelle regle access_control: /uploads/devis requiert ROLE_USER
  (empeche l'acces aux PDF de devis sans etre connecte)

migrations/Version20260402203334.php:
- Ajout colonnes submitter_siteconseil_id, submitter_customer_id,
  unsigned_pdf, signed_pdf, audit_pdf, updated_at sur la table devis

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 22:33:47 +02:00
Serreau Jovann
686de99909 init 2026-04-01 15:42:52 +02:00