create-crm-tmp 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/bin/create-crm-tmp.js +56 -35
  2. package/package.json +1 -1
  3. package/template/README.md +230 -115
  4. package/template/eslint.config.mjs +13 -0
  5. package/template/next.config.ts +14 -0
  6. package/template/package.json +15 -2
  7. package/template/prisma/migrations/20260318095700_init_db/migration.sql +978 -0
  8. package/template/prisma/migrations/migration_lock.toml +3 -0
  9. package/template/prisma/schema.prisma +132 -637
  10. package/template/src/app/(auth)/invite/[token]/page.tsx +10 -8
  11. package/template/src/app/(auth)/layout.tsx +1 -1
  12. package/template/src/app/(auth)/reset-password/complete/page.tsx +11 -8
  13. package/template/src/app/(auth)/reset-password/page.tsx +4 -4
  14. package/template/src/app/(auth)/reset-password/verify/page.tsx +4 -4
  15. package/template/src/app/(auth)/signin/page.tsx +14 -6
  16. package/template/src/app/(dashboard)/agenda/page.tsx +2243 -988
  17. package/template/src/app/(dashboard)/automatisation/_components/workflow-editor.tsx +18 -104
  18. package/template/src/app/(dashboard)/automatisation/page.tsx +10 -26
  19. package/template/src/app/(dashboard)/closing/page.tsx +78 -62
  20. package/template/src/app/(dashboard)/contacts/[id]/page.tsx +2082 -1080
  21. package/template/src/app/(dashboard)/contacts/companies/[id]/page.tsx +46 -47
  22. package/template/src/app/(dashboard)/contacts/page.tsx +1062 -780
  23. package/template/src/app/(dashboard)/dashboard/page.tsx +533 -37
  24. package/template/src/app/(dashboard)/dev/page.tsx +1291 -0
  25. package/template/src/app/(dashboard)/layout.tsx +6 -2
  26. package/template/src/app/(dashboard)/settings/page.tsx +797 -2582
  27. package/template/src/app/(dashboard)/templates/page.tsx +55 -54
  28. package/template/src/app/(dashboard)/users/list/page.tsx +51 -48
  29. package/template/src/app/(dashboard)/users/page.tsx +1 -1
  30. package/template/src/app/(dashboard)/users/permissions/page.tsx +2 -2
  31. package/template/src/app/(dashboard)/users/roles/page.tsx +7 -5
  32. package/template/src/app/api/agenda/google-events/route.ts +92 -0
  33. package/template/src/app/api/auth/check-active/route.ts +3 -2
  34. package/template/src/app/api/auth/google/route.ts +2 -1
  35. package/template/src/app/api/auth/google/status/route.ts +7 -31
  36. package/template/src/app/api/companies/[id]/activities/route.ts +1 -3
  37. package/template/src/app/api/companies/[id]/route.ts +1 -2
  38. package/template/src/app/api/companies/route.ts +42 -12
  39. package/template/src/app/api/contacts/[id]/files/[fileId]/preview/route.ts +9 -31
  40. package/template/src/app/api/contacts/[id]/files/[fileId]/route.ts +14 -32
  41. package/template/src/app/api/contacts/[id]/files/route.ts +112 -212
  42. package/template/src/app/api/contacts/[id]/interactions/[interactionId]/route.ts +27 -1
  43. package/template/src/app/api/contacts/[id]/interactions/route.ts +16 -16
  44. package/template/src/app/api/contacts/[id]/kyc/route.ts +21 -11
  45. package/template/src/app/api/contacts/[id]/meet/route.ts +19 -2
  46. package/template/src/app/api/contacts/[id]/route.ts +106 -34
  47. package/template/src/app/api/contacts/[id]/send-email/route.ts +27 -11
  48. package/template/src/app/api/contacts/[id]/workflows/run/route.ts +6 -0
  49. package/template/src/app/api/contacts/export/route.ts +9 -13
  50. package/template/src/app/api/contacts/import/route.ts +55 -25
  51. package/template/src/app/api/contacts/import-preview/route.ts +1 -1
  52. package/template/src/app/api/contacts/origins/route.ts +63 -0
  53. package/template/src/app/api/contacts/route.ts +153 -41
  54. package/template/src/app/api/cron/cleanup-editor-images/route.ts +166 -0
  55. package/template/src/app/api/dashboard/widgets/[id]/route.ts +44 -0
  56. package/template/src/app/api/dashboard/widgets/route.ts +181 -0
  57. package/template/src/app/api/dev/reminders/test/route.ts +114 -0
  58. package/template/src/app/api/editor/upload-image/route.ts +61 -0
  59. package/template/src/app/api/integrations/google-sheet/jobs/[jobId]/route.ts +47 -0
  60. package/template/src/app/api/integrations/google-sheet/jobs/usage/route.ts +50 -0
  61. package/template/src/app/api/integrations/google-sheet/sync/route.ts +24 -556
  62. package/template/src/app/api/jobs/google-sheet/process/route.ts +84 -0
  63. package/template/src/app/api/jobs/google-sheet/schedule/route.ts +50 -0
  64. package/template/src/app/api/reminders/clear/route.ts +120 -0
  65. package/template/src/app/api/reminders/clear/undo/route.ts +112 -0
  66. package/template/src/app/api/reminders/route.ts +164 -39
  67. package/template/src/app/api/reminders/state/route.ts +164 -0
  68. package/template/src/app/api/reset-password/request/route.ts +1 -1
  69. package/template/src/app/api/reset-password/verify/route.ts +1 -1
  70. package/template/src/app/api/send/route.ts +16 -4
  71. package/template/src/app/api/settings/google-ads/route.ts +14 -0
  72. package/template/src/app/api/settings/google-calendar/calendars/route.ts +97 -0
  73. package/template/src/app/api/settings/google-calendar/route.ts +124 -0
  74. package/template/src/app/api/settings/google-sheet/[id]/route.ts +28 -0
  75. package/template/src/app/api/settings/google-sheet/auto-map/route.ts +37 -4
  76. package/template/src/app/api/settings/google-sheet/preview/route.ts +9 -3
  77. package/template/src/app/api/settings/google-sheet/route.ts +14 -0
  78. package/template/src/app/api/settings/integrations/logs/route.ts +93 -0
  79. package/template/src/app/api/settings/integrations/notifications/route.ts +67 -0
  80. package/template/src/app/api/settings/meta-leads/[id]/route.ts +0 -1
  81. package/template/src/app/api/settings/meta-leads/route.ts +14 -2
  82. package/template/src/app/api/settings/smtp/route.ts +53 -6
  83. package/template/src/app/api/tasks/[id]/attendees/route.ts +24 -8
  84. package/template/src/app/api/tasks/[id]/route.ts +234 -58
  85. package/template/src/app/api/tasks/meet/route.ts +27 -19
  86. package/template/src/app/api/tasks/route.ts +62 -17
  87. package/template/src/app/api/users/[id]/route.ts +20 -14
  88. package/template/src/app/api/users/list/route.ts +57 -19
  89. package/template/src/app/api/webhooks/google-ads/route.ts +34 -14
  90. package/template/src/app/api/webhooks/meta-leads/route.ts +32 -12
  91. package/template/src/app/api/workflows/[id]/route.ts +0 -4
  92. package/template/src/app/api/workflows/process/route.ts +22 -51
  93. package/template/src/app/api/workflows/route.ts +0 -4
  94. package/template/src/app/globals.css +342 -4
  95. package/template/src/app/layout.tsx +11 -3
  96. package/template/src/app/page.tsx +1 -1
  97. package/template/src/components/address-autocomplete.tsx +7 -6
  98. package/template/src/components/config-error-alert.tsx +46 -0
  99. package/template/src/components/contacts/filter-bar.tsx +12 -3
  100. package/template/src/components/contacts/filter-builder.tsx +28 -43
  101. package/template/src/components/contacts/save-view-dialog.tsx +1 -1
  102. package/template/src/components/contacts/views-tab-bar.tsx +15 -6
  103. package/template/src/components/dashboard/activity-chart.tsx +41 -28
  104. package/template/src/components/dashboard/add-widget-dialog.tsx +157 -0
  105. package/template/src/components/dashboard/color-picker.tsx +64 -0
  106. package/template/src/components/dashboard/contacts-chart.tsx +69 -0
  107. package/template/src/components/dashboard/interactions-by-type-chart.tsx +121 -0
  108. package/template/src/components/dashboard/recent-activity.tsx +154 -0
  109. package/template/src/components/dashboard/stat-card.tsx +40 -40
  110. package/template/src/components/dashboard/status-distribution-chart.tsx +81 -0
  111. package/template/src/components/dashboard/tasks-pie-chart.tsx +37 -34
  112. package/template/src/components/dashboard/top-contacts-list.tsx +113 -0
  113. package/template/src/components/dashboard/upcoming-tasks-list.tsx +72 -81
  114. package/template/src/components/dashboard/widget-wrapper.tsx +36 -0
  115. package/template/src/components/date-picker.tsx +9 -6
  116. package/template/src/components/editor/upload-editor-image.ts +42 -0
  117. package/template/src/components/editor.tsx +161 -22
  118. package/template/src/components/email-template.tsx +2 -2
  119. package/template/src/components/global-search.tsx +30 -28
  120. package/template/src/components/header.tsx +178 -80
  121. package/template/src/components/inactive-account-guard.tsx +58 -0
  122. package/template/src/components/integration-notifications-listener.tsx +12 -0
  123. package/template/src/components/invitation-email-template.tsx +2 -2
  124. package/template/src/components/meet-cancellation-email-template.tsx +3 -3
  125. package/template/src/components/meet-confirmation-email-template.tsx +3 -3
  126. package/template/src/components/meet-update-email-template.tsx +3 -3
  127. package/template/src/components/page-header.tsx +5 -5
  128. package/template/src/components/protected-page.tsx +1 -1
  129. package/template/src/components/reset-password-email-template.tsx +2 -2
  130. package/template/src/components/settings/integrations/GoogleAdsIntegration.tsx +428 -0
  131. package/template/src/components/settings/integrations/GoogleSheetConfigMonitoringModal.tsx +680 -0
  132. package/template/src/components/settings/integrations/GoogleSheetIntegration.tsx +809 -0
  133. package/template/src/components/settings/integrations/ImportResultDialog.tsx +124 -0
  134. package/template/src/components/settings/integrations/IntegrationLogPanel.tsx +57 -0
  135. package/template/src/components/settings/integrations/IntegrationLogsTable.tsx +186 -0
  136. package/template/src/components/settings/integrations/MetaLeadIntegration.tsx +451 -0
  137. package/template/src/components/sidebar.tsx +45 -26
  138. package/template/src/components/skeleton.tsx +40 -43
  139. package/template/src/components/ui/accordion.tsx +2 -2
  140. package/template/src/components/ui/alert-dialog.tsx +1 -1
  141. package/template/src/components/ui/button.tsx +20 -9
  142. package/template/src/components/ui/components.tsx +1 -1
  143. package/template/src/components/ui/date-picker.tsx +422 -0
  144. package/template/src/components/ui/datetime-picker.tsx +338 -0
  145. package/template/src/components/ui/status-select.tsx +271 -0
  146. package/template/src/components/ui/tooltip.tsx +37 -0
  147. package/template/src/components/view-as-modal.tsx +13 -7
  148. package/template/src/contexts/app-toast-context.tsx +245 -57
  149. package/template/src/contexts/dashboard-theme-context.tsx +53 -0
  150. package/template/src/contexts/sidebar-context.tsx +22 -17
  151. package/template/src/contexts/task-reminder-context.tsx +134 -160
  152. package/template/src/contexts/view-as-context.tsx +33 -6
  153. package/template/src/hooks/use-focus-trap.ts +2 -2
  154. package/template/src/hooks/useIntegrationNotifications.ts +49 -0
  155. package/template/src/lib/auth.ts +8 -1
  156. package/template/src/lib/config-links.ts +14 -0
  157. package/template/src/lib/contact-duplicate.ts +79 -61
  158. package/template/src/lib/contact-interactions.ts +21 -21
  159. package/template/src/lib/contact-view-filters.ts +24 -64
  160. package/template/src/lib/contacts-list-url.ts +190 -0
  161. package/template/src/lib/dashboard-stats.ts +65 -7
  162. package/template/src/lib/dashboard-themes.ts +135 -0
  163. package/template/src/lib/date-utils.ts +127 -0
  164. package/template/src/lib/default-widgets.ts +12 -0
  165. package/template/src/lib/editor-html-image-dimensions.ts +172 -0
  166. package/template/src/lib/editor-image-limits.ts +19 -0
  167. package/template/src/lib/email-html-sanitize.ts +19 -0
  168. package/template/src/lib/encryption.ts +9 -6
  169. package/template/src/lib/fr-geography.ts +192 -0
  170. package/template/src/lib/google-calendar-agenda.ts +201 -0
  171. package/template/src/lib/google-calendar.ts +255 -5
  172. package/template/src/lib/google-sheet-sync-jobs.ts +96 -0
  173. package/template/src/lib/google-sheet-sync-runner.ts +514 -0
  174. package/template/src/lib/integration-import-log.ts +21 -0
  175. package/template/src/lib/permissions.ts +40 -10
  176. package/template/src/lib/prisma.ts +4 -1
  177. package/template/src/lib/qstash.ts +65 -0
  178. package/template/src/lib/reminder-state-server.ts +80 -0
  179. package/template/src/lib/reminder-state.ts +29 -0
  180. package/template/src/lib/supabase-storage.ts +113 -0
  181. package/template/src/lib/template-variables.ts +164 -23
  182. package/template/src/lib/utils.ts +45 -0
  183. package/template/src/lib/widget-registry.ts +173 -0
  184. package/template/src/lib/workflow-executor.ts +16 -70
  185. package/template/src/proxy.ts +1 -0
  186. package/template/vercel.json +3 -10
  187. package/template/skills-lock.json +0 -25
  188. package/template/src/components/dashboard/dashboard-content.tsx +0 -79
  189. package/template/src/lib/google-drive.ts +0 -1101
  190. package/template/src/types/yousign.ts +0 -52
@@ -66,13 +66,6 @@ model User {
66
66
  auditLogsAsActor AuditLog[] @relation("AuditActor")
67
67
  auditLogsAsTargetUser AuditLog[] @relation("AuditTargetUser")
68
68
  workflows Workflow[] @relation("WorkflowOwner")
69
- toursManaged Tour[] @relation("TourCommercial")
70
- transactionsCreated Transaction[] @relation("TransactionCreatedBy")
71
- transactionsAssigned Transaction[] @relation("TransactionAssignedTo")
72
- transactionAuditLogs TransactionAuditLog[]
73
- unavailableDatesCreated UnavailableDate[]
74
- distributionCampaignPayments DistributionCampaignPayment[]
75
- metaAdsPayments MetaAdsPayment[]
76
69
  contactViews ContactView[]
77
70
  contactViewPins ContactViewPin[]
78
71
  companiesAssignedCommercial Company[] @relation("CompanyAssignedCommercial")
@@ -83,13 +76,23 @@ model User {
83
76
  workflowActionsAssignCommercial WorkflowAction[] @relation("WorkflowActionAssignCommercial")
84
77
  workflowActionsAssignTelepro WorkflowAction[] @relation("WorkflowActionAssignTelepro")
85
78
  workflowActionsNotifyUser WorkflowAction[] @relation("WorkflowActionNotifyUser")
86
- refinerSubmissions RefinerSubmission[] @relation("RefinerSubmissionCreatedBy")
79
+ dashboardWidgets DashboardWidget[]
80
+ integrationImportLogs IntegrationImportLog[]
81
+ googleSheetSyncJobs GoogleSheetSyncJob[]
82
+ reminderStates UserReminderState[]
87
83
 
88
84
  @@unique([email])
89
85
  @@index([customRoleId])
90
86
  @@map("user")
91
87
  }
92
88
 
89
+ enum ReminderStateStatus {
90
+ UNREAD
91
+ READ
92
+ DISMISSED
93
+ CLEARED
94
+ }
95
+
93
96
  model AuditLog {
94
97
  id String @id @default(cuid())
95
98
  actorId String?
@@ -170,10 +173,10 @@ model Organization {
170
173
  siret String?
171
174
  vatNumber String?
172
175
  logo String?
173
- cerfaTemplateFileId String? // Google Drive File ID du template PDF Cerfa
174
- contractTemplateFileId String? // Google Drive File ID du template PDF de contrat de rachat
175
- yousignSignaturePosition Json? // Position de la signature Yousign {page, x, y, width, height}
176
- yousignRetractionPosition Json? // Position de la signature Yousign pour le formulaire de rétractation (page 4)
176
+ cerfaTemplateFileId String?
177
+ contractTemplateFileId String?
178
+ signaturePosition Json? // Position de la signature électronique {page, x, y, width, height}
179
+ retractionPosition Json? // Position pour le formulaire de rétractation
177
180
  createdAt DateTime @default(now())
178
181
  updatedAt DateTime @updatedAt
179
182
 
@@ -309,133 +312,6 @@ enum TaskPriority {
309
312
  URGENT
310
313
  }
311
314
 
312
- enum PlaceType {
313
- HOTEL
314
- RESTAURANT
315
- AUTRE
316
- }
317
-
318
- enum PaymentStatus {
319
- PAYE
320
- EN_ATTENTE
321
- ACOMPTE_VERSE
322
- }
323
-
324
- enum CampaignPaymentStatus {
325
- A_PAYER
326
- PARTIEL
327
- PAYE
328
- }
329
-
330
- enum CityHallStatus {
331
- OUI
332
- NON
333
- EN_COURS
334
- EN_ATTENTE
335
- }
336
-
337
- enum DistributionType {
338
- FLYERS
339
- COURRIERS
340
- MIX
341
- }
342
-
343
- enum IdType {
344
- CNI
345
- PASSPORT
346
- LICENSE
347
- RESIDENCE_PERMIT
348
- OTHER
349
- }
350
-
351
- enum TransactionStatus {
352
- DRAFT
353
- PENDING_ID_VERIFICATION
354
- ID_VERIFIED
355
- ITEMS_ENTERED
356
- PENDING_SIGNATURE // En attente de signature électronique Yousign
357
- SIGNED
358
- LOCKED
359
- PAYMENT_PENDING
360
- COMPLETED
361
- PENDING_RETRACTION // En attente de signature du formulaire de rétractation
362
- CANCELLED_RETRACTION
363
- CANCELLED
364
- }
365
-
366
- enum SignatureType {
367
- TABLET
368
- ELECTRONIC
369
- PAPER
370
- }
371
-
372
- enum PaymentMethod {
373
- CHECK
374
- BANK_TRANSFER
375
- }
376
-
377
- enum TransactionItemCategory {
378
- GOLD
379
- PLATINUM
380
- SILVER
381
- WATCHES
382
- COLLECTIBLES
383
- DIAMONDS
384
- SILVERED_METAL
385
- GOLD_PLATED
386
- TIN
387
- }
388
-
389
- enum TransactionItemProcessingStatus {
390
- A_VERIFIER
391
- TRAITE
392
- }
393
-
394
- enum StockDisposition {
395
- IN_STOCK
396
- EXCLUDED
397
- SENT_TO_REFINER
398
- SOLD
399
- }
400
-
401
- enum RefinerSubmissionStatus {
402
- PENDING
403
- PROVISIONAL_PAID
404
- COMPLETED
405
- }
406
-
407
- enum GoldPurity {
408
- P375
409
- P585
410
- P750
411
- P900
412
- P916
413
- P999
414
- }
415
-
416
- enum PlatinumPurity {
417
- P900
418
- P950
419
- }
420
-
421
- enum SilverPurity {
422
- P680
423
- P800
424
- P835
425
- P900
426
- P925
427
- P999
428
- }
429
-
430
- enum GoldType {
431
- JEWELRY
432
- DEBRIS
433
- COINS
434
- INGOTS
435
- TEETH
436
- GOLD_WATCHES
437
- }
438
-
439
315
  model Contact {
440
316
  id String @id @default(cuid())
441
317
  civility Civility?
@@ -448,9 +324,12 @@ model Contact {
448
324
  city String?
449
325
  postalCode String?
450
326
  origin String? // Origine du contact
327
+ companyName String? // Nom de société en texte libre (sans liaison entreprise)
451
328
  companyId String?
452
329
  company Company? @relation(fields: [companyId], references: [id], onDelete: SetNull)
453
330
  jobTitle String? // Intitulé du poste (pour hiérarchie dans l'entreprise)
331
+ website String? // Site internet (URL cliquable)
332
+ socialNetworks Json? // Réseaux sociaux : [{ platform: string, url: string }]
454
333
  statusId String?
455
334
  status Status? @relation(fields: [statusId], references: [id], onDelete: SetNull)
456
335
  closingReason String? // Motif de fermeture (si statut Fermé)
@@ -466,16 +345,14 @@ model Contact {
466
345
  tasks Task[]
467
346
  files ContactFile[]
468
347
  scheduledWorkflowActions ScheduledWorkflowAction[]
469
- tourLinks TourContact[]
470
348
  // KYC fields
471
349
  placeOfBirth String? // Lieu de naissance
472
350
  dateOfBirth DateTime? // Date de naissance
473
- idType IdType? // Type de pièce d'identité
351
+ idType String? // Type de pièce d'identité (texte libre)
474
352
  idNumber String? // Numéro de pièce d'identité
475
353
  idExpiryDate DateTime? // Date d'expiration de la pièce d'identité
476
- idDocumentUrl String? // URL/lien vers le document d'identité dans Google Drive
354
+ idDocumentUrl String?
477
355
  idVerifiedByAdmin Boolean @default(false) // Vérifié par un admin
478
- transactions Transaction[]
479
356
 
480
357
  @@index([statusId])
481
358
  @@index([assignedCommercialId])
@@ -528,8 +405,6 @@ model Task {
528
405
  id String @id @default(cuid())
529
406
  contactId String? // Optionnel : peut être créée depuis un contact
530
407
  contact Contact? @relation(fields: [contactId], references: [id], onDelete: SetNull)
531
- tourId String? // Optionnel : lien avec une tournée
532
- tour Tour? @relation(fields: [tourId], references: [id], onDelete: SetNull)
533
408
  type TaskType
534
409
  title String?
535
410
  description String // Description HTML (avec Editor)
@@ -543,6 +418,7 @@ model Task {
543
418
  completed Boolean @default(false) // Tâche terminée ou non
544
419
  completedAt DateTime? // Date de complétion
545
420
  googleEventId String? // ID de l'évènement Google Calendar
421
+ googleCalendarId String? // Calendrier Google contenant l'évènement (null = primary pour les anciennes lignes)
546
422
  googleMeetLink String? // URL du Google Meet
547
423
  durationMinutes Int? // Durée de la réunion en minutes (pour Google Meet)
548
424
  internalNote String? // Note personnelle (non partagée dans les emails)
@@ -557,7 +433,6 @@ model Task {
557
433
  updatedAt DateTime @updatedAt
558
434
 
559
435
  @@index([contactId])
560
- @@index([tourId])
561
436
  @@index([assignedUserId])
562
437
  @@index([createdById])
563
438
  @@index([scheduledAt])
@@ -567,37 +442,60 @@ model Task {
567
442
  @@map("task")
568
443
  }
569
444
 
445
+ model UserReminderState {
446
+ id String @id @default(cuid())
447
+ userId String
448
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
449
+ reminderId String
450
+ status ReminderStateStatus
451
+ createdAt DateTime @default(now())
452
+ updatedAt DateTime @updatedAt
453
+ /** Expiration logique de la ligne (TTL rétention). */
454
+ expiresAt DateTime?
455
+ /** Pour `reminderId === __all__` + CLEARED : instant de coupure affichage (indépendant de updatedAt). */
456
+ clearedCutoffAt DateTime?
457
+ /** Métadonnées (ex. fenêtre undo après clear-all). */
458
+ metadata Json?
459
+
460
+ @@unique([userId, reminderId])
461
+ @@index([userId, status])
462
+ @@index([updatedAt])
463
+ @@index([userId, expiresAt])
464
+ @@map("user_reminder_state")
465
+ }
466
+
570
467
  model UserGoogleAccount {
571
- id String @id @default(cuid())
572
- userId String @unique
573
- user User @relation(fields: [userId], references: [id], onDelete: Cascade)
574
- accessToken String
575
- refreshToken String
576
- tokenExpiresAt DateTime
577
- email String? // Email du compte Google connecté
578
- createdAt DateTime @default(now())
579
- updatedAt DateTime @updatedAt
468
+ id String @id @default(cuid())
469
+ userId String @unique
470
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
471
+ accessToken String
472
+ refreshToken String
473
+ tokenExpiresAt DateTime
474
+ email String? // Email du compte Google connecté
475
+ defaultGoogleCalendarId String? // Calendrier par défaut pour créer des événements (sinon primary)
476
+ agendaVisibleGoogleCalendarIds Json? // IDs des calendriers dont les événements sont affichés dans l'agenda CRM
477
+ agendaGoogleEventColor String? // Couleur d'affichage (#RRGGBB) des événements Google dans l'agenda CRM
478
+ createdAt DateTime @default(now())
479
+ updatedAt DateTime @updatedAt
580
480
 
581
481
  @@map("user_google_account")
582
482
  }
583
483
 
584
484
  model ContactFile {
585
- id String @id @default(cuid())
586
- contactId String
587
- contact Contact @relation(fields: [contactId], references: [id], onDelete: Cascade)
588
- fileName String // Nom original du fichier
589
- fileSize Int // Taille en octets
590
- mimeType String // Type MIME du fichier
591
- googleDriveFileId String // ID du fichier dans Google Drive
592
- isIdentityDocument Boolean @default(false) // Indique si c'est une pièce d'identité
593
- uploadedById String? // Utilisateur qui a uploadé le fichier
594
- uploadedBy User? @relation("ContactFileUploadedBy", fields: [uploadedById], references: [id], onDelete: SetNull)
595
- createdAt DateTime @default(now())
596
- updatedAt DateTime @updatedAt
485
+ id String @id @default(cuid())
486
+ contactId String
487
+ contact Contact @relation(fields: [contactId], references: [id], onDelete: Cascade)
488
+ fileName String
489
+ fileSize Int
490
+ mimeType String
491
+ storagePath String
492
+ uploadedById String?
493
+ uploadedBy User? @relation("ContactFileUploadedBy", fields: [uploadedById], references: [id], onDelete: SetNull)
494
+ createdAt DateTime @default(now())
495
+ updatedAt DateTime @updatedAt
597
496
 
598
497
  @@index([contactId])
599
498
  @@index([uploadedById])
600
- @@index([contactId, isIdentityDocument])
601
499
  @@map("contact_file")
602
500
  }
603
501
 
@@ -661,6 +559,60 @@ model GoogleSheetSyncConfig {
661
559
  @@map("google_sheet_sync_config")
662
560
  }
663
561
 
562
+ model IntegrationImportLog {
563
+ id String @id @default(cuid())
564
+ integrationType String // "google_sheet" | "meta_lead" | "google_ads"
565
+ configId String
566
+ configName String
567
+ action String // "created" | "updated" | "synced" | "deleted"
568
+ actorId String?
569
+ actor User? @relation(fields: [actorId], references: [id], onDelete: SetNull)
570
+ totalImported Int @default(0)
571
+ totalDuplicates Int @default(0)
572
+ totalUpdated Int @default(0)
573
+ totalErrors Int @default(0)
574
+ errorDetails Json?
575
+ createdAt DateTime @default(now())
576
+
577
+ @@index([integrationType, configId])
578
+ @@index([createdAt])
579
+ @@map("integration_import_log")
580
+ }
581
+
582
+ enum GoogleSheetSyncJobStatus {
583
+ QUEUED
584
+ RUNNING
585
+ SUCCEEDED
586
+ FAILED
587
+ }
588
+
589
+ enum GoogleSheetSyncJobTriggerType {
590
+ MANUAL
591
+ SCHEDULED
592
+ }
593
+
594
+ model GoogleSheetSyncJob {
595
+ id String @id @default(cuid())
596
+ status GoogleSheetSyncJobStatus @default(QUEUED)
597
+ triggerType GoogleSheetSyncJobTriggerType @default(MANUAL)
598
+ requestedByUserId String?
599
+ requestedByUser User? @relation(fields: [requestedByUserId], references: [id], onDelete: SetNull)
600
+ configId String?
601
+ payload Json?
602
+ result Json?
603
+ error String?
604
+ startedAt DateTime?
605
+ finishedAt DateTime?
606
+ createdAt DateTime @default(now())
607
+ updatedAt DateTime @updatedAt
608
+
609
+ @@index([status])
610
+ @@index([createdAt])
611
+ @@index([requestedByUserId])
612
+ @@index([triggerType, createdAt])
613
+ @@map("google_sheet_sync_job")
614
+ }
615
+
664
616
  model ClosingReason {
665
617
  id String @id @default(cuid())
666
618
  name String // Libellé du motif de fermeture (ex: Faux numéro, Pas intéressé, etc.)
@@ -685,7 +637,6 @@ model Template {
685
637
  userId String? // Utilisateur qui a créé le template
686
638
  user User? @relation("TemplateCreatedBy", fields: [userId], references: [id], onDelete: SetNull)
687
639
  workflowActions WorkflowAction[] @relation("WorkflowActionEmailTemplate")
688
- placeReminderConfigs PlaceReminderConfig[]
689
640
  createdAt DateTime @default(now())
690
641
  updatedAt DateTime @updatedAt
691
642
 
@@ -694,25 +645,12 @@ model Template {
694
645
  @@map("template")
695
646
  }
696
647
 
697
- model PlaceReminderConfig {
698
- id String @id @default("place-reminder-config")
699
- enabled Boolean @default(true)
700
- delayDays Int @default(7)
701
- templateId String?
702
- template Template? @relation(fields: [templateId], references: [id], onDelete: SetNull)
703
- updatedAt DateTime @updatedAt
704
-
705
- @@map("place_reminder_config")
706
- }
707
-
708
648
  enum WorkflowTriggerType {
709
649
  CONTACT_CREATED // Nouveau contact créé
710
650
  STATUS_CHANGED // Changement de statut
711
651
  TIME_BASED // Basé sur le temps
712
652
  MANUAL // Déclencheur manuel
713
653
  TASK_COMPLETED // Tâche complétée
714
- TRANSACTION_CREATED // Transaction créée
715
- TRANSACTION_STATUS_CHANGED // Changement de statut de transaction
716
654
  CONTACT_ASSIGNMENT_CHANGED // Changement d'assignation du contact
717
655
  }
718
656
 
@@ -763,10 +701,6 @@ model Workflow {
763
701
  // Pour TASK_COMPLETED
764
702
  triggerTaskType TaskType? // Type de tâche (optionnel, null = toutes)
765
703
 
766
- // Pour TRANSACTION_STATUS_CHANGED
767
- triggerTransactionFromStatus String? // Statut source de la transaction (ex: DRAFT, SIGNED)
768
- triggerTransactionToStatus String? // Statut cible de la transaction
769
-
770
704
  actions WorkflowAction[]
771
705
  scheduledActions ScheduledWorkflowAction[]
772
706
  createdAt DateTime @default(now())
@@ -862,386 +796,6 @@ model ScheduledWorkflowAction {
862
796
  @@map("scheduled_workflow_action")
863
797
  }
864
798
 
865
- /// Tournée commerciale (inclut infos tournée, lieu, mairie, campagnes de distribution)
866
- model Tour {
867
- id String @id @default(cuid())
868
- number String // Numéro de tournée (#T_${année}${mois}${cp})
869
- region String?
870
- department String?
871
- city String?
872
- postalCode String?
873
- isoWeek Int? // Semaine ISO
874
-
875
- presenceStart DateTime? // Début de présence (créneau)
876
- presenceEnd DateTime? // Fin de présence (créneau)
877
-
878
- // Lieu
879
- placeType PlaceType? // Hôtel / Restaurant / Autre
880
- placeName String?
881
- placeAddress String?
882
- placePhone String?
883
- placeEmail String?
884
- placeContactName String?
885
- placeContactRole String?
886
- placeContacts Json? // Contacts sur place multiples [{name, role, email, phone}]
887
- placeRentalPriceCents Int? // Prix location en centimes (TTC)
888
- placePaymentDepositCents Int? // Acompte versé en centimes
889
- placePaymentDate DateTime?
890
- placePaymentStatus PaymentStatus? // Payé / En attente / Acompte versé
891
- placeInvoiceRef String?
892
- placeInvoiceFileId String? // ID fichier (PDF) éventuel
893
-
894
- // Lieu – emails
895
- placeEmailSentDate DateTime?
896
- placeReminderSentDate DateTime?
897
- placeEmailSentById String?
898
-
899
- // Mairie
900
- cityHallName String?
901
- cityHallAddress String?
902
- cityHallCity String?
903
- cityHallPostalCode String?
904
- cityHallPhone String?
905
- cityHallEmail String?
906
- cityHallContactName String?
907
- cityHallContacts Json? // Contacts mairie multiples [{name, role, email, phone}]
908
- cityHallStatus CityHallStatus? // Oui / Non / En cours
909
- cityHallRequestDate DateTime?
910
- cityHallReminderDate DateTime?
911
- cityHallDecisionDate DateTime?
912
- cityHallDecision String? // Validation / Refus
913
- cityHallRequestFileId String?
914
- cityHallResponseFileId String?
915
- cityHallAuthorizationFileId String?
916
-
917
- // Campagnes de distribution
918
- distributionType DistributionType? // Flyers / Courriers / Mix
919
- distributionFlyersQty Int? // nombre de flyers
920
- distributionLettersQty Int? // nombre de courriers
921
- distributionProvider String? // Prestataire (ex: Mediapost)
922
- distributionCampaignRef String?
923
- distributionWeek String? // Semaine de distribution (texte)
924
- distributionEndDate DateTime?
925
- distributionZones String? // Zones couvertes (CP, quartiers...)
926
- distributionDailyCostCents Int?
927
- distributionFlyersHTCents Int? // Prix HT flyers en centimes
928
- distributionLettersHTCents Int? // Prix HT courriers en centimes
929
- distributionTotalCostCents Int? // Prix total TTC calculé automatiquement
930
- distributionInvoiceFileId String?
931
-
932
- // Relations
933
- commercialId String?
934
- commercial User? @relation("TourCommercial", fields: [commercialId], references: [id], onDelete: SetNull)
935
- contacts TourContact[]
936
- tasks Task[] // Tâches liées à cette tournée
937
- transactions Transaction[] @relation("TransactionTour") // Transactions liées à cette tournée
938
-
939
- // Note / Instructions
940
- note String?
941
-
942
- // Compteur interactions manuelles
943
- interactionCount Int @default(0)
944
-
945
- createdAt DateTime @default(now())
946
- updatedAt DateTime @updatedAt
947
-
948
- @@index([number])
949
- @@index([commercialId])
950
- @@index([distributionWeek])
951
- @@map("tour")
952
- }
953
-
954
- /// Liaison plusieurs contacts <-> tournée
955
- model TourContact {
956
- id String @id @default(cuid())
957
- tourId String
958
- contactId String
959
-
960
- tour Tour @relation(fields: [tourId], references: [id], onDelete: Cascade)
961
- contact Contact @relation(fields: [contactId], references: [id], onDelete: Cascade)
962
-
963
- createdAt DateTime @default(now())
964
-
965
- @@unique([tourId, contactId])
966
- @@index([tourId])
967
- @@index([contactId])
968
- @@map("tour_contact")
969
- }
970
-
971
- /// Prestataires de distribution (configurés par l'admin)
972
- model DistributionProvider {
973
- id String @id @default(cuid())
974
- name String
975
- isDefault Boolean @default(false)
976
- createdAt DateTime @default(now())
977
- updatedAt DateTime @updatedAt
978
-
979
- @@map("distribution_provider")
980
- }
981
-
982
- /// Documents requis pour la demande d'autorisation en mairie (configurés par l'admin)
983
- model CityHallRequiredDocument {
984
- id String @id @default(cuid())
985
- name String // Nom du document (ex: "Plan d'implantation", "Demande d'autorisation", etc.)
986
- fileId String // ID du fichier Google Drive
987
- fileName String // Nom du fichier original
988
- order Int @default(0) // Ordre d'affichage
989
- createdAt DateTime @default(now())
990
- updatedAt DateTime @updatedAt
991
-
992
- @@index([order])
993
- @@map("city_hall_required_document")
994
- }
995
-
996
- /// Transaction d'achat d'or/métaux précieux
997
- model Transaction {
998
- id String @id @default(cuid())
999
- contactId String
1000
- contact Contact @relation(fields: [contactId], references: [id], onDelete: Restrict)
1001
- tourId String? // Optionnel : lié à une tournée
1002
- tour Tour? @relation("TransactionTour", fields: [tourId], references: [id], onDelete: SetNull)
1003
- salesRepId String? // Commercial assigné
1004
- salesRep User? @relation("TransactionAssignedTo", fields: [salesRepId], references: [id], onDelete: SetNull)
1005
- createdById String?
1006
- createdBy User? @relation("TransactionCreatedBy", fields: [createdById], references: [id], onDelete: SetNull)
1007
- status TransactionStatus @default(DRAFT)
1008
- paymentMethod PaymentMethod?
1009
- paymentReference String? // Numéro de chèque ou nom de la banque
1010
- signedAt DateTime? // Date de signature
1011
- retractionDeadline DateTime? // Date limite de rétractation (48 heures après signature)
1012
- contractPdfFileId String? // ID du fichier PDF du contrat dans Google Drive
1013
- signatureType SignatureType? // Type de signature : ELECTRONIC, TABLET, PAPER
1014
- signatureData String? // Données de signature (pour tablet) ou URL du scan (pour papier)
1015
- yousignSignatureRequestId String? @unique // ID de la demande de signature Yousign
1016
- yousignSignatureUrl String? // URL de signature Yousign
1017
- yousignRetractionRequestId String? @unique // ID de la demande de signature de rétractation Yousign
1018
- retractionPdfFileId String? // ID du fichier PDF de rétractation signé dans Google Drive
1019
- transactionAddress String? // Adresse du lieu de la transaction (si pas de tournée)
1020
- totalAmountCents Int? // Montant total en centimes
1021
- lockedAt DateTime? // Date de verrouillage
1022
- lockedBy String? // ID de l'utilisateur qui a verrouillé
1023
- completedAt DateTime? // Date de complétion
1024
- cancelledAt DateTime? // Date d'annulation
1025
- items TransactionItem[]
1026
- auditLogs TransactionAuditLog[]
1027
- createdAt DateTime @default(now())
1028
- updatedAt DateTime @updatedAt
1029
-
1030
- @@index([contactId])
1031
- @@index([salesRepId])
1032
- @@index([createdById])
1033
- @@index([status])
1034
- @@index([tourId])
1035
- @@index([status, contactId])
1036
- @@index([status, salesRepId])
1037
- @@index([status, createdAt])
1038
- @@index([signedAt])
1039
- @@index([salesRepId, signedAt])
1040
- @@map("transaction")
1041
- }
1042
-
1043
- /// Articles d'une transaction (polymorphique)
1044
- model TransactionItem {
1045
- id String @id @default(cuid())
1046
- transactionId String
1047
- transaction Transaction @relation(fields: [transactionId], references: [id], onDelete: Cascade)
1048
- category TransactionItemCategory
1049
- order Int @default(0)
1050
- processingStatus TransactionItemProcessingStatus @default(A_VERIFIER)
1051
-
1052
- // Disposition dans le stock (après traitement)
1053
- stockDisposition StockDisposition @default(IN_STOCK)
1054
- exclusionReason String? // "Pas en étain", "Contrefaçon", "Irréparable", "Sans intérêt"
1055
-
1056
- // Vente manuelle (pour articles d'occasion)
1057
- saleAmountCents Int?
1058
- saleDate DateTime?
1059
- saleNotes String?
1060
-
1061
- // Pour les métaux (OR, PLATINE, ARGENT)
1062
- purity Int?
1063
- weightGross Float?
1064
- weightNet Float?
1065
- type String?
1066
- tmpValueCents Int?
1067
-
1068
- // Pour les unités (montres, collectibles, diamants)
1069
- brand String?
1070
- model String?
1071
- state String?
1072
- certificate Boolean?
1073
- pricePerUnitCents Int?
1074
- quantity Int?
1075
-
1076
- // Pour les diamants (4C)
1077
- carat Float?
1078
- color String?
1079
- clarity String?
1080
- cut String?
1081
-
1082
- // Pour métal argenté, plaqué or, étains
1083
- weightKg Float?
1084
-
1085
- // Fichiers/photos
1086
- photoFileId String?
1087
-
1088
- // Métadonnées JSON pour flexibilité
1089
- metadata Json?
1090
-
1091
- refinerSubmissionItems RefinerSubmissionItem[]
1092
-
1093
- createdAt DateTime @default(now())
1094
- updatedAt DateTime @updatedAt
1095
-
1096
- @@index([transactionId])
1097
- @@index([category])
1098
- @@index([stockDisposition])
1099
- @@map("transaction_item")
1100
- }
1101
-
1102
- /// Journal d'audit pour les transactions verrouillées
1103
- model TransactionAuditLog {
1104
- id String @id @default(cuid())
1105
- transactionId String
1106
- transaction Transaction @relation(fields: [transactionId], references: [id], onDelete: Cascade)
1107
- userId String?
1108
- user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
1109
- fieldChanged String // Nom du champ modifié
1110
- oldValue String? // Ancienne valeur (JSON stringifié si nécessaire)
1111
- newValue String? // Nouvelle valeur (JSON stringifié si nécessaire)
1112
- createdAt DateTime @default(now())
1113
-
1114
- @@index([transactionId])
1115
- @@index([userId])
1116
- @@index([createdAt])
1117
- @@map("transaction_audit_log")
1118
- }
1119
-
1120
- /// Types de récurrence pour les jours d'indisponibilité
1121
- enum RecurrenceType {
1122
- NONE // Pas de récurrence (date unique)
1123
- PERIOD // Période (du... au...)
1124
- WEEKLY // Récurrence hebdomadaire (tous les lundis, mardis, etc.)
1125
- MONTHLY_DAY // Récurrence mensuelle par jour (tous les 5 du mois)
1126
- YEARLY // Récurrence annuelle (tous les 25 décembre)
1127
- }
1128
-
1129
- /// Types de jour d'indisponibilité
1130
- enum UnavailableDateType {
1131
- PUBLIC_HOLIDAY // Jour férié national
1132
- CUSTOM // Jour personnalisé par l'admin
1133
- }
1134
-
1135
- /// Jours d'indisponibilité pour les tournées
1136
- model UnavailableDate {
1137
- id String @id @default(cuid())
1138
- name String // Nom/Description (ex: "Noël", "Fermeture estivale")
1139
- type UnavailableDateType @default(CUSTOM)
1140
- date DateTime? // Date spécifique (si pas de récurrence ou date de début de période)
1141
- endDate DateTime? // Date de fin (pour les périodes, ex: du 7 au 22 janvier)
1142
- recurrenceType RecurrenceType @default(NONE)
1143
- // Pour WEEKLY : 0=Dimanche, 1=Lundi, 2=Mardi, etc.
1144
- // Pour MONTHLY_DAY : jour du mois (1-31)
1145
- // Pour YEARLY : null (utilise la date)
1146
- recurrenceValue Int? // Valeur de la récurrence
1147
- isActive Boolean @default(true) // Permet de désactiver temporairement
1148
- createdById String?
1149
- createdBy User? @relation(fields: [createdById], references: [id], onDelete: SetNull)
1150
- createdAt DateTime @default(now())
1151
- updatedAt DateTime @updatedAt
1152
-
1153
- @@index([type])
1154
- @@index([isActive])
1155
- @@index([createdById])
1156
- @@map("unavailable_date")
1157
- }
1158
-
1159
- /// Mode de paiement
1160
- enum PaymentMode {
1161
- VIREMENT
1162
- CHEQUE
1163
- ESPECES
1164
- CB
1165
- }
1166
-
1167
- /// Paiement de campagne de distribution
1168
- model DistributionCampaignPayment {
1169
- id String @id @default(cuid())
1170
- paymentKey String @unique // Clé de paiement (ex: PV-2026-S02)
1171
- year Int // Année
1172
- isoWeek Int // Semaine ISO
1173
- tourDate DateTime // Date tournée
1174
- amountHT Float // Montant HT
1175
- tva Float // TVA 20%
1176
- amountTTC Float // Montant TTC
1177
-
1178
- // Acompte 1
1179
- deposit1Date DateTime? // Date acompte 1
1180
- deposit1Amount Float? @default(0) // Acompte 1
1181
-
1182
- // Acompte 2
1183
- deposit2Date DateTime? // Date acompte 2
1184
- deposit2Amount Float? @default(0) // Acompte 2
1185
-
1186
- // Acompte 3
1187
- deposit3Date DateTime? // Date acompte 3
1188
- deposit3Amount Float? @default(0) // Acompte 3
1189
-
1190
- // Solde 1
1191
- balance1Date DateTime? // Date solde 1
1192
- balance1Amount Float? @default(0) // Solde 1
1193
-
1194
- // Solde 2
1195
- balance2Date DateTime? // Date solde 2
1196
- balance2Amount Float? @default(0) // Solde 2
1197
-
1198
- // Solde 3
1199
- balance3Date DateTime? // Date solde 3
1200
- balance3Amount Float? @default(0) // Solde 3
1201
-
1202
- totalPaid Float @default(0) // Montant total payé (calculé)
1203
- remainingBalance Float // Solde restant (calculé)
1204
- status CampaignPaymentStatus @default(A_PAYER) // Statut
1205
-
1206
- createdById String?
1207
- createdBy User? @relation(fields: [createdById], references: [id], onDelete: SetNull)
1208
- createdAt DateTime @default(now())
1209
- updatedAt DateTime @updatedAt
1210
-
1211
- @@index([year])
1212
- @@index([isoWeek])
1213
- @@index([status])
1214
- @@index([createdById])
1215
- @@map("distribution_campaign_payment")
1216
- }
1217
-
1218
- /// Paiement publicité Meta
1219
- model MetaAdsPayment {
1220
- id String @id @default(cuid())
1221
- paymentKey String @unique // Clé paiement Meta (ex: META-2025-12-1)
1222
- year Int // Année
1223
- month String // Mois (ex: "décembre")
1224
- periodCovered String? // Période couverte (ex: "S50 à S52")
1225
- invoiceNumber String? // N° Facture Meta
1226
- invoiceDate DateTime? // Date de Facture
1227
- invoiceDueDate DateTime? // Date d'échéance Facture
1228
- paymentDate DateTime? // Date de Paiement
1229
- invoiceAmount Float // Montant facture META
1230
- paymentMode PaymentMode @default(VIREMENT) // Mode de paiement
1231
- paymentStatus CampaignPaymentStatus @default(A_PAYER) // Statut paiement
1232
-
1233
- createdById String?
1234
- createdBy User? @relation(fields: [createdById], references: [id], onDelete: SetNull)
1235
- createdAt DateTime @default(now())
1236
- updatedAt DateTime @updatedAt
1237
-
1238
- @@index([year])
1239
- @@index([month])
1240
- @@index([paymentStatus])
1241
- @@index([createdById])
1242
- @@map("meta_ads_payment")
1243
- }
1244
-
1245
799
  model ContactView {
1246
800
  id String @id @default(cuid())
1247
801
  name String
@@ -1276,76 +830,17 @@ model ContactViewPin {
1276
830
  @@map("contact_view_pin")
1277
831
  }
1278
832
 
1279
- /// Remise affineur (lot envoyé à l'affineur pour rachat)
1280
- model RefinerSubmission {
1281
- id String @id @default(cuid())
1282
- submissionDate DateTime
1283
- category TransactionItemCategory
1284
- purity Int?
1285
- metalPricePerKgCents Int
1286
- brokeragePercent Float
1287
- refinerPricePerGramCents Int
1288
- totalWeightGrams Float
1289
- totalFineWeightGrams Float
1290
- provisionalAmountCents Int?
1291
- actualAmountCents Int?
1292
- status RefinerSubmissionStatus @default(PENDING)
1293
- notes String?
1294
- createdById String?
1295
- createdBy User? @relation("RefinerSubmissionCreatedBy", fields: [createdById], references: [id], onDelete: SetNull)
1296
- items RefinerSubmissionItem[]
1297
- documents RefinerDocument[]
1298
- createdAt DateTime @default(now())
1299
- updatedAt DateTime @updatedAt
1300
-
1301
- @@index([category])
1302
- @@index([status])
1303
- @@index([submissionDate])
1304
- @@index([createdById])
1305
- @@map("refiner_submission")
1306
- }
1307
-
1308
- /// Article lié à une remise affineur (snapshot des valeurs au moment de la remise)
1309
- model RefinerSubmissionItem {
1310
- id String @id @default(cuid())
1311
- submissionId String
1312
- submission RefinerSubmission @relation(fields: [submissionId], references: [id], onDelete: Cascade)
1313
- transactionItemId String
1314
- transactionItem TransactionItem @relation(fields: [transactionItemId], references: [id], onDelete: Restrict)
1315
- weightGrams Float
1316
- purity Int?
1317
- fineWeightGrams Float
1318
- provisionalPaymentPercent Float?
1319
- restitutionPercent Float?
1320
- calculatedAmountCents Int
1321
- createdAt DateTime @default(now())
1322
-
1323
- @@index([submissionId])
1324
- @@index([transactionItemId])
1325
- @@map("refiner_submission_item")
1326
- }
1327
-
1328
- /// Document attaché à une remise affineur (facture, bordereau)
1329
- model RefinerDocument {
1330
- id String @id @default(cuid())
1331
- submissionId String
1332
- submission RefinerSubmission @relation(fields: [submissionId], references: [id], onDelete: Cascade)
1333
- fileName String
1334
- fileUrl String
1335
- fileType String?
1336
- uploadedAt DateTime @default(now())
1337
-
1338
- @@index([submissionId])
1339
- @@map("refiner_document")
1340
- }
1341
-
1342
- /// Configuration de la valorisation du stock (clé/valeur)
1343
- model StockConfig {
1344
- id String @id @default(cuid())
1345
- key String @unique
1346
- value String
1347
- label String
1348
- updatedAt DateTime @updatedAt
833
+ model DashboardWidget {
834
+ id String @id @default(cuid())
835
+ userId String
836
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
837
+ type String
838
+ x Int @default(0)
839
+ y Int @default(0)
840
+ w Int @default(4)
841
+ h Int @default(3)
842
+ settings Json @default("{}")
1349
843
 
1350
- @@map("stock_config")
844
+ @@index([userId])
845
+ @@map("dashboard_widget")
1351
846
  }