elevenlabs-webhook-nodejs 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 (969) hide show
  1. package/.claude/settings.local.json +27 -0
  2. package/.dockerignore +6 -0
  3. package/.env.example +43 -0
  4. package/BEFORE-PRODUCTION.md +32 -0
  5. package/Dockerfile +23 -0
  6. package/SYSTEM_OVERVIEW.md +942 -0
  7. package/SYSTEM_STATUS.md +332 -0
  8. package/backup_script/main.py +146 -0
  9. package/baileys/.dockerignore +7 -0
  10. package/baileys/Dockerfile +13 -0
  11. package/baileys/README.md +412 -0
  12. package/baileys/index.js +499 -0
  13. package/baileys/package-lock.json +2532 -0
  14. package/baileys/package.json +25 -0
  15. package/baileys/server.js +96 -0
  16. package/baileys/src/config.js +55 -0
  17. package/baileys/src/middleware/api-key.js +16 -0
  18. package/baileys/src/routes/accounts.js +51 -0
  19. package/baileys/src/routes/chats.js +103 -0
  20. package/baileys/src/routes/webhooks.js +34 -0
  21. package/baileys/src/services/account-store.js +259 -0
  22. package/baileys/src/services/webhook-dispatcher.js +161 -0
  23. package/baileys/src/services/worker-manager.js +597 -0
  24. package/baileys/src/utils/jid.js +79 -0
  25. package/baileys/src/utils/logger.js +16 -0
  26. package/baileys/src/utils/use-mongodb-auth-state.js +122 -0
  27. package/baileys/worker.js +721 -0
  28. package/dist/app.d.ts +1 -0
  29. package/dist/app.js +84 -0
  30. package/dist/app.js.map +1 -0
  31. package/dist/config/agentPrompts.json +19 -0
  32. package/dist/config/database.d.ts +1 -0
  33. package/dist/config/database.js +26 -0
  34. package/dist/config/database.js.map +1 -0
  35. package/dist/config/env.d.ts +41 -0
  36. package/dist/config/env.js +81 -0
  37. package/dist/config/env.js.map +1 -0
  38. package/dist/config/index.d.ts +3 -0
  39. package/dist/config/index.js +73 -0
  40. package/dist/config/index.js.map +1 -0
  41. package/dist/controllers/webhook.controller.d.ts +10 -0
  42. package/dist/controllers/webhook.controller.js +128 -0
  43. package/dist/controllers/webhook.controller.js.map +1 -0
  44. package/dist/errors/index.d.ts +4 -0
  45. package/dist/errors/index.js +13 -0
  46. package/dist/errors/index.js.map +1 -0
  47. package/dist/hooks/webhookValidator.d.ts +2 -0
  48. package/dist/hooks/webhookValidator.js +47 -0
  49. package/dist/hooks/webhookValidator.js.map +1 -0
  50. package/dist/index.d.ts +1 -0
  51. package/dist/index.js +55 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/migrations/001_session-architecture.d.ts +3 -0
  54. package/dist/migrations/001_session-architecture.js +119 -0
  55. package/dist/migrations/001_session-architecture.js.map +1 -0
  56. package/dist/migrations/002_agent-ref.d.ts +3 -0
  57. package/dist/migrations/002_agent-ref.js +55 -0
  58. package/dist/migrations/002_agent-ref.js.map +1 -0
  59. package/dist/migrations/003_shift-schedule.d.ts +3 -0
  60. package/dist/migrations/003_shift-schedule.js +48 -0
  61. package/dist/migrations/003_shift-schedule.js.map +1 -0
  62. package/dist/migrations/004_invert-shift-to-clinic-hours.d.ts +3 -0
  63. package/dist/migrations/004_invert-shift-to-clinic-hours.js +27 -0
  64. package/dist/migrations/004_invert-shift-to-clinic-hours.js.map +1 -0
  65. package/dist/migrations/005_composite-baileys-chat-ids.d.ts +3 -0
  66. package/dist/migrations/005_composite-baileys-chat-ids.js +47 -0
  67. package/dist/migrations/005_composite-baileys-chat-ids.js.map +1 -0
  68. package/dist/migrations/migration.model.d.ts +18 -0
  69. package/dist/migrations/migration.model.js +45 -0
  70. package/dist/migrations/migration.model.js.map +1 -0
  71. package/dist/migrations/migration.routes.d.ts +2 -0
  72. package/dist/migrations/migration.routes.js +37 -0
  73. package/dist/migrations/migration.routes.js.map +1 -0
  74. package/dist/migrations/migration.runner.d.ts +19 -0
  75. package/dist/migrations/migration.runner.js +74 -0
  76. package/dist/migrations/migration.runner.js.map +1 -0
  77. package/dist/models/ConversationClaim.d.ts +13 -0
  78. package/dist/models/ConversationClaim.js +44 -0
  79. package/dist/models/ConversationClaim.js.map +1 -0
  80. package/dist/models/ConversationEvaluation.d.ts +23 -0
  81. package/dist/models/ConversationEvaluation.js +92 -0
  82. package/dist/models/ConversationEvaluation.js.map +1 -0
  83. package/dist/models/Summary.d.ts +37 -0
  84. package/dist/models/Summary.js +78 -0
  85. package/dist/models/Summary.js.map +1 -0
  86. package/dist/models/Transcription.d.ts +34 -0
  87. package/dist/models/Transcription.js +71 -0
  88. package/dist/models/Transcription.js.map +1 -0
  89. package/dist/models/WhatsAppRecipient.d.ts +23 -0
  90. package/dist/models/WhatsAppRecipient.js +53 -0
  91. package/dist/models/WhatsAppRecipient.js.map +1 -0
  92. package/dist/modules/admin/admin.routes.d.ts +2 -0
  93. package/dist/modules/admin/admin.routes.js +1966 -0
  94. package/dist/modules/admin/admin.routes.js.map +1 -0
  95. package/dist/modules/admin/elevenlabs-test-chat.routes.d.ts +2 -0
  96. package/dist/modules/admin/elevenlabs-test-chat.routes.js +158 -0
  97. package/dist/modules/admin/elevenlabs-test-chat.routes.js.map +1 -0
  98. package/dist/modules/admin/whatsapp-test-chat.routes.d.ts +2 -0
  99. package/dist/modules/admin/whatsapp-test-chat.routes.js +204 -0
  100. package/dist/modules/admin/whatsapp-test-chat.routes.js.map +1 -0
  101. package/dist/modules/agents/agent.model.d.ts +38 -0
  102. package/dist/modules/agents/agent.model.js +92 -0
  103. package/dist/modules/agents/agent.model.js.map +1 -0
  104. package/dist/modules/agents/agent.routes.d.ts +2 -0
  105. package/dist/modules/agents/agent.routes.js +61 -0
  106. package/dist/modules/agents/agent.routes.js.map +1 -0
  107. package/dist/modules/appointment-validation/appointment-validation.model.d.ts +76 -0
  108. package/dist/modules/appointment-validation/appointment-validation.model.js +118 -0
  109. package/dist/modules/appointment-validation/appointment-validation.model.js.map +1 -0
  110. package/dist/modules/appointment-validation/appointment-validation.routes.d.ts +2 -0
  111. package/dist/modules/appointment-validation/appointment-validation.routes.js +202 -0
  112. package/dist/modules/appointment-validation/appointment-validation.routes.js.map +1 -0
  113. package/dist/modules/appointment-validation/appointment-validation.service.d.ts +53 -0
  114. package/dist/modules/appointment-validation/appointment-validation.service.js +827 -0
  115. package/dist/modules/appointment-validation/appointment-validation.service.js.map +1 -0
  116. package/dist/modules/auth/auth.model.d.ts +17 -0
  117. package/dist/modules/auth/auth.model.js +64 -0
  118. package/dist/modules/auth/auth.model.js.map +1 -0
  119. package/dist/modules/auth/auth.routes.d.ts +2 -0
  120. package/dist/modules/auth/auth.routes.js +202 -0
  121. package/dist/modules/auth/auth.routes.js.map +1 -0
  122. package/dist/modules/auth/auth.service.d.ts +28 -0
  123. package/dist/modules/auth/auth.service.js +183 -0
  124. package/dist/modules/auth/auth.service.js.map +1 -0
  125. package/dist/modules/auth/refresh-token.model.d.ts +13 -0
  126. package/dist/modules/auth/refresh-token.model.js +52 -0
  127. package/dist/modules/auth/refresh-token.model.js.map +1 -0
  128. package/dist/modules/billing/billing-alert.model.d.ts +16 -0
  129. package/dist/modules/billing/billing-alert.model.js +47 -0
  130. package/dist/modules/billing/billing-alert.model.js.map +1 -0
  131. package/dist/modules/billing/billing-period-snapshot.model.d.ts +35 -0
  132. package/dist/modules/billing/billing-period-snapshot.model.js +68 -0
  133. package/dist/modules/billing/billing-period-snapshot.model.js.map +1 -0
  134. package/dist/modules/billing/billing.model.d.ts +18 -0
  135. package/dist/modules/billing/billing.model.js +62 -0
  136. package/dist/modules/billing/billing.model.js.map +1 -0
  137. package/dist/modules/billing/billing.routes.d.ts +2 -0
  138. package/dist/modules/billing/billing.routes.js +63 -0
  139. package/dist/modules/billing/billing.routes.js.map +1 -0
  140. package/dist/modules/billing/billing.service.d.ts +69 -0
  141. package/dist/modules/billing/billing.service.js +498 -0
  142. package/dist/modules/billing/billing.service.js.map +1 -0
  143. package/dist/modules/billing/payment.model.d.ts +24 -0
  144. package/dist/modules/billing/payment.model.js +57 -0
  145. package/dist/modules/billing/payment.model.js.map +1 -0
  146. package/dist/modules/calls/call.model.d.ts +41 -0
  147. package/dist/modules/calls/call.model.js +97 -0
  148. package/dist/modules/calls/call.model.js.map +1 -0
  149. package/dist/modules/calls/call.routes.d.ts +2 -0
  150. package/dist/modules/calls/call.routes.js +103 -0
  151. package/dist/modules/calls/call.routes.js.map +1 -0
  152. package/dist/modules/campaigns/campaign.model.d.ts +45 -0
  153. package/dist/modules/campaigns/campaign.model.js +98 -0
  154. package/dist/modules/campaigns/campaign.model.js.map +1 -0
  155. package/dist/modules/campaigns/campaign.routes.d.ts +2 -0
  156. package/dist/modules/campaigns/campaign.routes.js +323 -0
  157. package/dist/modules/campaigns/campaign.routes.js.map +1 -0
  158. package/dist/modules/campaigns/campaign.service.d.ts +11 -0
  159. package/dist/modules/campaigns/campaign.service.js +86 -0
  160. package/dist/modules/campaigns/campaign.service.js.map +1 -0
  161. package/dist/modules/google-calendar/google-calendar.routes.d.ts +2 -0
  162. package/dist/modules/google-calendar/google-calendar.routes.js +32 -0
  163. package/dist/modules/google-calendar/google-calendar.routes.js.map +1 -0
  164. package/dist/modules/inbound-call/inbound-call-config.model.d.ts +20 -0
  165. package/dist/modules/inbound-call/inbound-call-config.model.js +68 -0
  166. package/dist/modules/inbound-call/inbound-call-config.model.js.map +1 -0
  167. package/dist/modules/inbound-call/inbound-call.routes.d.ts +2 -0
  168. package/dist/modules/inbound-call/inbound-call.routes.js +243 -0
  169. package/dist/modules/inbound-call/inbound-call.routes.js.map +1 -0
  170. package/dist/modules/leads/lead.model.d.ts +24 -0
  171. package/dist/modules/leads/lead.model.js +54 -0
  172. package/dist/modules/leads/lead.model.js.map +1 -0
  173. package/dist/modules/leads/lead.routes.d.ts +2 -0
  174. package/dist/modules/leads/lead.routes.js +201 -0
  175. package/dist/modules/leads/lead.routes.js.map +1 -0
  176. package/dist/modules/plans/plan.model.d.ts +25 -0
  177. package/dist/modules/plans/plan.model.js +59 -0
  178. package/dist/modules/plans/plan.model.js.map +1 -0
  179. package/dist/modules/surveys/survey.model.d.ts +30 -0
  180. package/dist/modules/surveys/survey.model.js +75 -0
  181. package/dist/modules/surveys/survey.model.js.map +1 -0
  182. package/dist/modules/surveys/survey.routes.d.ts +2 -0
  183. package/dist/modules/surveys/survey.routes.js +153 -0
  184. package/dist/modules/surveys/survey.routes.js.map +1 -0
  185. package/dist/modules/tenants/tenant.model.d.ts +86 -0
  186. package/dist/modules/tenants/tenant.model.js +127 -0
  187. package/dist/modules/tenants/tenant.model.js.map +1 -0
  188. package/dist/modules/tenants/tenant.routes.d.ts +2 -0
  189. package/dist/modules/tenants/tenant.routes.js +65 -0
  190. package/dist/modules/tenants/tenant.routes.js.map +1 -0
  191. package/dist/modules/users/user.routes.d.ts +2 -0
  192. package/dist/modules/users/user.routes.js +106 -0
  193. package/dist/modules/users/user.routes.js.map +1 -0
  194. package/dist/modules/webhooks/elevenlabs-tool.routes.d.ts +20 -0
  195. package/dist/modules/webhooks/elevenlabs-tool.routes.js +85 -0
  196. package/dist/modules/webhooks/elevenlabs-tool.routes.js.map +1 -0
  197. package/dist/modules/webhooks/elevenlabs-tool.service.d.ts +11 -0
  198. package/dist/modules/webhooks/elevenlabs-tool.service.js +360 -0
  199. package/dist/modules/webhooks/elevenlabs-tool.service.js.map +1 -0
  200. package/dist/modules/webhooks/elevenlabs.routes.d.ts +2 -0
  201. package/dist/modules/webhooks/elevenlabs.routes.js +34 -0
  202. package/dist/modules/webhooks/elevenlabs.routes.js.map +1 -0
  203. package/dist/modules/webhooks/elevenlabs.service.d.ts +6 -0
  204. package/dist/modules/webhooks/elevenlabs.service.js +512 -0
  205. package/dist/modules/webhooks/elevenlabs.service.js.map +1 -0
  206. package/dist/modules/webhooks/unipile.routes.d.ts +2 -0
  207. package/dist/modules/webhooks/unipile.routes.js +780 -0
  208. package/dist/modules/webhooks/unipile.routes.js.map +1 -0
  209. package/dist/modules/whatsapp/appointment.model.d.ts +27 -0
  210. package/dist/modules/whatsapp/appointment.model.js +58 -0
  211. package/dist/modules/whatsapp/appointment.model.js.map +1 -0
  212. package/dist/modules/whatsapp/operator-request.model.d.ts +29 -0
  213. package/dist/modules/whatsapp/operator-request.model.js +65 -0
  214. package/dist/modules/whatsapp/operator-request.model.js.map +1 -0
  215. package/dist/modules/whatsapp/stt-usage.model.d.ts +16 -0
  216. package/dist/modules/whatsapp/stt-usage.model.js +53 -0
  217. package/dist/modules/whatsapp/stt-usage.model.js.map +1 -0
  218. package/dist/modules/whatsapp/whatsapp-chat.model.d.ts +23 -0
  219. package/dist/modules/whatsapp/whatsapp-chat.model.js +55 -0
  220. package/dist/modules/whatsapp/whatsapp-chat.model.js.map +1 -0
  221. package/dist/modules/whatsapp/whatsapp-contact-profile.model.d.ts +23 -0
  222. package/dist/modules/whatsapp/whatsapp-contact-profile.model.js +54 -0
  223. package/dist/modules/whatsapp/whatsapp-contact-profile.model.js.map +1 -0
  224. package/dist/modules/whatsapp/whatsapp-message.model.d.ts +30 -0
  225. package/dist/modules/whatsapp/whatsapp-message.model.js +52 -0
  226. package/dist/modules/whatsapp/whatsapp-message.model.js.map +1 -0
  227. package/dist/modules/whatsapp/whatsapp-session.model.d.ts +33 -0
  228. package/dist/modules/whatsapp/whatsapp-session.model.js +65 -0
  229. package/dist/modules/whatsapp/whatsapp-session.model.js.map +1 -0
  230. package/dist/modules/whatsapp/whatsapp.routes.d.ts +2 -0
  231. package/dist/modules/whatsapp/whatsapp.routes.js +1237 -0
  232. package/dist/modules/whatsapp/whatsapp.routes.js.map +1 -0
  233. package/dist/plugins/cors.d.ts +3 -0
  234. package/dist/plugins/cors.js +11 -0
  235. package/dist/plugins/cors.js.map +1 -0
  236. package/dist/plugins/jwt.d.ts +3 -0
  237. package/dist/plugins/jwt.js +22 -0
  238. package/dist/plugins/jwt.js.map +1 -0
  239. package/dist/plugins/rawBody.d.ts +3 -0
  240. package/dist/plugins/rawBody.js +16 -0
  241. package/dist/plugins/rawBody.js.map +1 -0
  242. package/dist/plugins/rbac.d.ts +5 -0
  243. package/dist/plugins/rbac.js +29 -0
  244. package/dist/plugins/rbac.js.map +1 -0
  245. package/dist/routes/admin.routes.d.ts +2 -0
  246. package/dist/routes/admin.routes.js +169 -0
  247. package/dist/routes/admin.routes.js.map +1 -0
  248. package/dist/routes/health.routes.d.ts +2 -0
  249. package/dist/routes/health.routes.js +16 -0
  250. package/dist/routes/health.routes.js.map +1 -0
  251. package/dist/routes/webhook.routes.d.ts +2 -0
  252. package/dist/routes/webhook.routes.js +17 -0
  253. package/dist/routes/webhook.routes.js.map +1 -0
  254. package/dist/services/ai/base.ai.d.ts +19 -0
  255. package/dist/services/ai/base.ai.js +120 -0
  256. package/dist/services/ai/base.ai.js.map +1 -0
  257. package/dist/services/ai/gemini.service.d.ts +11 -0
  258. package/dist/services/ai/gemini.service.js +43 -0
  259. package/dist/services/ai/gemini.service.js.map +1 -0
  260. package/dist/services/ai/index.d.ts +2 -0
  261. package/dist/services/ai/index.js +26 -0
  262. package/dist/services/ai/index.js.map +1 -0
  263. package/dist/services/ai/openai.service.d.ts +11 -0
  264. package/dist/services/ai/openai.service.js +50 -0
  265. package/dist/services/ai/openai.service.js.map +1 -0
  266. package/dist/services/elevenlabs.service.d.ts +52 -0
  267. package/dist/services/elevenlabs.service.js +447 -0
  268. package/dist/services/elevenlabs.service.js.map +1 -0
  269. package/dist/services/google-calendar.service.d.ts +60 -0
  270. package/dist/services/google-calendar.service.js +494 -0
  271. package/dist/services/google-calendar.service.js.map +1 -0
  272. package/dist/services/inbound-call-schedule.service.d.ts +11 -0
  273. package/dist/services/inbound-call-schedule.service.js +162 -0
  274. package/dist/services/inbound-call-schedule.service.js.map +1 -0
  275. package/dist/services/netgsm.service.d.ts +41 -0
  276. package/dist/services/netgsm.service.js +89 -0
  277. package/dist/services/netgsm.service.js.map +1 -0
  278. package/dist/services/unipile.service.d.ts +41 -0
  279. package/dist/services/unipile.service.js +149 -0
  280. package/dist/services/unipile.service.js.map +1 -0
  281. package/dist/services/whatsapp-agent.service.d.ts +139 -0
  282. package/dist/services/whatsapp-agent.service.js +2055 -0
  283. package/dist/services/whatsapp-agent.service.js.map +1 -0
  284. package/dist/services/whatsapp.service.d.ts +26 -0
  285. package/dist/services/whatsapp.service.js +206 -0
  286. package/dist/services/whatsapp.service.js.map +1 -0
  287. package/dist/templates/index.d.ts +39 -0
  288. package/dist/templates/index.js +35 -0
  289. package/dist/templates/index.js.map +1 -0
  290. package/dist/templates/receptionist.d.ts +2 -0
  291. package/dist/templates/receptionist.js +39 -0
  292. package/dist/templates/receptionist.js.map +1 -0
  293. package/dist/templates/survey.d.ts +2 -0
  294. package/dist/templates/survey.js +41 -0
  295. package/dist/templates/survey.js.map +1 -0
  296. package/dist/types/index.d.ts +173 -0
  297. package/dist/types/index.js +3 -0
  298. package/dist/types/index.js.map +1 -0
  299. package/dist/utils/logger.d.ts +3 -0
  300. package/dist/utils/logger.js +105 -0
  301. package/dist/utils/logger.js.map +1 -0
  302. package/docker-compose.nestjs.yml +89 -0
  303. package/docker-compose.yml +78 -0
  304. package/docs/AI_AGENT_ENHANCEMENT_PLAN.md +164 -0
  305. package/docs/API.md +1193 -0
  306. package/docs/API_ENDPOINTS.md +344 -0
  307. package/docs/ARCHITECTURE.md +305 -0
  308. package/docs/AUTH_API.md +252 -0
  309. package/docs/BILLING_SMS_ALERTS.md +94 -0
  310. package/docs/CHAT_ASSIGNMENT_SYSTEM.md +118 -0
  311. package/docs/CLIENT_TOOLS_AND_FEATURES.md +337 -0
  312. package/docs/ELEVENLABS_WEBHOOK_TOOLS.md +644 -0
  313. package/docs/FRONTEND_CHECKLIST.md +227 -0
  314. package/docs/IMPLEMENTATION_STATUS.md +470 -0
  315. package/docs/MIGRATION_GUIDE.md +96 -0
  316. package/docs/MISSINGS_REPORT.md +507 -0
  317. package/docs/NESTJS_MIGRATION_REFERENCE.md +5136 -0
  318. package/docs/PROJECT_DESCRIPTION.md +1038 -0
  319. package/docs/SCALING.md +148 -0
  320. package/docs/SESSION_SUMMARY_2026_03_17.md +135 -0
  321. package/docs/WHATSAPP_AGENT.md +1086 -0
  322. package/docs/architecture/00-SYSTEM-OVERVIEW.md +318 -0
  323. package/docs/architecture/01-DATABASE-SCHEMA.md +2564 -0
  324. package/docs/architecture/02-AUTHENTICATION.md +1040 -0
  325. package/docs/architecture/03-MULTI-CLINIC.md +742 -0
  326. package/docs/architecture/04-WHATSAPP-AGENT.md +608 -0
  327. package/docs/architecture/05-OPERATOR-WORKFLOW.md +444 -0
  328. package/docs/architecture/06-BAILEYS-MICROSERVICE.md +616 -0
  329. package/docs/architecture/07-APPOINTMENTS.md +849 -0
  330. package/docs/architecture/08-VOICE-CALLS.md +470 -0
  331. package/docs/architecture/09-OUTBOUND-CAMPAIGNS.md +542 -0
  332. package/docs/architecture/10-CLIENT-TOOLS.md +665 -0
  333. package/docs/architecture/11-BILLING.md +458 -0
  334. package/docs/architecture/12-SECURITY.md +216 -0
  335. package/docs/architecture/13-LOGGING-AUDIT.md +549 -0
  336. package/docs/architecture/14-META-BUSINESS-API.md +454 -0
  337. package/docs/architecture/15-AI-MODULE.md +479 -0
  338. package/docs/architecture/16-BACKGROUND-JOBS.md +469 -0
  339. package/docs/architecture/17-REALTIME-LIVECHAT.md +447 -0
  340. package/docs/architecture/18-FILE-STORAGE.md +410 -0
  341. package/docs/architecture/19-PATIENTS.md +1034 -0
  342. package/docs/architecture/20-TREATMENTS-AND-PLANS.md +774 -0
  343. package/docs/architecture/21-BEFORE-AFTER-PHOTOS.md +519 -0
  344. package/docs/database.md +456 -0
  345. package/docs/ornek-randevu-onay.csv +3 -0
  346. package/ecosystem.config.js +16 -0
  347. package/elevenlabs-convai-api-reference.md +1171 -0
  348. package/frontend/.dockerignore +2 -0
  349. package/frontend/Dockerfile +24 -0
  350. package/frontend/README.md +75 -0
  351. package/frontend/components.json +25 -0
  352. package/frontend/eslint.config.js +23 -0
  353. package/frontend/index.html +13 -0
  354. package/frontend/nginx.conf +37 -0
  355. package/frontend/package-lock.json +8709 -0
  356. package/frontend/package.json +71 -0
  357. package/frontend/public/favicon.svg +1 -0
  358. package/frontend/public/icons.svg +24 -0
  359. package/frontend/src/App.tsx +125 -0
  360. package/frontend/src/components/error-boundary.tsx +50 -0
  361. package/frontend/src/components/shared/activity-timeline.tsx +66 -0
  362. package/frontend/src/components/shared/appointment-calendar.css +80 -0
  363. package/frontend/src/components/shared/appointment-calendar.tsx +245 -0
  364. package/frontend/src/components/shared/chat-bubble.tsx +72 -0
  365. package/frontend/src/components/shared/combobox.tsx +119 -0
  366. package/frontend/src/components/shared/confirm-dialog.tsx +57 -0
  367. package/frontend/src/components/shared/data-table-pagination.tsx +97 -0
  368. package/frontend/src/components/shared/data-table-toolbar.tsx +39 -0
  369. package/frontend/src/components/shared/empty-state.tsx +27 -0
  370. package/frontend/src/components/shared/file-upload.tsx +140 -0
  371. package/frontend/src/components/shared/index.ts +20 -0
  372. package/frontend/src/components/shared/language-switcher.tsx +29 -0
  373. package/frontend/src/components/shared/notification-dropdown.tsx +115 -0
  374. package/frontend/src/components/shared/page-header.tsx +23 -0
  375. package/frontend/src/components/shared/stat-card.tsx +37 -0
  376. package/frontend/src/components/shared/status-badge.tsx +70 -0
  377. package/frontend/src/components/shared/status-dot.tsx +43 -0
  378. package/frontend/src/components/ui/alert-dialog.tsx +187 -0
  379. package/frontend/src/components/ui/alert.tsx +76 -0
  380. package/frontend/src/components/ui/avatar.tsx +109 -0
  381. package/frontend/src/components/ui/badge.tsx +52 -0
  382. package/frontend/src/components/ui/breadcrumb.tsx +125 -0
  383. package/frontend/src/components/ui/button.tsx +60 -0
  384. package/frontend/src/components/ui/calendar.tsx +219 -0
  385. package/frontend/src/components/ui/card.tsx +103 -0
  386. package/frontend/src/components/ui/chart.tsx +371 -0
  387. package/frontend/src/components/ui/checkbox.tsx +29 -0
  388. package/frontend/src/components/ui/collapsible.tsx +19 -0
  389. package/frontend/src/components/ui/command.tsx +194 -0
  390. package/frontend/src/components/ui/dialog.tsx +158 -0
  391. package/frontend/src/components/ui/dropdown-menu.tsx +268 -0
  392. package/frontend/src/components/ui/input-group.tsx +156 -0
  393. package/frontend/src/components/ui/input.tsx +20 -0
  394. package/frontend/src/components/ui/label.tsx +20 -0
  395. package/frontend/src/components/ui/pagination.tsx +130 -0
  396. package/frontend/src/components/ui/popover.tsx +90 -0
  397. package/frontend/src/components/ui/progress.tsx +83 -0
  398. package/frontend/src/components/ui/radio-group.tsx +36 -0
  399. package/frontend/src/components/ui/scroll-area.tsx +54 -0
  400. package/frontend/src/components/ui/select.tsx +199 -0
  401. package/frontend/src/components/ui/separator.tsx +23 -0
  402. package/frontend/src/components/ui/sheet.tsx +138 -0
  403. package/frontend/src/components/ui/sidebar.tsx +723 -0
  404. package/frontend/src/components/ui/skeleton.tsx +13 -0
  405. package/frontend/src/components/ui/sonner.tsx +47 -0
  406. package/frontend/src/components/ui/switch.tsx +30 -0
  407. package/frontend/src/components/ui/table.tsx +114 -0
  408. package/frontend/src/components/ui/tabs.tsx +82 -0
  409. package/frontend/src/components/ui/textarea.tsx +18 -0
  410. package/frontend/src/components/ui/toggle-group.tsx +89 -0
  411. package/frontend/src/components/ui/toggle.tsx +43 -0
  412. package/frontend/src/components/ui/tooltip.tsx +64 -0
  413. package/frontend/src/hooks/use-mobile.ts +19 -0
  414. package/frontend/src/i18n/index.ts +20 -0
  415. package/frontend/src/i18n/locales/en.json +786 -0
  416. package/frontend/src/i18n/locales/tr.json +786 -0
  417. package/frontend/src/index.css +134 -0
  418. package/frontend/src/layouts/admin-layout.tsx +111 -0
  419. package/frontend/src/layouts/app-header.tsx +130 -0
  420. package/frontend/src/layouts/app-layout.tsx +19 -0
  421. package/frontend/src/layouts/app-sidebar.tsx +212 -0
  422. package/frontend/src/layouts/auth-guard.tsx +31 -0
  423. package/frontend/src/layouts/mobile-sidebar.tsx +120 -0
  424. package/frontend/src/lib/api.ts +68 -0
  425. package/frontend/src/lib/hooks/use-appointments.ts +224 -0
  426. package/frontend/src/lib/hooks/use-availability-blocks.ts +83 -0
  427. package/frontend/src/lib/hooks/use-chats.ts +236 -0
  428. package/frontend/src/lib/hooks/use-clinic-detail.ts +171 -0
  429. package/frontend/src/lib/hooks/use-clinics.ts +37 -0
  430. package/frontend/src/lib/hooks/use-doctor-calendar.ts +80 -0
  431. package/frontend/src/lib/hooks/use-examinations.ts +89 -0
  432. package/frontend/src/lib/hooks/use-medical-history.ts +52 -0
  433. package/frontend/src/lib/hooks/use-patients.ts +296 -0
  434. package/frontend/src/lib/hooks/use-photo-sets.ts +118 -0
  435. package/frontend/src/lib/hooks/use-treatment-plans.ts +152 -0
  436. package/frontend/src/lib/hooks/use-treatments.ts +125 -0
  437. package/frontend/src/lib/hooks/use-users.ts +172 -0
  438. package/frontend/src/lib/utils.ts +6 -0
  439. package/frontend/src/main.tsx +17 -0
  440. package/frontend/src/pages/admin/agents/detail.tsx +774 -0
  441. package/frontend/src/pages/admin/agents/import.tsx +280 -0
  442. package/frontend/src/pages/admin/agents/index.tsx +245 -0
  443. package/frontend/src/pages/admin/ai-playground.tsx +543 -0
  444. package/frontend/src/pages/appointments/create-appointment-dialog.tsx +390 -0
  445. package/frontend/src/pages/appointments/index.tsx +860 -0
  446. package/frontend/src/pages/audit/index.tsx +24 -0
  447. package/frontend/src/pages/auth/login.tsx +194 -0
  448. package/frontend/src/pages/billing/index.tsx +24 -0
  449. package/frontend/src/pages/calendar/index.tsx +704 -0
  450. package/frontend/src/pages/calendar-connections/index.tsx +295 -0
  451. package/frontend/src/pages/calls/index.tsx +24 -0
  452. package/frontend/src/pages/campaigns/index.tsx +24 -0
  453. package/frontend/src/pages/chats/index.tsx +981 -0
  454. package/frontend/src/pages/clinics/index.tsx +224 -0
  455. package/frontend/src/pages/clinics/settings.tsx +412 -0
  456. package/frontend/src/pages/components-showcase.tsx +773 -0
  457. package/frontend/src/pages/connections/index.tsx +328 -0
  458. package/frontend/src/pages/dashboard.tsx +50 -0
  459. package/frontend/src/pages/leads/index.tsx +24 -0
  460. package/frontend/src/pages/my-schedule/index.tsx +496 -0
  461. package/frontend/src/pages/patients/create-patient-dialog.tsx +358 -0
  462. package/frontend/src/pages/patients/detail.tsx +1195 -0
  463. package/frontend/src/pages/patients/edit-patient-dialog.tsx +387 -0
  464. package/frontend/src/pages/patients/examinations-tab.tsx +460 -0
  465. package/frontend/src/pages/patients/index.tsx +381 -0
  466. package/frontend/src/pages/patients/medical-history-dialog.tsx +207 -0
  467. package/frontend/src/pages/patients/photo-sets-tab.tsx +616 -0
  468. package/frontend/src/pages/patients/timeline-tab.tsx +164 -0
  469. package/frontend/src/pages/patients/treatment-plans-tab.tsx +598 -0
  470. package/frontend/src/pages/phone-numbers/detail.tsx +427 -0
  471. package/frontend/src/pages/phone-numbers/index.tsx +455 -0
  472. package/frontend/src/pages/platform/index.tsx +454 -0
  473. package/frontend/src/pages/settings/index.tsx +126 -0
  474. package/frontend/src/pages/treatments/index.tsx +487 -0
  475. package/frontend/src/pages/users/doctor-profile.tsx +672 -0
  476. package/frontend/src/pages/users/edit.tsx +329 -0
  477. package/frontend/src/pages/users/index.tsx +407 -0
  478. package/frontend/src/pages/validation/index.tsx +24 -0
  479. package/frontend/src/stores/auth.store.ts +108 -0
  480. package/frontend/src/stores/ui.store.ts +41 -0
  481. package/frontend/tsconfig.app.json +32 -0
  482. package/frontend/tsconfig.json +13 -0
  483. package/frontend/tsconfig.node.json +26 -0
  484. package/frontend/vite.config.ts +29 -0
  485. package/nestjs/.dockerignore +5 -0
  486. package/nestjs/.env.docker +64 -0
  487. package/nestjs/.prettierrc +4 -0
  488. package/nestjs/Dockerfile +36 -0
  489. package/nestjs/README.md +98 -0
  490. package/nestjs/eslint.config.mjs +35 -0
  491. package/nestjs/nest-cli.json +8 -0
  492. package/nestjs/package-lock.json +13390 -0
  493. package/nestjs/package.json +114 -0
  494. package/nestjs/prisma/migrations/20260409161536_add_message_metadata_fields/migration.sql +1746 -0
  495. package/nestjs/prisma/migrations/20260410140436_add_agent_ai_fields/migration.sql +36 -0
  496. package/nestjs/prisma/migrations/20260410175519_add_agent_clinic_assignments/migration.sql +21 -0
  497. package/nestjs/prisma/migrations/20260412094344_make_agent_tenant_optional/migration.sql +2 -0
  498. package/nestjs/prisma/migrations/20260412110008_add_admin_chat_sessions/migration.sql +47 -0
  499. package/nestjs/prisma/migrations/migration_lock.toml +3 -0
  500. package/nestjs/prisma/schema.prisma +1843 -0
  501. package/nestjs/prisma/seed.ts +375 -0
  502. package/nestjs/prisma.config.ts +14 -0
  503. package/nestjs/src/admin/admin.controller.ts +27 -0
  504. package/nestjs/src/admin/admin.module.ts +16 -0
  505. package/nestjs/src/admin/admin.service.ts +91 -0
  506. package/nestjs/src/admin/ai-chat-session.service.ts +454 -0
  507. package/nestjs/src/admin/ai-test.controller.ts +191 -0
  508. package/nestjs/src/admin/superadmin.controller.ts +106 -0
  509. package/nestjs/src/agents/agents.controller.ts +262 -0
  510. package/nestjs/src/agents/agents.module.ts +13 -0
  511. package/nestjs/src/agents/agents.service.ts +733 -0
  512. package/nestjs/src/agents/dto/create-agent.dto.ts +99 -0
  513. package/nestjs/src/agents/dto/index.ts +2 -0
  514. package/nestjs/src/agents/dto/update-agent.dto.ts +148 -0
  515. package/nestjs/src/app.module.ts +115 -0
  516. package/nestjs/src/appointment-validation/appointment-validation.controller.ts +194 -0
  517. package/nestjs/src/appointment-validation/appointment-validation.module.ts +16 -0
  518. package/nestjs/src/appointment-validation/appointment-validation.service.ts +450 -0
  519. package/nestjs/src/appointment-validation/dto/create-batch.dto.ts +105 -0
  520. package/nestjs/src/appointment-validation/dto/index.ts +1 -0
  521. package/nestjs/src/appointment-validation/processors/validation-dispatch.processor.ts +26 -0
  522. package/nestjs/src/appointment-validation/processors/validation-sync.processor.ts +23 -0
  523. package/nestjs/src/appointments/appointments.controller.ts +268 -0
  524. package/nestjs/src/appointments/appointments.module.ts +13 -0
  525. package/nestjs/src/appointments/appointments.service.ts +773 -0
  526. package/nestjs/src/appointments/dto/create-appointment.dto.ts +72 -0
  527. package/nestjs/src/appointments/dto/index.ts +4 -0
  528. package/nestjs/src/appointments/dto/query-appointments.dto.ts +60 -0
  529. package/nestjs/src/appointments/dto/update-appointment.dto.ts +43 -0
  530. package/nestjs/src/appointments/dto/update-status.dto.ts +18 -0
  531. package/nestjs/src/appointments/processors/reminder.processor.ts +243 -0
  532. package/nestjs/src/audit/audit.controller.ts +84 -0
  533. package/nestjs/src/audit/audit.decorator.ts +20 -0
  534. package/nestjs/src/audit/audit.interceptor.ts +67 -0
  535. package/nestjs/src/audit/audit.interfaces.ts +15 -0
  536. package/nestjs/src/audit/audit.module.ts +12 -0
  537. package/nestjs/src/audit/audit.service.ts +177 -0
  538. package/nestjs/src/auth/auth.controller.ts +116 -0
  539. package/nestjs/src/auth/auth.module.ts +25 -0
  540. package/nestjs/src/auth/auth.service.ts +612 -0
  541. package/nestjs/src/auth/dto/change-password.dto.ts +13 -0
  542. package/nestjs/src/auth/dto/forgot-password.dto.ts +8 -0
  543. package/nestjs/src/auth/dto/index.ts +6 -0
  544. package/nestjs/src/auth/dto/login.dto.ts +13 -0
  545. package/nestjs/src/auth/dto/refresh.dto.ts +8 -0
  546. package/nestjs/src/auth/dto/register.dto.ts +28 -0
  547. package/nestjs/src/auth/dto/reset-password.dto.ts +13 -0
  548. package/nestjs/src/auth/permissions.config.ts +85 -0
  549. package/nestjs/src/availability-blocks/availability-blocks.controller.ts +83 -0
  550. package/nestjs/src/availability-blocks/availability-blocks.module.ts +10 -0
  551. package/nestjs/src/availability-blocks/availability-blocks.service.ts +202 -0
  552. package/nestjs/src/billing/billing.controller.ts +104 -0
  553. package/nestjs/src/billing/billing.module.ts +12 -0
  554. package/nestjs/src/billing/billing.service.ts +398 -0
  555. package/nestjs/src/billing/dto/index.ts +2 -0
  556. package/nestjs/src/billing/dto/query-billing.dto.ts +29 -0
  557. package/nestjs/src/billing/dto/record-payment.dto.ts +60 -0
  558. package/nestjs/src/billing/processors/alerts.processor.ts +216 -0
  559. package/nestjs/src/billing/processors/snapshot.processor.ts +181 -0
  560. package/nestjs/src/calls/calls.controller.ts +92 -0
  561. package/nestjs/src/calls/calls.module.ts +10 -0
  562. package/nestjs/src/calls/calls.service.ts +359 -0
  563. package/nestjs/src/calls/dto/index.ts +1 -0
  564. package/nestjs/src/calls/dto/query-calls.dto.ts +46 -0
  565. package/nestjs/src/clinics/clinics.controller.ts +226 -0
  566. package/nestjs/src/clinics/clinics.module.ts +11 -0
  567. package/nestjs/src/clinics/clinics.service.ts +203 -0
  568. package/nestjs/src/clinics/dto/create-clinic.dto.ts +40 -0
  569. package/nestjs/src/clinics/dto/create-meta-connection.dto.ts +44 -0
  570. package/nestjs/src/clinics/dto/index.ts +4 -0
  571. package/nestjs/src/clinics/dto/update-clinic.dto.ts +133 -0
  572. package/nestjs/src/clinics/dto/update-meta-connection.dto.ts +22 -0
  573. package/nestjs/src/clinics/meta-connections.service.ts +210 -0
  574. package/nestjs/src/common/decorators/accessible-clinics.decorator.ts +9 -0
  575. package/nestjs/src/common/decorators/current-user.decorator.ts +10 -0
  576. package/nestjs/src/common/decorators/features.decorator.ts +7 -0
  577. package/nestjs/src/common/decorators/index.ts +4 -0
  578. package/nestjs/src/common/decorators/permissions.decorator.ts +13 -0
  579. package/nestjs/src/common/gateways/events.gateway.ts +157 -0
  580. package/nestjs/src/common/guards/clinic-access.guard.ts +40 -0
  581. package/nestjs/src/common/guards/features.guard.ts +38 -0
  582. package/nestjs/src/common/guards/index.ts +5 -0
  583. package/nestjs/src/common/guards/jwt-auth.guard.ts +54 -0
  584. package/nestjs/src/common/guards/permissions.guard.ts +50 -0
  585. package/nestjs/src/common/guards/superadmin.guard.ts +35 -0
  586. package/nestjs/src/common/interceptors/request-context.interceptor.ts +32 -0
  587. package/nestjs/src/common/interceptors/superadmin-tenant.interceptor.ts +42 -0
  588. package/nestjs/src/common/interfaces/jwt-payload.interface.ts +11 -0
  589. package/nestjs/src/config/config.module.ts +13 -0
  590. package/nestjs/src/database/database.module.ts +9 -0
  591. package/nestjs/src/database/prisma.service.ts +20 -0
  592. package/nestjs/src/database/tenant-context.ts +27 -0
  593. package/nestjs/src/google-calendar/google-calendar.controller.ts +259 -0
  594. package/nestjs/src/google-calendar/google-calendar.module.ts +10 -0
  595. package/nestjs/src/google-calendar/google-calendar.service.ts +811 -0
  596. package/nestjs/src/integrations/ai/ai.interface.ts +74 -0
  597. package/nestjs/src/integrations/ai/ai.module.ts +11 -0
  598. package/nestjs/src/integrations/ai/ai.service.ts +148 -0
  599. package/nestjs/src/integrations/ai/providers/anthropic.provider.ts +146 -0
  600. package/nestjs/src/integrations/ai/providers/openai.provider.ts +158 -0
  601. package/nestjs/src/integrations/elevenlabs/elevenlabs.module.ts +8 -0
  602. package/nestjs/src/integrations/elevenlabs/elevenlabs.service.ts +226 -0
  603. package/nestjs/src/integrations/encryption/encryption.module.ts +9 -0
  604. package/nestjs/src/integrations/encryption/encryption.service.ts +31 -0
  605. package/nestjs/src/integrations/image/image.module.ts +9 -0
  606. package/nestjs/src/integrations/image/image.service.ts +61 -0
  607. package/nestjs/src/integrations/meta-business/meta-business.module.ts +10 -0
  608. package/nestjs/src/integrations/meta-business/meta-instagram.service.ts +94 -0
  609. package/nestjs/src/integrations/meta-business/meta-webhook.service.ts +52 -0
  610. package/nestjs/src/integrations/meta-business/meta-whatsapp.service.ts +254 -0
  611. package/nestjs/src/integrations/minio/minio.module.ts +9 -0
  612. package/nestjs/src/integrations/minio/minio.service.ts +88 -0
  613. package/nestjs/src/integrations/netgsm/netgsm.module.ts +8 -0
  614. package/nestjs/src/integrations/netgsm/netgsm.service.ts +17 -0
  615. package/nestjs/src/integrations/tektippay/tektippay.module.ts +8 -0
  616. package/nestjs/src/integrations/tektippay/tektippay.service.ts +23 -0
  617. package/nestjs/src/leads/dto/index.ts +2 -0
  618. package/nestjs/src/leads/dto/query-leads.dto.ts +50 -0
  619. package/nestjs/src/leads/dto/update-lead.dto.ts +26 -0
  620. package/nestjs/src/leads/leads.controller.ts +184 -0
  621. package/nestjs/src/leads/leads.module.ts +10 -0
  622. package/nestjs/src/leads/leads.service.ts +375 -0
  623. package/nestjs/src/logging/logging.controller.ts +82 -0
  624. package/nestjs/src/logging/logging.module.ts +11 -0
  625. package/nestjs/src/logging/logging.service.ts +180 -0
  626. package/nestjs/src/main.ts +86 -0
  627. package/nestjs/src/outbound-campaigns/dto/create-campaign.dto.ts +47 -0
  628. package/nestjs/src/outbound-campaigns/dto/index.ts +3 -0
  629. package/nestjs/src/outbound-campaigns/dto/update-campaign.dto.ts +31 -0
  630. package/nestjs/src/outbound-campaigns/dto/upload-entries.dto.ts +35 -0
  631. package/nestjs/src/outbound-campaigns/outbound-campaigns.controller.ts +307 -0
  632. package/nestjs/src/outbound-campaigns/outbound-campaigns.module.ts +13 -0
  633. package/nestjs/src/outbound-campaigns/outbound-campaigns.service.ts +471 -0
  634. package/nestjs/src/outbound-campaigns/processors/campaign-dispatch.processor.ts +366 -0
  635. package/nestjs/src/patients/documents.service.ts +231 -0
  636. package/nestjs/src/patients/dto/create-examination.dto.ts +34 -0
  637. package/nestjs/src/patients/dto/create-note.dto.ts +14 -0
  638. package/nestjs/src/patients/dto/create-patient.dto.ts +86 -0
  639. package/nestjs/src/patients/dto/create-photo-set.dto.ts +32 -0
  640. package/nestjs/src/patients/dto/index.ts +10 -0
  641. package/nestjs/src/patients/dto/update-examination.dto.ts +29 -0
  642. package/nestjs/src/patients/dto/update-medical-history.dto.ts +47 -0
  643. package/nestjs/src/patients/dto/update-patient.dto.ts +87 -0
  644. package/nestjs/src/patients/dto/update-photo-set.dto.ts +28 -0
  645. package/nestjs/src/patients/dto/upload-document.dto.ts +31 -0
  646. package/nestjs/src/patients/dto/upload-photo.dto.ts +27 -0
  647. package/nestjs/src/patients/examinations.service.ts +271 -0
  648. package/nestjs/src/patients/medical-history.service.ts +149 -0
  649. package/nestjs/src/patients/notes.service.ts +172 -0
  650. package/nestjs/src/patients/patients.controller.ts +485 -0
  651. package/nestjs/src/patients/patients.module.ts +22 -0
  652. package/nestjs/src/patients/patients.service.ts +412 -0
  653. package/nestjs/src/patients/photo-sets.service.ts +389 -0
  654. package/nestjs/src/phone-numbers/dto/create-phone-number.dto.ts +57 -0
  655. package/nestjs/src/phone-numbers/dto/index.ts +3 -0
  656. package/nestjs/src/phone-numbers/dto/update-phone-number.dto.ts +38 -0
  657. package/nestjs/src/phone-numbers/dto/update-schedule.dto.ts +39 -0
  658. package/nestjs/src/phone-numbers/phone-numbers.controller.ts +125 -0
  659. package/nestjs/src/phone-numbers/phone-numbers.module.ts +10 -0
  660. package/nestjs/src/phone-numbers/phone-numbers.service.ts +209 -0
  661. package/nestjs/src/plans/dto/create-plan.dto.ts +70 -0
  662. package/nestjs/src/plans/dto/index.ts +2 -0
  663. package/nestjs/src/plans/dto/update-plan.dto.ts +80 -0
  664. package/nestjs/src/plans/plans.controller.ts +50 -0
  665. package/nestjs/src/plans/plans.module.ts +10 -0
  666. package/nestjs/src/plans/plans.service.ts +115 -0
  667. package/nestjs/src/platform/dto/create-tenant.dto.ts +36 -0
  668. package/nestjs/src/platform/dto/index.ts +2 -0
  669. package/nestjs/src/platform/dto/update-tenant-platform.dto.ts +44 -0
  670. package/nestjs/src/platform/platform.controller.ts +79 -0
  671. package/nestjs/src/platform/platform.module.ts +10 -0
  672. package/nestjs/src/platform/platform.service.ts +301 -0
  673. package/nestjs/src/queue/queue.module.ts +56 -0
  674. package/nestjs/src/redis/redis.module.ts +20 -0
  675. package/nestjs/src/tenants/dto/index.ts +1 -0
  676. package/nestjs/src/tenants/dto/update-tenant.dto.ts +15 -0
  677. package/nestjs/src/tenants/tenants.controller.ts +45 -0
  678. package/nestjs/src/tenants/tenants.module.ts +10 -0
  679. package/nestjs/src/tenants/tenants.service.ts +41 -0
  680. package/nestjs/src/tools/adapters/elevenlabs-http.adapter.ts +51 -0
  681. package/nestjs/src/tools/adapters/elevenlabs-ws.adapter.ts +59 -0
  682. package/nestjs/src/tools/handlers/calendar.tools.ts +441 -0
  683. package/nestjs/src/tools/handlers/notification.tools.ts +34 -0
  684. package/nestjs/src/tools/handlers/operator.tools.ts +303 -0
  685. package/nestjs/src/tools/handlers/patient.tools.ts +242 -0
  686. package/nestjs/src/tools/handlers/payment.tools.ts +43 -0
  687. package/nestjs/src/tools/handlers/validation.tools.ts +152 -0
  688. package/nestjs/src/tools/tool-registry.service.ts +221 -0
  689. package/nestjs/src/tools/tool.decorator.ts +16 -0
  690. package/nestjs/src/tools/tool.interfaces.ts +26 -0
  691. package/nestjs/src/tools/tools.module.ts +50 -0
  692. package/nestjs/src/treatments/dto/create-plan-item.dto.ts +27 -0
  693. package/nestjs/src/treatments/dto/create-treatment-plan.dto.ts +69 -0
  694. package/nestjs/src/treatments/dto/create-treatment.dto.ts +59 -0
  695. package/nestjs/src/treatments/dto/index.ts +6 -0
  696. package/nestjs/src/treatments/dto/update-plan-item.dto.ts +23 -0
  697. package/nestjs/src/treatments/dto/update-treatment-plan.dto.ts +22 -0
  698. package/nestjs/src/treatments/dto/update-treatment.dto.ts +70 -0
  699. package/nestjs/src/treatments/treatment-plans.service.ts +362 -0
  700. package/nestjs/src/treatments/treatments.controller.ts +265 -0
  701. package/nestjs/src/treatments/treatments.module.ts +14 -0
  702. package/nestjs/src/treatments/treatments.service.ts +165 -0
  703. package/nestjs/src/users/doctor-profiles.service.ts +202 -0
  704. package/nestjs/src/users/dto/index.ts +4 -0
  705. package/nestjs/src/users/dto/invite-user.dto.ts +52 -0
  706. package/nestjs/src/users/dto/update-clinic-assignments.dto.ts +9 -0
  707. package/nestjs/src/users/dto/update-doctor-profile.dto.ts +49 -0
  708. package/nestjs/src/users/dto/update-user.dto.ts +41 -0
  709. package/nestjs/src/users/users.controller.ts +142 -0
  710. package/nestjs/src/users/users.module.ts +11 -0
  711. package/nestjs/src/users/users.service.ts +250 -0
  712. package/nestjs/src/webhooks/elevenlabs-tool.controller.ts +66 -0
  713. package/nestjs/src/webhooks/elevenlabs-webhook.controller.ts +60 -0
  714. package/nestjs/src/webhooks/meta-webhook.controller.ts +178 -0
  715. package/nestjs/src/webhooks/processors/elevenlabs-webhook.processor.ts +28 -0
  716. package/nestjs/src/webhooks/webhooks.module.ts +17 -0
  717. package/nestjs/src/whatsapp/chat-context.service.ts +281 -0
  718. package/nestjs/src/whatsapp/dto/add-blacklist.dto.ts +13 -0
  719. package/nestjs/src/whatsapp/dto/index.ts +2 -0
  720. package/nestjs/src/whatsapp/dto/send-message.dto.ts +14 -0
  721. package/nestjs/src/whatsapp/listeners/meta-message.listener.ts +579 -0
  722. package/nestjs/src/whatsapp/meta-auth.controller.ts +268 -0
  723. package/nestjs/src/whatsapp/meta-instagram-auth.controller.ts +244 -0
  724. package/nestjs/src/whatsapp/operator.service.ts +692 -0
  725. package/nestjs/src/whatsapp/processors/cost-sweep.processor.ts +130 -0
  726. package/nestjs/src/whatsapp/processors/grace.processor.ts +191 -0
  727. package/nestjs/src/whatsapp/processors/message-buffer.processor.ts +138 -0
  728. package/nestjs/src/whatsapp/processors/message-cleanup.processor.ts +148 -0
  729. package/nestjs/src/whatsapp/processors/meta-token-refresh.processor.ts +114 -0
  730. package/nestjs/src/whatsapp/processors/operator-expiry.processor.ts +105 -0
  731. package/nestjs/src/whatsapp/processors/profile-update.processor.ts +234 -0
  732. package/nestjs/src/whatsapp/processors/session-cleanup.processor.ts +178 -0
  733. package/nestjs/src/whatsapp/processors/session-labels.processor.ts +248 -0
  734. package/nestjs/src/whatsapp/whatsapp-agent.service.ts +2506 -0
  735. package/nestjs/src/whatsapp/whatsapp-recovery.service.ts +117 -0
  736. package/nestjs/src/whatsapp/whatsapp.controller.ts +398 -0
  737. package/nestjs/src/whatsapp/whatsapp.module.ts +51 -0
  738. package/nestjs/src/whatsapp/whatsapp.service.ts +592 -0
  739. package/nestjs/test/app.e2e-spec.ts +25 -0
  740. package/nestjs/test/jest-e2e.json +9 -0
  741. package/nestjs/tsconfig.build.json +4 -0
  742. package/nestjs/tsconfig.json +25 -0
  743. package/nginx.example.conf +18 -0
  744. package/package.json +47 -0
  745. package/scripts/addRecipient.ts +48 -0
  746. package/scripts/listRecipients.ts +31 -0
  747. package/scripts/migrate-agent-ref.ts +86 -0
  748. package/scripts/migrate-sessions.ts +183 -0
  749. package/scripts/promote.ts +27 -0
  750. package/scripts/retrigger.ts +84 -0
  751. package/scripts/seed.ts +435 -0
  752. package/scripts/testSend.ts +63 -0
  753. package/src/app.ts +85 -0
  754. package/src/config/agentPrompts.json +19 -0
  755. package/src/config/database.ts +21 -0
  756. package/src/config/env.ts +94 -0
  757. package/src/config/index.ts +86 -0
  758. package/src/controllers/webhook.controller.ts +150 -0
  759. package/src/errors/index.ts +9 -0
  760. package/src/hooks/webhookValidator.ts +55 -0
  761. package/src/index.ts +68 -0
  762. package/src/migrations/001_session-architecture.ts +138 -0
  763. package/src/migrations/002_agent-ref.ts +65 -0
  764. package/src/migrations/003_shift-schedule.ts +55 -0
  765. package/src/migrations/004_invert-shift-to-clinic-hours.ts +30 -0
  766. package/src/migrations/005_composite-baileys-chat-ids.ts +60 -0
  767. package/src/migrations/migration.model.ts +27 -0
  768. package/src/migrations/migration.routes.ts +40 -0
  769. package/src/migrations/migration.runner.ts +112 -0
  770. package/src/models/ConversationClaim.ts +17 -0
  771. package/src/models/ConversationEvaluation.ts +91 -0
  772. package/src/models/Summary.ts +77 -0
  773. package/src/models/Transcription.ts +68 -0
  774. package/src/models/WhatsAppRecipient.ts +37 -0
  775. package/src/modules/admin/admin.routes.ts +2385 -0
  776. package/src/modules/admin/elevenlabs-test-chat.routes.ts +193 -0
  777. package/src/modules/admin/whatsapp-test-chat.routes.ts +244 -0
  778. package/src/modules/agents/agent.model.ts +93 -0
  779. package/src/modules/agents/agent.routes.ts +65 -0
  780. package/src/modules/appointment-validation/appointment-validation.model.ts +163 -0
  781. package/src/modules/appointment-validation/appointment-validation.routes.ts +275 -0
  782. package/src/modules/appointment-validation/appointment-validation.service.ts +1028 -0
  783. package/src/modules/auth/auth.model.ts +42 -0
  784. package/src/modules/auth/auth.routes.ts +199 -0
  785. package/src/modules/auth/auth.service.ts +210 -0
  786. package/src/modules/auth/refresh-token.model.ts +26 -0
  787. package/src/modules/billing/billing-alert.model.ts +28 -0
  788. package/src/modules/billing/billing-period-snapshot.model.ts +68 -0
  789. package/src/modules/billing/billing.model.ts +42 -0
  790. package/src/modules/billing/billing.routes.ts +67 -0
  791. package/src/modules/billing/billing.service.ts +562 -0
  792. package/src/modules/billing/payment.model.ts +42 -0
  793. package/src/modules/calls/call.model.ts +102 -0
  794. package/src/modules/calls/call.routes.ts +118 -0
  795. package/src/modules/campaigns/campaign.model.ts +111 -0
  796. package/src/modules/campaigns/campaign.routes.ts +402 -0
  797. package/src/modules/campaigns/campaign.service.ts +99 -0
  798. package/src/modules/google-calendar/google-calendar.routes.ts +31 -0
  799. package/src/modules/inbound-call/inbound-call-config.model.ts +49 -0
  800. package/src/modules/inbound-call/inbound-call.routes.ts +289 -0
  801. package/src/modules/leads/lead.model.ts +40 -0
  802. package/src/modules/leads/lead.routes.ts +246 -0
  803. package/src/modules/logs/log.model.ts +27 -0
  804. package/src/modules/logs/log.routes.ts +102 -0
  805. package/src/modules/plans/plan.model.ts +45 -0
  806. package/src/modules/surveys/survey.model.ts +70 -0
  807. package/src/modules/surveys/survey.routes.ts +187 -0
  808. package/src/modules/tenants/tenant.model.ts +181 -0
  809. package/src/modules/tenants/tenant.routes.ts +78 -0
  810. package/src/modules/users/user.routes.ts +126 -0
  811. package/src/modules/webhooks/elevenlabs-tool.routes.ts +94 -0
  812. package/src/modules/webhooks/elevenlabs-tool.service.ts +491 -0
  813. package/src/modules/webhooks/elevenlabs.routes.ts +34 -0
  814. package/src/modules/webhooks/elevenlabs.service.ts +565 -0
  815. package/src/modules/webhooks/unipile.routes.ts +917 -0
  816. package/src/modules/whatsapp/appointment.model.ts +47 -0
  817. package/src/modules/whatsapp/operator-request.model.ts +58 -0
  818. package/src/modules/whatsapp/stt-usage.model.ts +30 -0
  819. package/src/modules/whatsapp/whatsapp-chat.model.ts +39 -0
  820. package/src/modules/whatsapp/whatsapp-contact-profile.model.ts +41 -0
  821. package/src/modules/whatsapp/whatsapp-message.model.ts +41 -0
  822. package/src/modules/whatsapp/whatsapp-session.model.ts +60 -0
  823. package/src/modules/whatsapp/whatsapp.routes.ts +1435 -0
  824. package/src/plugins/cors.ts +7 -0
  825. package/src/plugins/jwt.ts +18 -0
  826. package/src/plugins/rawBody.ts +12 -0
  827. package/src/plugins/rbac.ts +24 -0
  828. package/src/routes/admin.routes.ts +208 -0
  829. package/src/routes/health.routes.ts +12 -0
  830. package/src/routes/webhook.routes.ts +12 -0
  831. package/src/services/ai/base.ai.ts +132 -0
  832. package/src/services/ai/gemini.service.ts +41 -0
  833. package/src/services/ai/index.ts +24 -0
  834. package/src/services/ai/openai.service.ts +48 -0
  835. package/src/services/elevenlabs.service.ts +532 -0
  836. package/src/services/google-calendar.service.ts +656 -0
  837. package/src/services/inbound-call-schedule.service.ts +174 -0
  838. package/src/services/netgsm.service.ts +128 -0
  839. package/src/services/unipile.service.ts +200 -0
  840. package/src/services/whatsapp-agent.service.ts +2479 -0
  841. package/src/services/whatsapp.service.ts +245 -0
  842. package/src/templates/index.ts +71 -0
  843. package/src/templates/receptionist.ts +44 -0
  844. package/src/templates/survey.ts +44 -0
  845. package/src/types/index.ts +218 -0
  846. package/src/utils/logger.ts +83 -0
  847. package/tsconfig.json +19 -0
  848. package/web/.dockerignore +4 -0
  849. package/web/Dockerfile +18 -0
  850. package/web/README.md +73 -0
  851. package/web/components.json +23 -0
  852. package/web/eslint.config.js +23 -0
  853. package/web/index.html +14 -0
  854. package/web/nginx.conf +18 -0
  855. package/web/package-lock.json +10292 -0
  856. package/web/package.json +48 -0
  857. package/web/public/favicon.ico +0 -0
  858. package/web/public/vite.svg +1 -0
  859. package/web/src/App.tsx +191 -0
  860. package/web/src/assets/react.svg +1 -0
  861. package/web/src/components/Layout.tsx +261 -0
  862. package/web/src/components/LeadConversation.tsx +251 -0
  863. package/web/src/components/ProtectedRoute.tsx +20 -0
  864. package/web/src/components/conversation-review/CardAudioPlayer.tsx +200 -0
  865. package/web/src/components/conversation-review/CardEvaluation.tsx +351 -0
  866. package/web/src/components/conversation-review/CardMetadata.tsx +44 -0
  867. package/web/src/components/conversation-review/ConversationCard.tsx +95 -0
  868. package/web/src/components/conversation-review/ReviewContainer.tsx +120 -0
  869. package/web/src/components/conversation-review/ReviewFilters.tsx +88 -0
  870. package/web/src/components/empty-state.tsx +15 -0
  871. package/web/src/components/page-header.tsx +19 -0
  872. package/web/src/components/page-loader.tsx +32 -0
  873. package/web/src/components/pagination.tsx +38 -0
  874. package/web/src/components/stat-card.tsx +27 -0
  875. package/web/src/components/status-badge.tsx +125 -0
  876. package/web/src/components/ui/alert.tsx +66 -0
  877. package/web/src/components/ui/badge.tsx +48 -0
  878. package/web/src/components/ui/button.tsx +64 -0
  879. package/web/src/components/ui/card.tsx +92 -0
  880. package/web/src/components/ui/checkbox.tsx +32 -0
  881. package/web/src/components/ui/dialog.tsx +158 -0
  882. package/web/src/components/ui/dropdown-menu.tsx +255 -0
  883. package/web/src/components/ui/input.tsx +21 -0
  884. package/web/src/components/ui/label.tsx +22 -0
  885. package/web/src/components/ui/progress.tsx +29 -0
  886. package/web/src/components/ui/select.tsx +188 -0
  887. package/web/src/components/ui/separator.tsx +28 -0
  888. package/web/src/components/ui/sheet.tsx +123 -0
  889. package/web/src/components/ui/skeleton.tsx +13 -0
  890. package/web/src/components/ui/sonner.tsx +35 -0
  891. package/web/src/components/ui/table.tsx +116 -0
  892. package/web/src/components/ui/tabs.tsx +89 -0
  893. package/web/src/components/ui/textarea.tsx +18 -0
  894. package/web/src/components/ui/tooltip.tsx +57 -0
  895. package/web/src/components/whatsapp/ChatDetail.tsx +417 -0
  896. package/web/src/components/whatsapp/ChatHeader.tsx +78 -0
  897. package/web/src/components/whatsapp/ChatList.tsx +107 -0
  898. package/web/src/components/whatsapp/ChatListItem.tsx +60 -0
  899. package/web/src/components/whatsapp/MessageBubble.tsx +46 -0
  900. package/web/src/components/whatsapp/MessageInput.tsx +63 -0
  901. package/web/src/components/whatsapp/MessageStream.tsx +135 -0
  902. package/web/src/components/whatsapp/SessionDivider.tsx +65 -0
  903. package/web/src/components/whatsapp/SessionHistory.tsx +119 -0
  904. package/web/src/components/whatsapp/settings/AiSettingsTab.tsx +268 -0
  905. package/web/src/components/whatsapp/settings/CalendarTab.tsx +339 -0
  906. package/web/src/components/whatsapp/settings/ConnectionTab.tsx +236 -0
  907. package/web/src/components/whatsapp/settings/NotificationsTab.tsx +109 -0
  908. package/web/src/components/whatsapp/settings/OperatorTab.tsx +303 -0
  909. package/web/src/contexts/AuthContext.tsx +103 -0
  910. package/web/src/index.css +130 -0
  911. package/web/src/lib/api.ts +92 -0
  912. package/web/src/lib/utils.ts +6 -0
  913. package/web/src/main.tsx +10 -0
  914. package/web/src/pages/AppointmentDetail.tsx +206 -0
  915. package/web/src/pages/AppointmentValidation.tsx +157 -0
  916. package/web/src/pages/AppointmentValidationDetail.tsx +617 -0
  917. package/web/src/pages/AppointmentValidationNew.tsx +1005 -0
  918. package/web/src/pages/Appointments.tsx +283 -0
  919. package/web/src/pages/Billing.tsx +126 -0
  920. package/web/src/pages/CallDetail.tsx +293 -0
  921. package/web/src/pages/CallSettings.tsx +313 -0
  922. package/web/src/pages/Calls.tsx +188 -0
  923. package/web/src/pages/CampaignDetail.tsx +216 -0
  924. package/web/src/pages/CampaignNew.tsx +277 -0
  925. package/web/src/pages/CampaignResults.tsx +185 -0
  926. package/web/src/pages/Campaigns.tsx +171 -0
  927. package/web/src/pages/Dashboard.tsx +336 -0
  928. package/web/src/pages/InboundSchedule.tsx +246 -0
  929. package/web/src/pages/LeadDetail.tsx +183 -0
  930. package/web/src/pages/Leads.tsx +258 -0
  931. package/web/src/pages/Login.tsx +99 -0
  932. package/web/src/pages/Register.tsx +129 -0
  933. package/web/src/pages/Settings.tsx +133 -0
  934. package/web/src/pages/SurveyDetail.tsx +232 -0
  935. package/web/src/pages/SurveyPreview.tsx +179 -0
  936. package/web/src/pages/Surveys.tsx +207 -0
  937. package/web/src/pages/Users.tsx +199 -0
  938. package/web/src/pages/WhatsApp.tsx +147 -0
  939. package/web/src/pages/WhatsAppSettings.tsx +215 -0
  940. package/web/src/pages/admin/AdminBaileysMessageLog.tsx +331 -0
  941. package/web/src/pages/admin/AdminBaileysRawMessages.tsx +318 -0
  942. package/web/src/pages/admin/AdminConversationReview.tsx +116 -0
  943. package/web/src/pages/admin/AdminCredits.tsx +467 -0
  944. package/web/src/pages/admin/AdminElevenLabsAgentDetail.tsx +332 -0
  945. package/web/src/pages/admin/AdminElevenLabsAgents.tsx +164 -0
  946. package/web/src/pages/admin/AdminElevenLabsBatchCallDetail.tsx +214 -0
  947. package/web/src/pages/admin/AdminElevenLabsBatchCalls.tsx +293 -0
  948. package/web/src/pages/admin/AdminElevenLabsConversationDetail.tsx +230 -0
  949. package/web/src/pages/admin/AdminElevenLabsConversations.tsx +228 -0
  950. package/web/src/pages/admin/AdminElevenLabsInboundCalls.tsx +293 -0
  951. package/web/src/pages/admin/AdminElevenLabsPhoneNumbers.tsx +506 -0
  952. package/web/src/pages/admin/AdminElevenLabsTestChat.tsx +258 -0
  953. package/web/src/pages/admin/AdminElevenLabsWebhooks.tsx +289 -0
  954. package/web/src/pages/admin/AdminEvaluationDashboard.tsx +520 -0
  955. package/web/src/pages/admin/AdminLeads.tsx +339 -0
  956. package/web/src/pages/admin/AdminLogs.tsx +283 -0
  957. package/web/src/pages/admin/AdminMigrations.tsx +247 -0
  958. package/web/src/pages/admin/AdminPlans.tsx +313 -0
  959. package/web/src/pages/admin/AdminSystem.tsx +391 -0
  960. package/web/src/pages/admin/AdminTenantBillableItems.tsx +464 -0
  961. package/web/src/pages/admin/AdminTenantDetail.tsx +1317 -0
  962. package/web/src/pages/admin/AdminTenants.tsx +274 -0
  963. package/web/src/pages/admin/AdminWhatsApp.tsx +618 -0
  964. package/web/src/pages/admin/AdminWhatsAppTestChat.tsx +328 -0
  965. package/web/src/types/index.ts +242 -0
  966. package/web/tsconfig.app.json +32 -0
  967. package/web/tsconfig.json +13 -0
  968. package/web/tsconfig.node.json +26 -0
  969. package/web/vite.config.ts +23 -0
@@ -0,0 +1,1843 @@
1
+ // Portal Asistan 7/24 — Complete PostgreSQL Prisma Schema
2
+ // Source of truth: docs/architecture/01-DATABASE-SCHEMA.md
3
+ // 44 active tables (whatsapp_contact_profiles #19 and whatsapp_recipients #35 REMOVED)
4
+
5
+ generator client {
6
+ provider = "prisma-client-js"
7
+ }
8
+
9
+ datasource db {
10
+ provider = "postgresql"
11
+ }
12
+
13
+ // ─────────────────────────────────────────────
14
+ // ENUMS
15
+ // ─────────────────────────────────────────────
16
+
17
+ enum UserRole {
18
+ superadmin
19
+ sales
20
+ owner
21
+ admin
22
+ doctor
23
+ receptionist
24
+ }
25
+
26
+ enum PostCallStrategy {
27
+ summarize
28
+ none
29
+ }
30
+
31
+ enum CallDirection {
32
+ inbound
33
+ outbound
34
+ }
35
+
36
+ enum CallStatus {
37
+ completed
38
+ failed
39
+ no_answer
40
+ voicemail
41
+ transferred
42
+ }
43
+
44
+ enum Sentiment {
45
+ positive
46
+ neutral
47
+ negative
48
+ }
49
+
50
+ enum OutboundCampaignStatus {
51
+ draft
52
+ scheduled
53
+ running
54
+ paused
55
+ completed
56
+ }
57
+
58
+ enum CampaignEntryStatus {
59
+ pending
60
+ calling
61
+ completed
62
+ failed
63
+ no_answer
64
+ voicemail
65
+ }
66
+
67
+ enum SessionStatus {
68
+ waiting
69
+ active
70
+ resolved
71
+ }
72
+
73
+ enum SessionResolvedBy {
74
+ human
75
+ ai_timeout
76
+ timeout
77
+ manual
78
+ }
79
+
80
+ enum MessageSender {
81
+ contact
82
+ ai
83
+ human
84
+ system
85
+ }
86
+
87
+ enum OperatorRequestStatus {
88
+ pending
89
+ responded
90
+ expired
91
+ cancelled
92
+ }
93
+
94
+ enum AcmRole {
95
+ user
96
+ assistant
97
+ system
98
+ tool_result
99
+ }
100
+
101
+ enum LeadStatus {
102
+ new_lead
103
+ contacted
104
+ appointment_scheduled
105
+ completed
106
+ lost
107
+ expired
108
+ }
109
+
110
+ enum AppointmentStatus {
111
+ scheduled
112
+ confirmed
113
+ in_progress
114
+ completed
115
+ cancelled
116
+ no_show
117
+ }
118
+
119
+ enum AppointmentSource {
120
+ whatsapp
121
+ voice_call
122
+ dashboard
123
+ walk_in
124
+ }
125
+
126
+ enum AppointmentType {
127
+ appointment
128
+ walk_in
129
+ follow_up
130
+ consultation
131
+ }
132
+
133
+ enum BatchStatus {
134
+ draft
135
+ submitted
136
+ in_progress
137
+ completed
138
+ cancelled
139
+ }
140
+
141
+ enum EntryCallStatus {
142
+ pending
143
+ calling
144
+ completed
145
+ failed
146
+ no_answer
147
+ voicemail
148
+ }
149
+
150
+ enum ValidationResult {
151
+ confirmed
152
+ cancelled
153
+ reschedule
154
+ unresolved
155
+ }
156
+
157
+ enum BillingEventType {
158
+ call_charge
159
+ subscription
160
+ top_up
161
+ refund
162
+ }
163
+
164
+ enum PaymentType {
165
+ subscription
166
+ top_up
167
+ }
168
+
169
+ enum PaymentMethod {
170
+ cash
171
+ bank_transfer
172
+ other
173
+ }
174
+
175
+ enum AlertType {
176
+ usage_75
177
+ usage_90
178
+ usage_100
179
+ period_expiring
180
+ }
181
+
182
+ enum AlertService {
183
+ inbound_minutes
184
+ inbound_calls
185
+ wa_chats
186
+ billing_period
187
+ }
188
+
189
+ enum ChatChannel {
190
+ whatsapp
191
+ instagram
192
+ }
193
+
194
+ enum PhoneNumberPurpose {
195
+ whatsapp
196
+ inbound_call
197
+ outbound_call
198
+ }
199
+
200
+ enum PhoneNumberProvider {
201
+ meta_business
202
+ elevenlabs
203
+ }
204
+
205
+ enum MigrationStatus {
206
+ success
207
+ failed
208
+ }
209
+
210
+ enum NotificationDeliveryStatus {
211
+ pending
212
+ sending
213
+ sent
214
+ failed
215
+ }
216
+
217
+ enum TranscriptionProcessingStatus {
218
+ pending
219
+ summarizing
220
+ summarized
221
+ notified
222
+ failed
223
+ }
224
+
225
+ enum AvailabilityBlockType {
226
+ holiday
227
+ leave
228
+ break_time
229
+ other
230
+ }
231
+
232
+ enum TreatmentPlanStatus {
233
+ active
234
+ completed
235
+ cancelled
236
+ }
237
+
238
+ enum TreatmentPlanItemStatus {
239
+ planned
240
+ scheduled
241
+ in_progress
242
+ completed
243
+ cancelled
244
+ }
245
+
246
+ // ─────────────────────────────────────────────
247
+ // 1. TENANTS
248
+ // ─────────────────────────────────────────────
249
+
250
+ model Tenant {
251
+ tenant_id String @id @default(uuid())
252
+ tenant_name String
253
+ tenant_plan_id String?
254
+ tenant_enabled_features String[] @default([])
255
+ tenant_is_active Boolean @default(true)
256
+ tenant_deleted_at DateTime?
257
+ tenant_kvkk_consent Boolean @default(false)
258
+ tenant_max_clinics Int @default(1)
259
+ tenant_max_users Int @default(5)
260
+ tenant_max_doctors Int @default(2)
261
+ tenant_max_patients Int @default(500)
262
+ tenant_created_at DateTime @default(now())
263
+ tenant_updated_at DateTime @updatedAt
264
+
265
+ // Relations
266
+ plan Plan? @relation(fields: [tenant_plan_id], references: [plan_id])
267
+
268
+ clinics Clinic[]
269
+ users User[]
270
+ agents Agent[]
271
+ phone_numbers PhoneNumber[]
272
+ patients Patient[]
273
+ treatments Treatment[]
274
+ calls Call[]
275
+ leads Lead[]
276
+ outbound_campaigns OutboundCampaign[]
277
+ whatsapp_chats WhatsappChat[]
278
+ whatsapp_sessions WhatsappSession[]
279
+ whatsapp_messages WhatsappMessage[]
280
+ operator_requests OperatorRequest[]
281
+ appointments Appointment[]
282
+ appointment_validation_batches AppointmentValidationBatch[]
283
+ billing_events BillingEvent[]
284
+ payments Payment[]
285
+ billing_period_snapshots BillingPeriodSnapshot[]
286
+ billing_alerts BillingAlert[]
287
+ stt_usages SttUsage[]
288
+ treatment_plans TreatmentPlan[]
289
+ patient_documents PatientDocument[]
290
+ patient_notes PatientNote[]
291
+ patient_photo_sets PatientPhotoSet[]
292
+ examination_records ExaminationRecord[]
293
+ availability_blocks AvailabilityBlock[]
294
+
295
+ @@index([tenant_plan_id], name: "idx_tenants_plan")
296
+ @@map("tenants")
297
+ }
298
+
299
+ // ─────────────────────────────────────────────
300
+ // 2. CLINICS
301
+ // ─────────────────────────────────────────────
302
+
303
+ model Clinic {
304
+ clinic_id String @id @default(uuid())
305
+ clinic_tenant_id String
306
+ clinic_name String
307
+ clinic_slug String
308
+ clinic_address String @default("")
309
+ clinic_phone String @default("")
310
+ clinic_email String @default("")
311
+ clinic_timezone String @default("Europe/Istanbul")
312
+ clinic_is_default Boolean @default(false)
313
+ clinic_is_active Boolean @default(true)
314
+ clinic_language String @default("tr")
315
+ clinic_ai_provider String @default("openai")
316
+ clinic_ai_model String @default("")
317
+ clinic_grace_period_seconds Int @default(180)
318
+ clinic_operator_phone String?
319
+ clinic_operator_prefix String @default("R")
320
+ clinic_operator_timeout_hours Int @default(24)
321
+ clinic_ai_shift_enabled Boolean @default(false)
322
+ clinic_ai_shift_schedule Json @default("[]")
323
+ clinic_blacklisted_numbers String[] @default([])
324
+ clinic_fixed_first_message String?
325
+ clinic_sms_enabled Boolean @default(false)
326
+ clinic_sms_phones String[] @default([])
327
+ clinic_notification_phones String[] @default([])
328
+ clinic_message_retention_days Int @default(7)
329
+ clinic_created_at DateTime @default(now())
330
+ clinic_updated_at DateTime @updatedAt
331
+
332
+ // Relations
333
+ tenant Tenant @relation(fields: [clinic_tenant_id], references: [tenant_id], onDelete: Cascade)
334
+
335
+ user_clinic_assignments UserClinicAssignment[]
336
+ calendar_connection ClinicCalendarConnection?
337
+ meta_connections ClinicMetaConnection[]
338
+ agents Agent[]
339
+ agent_assignments AgentClinicAssignment[]
340
+ phone_numbers PhoneNumber[]
341
+ patients Patient[]
342
+ treatments Treatment[]
343
+ calls Call[]
344
+ leads Lead[]
345
+ outbound_campaigns OutboundCampaign[]
346
+ whatsapp_chats WhatsappChat[]
347
+ whatsapp_sessions WhatsappSession[]
348
+ operator_requests OperatorRequest[]
349
+ appointments Appointment[]
350
+ appointment_validation_batches AppointmentValidationBatch[]
351
+ billing_events BillingEvent[]
352
+ stt_usages SttUsage[]
353
+ treatment_plans TreatmentPlan[]
354
+ patient_documents PatientDocument[]
355
+ patient_notes PatientNote[]
356
+ patient_photo_sets PatientPhotoSet[]
357
+ examination_records ExaminationRecord[]
358
+ availability_blocks AvailabilityBlock[]
359
+
360
+ @@unique([clinic_tenant_id, clinic_slug])
361
+ @@index([clinic_tenant_id], name: "idx_clinics_tenant")
362
+ @@index([clinic_tenant_id, clinic_operator_phone], name: "idx_clinics_operator")
363
+ @@map("clinics")
364
+ }
365
+
366
+ // ─────────────────────────────────────────────
367
+ // 3. CLINIC CALENDAR CONNECTIONS
368
+ // ─────────────────────────────────────────────
369
+
370
+ model ClinicCalendarConnection {
371
+ calcn_id String @id @default(uuid())
372
+ calcn_clinic_id String @unique
373
+ calcn_google_email String?
374
+ calcn_encrypted_refresh_token String?
375
+ calcn_calendar_id String?
376
+ calcn_calendar_name String?
377
+ calcn_appointment_duration Int @default(30)
378
+ calcn_working_hours Json @default("[]")
379
+ calcn_blocked_dates Json @default("[]")
380
+ calcn_connected_at DateTime?
381
+ calcn_created_at DateTime @default(now())
382
+ calcn_updated_at DateTime @updatedAt
383
+
384
+ // Relations
385
+ clinic Clinic @relation(fields: [calcn_clinic_id], references: [clinic_id], onDelete: Cascade)
386
+
387
+ @@map("clinic_calendar_connections")
388
+ }
389
+
390
+ // ─────────────────────────────────────────────
391
+ // 4. CLINIC META CONNECTIONS
392
+ // ─────────────────────────────────────────────
393
+
394
+ model ClinicMetaConnection {
395
+ meta_id String @id @default(uuid())
396
+ meta_clinic_id String
397
+ meta_type String
398
+ meta_label String @default("")
399
+ meta_waba_id String?
400
+ meta_phone_number_id String?
401
+ meta_display_phone String?
402
+ meta_instagram_page_id String? // Instagram Business Account ID
403
+ meta_facebook_page_id String? // Facebook Page ID (used for IG messaging API)
404
+ meta_encrypted_access_token String?
405
+ meta_token_expires_at DateTime?
406
+ meta_token_refreshed_at DateTime?
407
+ meta_is_active Boolean @default(true)
408
+ meta_connected_at DateTime?
409
+ meta_created_at DateTime @default(now())
410
+ meta_updated_at DateTime @updatedAt
411
+
412
+ // Relations
413
+ clinic Clinic @relation(fields: [meta_clinic_id], references: [clinic_id], onDelete: Cascade)
414
+
415
+ @@index([meta_clinic_id], name: "idx_meta_clinic")
416
+ @@index([meta_clinic_id, meta_type], name: "idx_meta_clinic_type")
417
+ @@index([meta_phone_number_id], name: "idx_meta_phone_number")
418
+ @@index([meta_instagram_page_id], name: "idx_meta_instagram_page")
419
+ @@map("clinic_meta_connections")
420
+ }
421
+
422
+ // ─────────────────────────────────────────────
423
+ // 5. PHONE NUMBERS
424
+ // ─────────────────────────────────────────────
425
+
426
+ model PhoneNumber {
427
+ phone_id String @id @default(uuid())
428
+ phone_tenant_id String
429
+ phone_clinic_id String?
430
+ phone_number String
431
+ phone_label String @default("")
432
+ phone_purpose PhoneNumberPurpose
433
+ phone_provider PhoneNumberProvider
434
+ phone_external_account_id String?
435
+ phone_elevenlabs_phone_id String?
436
+ phone_elevenlabs_agent_id String?
437
+ phone_agent_id String?
438
+ phone_wa_connected Boolean @default(false)
439
+ phone_wa_connected_at DateTime?
440
+ phone_wa_bridge_provider String?
441
+ phone_schedule_enabled Boolean @default(false)
442
+ phone_schedule_mode String @default("active_hours")
443
+ phone_schedule Json @default("[]")
444
+ phone_agent_assigned Boolean @default(false)
445
+ phone_is_active Boolean @default(true)
446
+ phone_created_at DateTime @default(now())
447
+ phone_updated_at DateTime @updatedAt
448
+
449
+ // Relations
450
+ tenant Tenant @relation(fields: [phone_tenant_id], references: [tenant_id], onDelete: Cascade)
451
+ clinic Clinic? @relation(fields: [phone_clinic_id], references: [clinic_id])
452
+ agent Agent? @relation(fields: [phone_agent_id], references: [agent_id])
453
+
454
+ whatsapp_chats WhatsappChat[]
455
+ outbound_campaigns OutboundCampaign[]
456
+ appointment_validation_batches AppointmentValidationBatch[]
457
+
458
+ @@unique([phone_tenant_id, phone_number, phone_purpose])
459
+ @@index([phone_tenant_id, phone_purpose], name: "idx_phones_tenant_purpose")
460
+ @@index([phone_clinic_id], name: "idx_phones_clinic")
461
+ @@index([phone_provider, phone_external_account_id], name: "idx_phones_provider_external")
462
+ @@map("phone_numbers")
463
+ }
464
+
465
+ // ─────────────────────────────────────────────
466
+ // 6. USERS
467
+ // ─────────────────────────────────────────────
468
+
469
+ model User {
470
+ user_id String @id @default(uuid())
471
+ user_tenant_id String?
472
+ user_email String @unique
473
+ user_password_hash String
474
+ user_role UserRole @default(receptionist)
475
+ user_first_name String
476
+ user_last_name String
477
+ user_phone String?
478
+ user_is_active Boolean @default(true)
479
+ user_custom_permissions Json @default("[]")
480
+ user_last_login_at DateTime?
481
+ user_created_at DateTime @default(now())
482
+ user_updated_at DateTime @updatedAt
483
+
484
+ // Relations
485
+ tenant Tenant? @relation(fields: [user_tenant_id], references: [tenant_id], onDelete: Cascade)
486
+
487
+ doctor_profile DoctorProfile?
488
+ clinic_assignments UserClinicAssignment[]
489
+ refresh_tokens RefreshToken[]
490
+ whatsapp_messages WhatsappMessage[]
491
+ sessions_taken_over WhatsappSession[] @relation("TakenOverBy")
492
+ chats_assigned_to WhatsappChat[] @relation("ChatAssignedTo")
493
+ chats_assigned_by WhatsappChat[] @relation("ChatAssignedBy")
494
+ availability_blocks AvailabilityBlock[] @relation("BlockDoctor")
495
+ blocks_created AvailabilityBlock[] @relation("BlockCreatedBy")
496
+ payments_recorded Payment[] @relation("RecordedBy")
497
+ batches_created AppointmentValidationBatch[] @relation("CreatedBy")
498
+ treatment_plans_as_doctor TreatmentPlan[] @relation("PlanDoctor")
499
+ patient_notes_authored PatientNote[] @relation("NoteAuthor")
500
+ patient_documents_uploaded PatientDocument[] @relation("DocUploader")
501
+ patient_photo_sets_taken PatientPhotoSet[] @relation("PhotoTaker")
502
+ examination_records ExaminationRecord[] @relation("ExamDoctor")
503
+ appointments_as_doctor Appointment[] @relation("AppointmentDoctor")
504
+ prompt_versions_changed AgentPromptVersion[]
505
+ admin_chat_sessions AdminChatSession[]
506
+
507
+ @@index([user_tenant_id], name: "idx_users_tenant")
508
+ @@map("users")
509
+ }
510
+
511
+ // ─────────────────────────────────────────────
512
+ // 7. USER CLINIC ASSIGNMENTS
513
+ // ─────────────────────────────────────────────
514
+
515
+ model UserClinicAssignment {
516
+ assign_id String @id @default(uuid())
517
+ assign_user_id String
518
+ assign_clinic_id String
519
+ assign_created_at DateTime @default(now())
520
+
521
+ // Relations
522
+ user User @relation(fields: [assign_user_id], references: [user_id], onDelete: Cascade)
523
+ clinic Clinic @relation(fields: [assign_clinic_id], references: [clinic_id], onDelete: Cascade)
524
+
525
+ @@unique([assign_user_id, assign_clinic_id])
526
+ @@index([assign_user_id], name: "idx_assign_user")
527
+ @@index([assign_clinic_id], name: "idx_assign_clinic")
528
+ @@map("user_clinic_assignments")
529
+ }
530
+
531
+ // ─────────────────────────────────────────────
532
+ // 8. REFRESH TOKENS
533
+ // ─────────────────────────────────────────────
534
+
535
+ model RefreshToken {
536
+ token_id String @id @default(uuid())
537
+ token_user_id String
538
+ token_value String @unique
539
+ token_expires_at DateTime
540
+ token_created_at DateTime @default(now())
541
+
542
+ // Relations
543
+ user User @relation(fields: [token_user_id], references: [user_id], onDelete: Cascade)
544
+
545
+ @@index([token_user_id], name: "idx_tokens_user")
546
+ @@index([token_expires_at], name: "idx_tokens_expires")
547
+ @@map("refresh_tokens")
548
+ }
549
+
550
+ // ─────────────────────────────────────────────
551
+ // 9. PLANS
552
+ // ─────────────────────────────────────────────
553
+
554
+ model Plan {
555
+ plan_id String @id @default(uuid())
556
+ plan_name String
557
+ plan_slug String @unique
558
+ plan_price Decimal
559
+ plan_overage_rate Decimal
560
+ plan_included_inbound_minutes Int @default(0)
561
+ plan_included_inbound_calls Int @default(0)
562
+ plan_included_outbound_minutes Int @default(0)
563
+ plan_included_outbound_calls Int @default(0)
564
+ plan_included_wa_chats Int @default(0)
565
+ plan_is_active Boolean @default(true)
566
+ plan_sort_order Int @default(0)
567
+ plan_created_at DateTime @default(now())
568
+ plan_updated_at DateTime @updatedAt
569
+
570
+ // Relations
571
+ tenants Tenant[]
572
+ billing_period_snapshots BillingPeriodSnapshot[]
573
+
574
+ @@map("plans")
575
+ }
576
+
577
+ // ─────────────────────────────────────────────
578
+ // 10. AGENTS
579
+ // ─────────────────────────────────────────────
580
+
581
+ model Agent {
582
+ agent_id String @id @default(uuid())
583
+ agent_tenant_id String?
584
+ agent_clinic_id String?
585
+ agent_elevenlabs_id String @default("")
586
+ agent_name String @default("")
587
+ agent_description String @default("")
588
+ agent_voice_id String @default("")
589
+ agent_language String @default("tr")
590
+ agent_greeting String @default("")
591
+ agent_system_prompt String @default("")
592
+ agent_ai_provider String? // "elevenlabs" | "anthropic" | "openai"
593
+ agent_ai_model String? // provider-specific model ID
594
+ agent_temperature Float @default(0.3)
595
+ agent_max_tokens Int @default(4096)
596
+ agent_post_call_strategy PostCallStrategy @default(summarize)
597
+ agent_post_call_wa_notify Boolean @default(true)
598
+ agent_post_call_sms_notify Boolean @default(false)
599
+ agent_summary_prompt String @default("")
600
+ agent_wa_message_template String @default("")
601
+ agent_enabled_tools String[] @default([]) // explicit tool whitelist (empty = all available)
602
+ agent_tags String[] @default([]) // free-form tags: ["receptionist", "sales", "appointment"]
603
+ agent_channels String[] @default([]) // channels: ["whatsapp", "instagram", "voice"] (empty = all)
604
+ agent_status String @default("draft") // "draft" | "testing" | "production" | "archived"
605
+ agent_metadata Json @default("{}") // free-form key-value pairs
606
+ agent_extra_config Json @default("{}")
607
+ agent_el_synced_at DateTime? // last ElevenLabs sync timestamp
608
+ agent_el_sync_error String? // last sync error message
609
+ agent_is_active Boolean @default(true)
610
+ agent_created_at DateTime @default(now())
611
+ agent_updated_at DateTime @updatedAt
612
+
613
+ // Relations
614
+ tenant Tenant? @relation(fields: [agent_tenant_id], references: [tenant_id], onDelete: Cascade)
615
+ clinic Clinic? @relation(fields: [agent_clinic_id], references: [clinic_id])
616
+ clinic_assignments AgentClinicAssignment[]
617
+ prompt_versions AgentPromptVersion[]
618
+
619
+ phone_numbers PhoneNumber[]
620
+ calls Call[]
621
+ outbound_campaigns OutboundCampaign[]
622
+ appointment_validation_batches AppointmentValidationBatch[]
623
+
624
+ @@index([agent_tenant_id], name: "idx_agents_tenant")
625
+ @@index([agent_clinic_id], name: "idx_agents_clinic")
626
+ @@index([agent_elevenlabs_id], name: "idx_agents_elevenlabs")
627
+ @@map("agents")
628
+ }
629
+
630
+ model AgentClinicAssignment {
631
+ aca_id String @id @default(uuid())
632
+ aca_agent_id String
633
+ aca_clinic_id String
634
+ aca_created_at DateTime @default(now())
635
+
636
+ agent Agent @relation(fields: [aca_agent_id], references: [agent_id], onDelete: Cascade)
637
+ clinic Clinic @relation(fields: [aca_clinic_id], references: [clinic_id], onDelete: Cascade)
638
+
639
+ @@unique([aca_agent_id, aca_clinic_id])
640
+ @@index([aca_clinic_id], name: "idx_aca_clinic")
641
+ @@map("agent_clinic_assignments")
642
+ }
643
+
644
+ model AgentPromptVersion {
645
+ pv_id String @id @default(uuid())
646
+ pv_agent_id String
647
+ pv_version Int
648
+ pv_prompt String // the full system prompt at this version
649
+ pv_change_note String @default("") // what changed and why
650
+ pv_changed_by String? // user ID who made the change
651
+ pv_created_at DateTime @default(now())
652
+
653
+ // Relations
654
+ agent Agent @relation(fields: [pv_agent_id], references: [agent_id], onDelete: Cascade)
655
+ changed_by User? @relation(fields: [pv_changed_by], references: [user_id])
656
+
657
+ @@unique([pv_agent_id, pv_version])
658
+ @@index([pv_agent_id, pv_created_at(sort: Desc)], name: "idx_prompt_versions_agent")
659
+ @@map("agent_prompt_versions")
660
+ }
661
+
662
+ // ─────────────────────────────────────────────
663
+ // 11. CALLS
664
+ // ─────────────────────────────────────────────
665
+
666
+ model Call {
667
+ call_id String @id @default(uuid())
668
+ call_tenant_id String
669
+ call_clinic_id String
670
+ call_patient_id String?
671
+ call_agent_id String
672
+ call_campaign_id String?
673
+ call_conversation_id String?
674
+ call_direction CallDirection
675
+ call_caller_number String
676
+ call_callee_number String
677
+ call_duration_seconds Int @default(0)
678
+ call_start_time DateTime?
679
+ call_end_time DateTime?
680
+ call_termination_reason String?
681
+ call_cost Decimal?
682
+ call_language String?
683
+ call_elevenlabs_status String?
684
+ call_status CallStatus
685
+ call_sentiment Sentiment?
686
+ call_categories String[] @default([])
687
+ call_wa_notification_sent Boolean @default(false)
688
+ call_created_at DateTime @default(now())
689
+ call_updated_at DateTime @updatedAt
690
+
691
+ // Relations
692
+ tenant Tenant @relation(fields: [call_tenant_id], references: [tenant_id], onDelete: Cascade)
693
+ clinic Clinic @relation(fields: [call_clinic_id], references: [clinic_id])
694
+ patient Patient? @relation(fields: [call_patient_id], references: [patient_id])
695
+ agent Agent @relation(fields: [call_agent_id], references: [agent_id])
696
+ campaign OutboundCampaign? @relation(fields: [call_campaign_id], references: [campaign_id])
697
+
698
+ call_detail CallDetail?
699
+ billing_events BillingEvent[]
700
+ leads Lead[]
701
+ outbound_campaign_entries OutboundCampaignEntry[]
702
+
703
+ @@index([call_tenant_id, call_created_at(sort: Desc)], name: "idx_calls_tenant_date")
704
+ @@index([call_clinic_id, call_created_at(sort: Desc)], name: "idx_calls_clinic_date")
705
+ @@index([call_campaign_id, call_status], name: "idx_calls_campaign_status")
706
+ @@index([call_tenant_id, call_direction, call_created_at(sort: Desc)], name: "idx_calls_tenant_direction_date")
707
+ @@index([call_conversation_id], name: "idx_calls_conversation")
708
+ @@index([call_tenant_id, call_callee_number], name: "idx_calls_tenant_callee")
709
+ @@index([call_patient_id, call_created_at(sort: Desc)], name: "idx_calls_patient_date")
710
+ @@map("calls")
711
+ }
712
+
713
+ // ─────────────────────────────────────────────
714
+ // 12. CALL DETAILS
715
+ // ─────────────────────────────────────────────
716
+
717
+ model CallDetail {
718
+ detail_id String @id @default(uuid())
719
+ detail_call_id String @unique
720
+ detail_transcript String @default("")
721
+ detail_llm_summary String?
722
+ detail_extracted_data Json?
723
+ detail_recording_url String?
724
+ detail_recording_key String?
725
+ detail_analysis Json?
726
+ detail_created_at DateTime @default(now())
727
+ detail_updated_at DateTime @updatedAt
728
+
729
+ // Relations
730
+ call Call @relation(fields: [detail_call_id], references: [call_id], onDelete: Cascade)
731
+
732
+ @@map("call_details")
733
+ }
734
+
735
+ // ─────────────────────────────────────────────
736
+ // 13. LEADS
737
+ // ─────────────────────────────────────────────
738
+
739
+ model Lead {
740
+ lead_id String @id @default(uuid())
741
+ lead_tenant_id String
742
+ lead_clinic_id String
743
+ lead_patient_id String?
744
+ lead_call_id String?
745
+ lead_session_id String?
746
+ lead_chat_id String?
747
+ lead_name String?
748
+ lead_phone String
749
+ lead_service_of_interest String?
750
+ lead_status LeadStatus @default(new_lead)
751
+ lead_categories String[] @default([])
752
+ lead_summary String?
753
+ lead_created_at DateTime @default(now())
754
+ lead_updated_at DateTime @updatedAt
755
+
756
+ // Relations
757
+ tenant Tenant @relation(fields: [lead_tenant_id], references: [tenant_id], onDelete: Cascade)
758
+ clinic Clinic @relation(fields: [lead_clinic_id], references: [clinic_id])
759
+ patient Patient? @relation(fields: [lead_patient_id], references: [patient_id])
760
+ call Call? @relation(fields: [lead_call_id], references: [call_id])
761
+ session WhatsappSession? @relation(fields: [lead_session_id], references: [session_id])
762
+ chat WhatsappChat? @relation(fields: [lead_chat_id], references: [chat_id])
763
+
764
+ @@index([lead_tenant_id, lead_created_at(sort: Desc)], name: "idx_leads_tenant_date")
765
+ @@index([lead_tenant_id, lead_status], name: "idx_leads_tenant_status")
766
+ @@index([lead_call_id], name: "idx_leads_call")
767
+ @@index([lead_session_id], name: "idx_leads_session")
768
+ @@index([lead_patient_id], name: "idx_leads_patient")
769
+ @@map("leads")
770
+ }
771
+
772
+ // ─────────────────────────────────────────────
773
+ // 14. OUTBOUND CAMPAIGNS
774
+ // ─────────────────────────────────────────────
775
+
776
+ model OutboundCampaign {
777
+ campaign_id String @id @default(uuid())
778
+ campaign_tenant_id String
779
+ campaign_clinic_id String
780
+ campaign_agent_id String
781
+ campaign_name String
782
+ campaign_description String @default("")
783
+ campaign_status OutboundCampaignStatus @default(draft)
784
+ campaign_agent_config Json @default("{}")
785
+ campaign_schedule Json
786
+ campaign_phone_id String?
787
+ campaign_stats Json @default("{}")
788
+ campaign_created_at DateTime @default(now())
789
+ campaign_updated_at DateTime @updatedAt
790
+
791
+ // Relations
792
+ tenant Tenant @relation(fields: [campaign_tenant_id], references: [tenant_id], onDelete: Cascade)
793
+ clinic Clinic @relation(fields: [campaign_clinic_id], references: [clinic_id])
794
+ agent Agent @relation(fields: [campaign_agent_id], references: [agent_id])
795
+ phone PhoneNumber? @relation(fields: [campaign_phone_id], references: [phone_id])
796
+
797
+ entries OutboundCampaignEntry[]
798
+ calls Call[]
799
+
800
+ @@index([campaign_tenant_id, campaign_status], name: "idx_campaigns_tenant_status")
801
+ @@index([campaign_clinic_id], name: "idx_campaigns_clinic")
802
+ @@map("outbound_campaigns")
803
+ }
804
+
805
+ // ─────────────────────────────────────────────
806
+ // 15. OUTBOUND CAMPAIGN ENTRIES
807
+ // ─────────────────────────────────────────────
808
+
809
+ model OutboundCampaignEntry {
810
+ centry_id String @id @default(uuid())
811
+ centry_campaign_id String
812
+ centry_phone String
813
+ centry_contact_name String @default("")
814
+ centry_custom_data Json @default("{}")
815
+ centry_status CampaignEntryStatus @default(pending)
816
+ centry_attempts Int @default(0)
817
+ centry_max_attempts Int @default(3)
818
+ centry_last_attempt_at DateTime?
819
+ centry_conversation_id String?
820
+ centry_call_id String?
821
+ centry_call_duration_secs Int @default(0)
822
+ centry_extracted_data Json?
823
+ centry_summary String?
824
+ centry_called_at DateTime?
825
+ centry_completed_at DateTime?
826
+ centry_created_at DateTime @default(now())
827
+ centry_updated_at DateTime @updatedAt
828
+
829
+ // Relations
830
+ campaign OutboundCampaign @relation(fields: [centry_campaign_id], references: [campaign_id], onDelete: Cascade)
831
+ call Call? @relation(fields: [centry_call_id], references: [call_id])
832
+
833
+ @@index([centry_campaign_id, centry_status], name: "idx_centries_campaign_status")
834
+ @@index([centry_conversation_id], name: "idx_centries_conversation")
835
+ @@map("outbound_campaign_entries")
836
+ }
837
+
838
+ // ─────────────────────────────────────────────
839
+ // 16. WHATSAPP CHATS
840
+ // ─────────────────────────────────────────────
841
+
842
+ model WhatsappChat {
843
+ chat_id String @id @default(uuid())
844
+ chat_tenant_id String
845
+ chat_clinic_id String
846
+ chat_patient_id String?
847
+ chat_channel ChatChannel @default(whatsapp)
848
+ chat_external_id String
849
+ chat_phone_id String?
850
+ chat_contact_name String @default("Bilinmiyor")
851
+ chat_contact_phone String @default("")
852
+ chat_is_closed Boolean @default(false)
853
+ chat_active_session_id String?
854
+ chat_last_message_at DateTime @default(now())
855
+ chat_last_message_preview String @default("")
856
+ chat_message_count Int @default(0)
857
+ chat_assigned_to_id String?
858
+ chat_assigned_by_id String?
859
+ chat_assigned_at DateTime?
860
+ chat_deleted_at DateTime?
861
+ chat_created_at DateTime @default(now())
862
+ chat_updated_at DateTime @updatedAt
863
+
864
+ // Relations
865
+ tenant Tenant @relation(fields: [chat_tenant_id], references: [tenant_id], onDelete: Cascade)
866
+ clinic Clinic @relation(fields: [chat_clinic_id], references: [clinic_id])
867
+ patient Patient? @relation(fields: [chat_patient_id], references: [patient_id])
868
+ phone PhoneNumber? @relation(fields: [chat_phone_id], references: [phone_id])
869
+ assigned_to User? @relation("ChatAssignedTo", fields: [chat_assigned_to_id], references: [user_id])
870
+ assigned_by User? @relation("ChatAssignedBy", fields: [chat_assigned_by_id], references: [user_id])
871
+
872
+ sessions WhatsappSession[]
873
+ messages WhatsappMessage[]
874
+ operator_requests OperatorRequest[]
875
+ appointments Appointment[]
876
+ leads Lead[]
877
+
878
+ @@unique([chat_tenant_id, chat_external_id])
879
+ @@index([chat_tenant_id, chat_clinic_id], name: "idx_chats_tenant_clinic")
880
+ @@index([chat_tenant_id, chat_last_message_at(sort: Desc)], name: "idx_chats_tenant_lastmsg")
881
+ @@index([chat_tenant_id, chat_contact_phone], name: "idx_chats_tenant_phone")
882
+ @@map("whatsapp_chats")
883
+ }
884
+
885
+ // ─────────────────────────────────────────────
886
+ // 17. WHATSAPP SESSIONS
887
+ // ─────────────────────────────────────────────
888
+
889
+ model WhatsappSession {
890
+ session_id String @id @default(uuid())
891
+ session_chat_id String
892
+ session_tenant_id String
893
+ session_clinic_id String
894
+ session_status SessionStatus @default(waiting)
895
+ session_resolved_by SessionResolvedBy?
896
+ session_started_at DateTime @default(now())
897
+ session_resolved_at DateTime?
898
+ session_grace_deadline DateTime?
899
+ session_taken_over_by_id String?
900
+ session_taken_over_at DateTime?
901
+ session_el_conversation_id String?
902
+ session_el_prev_conversation_ids String[] @default([])
903
+ session_el_conversation_created DateTime?
904
+ session_el_last_interaction DateTime?
905
+ session_el_cost Decimal?
906
+ session_ref_code String?
907
+ session_awaiting_operator Boolean @default(false)
908
+ session_message_count Int @default(0)
909
+ session_llm_summary String?
910
+ session_sentiment Sentiment?
911
+ session_categories String[] @default([])
912
+ session_created_at DateTime @default(now())
913
+ session_updated_at DateTime @updatedAt
914
+
915
+ // Relations
916
+ tenant Tenant @relation(fields: [session_tenant_id], references: [tenant_id], onDelete: Cascade)
917
+ clinic Clinic @relation(fields: [session_clinic_id], references: [clinic_id])
918
+ chat WhatsappChat @relation(fields: [session_chat_id], references: [chat_id], onDelete: Cascade)
919
+ taken_over_by User? @relation("TakenOverBy", fields: [session_taken_over_by_id], references: [user_id])
920
+
921
+ messages WhatsappMessage[]
922
+ operator_requests OperatorRequest[]
923
+ appointments Appointment[]
924
+ leads Lead[]
925
+
926
+ @@index([session_chat_id, session_status], name: "idx_sessions_chat_status")
927
+ @@index([session_status, session_grace_deadline], name: "idx_sessions_status_grace")
928
+ @@index([session_tenant_id, session_status], name: "idx_sessions_tenant_status")
929
+ @@index([session_clinic_id, session_status], name: "idx_sessions_clinic_status")
930
+ @@index([session_status, session_updated_at], name: "idx_sessions_status_updated")
931
+ @@index([session_ref_code, session_tenant_id], name: "idx_sessions_ref_tenant")
932
+ @@map("whatsapp_sessions")
933
+ }
934
+
935
+ // ─────────────────────────────────────────────
936
+ // 18. WHATSAPP MESSAGES
937
+ // ─────────────────────────────────────────────
938
+
939
+ model WhatsappMessage {
940
+ msg_id String @id @default(uuid())
941
+ msg_chat_id String
942
+ msg_session_id String?
943
+ msg_tenant_id String
944
+ msg_external_id String?
945
+ msg_sender MessageSender
946
+ msg_sender_name String @default("")
947
+ msg_sender_user_id String?
948
+ msg_text String
949
+ msg_media_type String?
950
+ msg_media_key String?
951
+ msg_media_url String?
952
+ msg_media_mime String?
953
+ msg_media_filename String?
954
+ msg_ad_context Json?
955
+ msg_metadata Json? // Structured data: location, contacts, reaction, button reply, etc.
956
+ msg_sent_via_bridge Boolean @default(false)
957
+ msg_quoted_text String?
958
+ msg_created_at DateTime @default(now())
959
+
960
+ // Relations
961
+ tenant Tenant @relation(fields: [msg_tenant_id], references: [tenant_id], onDelete: Cascade)
962
+ chat WhatsappChat @relation(fields: [msg_chat_id], references: [chat_id], onDelete: Cascade)
963
+ session WhatsappSession? @relation(fields: [msg_session_id], references: [session_id])
964
+ sender_user User? @relation(fields: [msg_sender_user_id], references: [user_id])
965
+
966
+ @@index([msg_chat_id, msg_created_at], name: "idx_msgs_chat_date")
967
+ @@index([msg_session_id, msg_created_at], name: "idx_msgs_session_date")
968
+ @@index([msg_tenant_id, msg_created_at(sort: Desc)], name: "idx_msgs_tenant_date")
969
+ @@map("whatsapp_messages")
970
+ }
971
+
972
+ // ─────────────────────────────────────────────
973
+ // 20. OPERATOR REQUESTS
974
+ // ─────────────────────────────────────────────
975
+
976
+ model OperatorRequest {
977
+ opreq_id String @id @default(uuid())
978
+ opreq_tenant_id String
979
+ opreq_clinic_id String
980
+ opreq_session_id String
981
+ opreq_chat_id String
982
+ opreq_ref_code String
983
+ opreq_request_type String @default("general")
984
+ opreq_request_message String?
985
+ opreq_status OperatorRequestStatus @default(pending)
986
+ opreq_forwarded_media_types String[] @default([])
987
+ opreq_forwarded_count Int @default(0)
988
+ opreq_failed_count Int @default(0)
989
+ opreq_forwarded_at DateTime @default(now())
990
+ opreq_forwarded_to_phone String
991
+ opreq_operator_response String?
992
+ opreq_response_media_type String?
993
+ opreq_response_message_id String?
994
+ opreq_responded_at DateTime?
995
+ opreq_patient_message_ids String[] @default([])
996
+ opreq_expires_at DateTime
997
+ opreq_created_at DateTime @default(now())
998
+ opreq_updated_at DateTime @updatedAt
999
+
1000
+ // Relations
1001
+ tenant Tenant @relation(fields: [opreq_tenant_id], references: [tenant_id], onDelete: Cascade)
1002
+ clinic Clinic @relation(fields: [opreq_clinic_id], references: [clinic_id])
1003
+ session WhatsappSession @relation(fields: [opreq_session_id], references: [session_id])
1004
+ chat WhatsappChat @relation(fields: [opreq_chat_id], references: [chat_id])
1005
+
1006
+ @@unique([opreq_tenant_id, opreq_ref_code])
1007
+ @@index([opreq_session_id, opreq_status], name: "idx_opreqs_session_status")
1008
+ @@index([opreq_status, opreq_expires_at], name: "idx_opreqs_status_expires")
1009
+ @@map("operator_requests")
1010
+ }
1011
+
1012
+ // ─────────────────────────────────────────────
1013
+ // 21. APPOINTMENTS
1014
+ // ─────────────────────────────────────────────
1015
+
1016
+ model Appointment {
1017
+ appt_id String @id @default(uuid())
1018
+ appt_tenant_id String
1019
+ appt_clinic_id String
1020
+ appt_patient_id String
1021
+ appt_doctor_id String?
1022
+ appt_treatment_id String?
1023
+ appt_treatment_plan_item_id String?
1024
+ appt_chat_id String?
1025
+ appt_session_id String?
1026
+ appt_google_event_id String?
1027
+ appt_patient_name String
1028
+ appt_patient_phone String
1029
+ appt_start_time DateTime
1030
+ appt_end_time DateTime
1031
+ appt_duration_minutes Int
1032
+ appt_type AppointmentType @default(appointment)
1033
+ appt_status AppointmentStatus @default(scheduled)
1034
+ appt_source AppointmentSource @default(dashboard)
1035
+ appt_notes String @default("")
1036
+ appt_conversation_id String?
1037
+ appt_reminder_sent_24h Boolean @default(false)
1038
+ appt_reminder_sent_2h Boolean @default(false)
1039
+ appt_cancelled_at DateTime?
1040
+ appt_completed_at DateTime?
1041
+ appt_created_at DateTime @default(now())
1042
+ appt_updated_at DateTime @updatedAt
1043
+
1044
+ // Relations
1045
+ tenant Tenant @relation(fields: [appt_tenant_id], references: [tenant_id], onDelete: Cascade)
1046
+ clinic Clinic @relation(fields: [appt_clinic_id], references: [clinic_id])
1047
+ patient Patient @relation(fields: [appt_patient_id], references: [patient_id])
1048
+ doctor User? @relation("AppointmentDoctor", fields: [appt_doctor_id], references: [user_id])
1049
+ treatment Treatment? @relation(fields: [appt_treatment_id], references: [treatment_id])
1050
+ treatment_plan_item TreatmentPlanItem? @relation("AppointmentPlanItem", fields: [appt_treatment_plan_item_id], references: [tpitem_id])
1051
+ chat WhatsappChat? @relation(fields: [appt_chat_id], references: [chat_id])
1052
+ session WhatsappSession? @relation(fields: [appt_session_id], references: [session_id])
1053
+
1054
+ examination_record ExaminationRecord?
1055
+ treatment_plan_items_linked TreatmentPlanItem[] @relation("ItemAppointment")
1056
+ appointment_validation_entries AppointmentValidationEntry[]
1057
+ patient_documents PatientDocument[]
1058
+
1059
+ @@index([appt_tenant_id, appt_start_time], name: "idx_appts_tenant_start")
1060
+ @@index([appt_clinic_id, appt_start_time], name: "idx_appts_clinic_start")
1061
+ @@index([appt_patient_id, appt_start_time], name: "idx_appts_patient_start")
1062
+ @@index([appt_doctor_id, appt_start_time], name: "idx_appts_doctor_start")
1063
+ @@index([appt_tenant_id, appt_status], name: "idx_appts_tenant_status")
1064
+ @@index([appt_google_event_id], name: "idx_appts_google_event")
1065
+ @@map("appointments")
1066
+ }
1067
+
1068
+ // ─────────────────────────────────────────────
1069
+ // 22. APPOINTMENT VALIDATION BATCHES
1070
+ // ─────────────────────────────────────────────
1071
+
1072
+ model AppointmentValidationBatch {
1073
+ batch_id String @id @default(uuid())
1074
+ batch_tenant_id String
1075
+ batch_clinic_id String
1076
+ batch_created_by_id String
1077
+ batch_name String
1078
+ batch_status BatchStatus @default(draft)
1079
+ batch_el_batch_id String?
1080
+ batch_agent_id String?
1081
+ batch_phone_id String?
1082
+ batch_column_mapping Json
1083
+ batch_call_schedule Json
1084
+ batch_stats Json @default("{}")
1085
+ batch_created_at DateTime @default(now())
1086
+ batch_updated_at DateTime @updatedAt
1087
+
1088
+ // Relations
1089
+ tenant Tenant @relation(fields: [batch_tenant_id], references: [tenant_id], onDelete: Cascade)
1090
+ clinic Clinic @relation(fields: [batch_clinic_id], references: [clinic_id])
1091
+ created_by User @relation("CreatedBy", fields: [batch_created_by_id], references: [user_id])
1092
+ agent Agent? @relation(fields: [batch_agent_id], references: [agent_id])
1093
+ phone PhoneNumber? @relation(fields: [batch_phone_id], references: [phone_id])
1094
+
1095
+ entries AppointmentValidationEntry[]
1096
+
1097
+ @@index([batch_tenant_id, batch_created_at(sort: Desc)], name: "idx_batches_tenant_date")
1098
+ @@index([batch_el_batch_id], name: "idx_batches_el")
1099
+ @@index([batch_clinic_id], name: "idx_batches_clinic")
1100
+ @@map("appointment_validation_batches")
1101
+ }
1102
+
1103
+ // ─────────────────────────────────────────────
1104
+ // 23. APPOINTMENT VALIDATION ENTRIES
1105
+ // ─────────────────────────────────────────────
1106
+
1107
+ model AppointmentValidationEntry {
1108
+ bentry_id String @id @default(uuid())
1109
+ bentry_batch_id String
1110
+ bentry_appointment_id String?
1111
+ bentry_row_index Int
1112
+ bentry_external_id String @default("")
1113
+ bentry_patient_name String
1114
+ bentry_patient_phone String
1115
+ bentry_appointment_date String
1116
+ bentry_appointment_time String
1117
+ bentry_doctor_name String @default("")
1118
+ bentry_department String @default("")
1119
+ bentry_notes String @default("")
1120
+ bentry_raw_data Json @default("{}")
1121
+ bentry_call_status EntryCallStatus @default(pending)
1122
+ bentry_attempts Int @default(0)
1123
+ bentry_conversation_id String?
1124
+ bentry_validation_result ValidationResult?
1125
+ bentry_reschedule_request String?
1126
+ bentry_patient_message String?
1127
+ bentry_call_duration_secs Int @default(0)
1128
+ bentry_called_at DateTime?
1129
+ bentry_result_at DateTime?
1130
+ bentry_created_at DateTime @default(now())
1131
+ bentry_updated_at DateTime @updatedAt
1132
+
1133
+ // Relations
1134
+ batch AppointmentValidationBatch @relation(fields: [bentry_batch_id], references: [batch_id], onDelete: Cascade)
1135
+ appointment Appointment? @relation(fields: [bentry_appointment_id], references: [appt_id])
1136
+
1137
+ @@index([bentry_batch_id, bentry_call_status], name: "idx_bentries_batch_status")
1138
+ @@index([bentry_conversation_id], name: "idx_bentries_conversation")
1139
+ @@map("appointment_validation_entries")
1140
+ }
1141
+
1142
+ // ─────────────────────────────────────────────
1143
+ // 24. BILLING EVENTS
1144
+ // ─────────────────────────────────────────────
1145
+
1146
+ model BillingEvent {
1147
+ billing_id String @id @default(uuid())
1148
+ billing_tenant_id String
1149
+ billing_clinic_id String?
1150
+ billing_type BillingEventType
1151
+ billing_amount Decimal
1152
+ billing_currency String @default("TRY")
1153
+ billing_call_id String?
1154
+ billing_description String @default("")
1155
+ billing_created_at DateTime @default(now())
1156
+
1157
+ // Relations
1158
+ tenant Tenant @relation(fields: [billing_tenant_id], references: [tenant_id], onDelete: Cascade)
1159
+ clinic Clinic? @relation(fields: [billing_clinic_id], references: [clinic_id])
1160
+ call Call? @relation(fields: [billing_call_id], references: [call_id])
1161
+
1162
+ @@index([billing_tenant_id, billing_created_at(sort: Desc)], name: "idx_billing_tenant_date")
1163
+ @@map("billing_events")
1164
+ }
1165
+
1166
+ // ─────────────────────────────────────────────
1167
+ // 25. PAYMENTS
1168
+ // ─────────────────────────────────────────────
1169
+
1170
+ model Payment {
1171
+ payment_id String @id @default(uuid())
1172
+ payment_tenant_id String
1173
+ payment_type PaymentType @default(subscription)
1174
+ payment_plan_slug String
1175
+ payment_plan_name String
1176
+ payment_amount Decimal
1177
+ payment_extra_minutes Int @default(0)
1178
+ payment_period_start DateTime
1179
+ payment_period_end DateTime
1180
+ payment_method PaymentMethod @default(cash)
1181
+ payment_notes String @default("")
1182
+ payment_recorded_by_id String
1183
+ payment_created_at DateTime @default(now())
1184
+ payment_updated_at DateTime @updatedAt
1185
+
1186
+ // Relations
1187
+ tenant Tenant @relation(fields: [payment_tenant_id], references: [tenant_id], onDelete: Cascade)
1188
+ recorded_by User @relation("RecordedBy", fields: [payment_recorded_by_id], references: [user_id])
1189
+
1190
+ billing_period_snapshots BillingPeriodSnapshot[]
1191
+ billing_alerts BillingAlert[]
1192
+
1193
+ @@index([payment_tenant_id], name: "idx_payments_tenant")
1194
+ @@index([payment_tenant_id, payment_period_end(sort: Desc)], name: "idx_payments_tenant_period")
1195
+ @@map("payments")
1196
+ }
1197
+
1198
+ // ─────────────────────────────────────────────
1199
+ // 26. BILLING PERIOD SNAPSHOTS
1200
+ // ─────────────────────────────────────────────
1201
+
1202
+ model BillingPeriodSnapshot {
1203
+ snapshot_id String @id @default(uuid())
1204
+ snapshot_tenant_id String
1205
+ snapshot_payment_id String
1206
+ snapshot_plan_id String?
1207
+ snapshot_period_start DateTime
1208
+ snapshot_period_end DateTime
1209
+ snapshot_total_calls Int @default(0)
1210
+ snapshot_inbound_calls Int @default(0)
1211
+ snapshot_inbound_minutes Decimal @default(0)
1212
+ snapshot_outbound_calls Int @default(0)
1213
+ snapshot_outbound_minutes Decimal @default(0)
1214
+ snapshot_total_charges Decimal @default(0)
1215
+ snapshot_wa_billable_chats Int @default(0)
1216
+ snapshot_wa_total_sessions Int @default(0)
1217
+ snapshot_wa_total_messages Int @default(0)
1218
+ snapshot_wa_ai_messages Int @default(0)
1219
+ snapshot_wa_el_cost Decimal @default(0)
1220
+ snapshot_wa_stt_count Int @default(0)
1221
+ snapshot_wa_stt_seconds Decimal @default(0)
1222
+ snapshot_created_at DateTime @default(now())
1223
+
1224
+ // Relations
1225
+ tenant Tenant @relation(fields: [snapshot_tenant_id], references: [tenant_id], onDelete: Cascade)
1226
+ payment Payment @relation(fields: [snapshot_payment_id], references: [payment_id])
1227
+ plan Plan? @relation(fields: [snapshot_plan_id], references: [plan_id])
1228
+
1229
+ @@index([snapshot_tenant_id, snapshot_period_start(sort: Desc)], name: "idx_snapshots_tenant_period")
1230
+ @@map("billing_period_snapshots")
1231
+ }
1232
+
1233
+ // ─────────────────────────────────────────────
1234
+ // 27. BILLING ALERTS
1235
+ // ─────────────────────────────────────────────
1236
+
1237
+ model BillingAlert {
1238
+ alert_id String @id @default(uuid())
1239
+ alert_tenant_id String
1240
+ alert_type AlertType
1241
+ alert_service AlertService
1242
+ alert_payment_id String
1243
+ alert_created_at DateTime @default(now())
1244
+
1245
+ // Relations
1246
+ tenant Tenant @relation(fields: [alert_tenant_id], references: [tenant_id], onDelete: Cascade)
1247
+ payment Payment @relation(fields: [alert_payment_id], references: [payment_id])
1248
+
1249
+ @@unique([alert_tenant_id, alert_type, alert_service, alert_payment_id])
1250
+ @@map("billing_alerts")
1251
+ }
1252
+
1253
+ // ─────────────────────────────────────────────
1254
+ // 28. STT USAGES
1255
+ // ─────────────────────────────────────────────
1256
+
1257
+ model SttUsage {
1258
+ stt_id String @id @default(uuid())
1259
+ stt_tenant_id String
1260
+ stt_clinic_id String?
1261
+ stt_chat_id String @default("")
1262
+ stt_message_id String @default("")
1263
+ stt_duration_seconds Decimal
1264
+ stt_character_count Int
1265
+ stt_language String @default("tr")
1266
+ stt_created_at DateTime @default(now())
1267
+
1268
+ // Relations
1269
+ tenant Tenant @relation(fields: [stt_tenant_id], references: [tenant_id], onDelete: Cascade)
1270
+ clinic Clinic? @relation(fields: [stt_clinic_id], references: [clinic_id])
1271
+
1272
+ @@index([stt_tenant_id, stt_created_at(sort: Desc)], name: "idx_stt_tenant_date")
1273
+ @@map("stt_usages")
1274
+ }
1275
+
1276
+ // ─────────────────────────────────────────────
1277
+ // 29. LOGS (observability — no FKs)
1278
+ // ─────────────────────────────────────────────
1279
+
1280
+ model Log {
1281
+ log_id String @id @default(uuid())
1282
+ log_level String
1283
+ log_message String
1284
+ log_service String @default("api")
1285
+ log_meta Json @default("{}")
1286
+ log_request_id String?
1287
+ log_tenant_id String?
1288
+ log_clinic_id String?
1289
+ log_user_id String?
1290
+ log_timestamp DateTime @default(now())
1291
+
1292
+ @@index([log_level], name: "idx_logs_level")
1293
+ @@index([log_timestamp], name: "idx_logs_timestamp")
1294
+ @@index([log_level, log_timestamp(sort: Desc)], name: "idx_logs_level_timestamp")
1295
+ @@index([log_tenant_id, log_timestamp(sort: Desc)], name: "idx_logs_tenant_timestamp")
1296
+ @@index([log_request_id], name: "idx_logs_request")
1297
+ @@index([log_service, log_timestamp(sort: Desc)], name: "idx_logs_service_timestamp")
1298
+ @@map("logs")
1299
+ }
1300
+
1301
+ // ─────────────────────────────────────────────
1302
+ // 30. AUDIT LOGS (observability — no FKs)
1303
+ // ─────────────────────────────────────────────
1304
+
1305
+ model AuditLog {
1306
+ audit_id String @id @default(uuid())
1307
+ audit_tenant_id String?
1308
+ audit_clinic_id String?
1309
+ audit_user_id String?
1310
+ audit_user_email String?
1311
+ audit_user_role String?
1312
+ audit_action String
1313
+ audit_entity String
1314
+ audit_entity_id String
1315
+ audit_changes Json?
1316
+ audit_metadata Json?
1317
+ audit_created_at DateTime @default(now())
1318
+
1319
+ @@index([audit_tenant_id, audit_created_at(sort: Desc)], name: "idx_audit_tenant_date")
1320
+ @@index([audit_clinic_id, audit_created_at(sort: Desc)], name: "idx_audit_clinic_date")
1321
+ @@index([audit_entity, audit_entity_id], name: "idx_audit_entity")
1322
+ @@index([audit_user_id, audit_created_at(sort: Desc)], name: "idx_audit_user_date")
1323
+ @@index([audit_action, audit_created_at(sort: Desc)], name: "idx_audit_action_date")
1324
+ @@map("audit_logs")
1325
+ }
1326
+
1327
+ // ─────────────────────────────────────────────
1328
+ // 31. TOOL EXECUTION LOGS (observability — no FKs)
1329
+ // ─────────────────────────────────────────────
1330
+
1331
+ model ToolExecutionLog {
1332
+ toollog_id String @id @default(uuid())
1333
+ toollog_tenant_id String
1334
+ toollog_clinic_id String?
1335
+ toollog_tool_name String
1336
+ toollog_channel String
1337
+ toollog_patient_phone String @default("")
1338
+ toollog_conversation_id String?
1339
+ toollog_parameters Json @default("{}")
1340
+ toollog_result Json @default("{}")
1341
+ toollog_is_error Boolean @default(false)
1342
+ toollog_duration_ms Int @default(0)
1343
+ toollog_created_at DateTime @default(now())
1344
+
1345
+ @@index([toollog_tenant_id, toollog_created_at(sort: Desc)], name: "idx_toollog_tenant_date")
1346
+ @@index([toollog_tool_name, toollog_created_at(sort: Desc)], name: "idx_toollog_tool_date")
1347
+ @@index([toollog_conversation_id], name: "idx_toollog_conversation")
1348
+ @@map("tool_execution_logs")
1349
+ }
1350
+
1351
+ // ─────────────────────────────────────────────
1352
+ // 32. MIGRATIONS
1353
+ // ─────────────────────────────────────────────
1354
+
1355
+ model Migration {
1356
+ migration_id String @id @default(uuid())
1357
+ migration_name String @unique
1358
+ migration_ran_at DateTime
1359
+ migration_duration_ms Int
1360
+ migration_status MigrationStatus
1361
+ migration_error String?
1362
+ migration_created_at DateTime @default(now())
1363
+ migration_updated_at DateTime @updatedAt
1364
+
1365
+ @@map("migrations")
1366
+ }
1367
+
1368
+ // ─────────────────────────────────────────────
1369
+ // 33. TRANSCRIPTIONS
1370
+ // ─────────────────────────────────────────────
1371
+
1372
+ model Transcription {
1373
+ tx_id String @id @default(uuid())
1374
+ tx_conversation_id String @unique
1375
+ tx_agent_id String
1376
+ tx_agent_name String?
1377
+ tx_user_id String?
1378
+ tx_event_type String @default("post_call_transcription")
1379
+ tx_event_timestamp Int?
1380
+ tx_status String @default("done")
1381
+ tx_transcript Json @default("[]")
1382
+ tx_metadata Json?
1383
+ tx_analysis Json?
1384
+ tx_processing_status TranscriptionProcessingStatus @default(pending)
1385
+ tx_processing_error String?
1386
+ tx_raw_payload Json?
1387
+ tx_created_at DateTime @default(now())
1388
+ tx_updated_at DateTime @updatedAt
1389
+
1390
+ // Relations
1391
+ summary Summary?
1392
+
1393
+ @@index([tx_agent_id], name: "idx_tx_agent")
1394
+ @@index([tx_user_id], name: "idx_tx_user")
1395
+ @@index([tx_processing_status], name: "idx_tx_processing")
1396
+ @@index([tx_created_at(sort: Desc)], name: "idx_tx_date")
1397
+ @@map("transcriptions")
1398
+ }
1399
+
1400
+ // ─────────────────────────────────────────────
1401
+ // 34. SUMMARIES
1402
+ // ─────────────────────────────────────────────
1403
+
1404
+ model Summary {
1405
+ summary_id String @id @default(uuid())
1406
+ summary_transcription_id String @unique
1407
+ summary_conversation_id String
1408
+ summary_text String
1409
+ summary_title String?
1410
+ summary_key_points String[] @default([])
1411
+ summary_detected_intent String?
1412
+ summary_sentiment Sentiment?
1413
+ summary_ai_provider String
1414
+ summary_ai_model String?
1415
+ summary_token_usage Json?
1416
+ summary_notification_status NotificationDeliveryStatus @default(pending)
1417
+ summary_notified_recipients Json @default("[]")
1418
+ summary_language String @default("tr")
1419
+ summary_created_at DateTime @default(now())
1420
+ summary_updated_at DateTime @updatedAt
1421
+
1422
+ // Relations
1423
+ transcription Transcription @relation(fields: [summary_transcription_id], references: [tx_id])
1424
+
1425
+ @@index([summary_conversation_id], name: "idx_summary_conversation")
1426
+ @@map("summaries")
1427
+ }
1428
+
1429
+ // ─────────────────────────────────────────────
1430
+ // 36. PATIENTS
1431
+ // ─────────────────────────────────────────────
1432
+
1433
+ model Patient {
1434
+ patient_id String @id @default(uuid())
1435
+ patient_tenant_id String
1436
+ patient_clinic_id String?
1437
+ patient_phone String
1438
+ patient_email String?
1439
+ patient_first_name String @default("")
1440
+ patient_last_name String @default("")
1441
+ patient_display_name String @default("")
1442
+ patient_date_of_birth DateTime?
1443
+ patient_gender String?
1444
+ patient_id_number String?
1445
+ patient_blood_type String?
1446
+ patient_preferred_language String @default("tr")
1447
+ patient_source String?
1448
+ patient_source_detail String?
1449
+ patient_tags String[] @default([])
1450
+ patient_ai_summary String @default("")
1451
+ patient_is_active Boolean @default(true)
1452
+ patient_first_contact_at DateTime @default(now())
1453
+ patient_last_contact_at DateTime @default(now())
1454
+ patient_total_sessions Int @default(0)
1455
+ patient_total_appointments Int @default(0)
1456
+ patient_created_at DateTime @default(now())
1457
+ patient_updated_at DateTime @updatedAt
1458
+
1459
+ // Relations
1460
+ tenant Tenant @relation(fields: [patient_tenant_id], references: [tenant_id], onDelete: Cascade)
1461
+ clinic Clinic? @relation(fields: [patient_clinic_id], references: [clinic_id])
1462
+
1463
+ medical_history PatientMedicalHistory?
1464
+ treatment_plans TreatmentPlan[]
1465
+ appointments Appointment[]
1466
+ photo_sets PatientPhotoSet[]
1467
+ documents PatientDocument[]
1468
+ notes PatientNote[]
1469
+ whatsapp_chats WhatsappChat[]
1470
+ leads Lead[]
1471
+ calls Call[]
1472
+ examination_records ExaminationRecord[]
1473
+
1474
+ @@unique([patient_tenant_id, patient_phone])
1475
+ @@index([patient_tenant_id, patient_last_contact_at(sort: Desc)], name: "idx_patients_tenant_lastcontact")
1476
+ @@index([patient_clinic_id], name: "idx_patients_clinic")
1477
+ @@index([patient_tenant_id, patient_last_name, patient_first_name], name: "idx_patients_tenant_name")
1478
+ @@map("patients")
1479
+ }
1480
+
1481
+ // ─────────────────────────────────────────────
1482
+ // 37. PATIENT MEDICAL HISTORIES
1483
+ // ─────────────────────────────────────────────
1484
+
1485
+ model PatientMedicalHistory {
1486
+ history_id String @id @default(uuid())
1487
+ history_patient_id String @unique
1488
+ history_allergies String @default("")
1489
+ history_chronic_conditions String @default("")
1490
+ history_current_medications String @default("")
1491
+ history_past_surgeries String @default("")
1492
+ history_pregnancy_status String?
1493
+ history_smoking Boolean?
1494
+ history_alcohol Boolean?
1495
+ history_notes String @default("")
1496
+ history_anamnesis_completed Boolean @default(false)
1497
+ history_anamnesis_date DateTime?
1498
+ history_created_at DateTime @default(now())
1499
+ history_updated_at DateTime @updatedAt
1500
+
1501
+ // Relations
1502
+ patient Patient @relation(fields: [history_patient_id], references: [patient_id], onDelete: Cascade)
1503
+
1504
+ @@map("patient_medical_histories")
1505
+ }
1506
+
1507
+ // ─────────────────────────────────────────────
1508
+ // 38. PATIENT DOCUMENTS
1509
+ // ─────────────────────────────────────────────
1510
+
1511
+ model PatientDocument {
1512
+ doc_id String @id @default(uuid())
1513
+ doc_patient_id String
1514
+ doc_tenant_id String
1515
+ doc_clinic_id String
1516
+ doc_appointment_id String?
1517
+ doc_type String @default("other")
1518
+ doc_name String
1519
+ doc_media_key String
1520
+ doc_content_type String
1521
+ doc_size_bytes Int @default(0)
1522
+ doc_uploaded_by String?
1523
+ doc_notes String @default("")
1524
+ doc_created_at DateTime @default(now())
1525
+
1526
+ // Relations
1527
+ patient Patient @relation(fields: [doc_patient_id], references: [patient_id], onDelete: Cascade)
1528
+ tenant Tenant @relation(fields: [doc_tenant_id], references: [tenant_id])
1529
+ clinic Clinic @relation(fields: [doc_clinic_id], references: [clinic_id])
1530
+ appointment Appointment? @relation(fields: [doc_appointment_id], references: [appt_id])
1531
+ uploaded_by_user User? @relation("DocUploader", fields: [doc_uploaded_by], references: [user_id])
1532
+
1533
+ @@index([doc_patient_id, doc_created_at(sort: Desc)], name: "idx_docs_patient_date")
1534
+ @@index([doc_tenant_id, doc_type], name: "idx_docs_tenant_type")
1535
+ @@map("patient_documents")
1536
+ }
1537
+
1538
+ // ─────────────────────────────────────────────
1539
+ // 39. PATIENT NOTES
1540
+ // ─────────────────────────────────────────────
1541
+
1542
+ model PatientNote {
1543
+ note_id String @id @default(uuid())
1544
+ note_patient_id String
1545
+ note_tenant_id String
1546
+ note_clinic_id String
1547
+ note_author_id String
1548
+ note_text String
1549
+ note_is_pinned Boolean @default(false)
1550
+ note_created_at DateTime @default(now())
1551
+ note_updated_at DateTime @updatedAt
1552
+
1553
+ // Relations
1554
+ patient Patient @relation(fields: [note_patient_id], references: [patient_id], onDelete: Cascade)
1555
+ tenant Tenant @relation(fields: [note_tenant_id], references: [tenant_id])
1556
+ clinic Clinic @relation(fields: [note_clinic_id], references: [clinic_id])
1557
+ author User @relation("NoteAuthor", fields: [note_author_id], references: [user_id])
1558
+
1559
+ @@index([note_patient_id, note_created_at(sort: Desc)], name: "idx_notes_patient_date")
1560
+ @@map("patient_notes")
1561
+ }
1562
+
1563
+ // ─────────────────────────────────────────────
1564
+ // 40. TREATMENTS
1565
+ // ─────────────────────────────────────────────
1566
+
1567
+ model Treatment {
1568
+ treatment_id String @id @default(uuid())
1569
+ treatment_tenant_id String
1570
+ treatment_clinic_id String?
1571
+ treatment_name String
1572
+ treatment_category String @default("")
1573
+ treatment_description String @default("")
1574
+ treatment_duration_minutes Int @default(30)
1575
+ treatment_price Decimal?
1576
+ treatment_currency String @default("TRY")
1577
+ treatment_is_active Boolean @default(true)
1578
+ treatment_sort_order Int @default(0)
1579
+ treatment_recall_days Int?
1580
+ treatment_created_at DateTime @default(now())
1581
+ treatment_updated_at DateTime @updatedAt
1582
+
1583
+ // Relations
1584
+ tenant Tenant @relation(fields: [treatment_tenant_id], references: [tenant_id], onDelete: Cascade)
1585
+ clinic Clinic? @relation(fields: [treatment_clinic_id], references: [clinic_id])
1586
+
1587
+ treatment_plan_items TreatmentPlanItem[]
1588
+ appointments Appointment[]
1589
+
1590
+ @@index([treatment_tenant_id, treatment_is_active], name: "idx_treatments_tenant_active")
1591
+ @@index([treatment_tenant_id, treatment_category], name: "idx_treatments_tenant_category")
1592
+ @@index([treatment_clinic_id], name: "idx_treatments_clinic")
1593
+ @@map("treatments")
1594
+ }
1595
+
1596
+ // ─────────────────────────────────────────────
1597
+ // 41. TREATMENT PLANS
1598
+ // ─────────────────────────────────────────────
1599
+
1600
+ model TreatmentPlan {
1601
+ tplan_id String @id @default(uuid())
1602
+ tplan_tenant_id String
1603
+ tplan_clinic_id String
1604
+ tplan_patient_id String
1605
+ tplan_doctor_id String?
1606
+ tplan_name String
1607
+ tplan_status TreatmentPlanStatus @default(active)
1608
+ tplan_notes String @default("")
1609
+ tplan_created_at DateTime @default(now())
1610
+ tplan_updated_at DateTime @updatedAt
1611
+
1612
+ // Relations
1613
+ tenant Tenant @relation(fields: [tplan_tenant_id], references: [tenant_id], onDelete: Cascade)
1614
+ clinic Clinic @relation(fields: [tplan_clinic_id], references: [clinic_id])
1615
+ patient Patient @relation(fields: [tplan_patient_id], references: [patient_id])
1616
+ doctor User? @relation("PlanDoctor", fields: [tplan_doctor_id], references: [user_id])
1617
+
1618
+ items TreatmentPlanItem[]
1619
+ photo_sets PatientPhotoSet[]
1620
+
1621
+ @@index([tplan_patient_id, tplan_status], name: "idx_tplans_patient_status")
1622
+ @@index([tplan_tenant_id, tplan_status], name: "idx_tplans_tenant_status")
1623
+ @@index([tplan_doctor_id], name: "idx_tplans_doctor")
1624
+ @@index([tplan_clinic_id], name: "idx_tplans_clinic")
1625
+ @@map("treatment_plans")
1626
+ }
1627
+
1628
+ // ─────────────────────────────────────────────
1629
+ // 42. TREATMENT PLAN ITEMS
1630
+ // ─────────────────────────────────────────────
1631
+
1632
+ model TreatmentPlanItem {
1633
+ tpitem_id String @id @default(uuid())
1634
+ tpitem_plan_id String
1635
+ tpitem_treatment_id String?
1636
+ tpitem_appointment_id String?
1637
+ tpitem_name String
1638
+ tpitem_tooth_number String?
1639
+ tpitem_status TreatmentPlanItemStatus @default(planned)
1640
+ tpitem_notes String @default("")
1641
+ tpitem_sort_order Int @default(0)
1642
+ tpitem_completed_at DateTime?
1643
+ tpitem_created_at DateTime @default(now())
1644
+ tpitem_updated_at DateTime @updatedAt
1645
+
1646
+ // Relations
1647
+ plan TreatmentPlan @relation(fields: [tpitem_plan_id], references: [tplan_id], onDelete: Cascade)
1648
+ treatment Treatment? @relation(fields: [tpitem_treatment_id], references: [treatment_id])
1649
+ appointment Appointment? @relation("ItemAppointment", fields: [tpitem_appointment_id], references: [appt_id])
1650
+ appointments_for_item Appointment[] @relation("AppointmentPlanItem")
1651
+
1652
+ @@index([tpitem_plan_id, tpitem_sort_order], name: "idx_tpitems_plan_order")
1653
+ @@index([tpitem_appointment_id], name: "idx_tpitems_appointment")
1654
+ @@map("treatment_plan_items")
1655
+ }
1656
+
1657
+ // ─────────────────────────────────────────────
1658
+ // 43. DOCTOR PROFILES
1659
+ // ─────────────────────────────────────────────
1660
+
1661
+ model DoctorProfile {
1662
+ dprofile_id String @id @default(uuid())
1663
+ dprofile_user_id String @unique
1664
+ dprofile_specialty String @default("")
1665
+ dprofile_title String @default("")
1666
+ dprofile_bio String @default("")
1667
+ dprofile_working_hours Json @default("[]")
1668
+ dprofile_appointment_duration Int @default(30)
1669
+ dprofile_color String @default("")
1670
+ dprofile_is_accepting Boolean @default(true)
1671
+ dprofile_blocked_dates Json @default("[]")
1672
+ dprofile_google_email String?
1673
+ dprofile_google_encrypted_token String?
1674
+ dprofile_google_calendar_id String?
1675
+ dprofile_google_calendar_name String?
1676
+ dprofile_google_connected_at DateTime?
1677
+ dprofile_created_at DateTime @default(now())
1678
+ dprofile_updated_at DateTime @updatedAt
1679
+
1680
+ // Relations
1681
+ user User @relation(fields: [dprofile_user_id], references: [user_id], onDelete: Cascade)
1682
+
1683
+ @@map("doctor_profiles")
1684
+ }
1685
+
1686
+ // ─────────────────────────────────────────────
1687
+ // 44. PATIENT PHOTO SETS
1688
+ // ─────────────────────────────────────────────
1689
+
1690
+ model PatientPhotoSet {
1691
+ photoset_id String @id @default(uuid())
1692
+ photoset_patient_id String
1693
+ photoset_tenant_id String
1694
+ photoset_clinic_id String
1695
+ photoset_treatment_plan_id String?
1696
+ photoset_type String
1697
+ photoset_label String @default("")
1698
+ photoset_taken_at DateTime @default(now())
1699
+ photoset_taken_by String?
1700
+ photoset_notes String @default("")
1701
+ photoset_created_at DateTime @default(now())
1702
+ photoset_updated_at DateTime @updatedAt
1703
+
1704
+ // Relations
1705
+ patient Patient @relation(fields: [photoset_patient_id], references: [patient_id], onDelete: Cascade)
1706
+ tenant Tenant @relation(fields: [photoset_tenant_id], references: [tenant_id])
1707
+ clinic Clinic @relation(fields: [photoset_clinic_id], references: [clinic_id])
1708
+ treatment_plan TreatmentPlan? @relation(fields: [photoset_treatment_plan_id], references: [tplan_id])
1709
+ taken_by_user User? @relation("PhotoTaker", fields: [photoset_taken_by], references: [user_id])
1710
+
1711
+ photos PatientPhoto[]
1712
+
1713
+ @@index([photoset_patient_id, photoset_taken_at(sort: Desc)], name: "idx_photosets_patient_date")
1714
+ @@index([photoset_treatment_plan_id], name: "idx_photosets_plan")
1715
+ @@index([photoset_tenant_id, photoset_type], name: "idx_photosets_tenant_type")
1716
+ @@map("patient_photo_sets")
1717
+ }
1718
+
1719
+ // ─────────────────────────────────────────────
1720
+ // 45. PATIENT PHOTOS
1721
+ // ─────────────────────────────────────────────
1722
+
1723
+ model PatientPhoto {
1724
+ photo_id String @id @default(uuid())
1725
+ photo_set_id String
1726
+ photo_angle String @default("")
1727
+ photo_media_key String
1728
+ photo_thumbnail_key String?
1729
+ photo_caption String @default("")
1730
+ photo_sort_order Int @default(0)
1731
+ photo_created_at DateTime @default(now())
1732
+
1733
+ // Relations
1734
+ photo_set PatientPhotoSet @relation(fields: [photo_set_id], references: [photoset_id], onDelete: Cascade)
1735
+
1736
+ @@index([photo_set_id, photo_sort_order], name: "idx_photos_set_order")
1737
+ @@map("patient_photos")
1738
+ }
1739
+
1740
+ // ─────────────────────────────────────────────
1741
+ // 46. EXAMINATION RECORDS
1742
+ // ─────────────────────────────────────────────
1743
+
1744
+ model ExaminationRecord {
1745
+ exam_id String @id @default(uuid())
1746
+ exam_appointment_id String? @unique
1747
+ exam_patient_id String
1748
+ exam_doctor_id String
1749
+ exam_clinic_id String
1750
+ exam_tenant_id String
1751
+ exam_findings String @default("")
1752
+ exam_diagnosis String @default("")
1753
+ exam_procedure_notes String @default("")
1754
+ exam_prescription String @default("")
1755
+ exam_instructions String @default("")
1756
+ exam_created_at DateTime @default(now())
1757
+ exam_updated_at DateTime @updatedAt
1758
+
1759
+ // Relations
1760
+ appointment Appointment? @relation(fields: [exam_appointment_id], references: [appt_id], onDelete: Cascade)
1761
+ patient Patient @relation(fields: [exam_patient_id], references: [patient_id])
1762
+ doctor User @relation("ExamDoctor", fields: [exam_doctor_id], references: [user_id])
1763
+ clinic Clinic @relation(fields: [exam_clinic_id], references: [clinic_id])
1764
+ tenant Tenant @relation(fields: [exam_tenant_id], references: [tenant_id], onDelete: Cascade)
1765
+
1766
+ @@index([exam_patient_id, exam_created_at(sort: Desc)], name: "idx_exam_patient_date")
1767
+ @@index([exam_doctor_id, exam_created_at(sort: Desc)], name: "idx_exam_doctor_date")
1768
+ @@map("examination_records")
1769
+ }
1770
+
1771
+ // ─────────────────────────────────────────────
1772
+ // 47. AVAILABILITY BLOCKS (holidays, leaves, breaks)
1773
+ // ─────────────────────────────────────────────
1774
+
1775
+ model AvailabilityBlock {
1776
+ block_id String @id @default(uuid())
1777
+ block_tenant_id String
1778
+ block_clinic_id String
1779
+ block_doctor_id String? // null = clinic-wide, set = doctor-specific
1780
+ block_title String
1781
+ block_type AvailabilityBlockType @default(holiday)
1782
+ block_start_date DateTime @db.Date
1783
+ block_end_date DateTime @db.Date
1784
+ block_all_day Boolean @default(true)
1785
+ block_start_time String? // "14:00" when not all_day
1786
+ block_end_time String? // "16:00" when not all_day
1787
+ block_recurring Boolean @default(false)
1788
+ block_notes String @default("")
1789
+ block_created_by String?
1790
+ block_created_at DateTime @default(now())
1791
+
1792
+ // Relations
1793
+ tenant Tenant @relation(fields: [block_tenant_id], references: [tenant_id], onDelete: Cascade)
1794
+ clinic Clinic @relation(fields: [block_clinic_id], references: [clinic_id])
1795
+ doctor User? @relation("BlockDoctor", fields: [block_doctor_id], references: [user_id])
1796
+ created_by User? @relation("BlockCreatedBy", fields: [block_created_by], references: [user_id])
1797
+
1798
+ @@index([block_tenant_id, block_clinic_id, block_start_date], name: "idx_blocks_clinic_date")
1799
+ @@index([block_doctor_id, block_start_date], name: "idx_blocks_doctor_date")
1800
+ @@map("availability_blocks")
1801
+ }
1802
+
1803
+ // ─────────────────────────────────────────────
1804
+ // ADMIN CHAT SESSIONS (AI Playground)
1805
+ // ─────────────────────────────────────────────
1806
+
1807
+ model AdminChatSession {
1808
+ acs_id String @id @default(uuid())
1809
+ acs_user_id String
1810
+ acs_title String @default("")
1811
+ acs_provider String @default("anthropic")
1812
+ acs_tenant_id String?
1813
+ acs_clinic_id String?
1814
+ acs_agent_id String?
1815
+ acs_system_prompt String @default("")
1816
+ acs_enable_tools Boolean @default(false)
1817
+ acs_channel String @default("whatsapp")
1818
+ acs_message_count Int @default(0)
1819
+ acs_last_message_at DateTime?
1820
+ acs_metadata Json @default("{}")
1821
+ acs_created_at DateTime @default(now())
1822
+ acs_updated_at DateTime @updatedAt
1823
+
1824
+ user User @relation(fields: [acs_user_id], references: [user_id], onDelete: Cascade)
1825
+ messages AdminChatMessage[]
1826
+
1827
+ @@index([acs_user_id, acs_updated_at(sort: Desc)], name: "idx_acs_user_updated")
1828
+ @@map("admin_chat_sessions")
1829
+ }
1830
+
1831
+ model AdminChatMessage {
1832
+ acm_id String @id @default(uuid())
1833
+ acm_session_id String
1834
+ acm_role AcmRole
1835
+ acm_content String
1836
+ acm_metadata Json @default("{}")
1837
+ acm_created_at DateTime @default(now())
1838
+
1839
+ session AdminChatSession @relation(fields: [acm_session_id], references: [acs_id], onDelete: Cascade)
1840
+
1841
+ @@index([acm_session_id, acm_created_at], name: "idx_acm_session_date")
1842
+ @@map("admin_chat_messages")
1843
+ }