create-crm-tmp 1.0.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 (187) hide show
  1. package/bin/create-crm-tmp.js +93 -0
  2. package/package.json +25 -0
  3. package/template/.prettierignore +33 -0
  4. package/template/.prettierrc.json +25 -0
  5. package/template/README.md +173 -0
  6. package/template/eslint.config.mjs +18 -0
  7. package/template/exemple-contacts.csv +11 -0
  8. package/template/next.config.ts +8 -0
  9. package/template/package.json +64 -0
  10. package/template/postcss.config.mjs +7 -0
  11. package/template/prisma/migrations/20251126144728_init/migration.sql +78 -0
  12. package/template/prisma/migrations/20251126155204_add_user_roles/migration.sql +5 -0
  13. package/template/prisma/migrations/20251128095126_add_company_info/migration.sql +19 -0
  14. package/template/prisma/migrations/20251128123321_add_smtp_config/migration.sql +22 -0
  15. package/template/prisma/migrations/20251128132303_add_status/migration.sql +23 -0
  16. package/template/prisma/migrations/20251201102207_add_user_active/migration.sql +75 -0
  17. package/template/prisma/migrations/20251201105507_add_email_signature/migration.sql +2 -0
  18. package/template/prisma/migrations/20251201151122_add_tasks/migration.sql +45 -0
  19. package/template/prisma/migrations/20251202111854_add_task_reminder/migration.sql +2 -0
  20. package/template/prisma/migrations/20251202135859_add_google_meet_integration/migration.sql +27 -0
  21. package/template/prisma/migrations/20251203103317_add_meta_lead_integration/migration.sql +20 -0
  22. package/template/prisma/migrations/20251203104002_add_google_ads_integration/migration.sql +18 -0
  23. package/template/prisma/migrations/20251203112122_add_google_sheet_integration/migration.sql +32 -0
  24. package/template/prisma/migrations/20251203153853_allow_multiple_integration_configs/migration.sql +20 -0
  25. package/template/prisma/migrations/20251205141705_update_user_roles/migration.sql +12 -0
  26. package/template/prisma/migrations/20251205150000_add_commercial_and_telepro_assignment/migration.sql +21 -0
  27. package/template/prisma/migrations/20251205160000_add_interaction_logging/migration.sql +11 -0
  28. package/template/prisma/migrations/20251208090314_add_automatic_interaction_types/migration.sql +12 -0
  29. package/template/prisma/migrations/20251208094843_mg/migration.sql +14 -0
  30. package/template/prisma/migrations/20251208100000_add_company_support/migration.sql +14 -0
  31. package/template/prisma/migrations/20251208110000_add_templates/migration.sql +26 -0
  32. package/template/prisma/migrations/20251208141304_add_video_conference_task_type/migration.sql +2 -0
  33. package/template/prisma/migrations/20251209104759_add_internal_note_to_task/migration.sql +2 -0
  34. package/template/prisma/migrations/20251209134803_add_company_field/migration.sql +2 -0
  35. package/template/prisma/migrations/20251209150000_rename_company_to_company_name/migration.sql +3 -0
  36. package/template/prisma/migrations/20251209150016_add_email_tracking/migration.sql +21 -0
  37. package/template/prisma/migrations/20251209155908_add_notify_contact_to_task/migration.sql +2 -0
  38. package/template/prisma/migrations/20251210110019_add_appointment_types/migration.sql +10 -0
  39. package/template/prisma/migrations/20251210113928_add_contact_files/migration.sql +26 -0
  40. package/template/prisma/migrations/20251212132339_add_custom_roles/migration.sql +24 -0
  41. package/template/prisma/migrations/20251215104448_add_file_interaction_types/migration.sql +11 -0
  42. package/template/prisma/migrations/20251215145616_add_closing_reasons/migration.sql +12 -0
  43. package/template/prisma/migrations/20251216140850_add_log_users/migration.sql +25 -0
  44. package/template/prisma/migrations/20251216151000_rename_perdu_to_ferme/migration.sql +8 -0
  45. package/template/prisma/migrations/20251216162318_add_column_mappings_to_google_sheet/migration.sql +2 -0
  46. package/template/prisma/migrations/20251216185127_add_workflows/migration.sql +80 -0
  47. package/template/prisma/migrations/20251216192237_add_scheduled_workflow_actions/migration.sql +32 -0
  48. package/template/prisma/migrations/migration_lock.toml +3 -0
  49. package/template/prisma/schema.prisma +582 -0
  50. package/template/prisma.config.ts +14 -0
  51. package/template/src/app/(auth)/invite/[token]/page.tsx +200 -0
  52. package/template/src/app/(auth)/layout.tsx +3 -0
  53. package/template/src/app/(auth)/reset-password/complete/page.tsx +213 -0
  54. package/template/src/app/(auth)/reset-password/page.tsx +146 -0
  55. package/template/src/app/(auth)/reset-password/verify/page.tsx +183 -0
  56. package/template/src/app/(auth)/signin/page.tsx +166 -0
  57. package/template/src/app/(dashboard)/agenda/page.tsx +3051 -0
  58. package/template/src/app/(dashboard)/automatisation/[id]/page.tsx +24 -0
  59. package/template/src/app/(dashboard)/automatisation/_components/workflow-editor.tsx +905 -0
  60. package/template/src/app/(dashboard)/automatisation/new/page.tsx +20 -0
  61. package/template/src/app/(dashboard)/automatisation/page.tsx +337 -0
  62. package/template/src/app/(dashboard)/closing/page.tsx +1052 -0
  63. package/template/src/app/(dashboard)/contacts/[id]/page.tsx +6028 -0
  64. package/template/src/app/(dashboard)/contacts/page.tsx +3713 -0
  65. package/template/src/app/(dashboard)/dashboard/page.tsx +186 -0
  66. package/template/src/app/(dashboard)/layout.tsx +30 -0
  67. package/template/src/app/(dashboard)/settings/page.tsx +4070 -0
  68. package/template/src/app/(dashboard)/templates/page.tsx +567 -0
  69. package/template/src/app/(dashboard)/users/list/page.tsx +507 -0
  70. package/template/src/app/(dashboard)/users/page.tsx +457 -0
  71. package/template/src/app/(dashboard)/users/permissions/page.tsx +181 -0
  72. package/template/src/app/(dashboard)/users/roles/page.tsx +434 -0
  73. package/template/src/app/api/audit-logs/route.ts +57 -0
  74. package/template/src/app/api/auth/[...all]/route.ts +4 -0
  75. package/template/src/app/api/auth/check-active/route.ts +31 -0
  76. package/template/src/app/api/auth/google/callback/route.ts +94 -0
  77. package/template/src/app/api/auth/google/disconnect/route.ts +32 -0
  78. package/template/src/app/api/auth/google/route.ts +34 -0
  79. package/template/src/app/api/auth/google/status/route.ts +32 -0
  80. package/template/src/app/api/closing-reasons/route.ts +27 -0
  81. package/template/src/app/api/contacts/[id]/files/[fileId]/route.ts +94 -0
  82. package/template/src/app/api/contacts/[id]/files/route.ts +269 -0
  83. package/template/src/app/api/contacts/[id]/interactions/[interactionId]/route.ts +91 -0
  84. package/template/src/app/api/contacts/[id]/interactions/route.ts +103 -0
  85. package/template/src/app/api/contacts/[id]/meet/route.ts +296 -0
  86. package/template/src/app/api/contacts/[id]/route.ts +322 -0
  87. package/template/src/app/api/contacts/[id]/send-email/route.ts +254 -0
  88. package/template/src/app/api/contacts/export/route.ts +270 -0
  89. package/template/src/app/api/contacts/import/route.ts +381 -0
  90. package/template/src/app/api/contacts/route.ts +283 -0
  91. package/template/src/app/api/dashboard/stats/route.ts +299 -0
  92. package/template/src/app/api/email/track/[id]/route.ts +68 -0
  93. package/template/src/app/api/integrations/google-sheet/sync/route.ts +526 -0
  94. package/template/src/app/api/invite/complete/route.ts +88 -0
  95. package/template/src/app/api/invite/validate/route.ts +55 -0
  96. package/template/src/app/api/reminders/route.ts +95 -0
  97. package/template/src/app/api/reset-password/complete/route.ts +73 -0
  98. package/template/src/app/api/reset-password/request/route.ts +84 -0
  99. package/template/src/app/api/reset-password/validate/route.ts +49 -0
  100. package/template/src/app/api/reset-password/verify/route.ts +74 -0
  101. package/template/src/app/api/roles/[id]/route.ts +183 -0
  102. package/template/src/app/api/roles/route.ts +140 -0
  103. package/template/src/app/api/send/route.ts +282 -0
  104. package/template/src/app/api/settings/change-password/route.ts +95 -0
  105. package/template/src/app/api/settings/closing-reasons/[id]/route.ts +84 -0
  106. package/template/src/app/api/settings/closing-reasons/route.ts +74 -0
  107. package/template/src/app/api/settings/company/route.ts +121 -0
  108. package/template/src/app/api/settings/google-ads/[id]/route.ts +117 -0
  109. package/template/src/app/api/settings/google-ads/route.ts +122 -0
  110. package/template/src/app/api/settings/google-sheet/[id]/route.ts +230 -0
  111. package/template/src/app/api/settings/google-sheet/auto-map/route.ts +196 -0
  112. package/template/src/app/api/settings/google-sheet/route.ts +254 -0
  113. package/template/src/app/api/settings/meta-leads/[id]/route.ts +123 -0
  114. package/template/src/app/api/settings/meta-leads/route.ts +132 -0
  115. package/template/src/app/api/settings/profile/route.ts +42 -0
  116. package/template/src/app/api/settings/smtp/route.ts +130 -0
  117. package/template/src/app/api/settings/smtp/test/route.ts +121 -0
  118. package/template/src/app/api/settings/statuses/[id]/route.ts +101 -0
  119. package/template/src/app/api/settings/statuses/route.ts +83 -0
  120. package/template/src/app/api/statuses/route.ts +25 -0
  121. package/template/src/app/api/tasks/[id]/attendees/route.ts +76 -0
  122. package/template/src/app/api/tasks/[id]/route.ts +728 -0
  123. package/template/src/app/api/tasks/meet/route.ts +240 -0
  124. package/template/src/app/api/tasks/route.ts +417 -0
  125. package/template/src/app/api/templates/[id]/route.ts +140 -0
  126. package/template/src/app/api/templates/route.ts +91 -0
  127. package/template/src/app/api/users/[id]/route.ts +168 -0
  128. package/template/src/app/api/users/list/route.ts +45 -0
  129. package/template/src/app/api/users/me/route.ts +48 -0
  130. package/template/src/app/api/users/route.ts +250 -0
  131. package/template/src/app/api/webhooks/google-ads/route.ts +208 -0
  132. package/template/src/app/api/webhooks/meta-leads/route.ts +258 -0
  133. package/template/src/app/api/workflows/[id]/route.ts +192 -0
  134. package/template/src/app/api/workflows/process/route.ts +293 -0
  135. package/template/src/app/api/workflows/route.ts +124 -0
  136. package/template/src/app/favicon.ico +0 -0
  137. package/template/src/app/globals.css +1416 -0
  138. package/template/src/app/layout.tsx +31 -0
  139. package/template/src/app/page.tsx +32 -0
  140. package/template/src/components/dashboard/activity-chart.tsx +67 -0
  141. package/template/src/components/dashboard/contacts-chart.tsx +63 -0
  142. package/template/src/components/dashboard/recent-activity.tsx +164 -0
  143. package/template/src/components/dashboard/sales-analytics-chart.tsx +81 -0
  144. package/template/src/components/dashboard/stat-card.tsx +61 -0
  145. package/template/src/components/dashboard/status-distribution-chart.tsx +45 -0
  146. package/template/src/components/dashboard/tasks-pie-chart.tsx +88 -0
  147. package/template/src/components/dashboard/top-contacts-list.tsx +129 -0
  148. package/template/src/components/dashboard/upcoming-tasks-list.tsx +126 -0
  149. package/template/src/components/editor.tsx +856 -0
  150. package/template/src/components/email-template.tsx +35 -0
  151. package/template/src/components/header.tsx +320 -0
  152. package/template/src/components/invitation-email-template.tsx +79 -0
  153. package/template/src/components/meet-cancellation-email-template.tsx +120 -0
  154. package/template/src/components/meet-confirmation-email-template.tsx +156 -0
  155. package/template/src/components/meet-update-email-template.tsx +209 -0
  156. package/template/src/components/page-header.tsx +61 -0
  157. package/template/src/components/reset-password-email-template.tsx +79 -0
  158. package/template/src/components/sidebar.tsx +294 -0
  159. package/template/src/components/skeleton.tsx +380 -0
  160. package/template/src/components/ui/commands.tsx +396 -0
  161. package/template/src/components/ui/components.tsx +150 -0
  162. package/template/src/components/ui/theme.tsx +5 -0
  163. package/template/src/components/view-as-banner.tsx +45 -0
  164. package/template/src/components/view-as-modal.tsx +186 -0
  165. package/template/src/contexts/mobile-menu-context.tsx +31 -0
  166. package/template/src/contexts/sidebar-context.tsx +107 -0
  167. package/template/src/contexts/task-reminder-context.tsx +239 -0
  168. package/template/src/contexts/view-as-context.tsx +84 -0
  169. package/template/src/hooks/use-user-role.ts +82 -0
  170. package/template/src/lib/audit-log.ts +45 -0
  171. package/template/src/lib/auth-client.ts +16 -0
  172. package/template/src/lib/auth.ts +35 -0
  173. package/template/src/lib/check-permission.ts +193 -0
  174. package/template/src/lib/contact-duplicate.ts +112 -0
  175. package/template/src/lib/contact-interactions.ts +371 -0
  176. package/template/src/lib/encryption.ts +99 -0
  177. package/template/src/lib/google-calendar.ts +300 -0
  178. package/template/src/lib/google-drive.ts +372 -0
  179. package/template/src/lib/permissions.ts +412 -0
  180. package/template/src/lib/prisma.ts +32 -0
  181. package/template/src/lib/roles.ts +120 -0
  182. package/template/src/lib/template-variables.ts +76 -0
  183. package/template/src/lib/utils.ts +46 -0
  184. package/template/src/lib/workflow-executor.ts +482 -0
  185. package/template/src/proxy.ts +91 -0
  186. package/template/tsconfig.json +34 -0
  187. package/template/vercel.json +8 -0
@@ -0,0 +1,293 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+ import { prisma } from '@/lib/prisma';
3
+ import { changeStatusImmediate, createTaskImmediate } from '@/lib/workflow-executor';
4
+ import { decrypt } from '@/lib/encryption';
5
+ import nodemailer from 'nodemailer';
6
+ import { replaceTemplateVariables } from '@/lib/template-variables';
7
+
8
+ /**
9
+ * GET /api/workflows/process
10
+ * Endpoint appelé par Vercel Cron pour traiter les actions planifiées
11
+ */
12
+ export async function GET(request: NextRequest) {
13
+ try {
14
+ // Vérifier l'authentification Vercel Cron
15
+ // Vercel envoie automatiquement le header Authorization: Bearer <secret>
16
+ // si CRON_SECRET est défini dans les variables d'environnement
17
+ const cronSecret = process.env.CRON_SECRET;
18
+
19
+ if (cronSecret) {
20
+ const authHeader = request.headers.get('authorization');
21
+ const expectedAuth = `Bearer ${cronSecret}`;
22
+
23
+ if (authHeader !== expectedAuth) {
24
+ // En développement, on peut être plus permissif pour les tests
25
+ const isDevelopment = process.env.NODE_ENV === 'development';
26
+
27
+ if (!isDevelopment) {
28
+ return NextResponse.json(
29
+ { error: 'Unauthorized - Secret manquant ou invalide' },
30
+ { status: 401 },
31
+ );
32
+ }
33
+ }
34
+ }
35
+
36
+ // Récupérer les actions à exécuter maintenant
37
+ // On utilise une petite marge de 5 secondes pour éviter les problèmes de timing
38
+ const now = new Date();
39
+ const margin = new Date(now.getTime() + 5000); // 5 secondes de marge
40
+
41
+ const actionsToExecute = await prisma.scheduledWorkflowAction.findMany({
42
+ where: {
43
+ executed: false,
44
+ executeAt: {
45
+ lte: margin, // Date d'exécution <= maintenant + marge
46
+ },
47
+ },
48
+ include: {
49
+ contact: {
50
+ include: {
51
+ status: true,
52
+ },
53
+ },
54
+ workflow: {
55
+ include: {
56
+ user: {
57
+ include: {
58
+ smtpConfig: true,
59
+ },
60
+ },
61
+ },
62
+ },
63
+ },
64
+ orderBy: {
65
+ executeAt: 'asc', // Traiter les actions dans l'ordre chronologique
66
+ },
67
+ take: 50, // Limiter à 50 actions par exécution pour éviter les timeouts (limite Vercel: 60s)
68
+ });
69
+
70
+ if (actionsToExecute.length === 0) {
71
+ return NextResponse.json({
72
+ success: true,
73
+ processed: 0,
74
+ message: 'Aucune action à exécuter',
75
+ timestamp: now.toISOString(),
76
+ });
77
+ }
78
+
79
+ const results = {
80
+ success: 0,
81
+ failed: 0,
82
+ errors: [] as Array<{ id: string; error: string }>,
83
+ };
84
+
85
+ // Exécuter chaque action
86
+ for (const scheduledAction of actionsToExecute) {
87
+ try {
88
+ const actionData = scheduledAction.actionData as any;
89
+ const contact = scheduledAction.contact;
90
+ const workflow = scheduledAction.workflow;
91
+
92
+ switch (scheduledAction.actionType) {
93
+ case 'SEND_EMAIL':
94
+ await executeScheduledEmail(scheduledAction, actionData, contact, workflow);
95
+ break;
96
+
97
+ case 'SEND_SMS':
98
+ await executeScheduledSMS(scheduledAction, actionData, contact, workflow);
99
+ break;
100
+
101
+ case 'CHANGE_STATUS':
102
+ await changeStatusImmediate(contact.id, actionData.newStatusId);
103
+ break;
104
+
105
+ case 'CREATE_TASK':
106
+ await createTaskImmediate(
107
+ {
108
+ taskTitle: actionData.taskTitle,
109
+ taskDescription: actionData.taskDescription,
110
+ },
111
+ workflow,
112
+ contact.id,
113
+ scheduledAction.executeAt,
114
+ );
115
+ break;
116
+
117
+ case 'WAIT':
118
+ // L'action "Attendre" ne fait rien, elle est juste là pour le délai
119
+ break;
120
+
121
+ default:
122
+ throw new Error(`Type d'action inconnu: ${scheduledAction.actionType}`);
123
+ }
124
+
125
+ // Marquer comme exécutée
126
+ await prisma.scheduledWorkflowAction.update({
127
+ where: { id: scheduledAction.id },
128
+ data: {
129
+ executed: true,
130
+ executedAt: new Date(),
131
+ },
132
+ });
133
+
134
+ results.success++;
135
+ } catch (error: any) {
136
+ const errorMessage = error.message || 'Erreur inconnue';
137
+ const errorStack = error.stack || '';
138
+
139
+ console.error(
140
+ `[Workflow Cron] Erreur lors de l'exécution de l'action ${scheduledAction.id}:`,
141
+ {
142
+ actionType: scheduledAction.actionType,
143
+ contactId: scheduledAction.contactId,
144
+ workflowId: scheduledAction.workflowId,
145
+ error: errorMessage,
146
+ stack: errorStack,
147
+ },
148
+ );
149
+
150
+ // Marquer comme échouée avec le message d'erreur
151
+ // On limite la taille du message d'erreur pour éviter les problèmes de base de données
152
+ const truncatedError =
153
+ errorMessage.length > 500 ? errorMessage.substring(0, 500) + '...' : errorMessage;
154
+
155
+ await prisma.scheduledWorkflowAction.update({
156
+ where: { id: scheduledAction.id },
157
+ data: {
158
+ executed: true, // Marquer comme exécutée pour ne pas réessayer indéfiniment
159
+ executedAt: new Date(),
160
+ error: truncatedError,
161
+ },
162
+ });
163
+
164
+ results.failed++;
165
+ results.errors.push({
166
+ id: scheduledAction.id,
167
+ error: truncatedError,
168
+ });
169
+ }
170
+ }
171
+
172
+ return NextResponse.json({
173
+ success: true,
174
+ processed: actionsToExecute.length,
175
+ results,
176
+ timestamp: now.toISOString(),
177
+ executionTime: `${Date.now() - now.getTime()}ms`,
178
+ });
179
+ } catch (error: any) {
180
+ console.error('Erreur lors du traitement des workflows:', error);
181
+ return NextResponse.json({ error: error.message || 'Erreur serveur' }, { status: 500 });
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Exécute une action email planifiée
187
+ */
188
+ async function executeScheduledEmail(
189
+ scheduledAction: any,
190
+ actionData: any,
191
+ contact: any,
192
+ workflow: any,
193
+ ) {
194
+ if (!workflow.user.smtpConfig) {
195
+ throw new Error('Configuration SMTP non trouvée');
196
+ }
197
+
198
+ // Remplacer les variables dans le sujet et le contenu
199
+ const variables = {
200
+ firstName: contact.firstName || '',
201
+ lastName: contact.lastName || '',
202
+ civility: contact.civility || '',
203
+ email: contact.email || '',
204
+ phone: contact.phone || '',
205
+ secondaryPhone: contact.secondaryPhone || '',
206
+ address: contact.address || '',
207
+ city: contact.city || '',
208
+ postalCode: contact.postalCode || '',
209
+ companyName: contact.companyName || '',
210
+ };
211
+
212
+ const subject = replaceTemplateVariables(actionData.templateSubject || '', variables);
213
+ const content = replaceTemplateVariables(actionData.templateContent || '', variables);
214
+
215
+ // Déchiffrer le mot de passe SMTP
216
+ let password: string;
217
+ try {
218
+ password = decrypt(workflow.user.smtpConfig.password);
219
+ } catch (error) {
220
+ password = workflow.user.smtpConfig.password;
221
+ }
222
+
223
+ // Créer le transporteur SMTP
224
+ const transporter = nodemailer.createTransport({
225
+ host: workflow.user.smtpConfig.host,
226
+ port: workflow.user.smtpConfig.port,
227
+ secure: workflow.user.smtpConfig.secure,
228
+ auth: {
229
+ user: workflow.user.smtpConfig.username,
230
+ pass: password,
231
+ },
232
+ });
233
+
234
+ await transporter.sendMail({
235
+ from: workflow.user.smtpConfig.fromName
236
+ ? `"${workflow.user.smtpConfig.fromName}" <${workflow.user.smtpConfig.fromEmail}>`
237
+ : workflow.user.smtpConfig.fromEmail,
238
+ to: contact.email,
239
+ subject,
240
+ html: content,
241
+ });
242
+
243
+ // Créer une interaction pour tracer l'email envoyé
244
+ await prisma.interaction.create({
245
+ data: {
246
+ contactId: contact.id,
247
+ type: 'EMAIL',
248
+ title: `Email automatique: ${actionData.templateName || 'Template'}`,
249
+ content: `Email envoyé automatiquement via le workflow "${actionData.workflowName || workflow.name}"`,
250
+ userId: actionData.userId || workflow.userId,
251
+ date: new Date(),
252
+ },
253
+ });
254
+ }
255
+
256
+ /**
257
+ * Exécute une action SMS planifiée
258
+ */
259
+ async function executeScheduledSMS(
260
+ scheduledAction: any,
261
+ actionData: any,
262
+ contact: any,
263
+ workflow: any,
264
+ ) {
265
+ // Remplacer les variables dans le message
266
+ let message = actionData.smsMessage || '';
267
+ const variables: Record<string, string> = {
268
+ firstName: contact.firstName || '',
269
+ lastName: contact.lastName || '',
270
+ email: contact.email || '',
271
+ phone: contact.phone || '',
272
+ companyName: contact.companyName || '',
273
+ };
274
+
275
+ for (const [key, value] of Object.entries(variables)) {
276
+ message = message.replace(new RegExp(`{${key}}`, 'g'), value);
277
+ }
278
+
279
+ // TODO: Implémenter l'envoi de SMS (nécessite une API SMS)
280
+ console.log(`SMS à envoyer à ${contact.phone}: ${message}`);
281
+
282
+ // Créer une interaction pour tracer le SMS
283
+ await prisma.interaction.create({
284
+ data: {
285
+ contactId: contact.id,
286
+ type: 'SMS',
287
+ title: 'SMS automatique',
288
+ content: message,
289
+ userId: actionData.userId || workflow.userId,
290
+ date: new Date(),
291
+ },
292
+ });
293
+ }
@@ -0,0 +1,124 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+ import { auth } from '@/lib/auth';
3
+ import { prisma } from '@/lib/prisma';
4
+
5
+ // GET /api/workflows - Récupérer tous les workflows de l'utilisateur
6
+ export async function GET(request: NextRequest) {
7
+ try {
8
+ const session = await auth.api.getSession({
9
+ headers: request.headers,
10
+ });
11
+
12
+ if (!session) {
13
+ return NextResponse.json({ error: 'Non authentifié' }, { status: 401 });
14
+ }
15
+
16
+ const workflows = await prisma.workflow.findMany({
17
+ where: {
18
+ userId: session.user.id,
19
+ },
20
+ include: {
21
+ actions: {
22
+ orderBy: { order: 'asc' },
23
+ include: {
24
+ emailTemplate: true,
25
+ newStatus: true,
26
+ conditionStatus: true,
27
+ },
28
+ },
29
+ triggerStatus: true,
30
+ triggerToStatus: true,
31
+ },
32
+ orderBy: {
33
+ createdAt: 'desc',
34
+ },
35
+ });
36
+
37
+ return NextResponse.json(workflows);
38
+ } catch (error: any) {
39
+ console.error('Erreur lors de la récupération des workflows:', error);
40
+ return NextResponse.json({ error: error.message || 'Erreur serveur' }, { status: 500 });
41
+ }
42
+ }
43
+
44
+ // POST /api/workflows - Créer un nouveau workflow
45
+ export async function POST(request: NextRequest) {
46
+ try {
47
+ const session = await auth.api.getSession({
48
+ headers: request.headers,
49
+ });
50
+
51
+ if (!session) {
52
+ return NextResponse.json({ error: 'Non authentifié' }, { status: 401 });
53
+ }
54
+
55
+ const body = await request.json();
56
+ const {
57
+ name,
58
+ description,
59
+ active = true,
60
+ triggerType,
61
+ triggerFromStatusId,
62
+ triggerToStatusId,
63
+ triggerTimeDays,
64
+ triggerTimeHours,
65
+ actions = [],
66
+ } = body;
67
+
68
+ // Validation
69
+ if (!name || !triggerType) {
70
+ return NextResponse.json(
71
+ { error: 'Le nom et le type de déclencheur sont requis' },
72
+ { status: 400 },
73
+ );
74
+ }
75
+
76
+ // Créer le workflow
77
+ const workflow = await prisma.workflow.create({
78
+ data: {
79
+ name,
80
+ description: description || null,
81
+ active,
82
+ userId: session.user.id,
83
+ triggerType,
84
+ triggerFromStatusId: triggerFromStatusId || null,
85
+ triggerToStatusId: triggerToStatusId || null,
86
+ triggerTimeDays: triggerTimeDays || null,
87
+ triggerTimeHours: triggerTimeHours || null,
88
+ actions: {
89
+ create: actions.map((action: any, index: number) => ({
90
+ actionType: action.actionType,
91
+ order: index,
92
+ delayDays: action.delayDays || 0,
93
+ delayHours: action.delayHours || 0,
94
+ emailTemplateId: action.emailTemplateId || null,
95
+ smsMessage: action.smsMessage || null,
96
+ newStatusId: action.newStatusId || null,
97
+ taskTitle: action.taskTitle || null,
98
+ taskDescription: action.taskDescription || null,
99
+ conditionOperator: action.conditionOperator || null,
100
+ conditionStatusId: action.conditionStatusId || null,
101
+ })),
102
+ },
103
+ },
104
+ include: {
105
+ actions: {
106
+ orderBy: { order: 'asc' },
107
+ include: {
108
+ emailTemplate: true,
109
+ newStatus: true,
110
+ conditionStatus: true,
111
+ },
112
+ },
113
+ triggerStatus: true,
114
+ triggerToStatus: true,
115
+ },
116
+ });
117
+
118
+ return NextResponse.json(workflow, { status: 201 });
119
+ } catch (error: any) {
120
+ console.error('Erreur lors de la création du workflow:', error);
121
+ return NextResponse.json({ error: error.message || 'Erreur serveur' }, { status: 500 });
122
+ }
123
+ }
124
+
Binary file