@aglyn/plugins-crm 1.0.0-beta.221 → 1.0.0-beta.222

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 (514) hide show
  1. package/README.md +2 -1
  2. package/package.json +13 -13
  3. package/src/lib/components/activity-list.js +12 -5
  4. package/src/lib/components/activity-list.js.map +1 -1
  5. package/src/lib/components/companies-bulk-bar.d.ts +1 -4
  6. package/src/lib/components/companies-bulk-bar.js +7 -20
  7. package/src/lib/components/companies-bulk-bar.js.map +1 -1
  8. package/src/lib/components/companies-section.d.ts +3 -3
  9. package/src/lib/components/companies-section.js +149 -46
  10. package/src/lib/components/companies-section.js.map +1 -1
  11. package/src/lib/components/company-edit-drawer.js +281 -20
  12. package/src/lib/components/company-edit-drawer.js.map +1 -1
  13. package/src/lib/components/company-properties-card.js +99 -8
  14. package/src/lib/components/company-properties-card.js.map +1 -1
  15. package/src/lib/components/contact-detail-page.js +3 -1
  16. package/src/lib/components/contact-detail-page.js.map +1 -1
  17. package/src/lib/components/contact-merge-dialog.js +33 -10
  18. package/src/lib/components/contact-merge-dialog.js.map +1 -1
  19. package/src/lib/components/contact-properties-card.d.ts +0 -69
  20. package/src/lib/components/contact-properties-card.js +350 -60
  21. package/src/lib/components/contact-properties-card.js.map +1 -1
  22. package/src/lib/components/contact-reports-to-field.d.ts +46 -0
  23. package/src/lib/components/contact-reports-to-field.js +67 -0
  24. package/src/lib/components/contact-reports-to-field.js.map +1 -0
  25. package/src/lib/components/contacts-bulk-bar.d.ts +1 -8
  26. package/src/lib/components/contacts-bulk-bar.js +7 -19
  27. package/src/lib/components/contacts-bulk-bar.js.map +1 -1
  28. package/src/lib/components/contacts-section.js +46 -33
  29. package/src/lib/components/contacts-section.js.map +1 -1
  30. package/src/lib/components/crm-call-actions.d.ts +10 -0
  31. package/src/lib/components/crm-call-actions.js +26 -9
  32. package/src/lib/components/crm-call-actions.js.map +1 -1
  33. package/src/lib/components/crm-record-picker.d.ts +15 -0
  34. package/src/lib/components/crm-record-picker.js +16 -10
  35. package/src/lib/components/crm-record-picker.js.map +1 -1
  36. package/src/lib/components/crm-transfer-buttons.d.ts +54 -0
  37. package/src/lib/components/crm-transfer-buttons.js +167 -0
  38. package/src/lib/components/crm-transfer-buttons.js.map +1 -0
  39. package/src/lib/components/deal-contact-roles-card.d.ts +46 -0
  40. package/src/lib/components/deal-contact-roles-card.js +368 -0
  41. package/src/lib/components/deal-contact-roles-card.js.map +1 -0
  42. package/src/lib/components/deal-detail-page.d.ts +3 -2
  43. package/src/lib/components/deal-detail-page.js +25 -6
  44. package/src/lib/components/deal-detail-page.js.map +1 -1
  45. package/src/lib/components/deal-edit-drawer.d.ts +10 -0
  46. package/src/lib/components/deal-edit-drawer.js +219 -10
  47. package/src/lib/components/deal-edit-drawer.js.map +1 -1
  48. package/src/lib/components/deal-properties-card.d.ts +7 -0
  49. package/src/lib/components/deal-properties-card.js +34 -3
  50. package/src/lib/components/deal-properties-card.js.map +1 -1
  51. package/src/lib/components/deal-stage-card.d.ts +4 -0
  52. package/src/lib/components/deal-stage-card.js +10 -2
  53. package/src/lib/components/deal-stage-card.js.map +1 -1
  54. package/src/lib/components/deals-bulk-bar.d.ts +0 -3
  55. package/src/lib/components/deals-bulk-bar.js +7 -20
  56. package/src/lib/components/deals-bulk-bar.js.map +1 -1
  57. package/src/lib/components/deals-section.d.ts +3 -3
  58. package/src/lib/components/deals-section.js +123 -63
  59. package/src/lib/components/deals-section.js.map +1 -1
  60. package/src/lib/components/fields-section.js +31 -17
  61. package/src/lib/components/fields-section.js.map +1 -1
  62. package/src/lib/components/lead-convert-dialog.d.ts +4 -0
  63. package/src/lib/components/lead-convert-dialog.js +23 -1
  64. package/src/lib/components/lead-convert-dialog.js.map +1 -1
  65. package/src/lib/components/lead-detail-page.js +8 -2
  66. package/src/lib/components/lead-detail-page.js.map +1 -1
  67. package/src/lib/components/lead-profile-fields.d.ts +71 -0
  68. package/src/lib/components/lead-profile-fields.js +386 -0
  69. package/src/lib/components/lead-profile-fields.js.map +1 -0
  70. package/src/lib/components/lead-properties-card.d.ts +2 -1
  71. package/src/lib/components/lead-properties-card.js +85 -176
  72. package/src/lib/components/lead-properties-card.js.map +1 -1
  73. package/src/lib/components/lead-source-select.d.ts +4 -23
  74. package/src/lib/components/lead-source-select.js +9 -73
  75. package/src/lib/components/lead-source-select.js.map +1 -1
  76. package/src/lib/components/lead-status-chip.d.ts +9 -3
  77. package/src/lib/components/lead-status-chip.js +8 -4
  78. package/src/lib/components/lead-status-chip.js.map +1 -1
  79. package/src/lib/components/lead-status-options.d.ts +20 -0
  80. package/src/lib/components/lead-status-options.js +51 -0
  81. package/src/lib/components/lead-status-options.js.map +1 -0
  82. package/src/lib/components/lead-unqualify-dialog.d.ts +5 -0
  83. package/src/lib/components/lead-unqualify-dialog.js +50 -18
  84. package/src/lib/components/lead-unqualify-dialog.js.map +1 -1
  85. package/src/lib/components/leads-bulk-bar.d.ts +0 -3
  86. package/src/lib/components/leads-bulk-bar.js +29 -29
  87. package/src/lib/components/leads-bulk-bar.js.map +1 -1
  88. package/src/lib/components/leads-section.js +120 -68
  89. package/src/lib/components/leads-section.js.map +1 -1
  90. package/src/lib/components/linked-deals-card.d.ts +4 -0
  91. package/src/lib/components/linked-deals-card.js +47 -3
  92. package/src/lib/components/linked-deals-card.js.map +1 -1
  93. package/src/lib/components/log-activity-dialog.js +43 -3
  94. package/src/lib/components/log-activity-dialog.js.map +1 -1
  95. package/src/lib/components/new-contact-drawer.d.ts +8 -0
  96. package/src/lib/components/new-contact-drawer.js +108 -6
  97. package/src/lib/components/new-contact-drawer.js.map +1 -1
  98. package/src/lib/components/new-lead-drawer.d.ts +9 -2
  99. package/src/lib/components/new-lead-drawer.js +88 -121
  100. package/src/lib/components/new-lead-drawer.js.map +1 -1
  101. package/src/lib/components/picklist-select.d.ts +36 -0
  102. package/src/lib/components/picklist-select.js +114 -0
  103. package/src/lib/components/picklist-select.js.map +1 -0
  104. package/src/lib/components/picklist-values-card.d.ts +34 -0
  105. package/src/lib/components/{lead-source-values-card.js → picklist-values-card.js} +241 -58
  106. package/src/lib/components/picklist-values-card.js.map +1 -0
  107. package/src/lib/components/pipeline-stages-dialog.d.ts +7 -0
  108. package/src/lib/components/pipeline-stages-dialog.js +26 -4
  109. package/src/lib/components/pipeline-stages-dialog.js.map +1 -1
  110. package/src/lib/components/pipelines-dialog.js +15 -6
  111. package/src/lib/components/pipelines-dialog.js.map +1 -1
  112. package/src/lib/components/recent-activity-feed.js +20 -5
  113. package/src/lib/components/recent-activity-feed.js.map +1 -1
  114. package/src/lib/components/recipes-card.js +4 -2
  115. package/src/lib/components/recipes-card.js.map +1 -1
  116. package/src/lib/components/record-tasks-card.js +15 -8
  117. package/src/lib/components/record-tasks-card.js.map +1 -1
  118. package/src/lib/components/reports/forecast-card.d.ts +6 -0
  119. package/src/lib/components/reports/forecast-card.js +101 -3
  120. package/src/lib/components/reports/forecast-card.js.map +1 -1
  121. package/src/lib/components/reports/lead-funnel-card.d.ts +12 -0
  122. package/src/lib/components/reports/lead-funnel-card.js +9 -5
  123. package/src/lib/components/reports/lead-funnel-card.js.map +1 -1
  124. package/src/lib/components/reports/lead-source-card.d.ts +23 -0
  125. package/src/lib/components/reports/lead-source-card.js +318 -0
  126. package/src/lib/components/reports/lead-source-card.js.map +1 -0
  127. package/src/lib/components/reports/report-export.js +1 -1
  128. package/src/lib/components/reports/report-export.js.map +1 -1
  129. package/src/lib/components/reports-section.js +8 -0
  130. package/src/lib/components/reports-section.js.map +1 -1
  131. package/src/lib/components/sharing-rule-drawer.d.ts +5 -0
  132. package/src/lib/components/sharing-rule-drawer.js +108 -19
  133. package/src/lib/components/sharing-rule-drawer.js.map +1 -1
  134. package/src/lib/components/sharing-rules-card.js +11 -3
  135. package/src/lib/components/sharing-rules-card.js.map +1 -1
  136. package/src/lib/components/task-cells.d.ts +9 -1
  137. package/src/lib/components/task-cells.js +9 -4
  138. package/src/lib/components/task-cells.js.map +1 -1
  139. package/src/lib/components/task-edit-drawer.js +111 -43
  140. package/src/lib/components/task-edit-drawer.js.map +1 -1
  141. package/src/lib/components/tasks-bulk-bar.d.ts +0 -3
  142. package/src/lib/components/tasks-bulk-bar.js +7 -20
  143. package/src/lib/components/tasks-bulk-bar.js.map +1 -1
  144. package/src/lib/components/tasks-calendar.d.ts +3 -0
  145. package/src/lib/components/tasks-calendar.js +8 -1
  146. package/src/lib/components/tasks-calendar.js.map +1 -1
  147. package/src/lib/components/tasks-section.d.ts +3 -3
  148. package/src/lib/components/tasks-section.js +58 -43
  149. package/src/lib/components/tasks-section.js.map +1 -1
  150. package/src/lib/constants/api-routes.d.ts +2 -9
  151. package/src/lib/constants/api-routes.js +1 -7
  152. package/src/lib/constants/api-routes.js.map +1 -1
  153. package/src/lib/constants/bundle-common.d.ts +6 -0
  154. package/src/lib/constants/bundle-common.js +11 -0
  155. package/src/lib/constants/bundle-common.js.map +1 -1
  156. package/src/lib/constants/company-filters.d.ts +14 -0
  157. package/src/lib/constants/company-filters.js +51 -1
  158. package/src/lib/constants/company-filters.js.map +1 -1
  159. package/src/lib/constants/contact-filters.d.ts +2 -0
  160. package/src/lib/constants/contact-filters.js +18 -1
  161. package/src/lib/constants/contact-filters.js.map +1 -1
  162. package/src/lib/constants/deal-filters.d.ts +22 -1
  163. package/src/lib/constants/deal-filters.js +67 -4
  164. package/src/lib/constants/deal-filters.js.map +1 -1
  165. package/src/lib/declarations.console-server.d.ts +3 -0
  166. package/src/lib/declarations.console-server.js +35 -0
  167. package/src/lib/declarations.console-server.js.map +1 -1
  168. package/src/lib/declarations.d.ts +26 -0
  169. package/src/lib/declarations.js +35 -0
  170. package/src/lib/declarations.js.map +1 -0
  171. package/src/lib/declarations.server.d.ts +11 -0
  172. package/src/lib/declarations.server.js +92 -1
  173. package/src/lib/declarations.server.js.map +1 -1
  174. package/src/lib/hooks/use-company-picklists.d.ts +15 -0
  175. package/src/lib/hooks/use-company-picklists.js +55 -0
  176. package/src/lib/hooks/use-company-picklists.js.map +1 -0
  177. package/src/lib/hooks/use-crm-picklist.d.ts +25 -0
  178. package/src/lib/hooks/use-crm-picklist.js +53 -0
  179. package/src/lib/hooks/use-crm-picklist.js.map +1 -0
  180. package/src/lib/hooks/use-crm-record-names.d.ts +16 -0
  181. package/src/lib/hooks/use-crm-record-names.js +45 -19
  182. package/src/lib/hooks/use-crm-record-names.js.map +1 -1
  183. package/src/lib/hooks/use-crm-task-picklists.d.ts +11 -0
  184. package/src/lib/hooks/use-crm-task-picklists.js +45 -0
  185. package/src/lib/hooks/use-crm-task-picklists.js.map +1 -0
  186. package/src/lib/hooks/use-deals.d.ts +14 -0
  187. package/src/lib/hooks/use-deals.js +29 -0
  188. package/src/lib/hooks/use-deals.js.map +1 -1
  189. package/src/lib/hooks/use-lead-picklists.d.ts +14 -0
  190. package/src/lib/hooks/use-lead-picklists.js +46 -0
  191. package/src/lib/hooks/use-lead-picklists.js.map +1 -0
  192. package/src/lib/hooks/use-lead-source-picklist.d.ts +5 -19
  193. package/src/lib/hooks/use-lead-source-picklist.js +12 -22
  194. package/src/lib/hooks/use-lead-source-picklist.js.map +1 -1
  195. package/src/lib/hooks/use-lead-status-picklist.d.ts +9 -0
  196. package/src/lib/hooks/use-lead-status-picklist.js +40 -0
  197. package/src/lib/hooks/use-lead-status-picklist.js.map +1 -0
  198. package/src/lib/model/companies.d.ts +32 -3
  199. package/src/lib/model/companies.js +133 -16
  200. package/src/lib/model/companies.js.map +1 -1
  201. package/src/lib/model/contact-merge.d.ts +27 -3
  202. package/src/lib/model/contact-merge.js +81 -7
  203. package/src/lib/model/contact-merge.js.map +1 -1
  204. package/src/lib/model/contact-record.d.ts +17 -0
  205. package/src/lib/model/contact-record.js +15 -1
  206. package/src/lib/model/contact-record.js.map +1 -1
  207. package/src/lib/model/contact-update.d.ts +31 -2
  208. package/src/lib/model/contact-update.js +14 -0
  209. package/src/lib/model/contact-update.js.map +1 -1
  210. package/src/lib/model/crm-list-query.d.ts +5 -0
  211. package/src/lib/model/crm-list-query.js +8 -0
  212. package/src/lib/model/crm-list-query.js.map +1 -1
  213. package/src/lib/model/crm-recipes.d.ts +40 -0
  214. package/src/lib/model/crm-recipes.js +244 -0
  215. package/src/lib/model/crm-recipes.js.map +1 -0
  216. package/src/lib/model/crm-record-counts.d.ts +36 -0
  217. package/src/lib/model/crm-record-counts.js +54 -0
  218. package/src/lib/model/crm-record-counts.js.map +1 -0
  219. package/src/lib/model/crm-record-lists.d.ts +23 -0
  220. package/src/lib/model/crm-record-lists.js +161 -0
  221. package/src/lib/model/crm-record-lists.js.map +1 -0
  222. package/src/lib/model/crm-reports.d.ts +73 -3
  223. package/src/lib/model/crm-reports.js +120 -1
  224. package/src/lib/model/crm-reports.js.map +1 -1
  225. package/src/lib/model/crm-sharing.d.ts +21 -3
  226. package/src/lib/model/crm-sharing.js +27 -6
  227. package/src/lib/model/crm-sharing.js.map +1 -1
  228. package/src/lib/model/deal-board-model.d.ts +8 -2
  229. package/src/lib/model/deal-board-model.js +15 -2
  230. package/src/lib/model/deal-board-model.js.map +1 -1
  231. package/src/lib/model/deal-contact-roles.d.ts +45 -0
  232. package/src/lib/model/deal-contact-roles.js +73 -0
  233. package/src/lib/model/deal-contact-roles.js.map +1 -0
  234. package/src/lib/model/deal-form-model.d.ts +56 -0
  235. package/src/lib/model/deal-form-model.js +79 -7
  236. package/src/lib/model/deal-form-model.js.map +1 -1
  237. package/src/lib/model/download-text-file.d.ts +23 -0
  238. package/src/lib/model/download-text-file.js +34 -0
  239. package/src/lib/model/download-text-file.js.map +1 -0
  240. package/src/lib/model/lead-filters.d.ts +36 -2
  241. package/src/lib/model/lead-filters.js +123 -2
  242. package/src/lib/model/lead-filters.js.map +1 -1
  243. package/src/lib/model/lead-source-direction.d.ts +38 -0
  244. package/src/lib/model/lead-source-direction.js +52 -0
  245. package/src/lib/model/lead-source-direction.js.map +1 -0
  246. package/src/lib/model/picklist-values.d.ts +119 -0
  247. package/src/lib/model/picklist-values.js +256 -0
  248. package/src/lib/model/picklist-values.js.map +1 -0
  249. package/src/lib/model/record-facts-disclosed.d.ts +81 -0
  250. package/src/lib/model/record-facts-disclosed.js +281 -0
  251. package/src/lib/model/record-facts-disclosed.js.map +1 -0
  252. package/src/lib/model/record-facts.d.ts +215 -34
  253. package/src/lib/model/record-facts.js +307 -128
  254. package/src/lib/model/record-facts.js.map +1 -1
  255. package/src/lib/model/task-picklists.d.ts +52 -0
  256. package/src/lib/model/task-picklists.js +83 -0
  257. package/src/lib/model/task-picklists.js.map +1 -0
  258. package/src/lib/model/task-routes.d.ts +13 -0
  259. package/src/lib/model/task-routes.js +23 -4
  260. package/src/lib/model/task-routes.js.map +1 -1
  261. package/src/lib/plan-entitlements.js +6 -4
  262. package/src/lib/plan-entitlements.js.map +1 -1
  263. package/src/lib/plugin.js +17 -0
  264. package/src/lib/plugin.js.map +1 -1
  265. package/src/lib/server/api-v1/contacts.js +220 -14
  266. package/src/lib/server/api-v1/contacts.js.map +1 -1
  267. package/src/lib/server/api-v1/crm-activities.js +14 -1
  268. package/src/lib/server/api-v1/crm-activities.js.map +1 -1
  269. package/src/lib/server/api-v1/crm-companies.js +123 -14
  270. package/src/lib/server/api-v1/crm-companies.js.map +1 -1
  271. package/src/lib/server/api-v1/crm-deals.js +291 -26
  272. package/src/lib/server/api-v1/crm-deals.js.map +1 -1
  273. package/src/lib/server/api-v1/crm-leads.js +144 -38
  274. package/src/lib/server/api-v1/crm-leads.js.map +1 -1
  275. package/src/lib/server/api-v1/crm-pipelines.d.ts +6 -0
  276. package/src/lib/server/api-v1/crm-pipelines.js +8 -2
  277. package/src/lib/server/api-v1/crm-pipelines.js.map +1 -1
  278. package/src/lib/server/api-v1/crm-tasks.js +75 -33
  279. package/src/lib/server/api-v1/crm-tasks.js.map +1 -1
  280. package/src/lib/server/api-v1/openapi.d.ts +0 -11
  281. package/src/lib/server/api-v1/openapi.js +171 -16
  282. package/src/lib/server/api-v1/openapi.js.map +1 -1
  283. package/src/lib/server/assign-contact-owner.d.ts +162 -0
  284. package/src/lib/server/assign-contact-owner.js +340 -0
  285. package/src/lib/server/assign-contact-owner.js.map +1 -0
  286. package/src/lib/server/associate-company-by-domain.d.ts +70 -0
  287. package/src/lib/server/associate-company-by-domain.js +153 -0
  288. package/src/lib/server/associate-company-by-domain.js.map +1 -0
  289. package/src/lib/server/automation-steps.d.ts +139 -0
  290. package/src/lib/server/automation-steps.js +472 -0
  291. package/src/lib/server/automation-steps.js.map +1 -0
  292. package/src/lib/server/capture-contact.js +65 -21
  293. package/src/lib/server/capture-contact.js.map +1 -1
  294. package/src/lib/server/capture-host-contact.d.ts +104 -0
  295. package/src/lib/server/capture-host-contact.js +151 -0
  296. package/src/lib/server/capture-host-contact.js.map +1 -0
  297. package/src/lib/server/company-children.d.ts +25 -0
  298. package/src/lib/server/company-children.js +42 -0
  299. package/src/lib/server/company-children.js.map +1 -0
  300. package/src/lib/server/company-delete.d.ts +18 -0
  301. package/src/lib/server/company-delete.js +44 -21
  302. package/src/lib/server/company-delete.js.map +1 -1
  303. package/src/lib/server/contact-email-history.js +21 -19
  304. package/src/lib/server/contact-email-history.js.map +1 -1
  305. package/src/lib/server/contact-remove.js +27 -2
  306. package/src/lib/server/contact-remove.js.map +1 -1
  307. package/src/lib/server/contact-reports-to.d.ts +61 -0
  308. package/src/lib/server/contact-reports-to.js +114 -0
  309. package/src/lib/server/contact-reports-to.js.map +1 -0
  310. package/src/lib/server/contact-update.d.ts +42 -1
  311. package/src/lib/server/contact-update.js +204 -23
  312. package/src/lib/server/contact-update.js.map +1 -1
  313. package/src/lib/server/convert-host-lead.d.ts +46 -1
  314. package/src/lib/server/convert-host-lead.js +173 -15
  315. package/src/lib/server/convert-host-lead.js.map +1 -1
  316. package/src/lib/server/convert-open-lead.js +12 -5
  317. package/src/lib/server/convert-open-lead.js.map +1 -1
  318. package/src/lib/server/crm-record-indexes.d.ts +45 -0
  319. package/src/lib/server/crm-record-indexes.js +78 -0
  320. package/src/lib/server/crm-record-indexes.js.map +1 -0
  321. package/src/lib/server/crm-sharing.d.ts +9 -1
  322. package/src/lib/server/crm-sharing.js +23 -3
  323. package/src/lib/server/crm-sharing.js.map +1 -1
  324. package/src/lib/server/deal-contact-roles.d.ts +27 -0
  325. package/src/lib/server/deal-contact-roles.js +89 -0
  326. package/src/lib/server/deal-contact-roles.js.map +1 -0
  327. package/src/lib/server/lead-convert.d.ts +5 -0
  328. package/src/lib/server/lead-convert.js +19 -3
  329. package/src/lib/server/lead-convert.js.map +1 -1
  330. package/src/lib/server/lead-create.d.ts +17 -2
  331. package/src/lib/server/lead-create.js +46 -14
  332. package/src/lib/server/lead-create.js.map +1 -1
  333. package/src/lib/server/lead-nurturing.d.ts +6 -0
  334. package/src/lib/server/lead-nurturing.js +57 -20
  335. package/src/lib/server/lead-nurturing.js.map +1 -1
  336. package/src/lib/server/lead-picklists.d.ts +35 -0
  337. package/src/lib/server/lead-picklists.js +52 -0
  338. package/src/lib/server/lead-picklists.js.map +1 -0
  339. package/src/lib/server/lead-source-picklist.d.ts +1 -13
  340. package/src/lib/server/lead-source-picklist.js +6 -33
  341. package/src/lib/server/lead-source-picklist.js.map +1 -1
  342. package/src/lib/server/merge-contacts.js +22 -4
  343. package/src/lib/server/merge-contacts.js.map +1 -1
  344. package/src/lib/server/person-eraser.d.ts +53 -0
  345. package/src/lib/server/person-eraser.js +149 -0
  346. package/src/lib/server/person-eraser.js.map +1 -0
  347. package/src/lib/server/person-records.d.ts +69 -0
  348. package/src/lib/server/person-records.js +317 -0
  349. package/src/lib/server/person-records.js.map +1 -0
  350. package/src/lib/server/person-refund.d.ts +97 -0
  351. package/src/lib/server/person-refund.js +221 -0
  352. package/src/lib/server/person-refund.js.map +1 -0
  353. package/src/lib/server/picklist-values.d.ts +21 -0
  354. package/src/lib/server/picklist-values.js +308 -0
  355. package/src/lib/server/picklist-values.js.map +1 -0
  356. package/src/lib/server/read-picklist.d.ts +44 -0
  357. package/src/lib/server/read-picklist.js +65 -0
  358. package/src/lib/server/read-picklist.js.map +1 -0
  359. package/src/lib/server/recipe-routes.js +15 -7
  360. package/src/lib/server/recipe-routes.js.map +1 -1
  361. package/src/lib/server/record-email-state.js +7 -1
  362. package/src/lib/server/record-email-state.js.map +1 -1
  363. package/src/lib/server/record-facts.d.ts +3 -0
  364. package/src/lib/server/record-facts.js +233 -31
  365. package/src/lib/server/record-facts.js.map +1 -1
  366. package/src/lib/server/record-origin.d.ts +27 -0
  367. package/src/lib/server/record-origin.js +104 -0
  368. package/src/lib/server/record-origin.js.map +1 -0
  369. package/src/lib/server/record-timeline.js +15 -2
  370. package/src/lib/server/record-timeline.js.map +1 -1
  371. package/src/lib/server/suite-gate.js +4 -3
  372. package/src/lib/server/suite-gate.js.map +1 -1
  373. package/src/lib/server/task-routes.js +30 -16
  374. package/src/lib/server/task-routes.js.map +1 -1
  375. package/src/lib/server-deal-stage.d.ts +5 -1
  376. package/src/lib/server-deal-stage.js +10 -5
  377. package/src/lib/server-deal-stage.js.map +1 -1
  378. package/src/lib/server.d.ts +8 -3
  379. package/src/lib/server.js +47 -43
  380. package/src/lib/server.js.map +1 -1
  381. package/src/lib/testing/memory-firestore.d.ts +55 -0
  382. package/src/lib/testing/memory-firestore.js +335 -0
  383. package/src/lib/testing/memory-firestore.js.map +1 -0
  384. package/src/lib/testing/stand-in-email-send-index.d.ts +25 -0
  385. package/src/lib/testing/stand-in-email-send-index.js +49 -0
  386. package/src/lib/testing/stand-in-email-send-index.js.map +1 -0
  387. package/src/lib/transfer/activities.d.ts +30 -0
  388. package/src/lib/transfer/activities.js +132 -0
  389. package/src/lib/transfer/activities.js.map +1 -0
  390. package/src/lib/transfer/aliases.d.ts +22 -0
  391. package/src/lib/transfer/aliases.js +1342 -0
  392. package/src/lib/transfer/aliases.js.map +1 -0
  393. package/src/lib/transfer/common.d.ts +222 -0
  394. package/src/lib/transfer/common.js +832 -0
  395. package/src/lib/transfer/common.js.map +1 -0
  396. package/src/lib/transfer/companies.d.ts +43 -0
  397. package/src/lib/transfer/companies.js +549 -0
  398. package/src/lib/transfer/companies.js.map +1 -0
  399. package/src/lib/transfer/contacts.d.ts +31 -0
  400. package/src/lib/transfer/contacts.js +727 -0
  401. package/src/lib/transfer/contacts.js.map +1 -0
  402. package/src/lib/transfer/deals.d.ts +66 -0
  403. package/src/lib/transfer/deals.js +698 -0
  404. package/src/lib/transfer/deals.js.map +1 -0
  405. package/src/lib/transfer/email-templates-package.d.ts +40 -0
  406. package/src/lib/transfer/email-templates-package.js +76 -0
  407. package/src/lib/transfer/email-templates-package.js.map +1 -0
  408. package/src/lib/transfer/email-templates-package.server.d.ts +32 -0
  409. package/src/lib/transfer/email-templates-package.server.js +176 -0
  410. package/src/lib/transfer/email-templates-package.server.js.map +1 -0
  411. package/src/lib/transfer/fields.d.ts +102 -0
  412. package/src/lib/transfer/fields.js +1755 -0
  413. package/src/lib/transfer/fields.js.map +1 -0
  414. package/src/lib/transfer/leads.d.ts +30 -0
  415. package/src/lib/transfer/leads.js +582 -0
  416. package/src/lib/transfer/leads.js.map +1 -0
  417. package/src/lib/transfer/pipelines.d.ts +21 -0
  418. package/src/lib/transfer/pipelines.js +172 -0
  419. package/src/lib/transfer/pipelines.js.map +1 -0
  420. package/src/lib/transfer/register.d.ts +47 -0
  421. package/src/lib/transfer/register.js +277 -0
  422. package/src/lib/transfer/register.js.map +1 -0
  423. package/src/lib/transfer/tasks.d.ts +30 -0
  424. package/src/lib/transfer/tasks.js +418 -0
  425. package/src/lib/transfer/tasks.js.map +1 -0
  426. package/src/lib/transfer/ui.d.ts +20 -0
  427. package/src/lib/transfer/ui.js +42 -0
  428. package/src/lib/transfer/ui.js.map +1 -0
  429. package/src/lib/components/company-import-drawer.d.ts +0 -42
  430. package/src/lib/components/company-import-drawer.js +0 -99
  431. package/src/lib/components/company-import-drawer.js.map +0 -1
  432. package/src/lib/components/contact-import-drawer.d.ts +0 -46
  433. package/src/lib/components/contact-import-drawer.js +0 -149
  434. package/src/lib/components/contact-import-drawer.js.map +0 -1
  435. package/src/lib/components/crm-export-all-button.d.ts +0 -39
  436. package/src/lib/components/crm-export-all-button.js +0 -98
  437. package/src/lib/components/crm-export-all-button.js.map +0 -1
  438. package/src/lib/components/csv-import-drawer.d.ts +0 -139
  439. package/src/lib/components/csv-import-drawer.js +0 -757
  440. package/src/lib/components/csv-import-drawer.js.map +0 -1
  441. package/src/lib/components/deal-import-drawer.d.ts +0 -24
  442. package/src/lib/components/deal-import-drawer.js +0 -83
  443. package/src/lib/components/deal-import-drawer.js.map +0 -1
  444. package/src/lib/components/lead-import-drawer.d.ts +0 -27
  445. package/src/lib/components/lead-import-drawer.js +0 -118
  446. package/src/lib/components/lead-import-drawer.js.map +0 -1
  447. package/src/lib/components/lead-source-values-card.d.ts +0 -27
  448. package/src/lib/components/lead-source-values-card.js.map +0 -1
  449. package/src/lib/components/task-import-drawer.d.ts +0 -24
  450. package/src/lib/components/task-import-drawer.js +0 -82
  451. package/src/lib/components/task-import-drawer.js.map +0 -1
  452. package/src/lib/model/companies-csv.d.ts +0 -36
  453. package/src/lib/model/companies-csv.js +0 -38
  454. package/src/lib/model/companies-csv.js.map +0 -1
  455. package/src/lib/model/contacts-csv.d.ts +0 -54
  456. package/src/lib/model/contacts-csv.js +0 -67
  457. package/src/lib/model/contacts-csv.js.map +0 -1
  458. package/src/lib/model/crm-company-import.d.ts +0 -154
  459. package/src/lib/model/crm-company-import.js +0 -331
  460. package/src/lib/model/crm-company-import.js.map +0 -1
  461. package/src/lib/model/crm-csv.d.ts +0 -239
  462. package/src/lib/model/crm-csv.js +0 -467
  463. package/src/lib/model/crm-csv.js.map +0 -1
  464. package/src/lib/model/crm-deal-import.d.ts +0 -112
  465. package/src/lib/model/crm-deal-import.js +0 -263
  466. package/src/lib/model/crm-deal-import.js.map +0 -1
  467. package/src/lib/model/crm-import.d.ts +0 -250
  468. package/src/lib/model/crm-import.js +0 -467
  469. package/src/lib/model/crm-import.js.map +0 -1
  470. package/src/lib/model/crm-lead-import.d.ts +0 -138
  471. package/src/lib/model/crm-lead-import.js +0 -446
  472. package/src/lib/model/crm-lead-import.js.map +0 -1
  473. package/src/lib/model/crm-task-import.d.ts +0 -94
  474. package/src/lib/model/crm-task-import.js +0 -275
  475. package/src/lib/model/crm-task-import.js.map +0 -1
  476. package/src/lib/model/deals-csv.d.ts +0 -32
  477. package/src/lib/model/deals-csv.js +0 -36
  478. package/src/lib/model/deals-csv.js.map +0 -1
  479. package/src/lib/model/import-column-shapes.d.ts +0 -36
  480. package/src/lib/model/import-column-shapes.js +0 -76
  481. package/src/lib/model/import-column-shapes.js.map +0 -1
  482. package/src/lib/model/lead-source-values.d.ts +0 -82
  483. package/src/lib/model/lead-source-values.js +0 -149
  484. package/src/lib/model/lead-source-values.js.map +0 -1
  485. package/src/lib/model/leads-csv.d.ts +0 -40
  486. package/src/lib/model/leads-csv.js +0 -40
  487. package/src/lib/model/leads-csv.js.map +0 -1
  488. package/src/lib/model/tasks-csv.d.ts +0 -28
  489. package/src/lib/model/tasks-csv.js +0 -28
  490. package/src/lib/model/tasks-csv.js.map +0 -1
  491. package/src/lib/server/companies-import.d.ts +0 -57
  492. package/src/lib/server/companies-import.js +0 -242
  493. package/src/lib/server/companies-import.js.map +0 -1
  494. package/src/lib/server/contacts-import.d.ts +0 -109
  495. package/src/lib/server/contacts-import.js +0 -393
  496. package/src/lib/server/contacts-import.js.map +0 -1
  497. package/src/lib/server/deals-import.d.ts +0 -76
  498. package/src/lib/server/deals-import.js +0 -248
  499. package/src/lib/server/deals-import.js.map +0 -1
  500. package/src/lib/server/export-route.d.ts +0 -60
  501. package/src/lib/server/export-route.js +0 -447
  502. package/src/lib/server/export-route.js.map +0 -1
  503. package/src/lib/server/import-context.d.ts +0 -87
  504. package/src/lib/server/import-context.js +0 -182
  505. package/src/lib/server/import-context.js.map +0 -1
  506. package/src/lib/server/lead-source-values.d.ts +0 -50
  507. package/src/lib/server/lead-source-values.js +0 -191
  508. package/src/lib/server/lead-source-values.js.map +0 -1
  509. package/src/lib/server/leads-import.d.ts +0 -84
  510. package/src/lib/server/leads-import.js +0 -367
  511. package/src/lib/server/leads-import.js.map +0 -1
  512. package/src/lib/server/tasks-import.d.ts +0 -54
  513. package/src/lib/server/tasks-import.js +0 -160
  514. package/src/lib/server/tasks-import.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../libs/plugins/crm/src/lib/server/api-v1/crm-deals.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * `/v1/deals` (AGL-2606) — the most commercially sensitive row in the CRM.\n *\n * ## The stage owns the status\n *\n * `status` is denormalized from the stage's `kind` (`crm.ts`), so the two\n * can never disagree on a stored deal. A client may move a deal by either\n * name: `stageId` picks a stage and the status follows; `status` alone picks\n * the pipeline's one `won` or `lost` stage, or its FIRST open stage for\n * `open` — a reopen has to land somewhere, and the top of the pipeline is\n * the only somewhere that needs no second field. Both together must agree,\n * and a pair that does not is refused rather than resolved in favor of\n * either, because whichever one we picked would be the one the client did\n * not mean.\n *\n * Every stage move stamps `stageChangedAtMs`, which is what \"stuck in\n * stage\" reports read, and a move into or out of a closed stage sets or\n * clears `closedAtMs`.\n *\n * ## A won deal makes its contact a customer\n *\n * The console's stage route floors the linked contact's lifecycle stage at\n * `customer` when a deal is won (AGL-2641), and this resource is the same\n * writer with a different door: a `PATCH` that moves a deal into its `won`\n * stage, or a `POST` that creates one there, applies the same floor to the\n * contact the deal names, in the facet of the deal's site — filling an\n * empty stage, advancing an earlier one, never moving anybody back. The\n * deal's own write is not undone by a contact write that fails; the deal\n * is what the integrator asked for, and the floor is what the win implies.\n *\n * ## The line items own the amount\n *\n * A deal may carry `lineItems` (AGL-2620) — the products behind its value,\n * each in the deal's currency. With one or more lines the stored\n * `amountCents` IS their sum, written beside them, so a typed `amountCents`\n * in the same body, or alone on a deal that has lines, is refused rather\n * than reconciled: whichever number we kept would be the one the client did\n * not mean. `lineItems: []` clears the lines and hands the amount back to\n * the client; the last sum stays until it is retyped. Changing the currency\n * of a deal with lines needs the lines resent in that currency, because\n * their sum is one number in one unit.\n */\nimport {\n CRM_COLLECTIONS,\n CRM_MEDIA_IDS_MAX,\n type CrmDeal,\n type CrmDealLineItem,\n type CrmDealStage,\n type CrmDealStatus,\n createResourceUid,\n crmNewRecordListFields,\n dealStageById,\n lineItemsTotalCents,\n normalizeCrmMediaIds,\n readDealLineItems,\n} from '@aglyn/aglyn/server'\nimport { apiJson, ApiErrors, restampCrmListFieldsAt } from '@aglyn/tenant-data-admin'\nimport { Timestamp } from 'firebase-admin/firestore'\nimport {\n type ApiV1Context,\n claimWrite,\n readJsonBody,\n requireScope,\n} from '@aglyn/tenant-data-admin/server/api-v1-kit'\nimport { floorContactLifecycleStage } from '../contact-lifecycle-floor'\nimport { orderedStages, type ResolvedPipeline, resolvePipeline } from './crm-pipelines'\nimport {\n type Clearable,\n CRM_TEXT_MAX,\n CRM_TITLE_MAX,\n createPayload,\n crmCollection,\n crmCreateStamp,\n crmCustomUpdate,\n crmCustomView,\n crmRecordsBandRefusal,\n crmRefErrors,\n crmTimes,\n crmValidationFailed,\n isoFromMs,\n listCrm,\n memberError,\n parseIsoInstant,\n readChoice,\n readCrmCustomBody,\n readCrmSite,\n readEqualityFilters,\n readOptionalText,\n readRefId,\n refuseUnknownKeys,\n updatePayload,\n} from './crm-shared'\n\nconst DEAL_STATUSES = ['open', 'won', 'lost'] as const\n\n/** One line as published: the stored shape, with `productId` always present. */\nfunction lineItemView(item: CrmDealLineItem) {\n return {\n productId: item.productId ?? null,\n name: item.name,\n quantity: item.quantity,\n unitAmountCents: item.unitAmountCents,\n currency: item.currency,\n }\n}\n\n/** The deal object as published. Every writable field appears here. */\nfunction dealView(doc: FirebaseFirestore.DocumentSnapshot) {\n const data = (doc.data() ?? {}) as Partial<CrmDeal>\n return {\n id: doc.id,\n object: 'deal',\n title: data.title ?? null,\n pipelineId: data.pipelineId ?? null,\n stageId: data.stageId ?? null,\n status: data.status ?? null,\n amountCents: typeof data.amountCents === 'number' ? data.amountCents : null,\n // `'usd'` when absent, as the model says — a deal with no currency is a\n // dollar deal, not a deal with an unknown one.\n currency: data.currency ?? 'usd',\n lineItems: Array.isArray(data.lineItems) ? data.lineItems.map(lineItemView) : [],\n expectedCloseAt: isoFromMs(data.expectedCloseAtMs),\n closedAt: isoFromMs(data.closedAtMs),\n stageChangedAt: isoFromMs(data.stageChangedAtMs),\n ownerUid: data.ownerUid ?? null,\n contactId: data.contactId ?? null,\n companyId: data.companyId ?? null,\n lostReason: data.lostReason ?? null,\n notes: data.notes ?? null,\n // The org's deal custom fields, keyed by field key (AGL-2661).\n custom: crmCustomView(data as FirebaseFirestore.DocumentData),\n // When the earliest open task against the deal is due — see\n // `CrmDeal.nextTaskAtMs`. Read-only: the tasks resource maintains it.\n nextTaskAt: isoFromMs(data.nextTaskAtMs),\n mediaIds: normalizeCrmMediaIds(data.mediaIds),\n siteId: data.hostId ?? null,\n ...crmTimes(data as FirebaseFirestore.DocumentData),\n }\n}\n\nconst DEAL_WRITABLE = new Set([\n 'title',\n 'stageId',\n 'status',\n 'amountCents',\n 'currency',\n 'lineItems',\n 'expectedCloseAt',\n 'ownerUid',\n 'contactId',\n 'companyId',\n 'lostReason',\n 'notes',\n 'custom',\n 'mediaIds',\n])\n\ninterface DealInput {\n title?: string\n pipelineId?: string\n stageId?: string\n status?: CrmDealStatus\n amountCents?: Clearable<number>\n currency?: string\n /**\n * The lines as sent, validated only for shape here; the currency check\n * and the sum wait for `placeLineItems`, which knows the deal's currency\n * on a PATCH that did not send one. `[]` means \"clear them\".\n */\n lineItems?: unknown[]\n expectedCloseAtMs?: Clearable<number>\n ownerUid?: Clearable<string>\n contactId?: Clearable<string>\n companyId?: Clearable<string>\n lostReason?: Clearable<string>\n notes?: Clearable<string>\n /** Org-library files attached to the deal (AGL-2662), by media id. */\n mediaIds?: string[]\n}\n\n/**\n * The writable half of a deal, validated. `pipelineId` is accepted on a\n * create only: a deal's stages are its pipeline's, and moving one between\n * pipelines is a new deal in the other pipeline, not an edit.\n */\nfunction readDealInput(\n body: Record<string, unknown>,\n { partial }: { partial: boolean },\n): { values: DealInput } | { errors: Record<string, string> } {\n const errors: Record<string, string> = {}\n const values: DealInput = {}\n const allowed = new Set(DEAL_WRITABLE)\n if (!partial) {\n allowed.add('consentSiteId')\n allowed.add('pipelineId')\n }\n refuseUnknownKeys(body, allowed, 'deal', errors)\n if (partial && body.pipelineId !== undefined) {\n errors.pipelineId = 'Not writable — create the deal in the other pipeline'\n }\n\n if (body.mediaIds !== undefined) {\n if (!Array.isArray(body.mediaIds)) {\n errors.mediaIds = 'Must be an array of media ids'\n } else if (body.mediaIds.length > CRM_MEDIA_IDS_MAX) {\n errors.mediaIds = `At most ${CRM_MEDIA_IDS_MAX} files may be attached`\n } else {\n // The SAME normalizer the console card writes through, so the API\n // cannot store a list the console would refuse. An empty array is\n // legal and clears the attachments.\n values.mediaIds = normalizeCrmMediaIds(body.mediaIds)\n }\n }\n\n if (body.title !== undefined || !partial) {\n const title = String(body.title ?? '')\n .trim()\n .slice(0, CRM_TITLE_MAX)\n if (title) values.title = title\n else errors.title = partial ? 'Must not be empty' : 'A title is required'\n }\n\n if (!partial && body.pipelineId !== undefined) {\n const pipelineId = readRefId(body, 'pipelineId', errors)\n if (pipelineId) values.pipelineId = pipelineId\n else if (pipelineId === null) errors.pipelineId = 'Must be an id'\n }\n\n const stageId = readRefId(body, 'stageId', errors)\n if (stageId) values.stageId = stageId\n else if (stageId === null) errors.stageId = 'Must be a stage id'\n\n const status = readChoice(body, 'status', DEAL_STATUSES, errors)\n if (status) values.status = status\n\n if (body.amountCents !== undefined) {\n if (body.amountCents === null) {\n values.amountCents = null\n } else if (\n typeof body.amountCents !== 'number' ||\n !Number.isInteger(body.amountCents) ||\n body.amountCents < 0\n ) {\n errors.amountCents = 'Must be a whole number of cents, 0 or more'\n } else {\n values.amountCents = body.amountCents\n }\n }\n\n if (body.currency !== undefined) {\n const currency = String(body.currency ?? '')\n .trim()\n .toLowerCase()\n if (/^[a-z]{3}$/.test(currency)) values.currency = currency\n else errors.currency = 'Must be a three-letter ISO 4217 code, like usd'\n }\n\n if (body.lineItems !== undefined) {\n if (body.lineItems === null || (Array.isArray(body.lineItems) && body.lineItems.length === 0)) {\n values.lineItems = []\n } else if (!Array.isArray(body.lineItems)) {\n errors.lineItems = 'Must be a list of line items'\n } else {\n values.lineItems = body.lineItems\n if (body.amountCents !== undefined) {\n errors.amountCents = 'Derived from lineItems — omit it, or send lineItems: [] to type an amount'\n }\n }\n }\n\n if (body.expectedCloseAt !== undefined) {\n if (body.expectedCloseAt === null) {\n values.expectedCloseAtMs = null\n } else {\n const ms = parseIsoInstant(body.expectedCloseAt)\n if (ms === null) {\n errors.expectedCloseAt =\n 'Must be an ISO 8601 instant, like 2026-12-31T00:00:00Z'\n } else {\n values.expectedCloseAtMs = ms\n }\n }\n }\n\n const ownerUid = readOptionalText(body, 'ownerUid', CRM_TITLE_MAX, errors)\n if (ownerUid !== undefined) values.ownerUid = ownerUid\n const contactId = readRefId(body, 'contactId', errors)\n if (contactId !== undefined) values.contactId = contactId\n const companyId = readRefId(body, 'companyId', errors)\n if (companyId !== undefined) values.companyId = companyId\n const lostReason = readOptionalText(body, 'lostReason', CRM_TEXT_MAX, errors)\n if (lostReason !== undefined) values.lostReason = lostReason\n const notes = readOptionalText(body, 'notes', CRM_TEXT_MAX, errors)\n if (notes !== undefined) values.notes = notes\n\n // `custom` is shape-checked here and judged against the org's\n // definitions by the writers, which is where the read is paid.\n if (body.custom !== undefined) {\n if (!body.custom || typeof body.custom !== 'object' || Array.isArray(body.custom)) {\n errors.custom = 'Must be an object of field values keyed by field key'\n }\n }\n\n return Object.keys(errors).length ? { errors } : { values }\n}\n\n/**\n * The stage a write lands the deal in, from `stageId` and/or `status` — see\n * the module header for the rule. `null` when neither was sent, which on a\n * PATCH means \"leave the stage alone\" and on a create means the first open\n * stage.\n */\nfunction resolveStage(\n pipeline: ResolvedPipeline['pipeline'],\n values: Pick<DealInput, 'stageId' | 'status'>,\n): { stage: CrmDealStage | null } | { errors: Record<string, string> } {\n const stages = orderedStages(pipeline)\n if (values.stageId) {\n const stage = dealStageById(pipeline, values.stageId)\n if (!stage) return { errors: { stageId: 'No such stage in this pipeline' } }\n if (values.status && values.status !== stage.kind) {\n return { errors: { status: `Must match the stage, which is ${stage.kind}` } }\n }\n return { stage }\n }\n if (values.status) {\n const stage =\n values.status === 'open'\n ? stages.find((candidate) => candidate.kind === 'open')\n : stages.find((candidate) => candidate.kind === values.status)\n if (!stage) {\n return { errors: { status: `This pipeline has no ${values.status} stage` } }\n }\n return { stage }\n }\n return { stage: null }\n}\n\n/**\n * The stored lines and the amount they derive, for a write that sent\n * `lineItems`, validated against the currency the deal WILL have — the\n * body's, else the stored one, else `usd`. Returns nothing to write when\n * the body carried no lines.\n */\nfunction placeLineItems(\n values: Pick<DealInput, 'lineItems' | 'currency'>,\n stored: Partial<CrmDeal> | null,\n): { fields: Record<string, unknown> } | { errors: Record<string, string> } {\n if (values.lineItems === undefined) return { fields: {} }\n const currency = values.currency ?? stored?.currency ?? 'usd'\n const read = readDealLineItems(values.lineItems, currency)\n if ('error' in read) return { errors: { lineItems: read.error } }\n return {\n fields: {\n lineItems: read.items,\n ...(read.items.length ? { amountCents: lineItemsTotalCents(read.items) } : {}),\n },\n }\n}\n\n/**\n * The customer floor a win applies to the deal's contact (AGL-2641), after\n * the deal itself is written. A contact write that fails is logged and\n * swallowed: the deal is already won, and a `500` would tell the integrator\n * the move they can see in the console did not happen.\n */\nasync function floorWonDealContact(\n ctx: ApiV1Context,\n deal: { contactId?: string | null; hostId?: string | null },\n): Promise<void> {\n const contactId = String(deal.contactId ?? '').trim()\n if (!contactId) return\n try {\n await floorContactLifecycleStage({\n contactRef: ctx.firestore\n .collection('orgs')\n .doc(ctx.orgId)\n .collection('contacts')\n .doc(contactId),\n org: ctx.org as Record<string, unknown>,\n hostId: deal.hostId ?? null,\n floor: 'customer',\n })\n } catch (error) {\n console.error('[api-v1] deals: the customer floor failed', contactId, error)\n }\n}\n\n/** The fields a stage move writes, beside the stage itself. */\nfunction stageMove(stage: CrmDealStage, nowMs: number) {\n return {\n stageId: stage.id,\n status: stage.kind,\n stageChangedAtMs: nowMs,\n closedAtMs: stage.kind === 'open' ? null : nowMs,\n }\n}\n\n/** The membership and reference checks a deal write makes, merged. */\nasync function dealRefErrors(\n ctx: ApiV1Context,\n values: DealInput,\n): Promise<Record<string, string>> {\n const [owner, refs] = await Promise.all([\n memberError(ctx, 'ownerUid', values.ownerUid),\n crmRefErrors(ctx, {\n contactId: values.contactId ?? undefined,\n companyId: values.companyId ?? undefined,\n }),\n ])\n return { ...owner, ...refs }\n}\n\n/**\n * `POST /v1/deals`. The pipeline is resolved AFTER the claim because\n * resolving it can create one (`resolvePipeline`), and a refusal past that\n * point releases the key so the retry that names a real stage still can.\n */\nasync function createDeal(request: Request, ctx: ApiV1Context): Promise<Response> {\n const body = await readJsonBody(request)\n const parsed = readDealInput(body, { partial: false })\n if ('errors' in parsed) return crmValidationFailed(ctx, 'deal', parsed.errors)\n const site = readCrmSite(ctx, 'deal', body)\n if ('response' in site) return site.response\n const refErrors = await dealRefErrors(ctx, parsed.values)\n if (Object.keys(refErrors).length) return crmValidationFailed(ctx, 'deal', refErrors)\n // Judged against the org's deal definitions, above the claim (AGL-2661).\n const custom = await readCrmCustomBody(ctx, body, 'deal')\n if (custom && 'errors' in custom) return crmValidationFailed(ctx, 'deal', custom.errors)\n const customValues = custom && 'values' in custom ? custom.values : {}\n\n const collection = crmCollection(ctx, CRM_COLLECTIONS.deals)\n const claimed = await claimWrite(\n ctx,\n '*',\n request.headers.get('Idempotency-Key'),\n 'deals',\n )\n if ('replay' in claimed) return claimed.replay\n const { claim } = claimed\n\n try {\n const { title, pipelineId, stageId, status, lineItems, ...rest } = parsed.values\n const placedLines = placeLineItems({ lineItems, currency: rest.currency }, null)\n if ('errors' in placedLines) {\n await claim.release()\n return crmValidationFailed(ctx, 'deal', placedLines.errors)\n }\n const resolved = await resolvePipeline(ctx, site.siteId, pipelineId)\n if ('error' in resolved) {\n await claim.release()\n return crmValidationFailed(ctx, 'deal', { pipelineId: resolved.error })\n }\n const placed = resolveStage(resolved.pipeline, { stageId, status })\n if ('errors' in placed) {\n await claim.release()\n return crmValidationFailed(ctx, 'deal', placed.errors)\n }\n const stage = placed.stage ?? orderedStages(resolved.pipeline)[0]\n if (!stage) {\n await claim.release()\n return crmValidationFailed(ctx, 'deal', {\n pipelineId: 'This pipeline has no stages',\n })\n }\n // The records band (AGL-2611), asked last so a refusal past the pipeline\n // resolution releases the key exactly as a bad stage does.\n const bandFull = await crmRecordsBandRefusal(ctx)\n if (bandFull) {\n await claim.release()\n return bandFull\n }\n const id = createResourceUid()\n // One clock: the stage move is stamped with the instant the record's own\n // `createdAt` carries, so a deal created won closed the moment it began.\n const stamp = crmCreateStamp(ctx, site.siteId)\n const record: Record<string, unknown> = {\n title,\n titleLower: (title ?? '').toLowerCase(),\n pipelineId: resolved.id,\n ...createPayload({\n ...rest,\n ...placedLines.fields,\n ...stageMove(stage, stamp.createdAt.toMillis()),\n }),\n ...(Object.keys(customValues).length\n ? { custom: createPayload(customValues) }\n : {}),\n ...stamp,\n }\n // What the console's Deals list searches and filters by (AGL-3321).\n await collection.doc(id).create({ ...record, ...crmNewRecordListFields('deals', record) })\n // A deal created won is a won deal: its contact is a customer from birth.\n if (stage.kind === 'won') {\n await floorWonDealContact(ctx, { contactId: rest.contactId, hostId: site.siteId })\n }\n const view = dealView(await collection.doc(id).get())\n await claim.record(200, view)\n return apiJson(view, { status: 201, headers: ctx.headers })\n } catch (error) {\n await claim.release()\n throw error\n }\n}\n\n/** `PATCH /v1/deals/{id}`. */\nasync function updateDeal(\n request: Request,\n ctx: ApiV1Context,\n ref: FirebaseFirestore.DocumentReference,\n): Promise<Response> {\n const body = await readJsonBody(request)\n const parsed = readDealInput(body, { partial: true })\n if ('errors' in parsed) return crmValidationFailed(ctx, 'deal', parsed.errors)\n const snap = await ref.get()\n if (!snap.exists) {\n return ApiErrors.notFound({ message: 'No such deal', headers: ctx.headers })\n }\n const refErrors = await dealRefErrors(ctx, parsed.values)\n if (Object.keys(refErrors).length) return crmValidationFailed(ctx, 'deal', refErrors)\n const custom = await readCrmCustomBody(ctx, body, 'deal')\n if (custom && 'errors' in custom) return crmValidationFailed(ctx, 'deal', custom.errors)\n\n const { title, stageId, status, lineItems, ...rest } = parsed.values\n const stored = snap.data() as Partial<CrmDeal>\n const storedLines = Array.isArray(stored.lineItems) && stored.lineItems.length > 0\n const keepsLines = storedLines && lineItems === undefined\n if (keepsLines && rest.amountCents !== undefined) {\n return crmValidationFailed(ctx, 'deal', {\n amountCents: \"This deal's amount is the sum of its line items — edit lineItems instead\",\n })\n }\n if (keepsLines && rest.currency !== undefined && rest.currency !== (stored.currency ?? 'usd')) {\n return crmValidationFailed(ctx, 'deal', {\n currency: \"Every line item is in the deal's currency — send lineItems in the new currency with it\",\n })\n }\n const placedLines = placeLineItems({ lineItems, currency: rest.currency }, stored)\n if ('errors' in placedLines) return crmValidationFailed(ctx, 'deal', placedLines.errors)\n const update: Record<string, unknown> = {\n ...(title !== undefined ? { title, titleLower: title.toLowerCase() } : {}),\n ...updatePayload({ ...rest, ...placedLines.fields }),\n ...(custom && 'values' in custom ? crmCustomUpdate(custom.values) : {}),\n }\n // The write's one instant: `updatedAt`, and the stage move if there is one,\n // so a deal closed at T reads updated at T.\n const now = Timestamp.now()\n let won = false\n if (stageId !== undefined || status !== undefined) {\n const current = snap.data() as CrmDeal\n const resolved = await resolvePipeline(ctx, current.hostId, current.pipelineId, {\n allowArchived: true,\n })\n if ('error' in resolved) {\n return crmValidationFailed(ctx, 'deal', {\n stageId: \"This deal's pipeline no longer exists\",\n })\n }\n const placed = resolveStage(resolved.pipeline, { stageId, status })\n if ('errors' in placed) return crmValidationFailed(ctx, 'deal', placed.errors)\n if (placed.stage && placed.stage.id !== current.stageId) {\n Object.assign(update, stageMove(placed.stage, now.toMillis()))\n // The transition INTO won, not a won deal edited: a deal already\n // closed won floored its contact when it closed.\n won = placed.stage.kind === 'won' && current.status !== 'won'\n }\n }\n if (Object.keys(update).length > 0) {\n await ref.update({ ...update, updatedAt: now })\n // What the console's Deals list searches (AGL-3321).\n if ('title' in update) await restampCrmListFieldsAt(ref, 'deals')\n }\n if (won) {\n await floorWonDealContact(ctx, {\n contactId: rest.contactId !== undefined ? rest.contactId : stored.contactId,\n hostId: stored.hostId,\n })\n }\n return apiJson(dealView(await ref.get()), { headers: ctx.headers })\n}\n\n/** `DELETE /v1/deals/{id}` — the deal alone; its tasks and activities stay. */\nasync function deleteDeal(\n request: Request,\n ctx: ApiV1Context,\n ref: FirebaseFirestore.DocumentReference,\n): Promise<Response> {\n const claimed = await claimWrite(\n ctx,\n '*',\n request.headers.get('Idempotency-Key'),\n 'deal-deletes',\n )\n if ('replay' in claimed) return claimed.replay\n const { claim } = claimed\n try {\n const snap = await ref.get()\n if (!snap.exists) {\n await claim.release()\n return ApiErrors.notFound({ message: 'No such deal', headers: ctx.headers })\n }\n await ref.delete()\n const view = { id: ref.id, object: 'deal', deleted: true }\n await claim.record(200, view)\n return apiJson(view, { headers: ctx.headers })\n } catch (error) {\n await claim.release()\n throw error\n }\n}\n\n/**\n * `GET /v1/deals` filters, most selective first — the order `listCrm`\n * indexes them in. `status` is validated against the three values a deal\n * can hold, because `?status=closed` matching nothing is the plausible empty\n * page the conventions refuse to serve.\n */\nasync function listDeals(\n ctx: ApiV1Context,\n collection: FirebaseFirestore.CollectionReference,\n url: URL,\n): Promise<Response> {\n const rawStatus = url.searchParams.get('status')\n if (rawStatus !== null && rawStatus.trim() !== '' && !(DEAL_STATUSES as readonly string[]).includes(rawStatus.trim())) {\n return crmValidationFailed(ctx, 'deal filter', {\n status: `Must be one of: ${DEAL_STATUSES.join(', ')}`,\n })\n }\n const filters = readEqualityFilters(url, [\n 'contactId',\n 'companyId',\n 'pipelineId',\n 'ownerUid',\n 'status',\n ])\n return listCrm(ctx, collection, url, filters, dealView)\n}\n\nexport async function handleDeals(\n request: Request,\n ctx: ApiV1Context,\n segments: string[],\n url: URL,\n): Promise<Response> {\n const collection = crmCollection(ctx, CRM_COLLECTIONS.deals)\n const [, dealId] = segments\n\n if (!dealId) {\n if (request.method === 'GET') {\n const denied = requireScope(ctx, 'crm:read')\n if (denied) return denied\n return listDeals(ctx, collection, url)\n }\n if (request.method === 'POST') {\n const denied = requireScope(ctx, 'crm:write')\n if (denied) return denied\n return createDeal(request, ctx)\n }\n return ApiErrors.methodNotAllowed({\n headers: { ...ctx.headers, Allow: 'GET, POST' },\n })\n }\n\n const ref = collection.doc(dealId)\n if (request.method === 'GET') {\n const denied = requireScope(ctx, 'crm:read')\n if (denied) return denied\n const snap = await ref.get()\n if (!snap.exists) {\n return ApiErrors.notFound({ message: 'No such deal', headers: ctx.headers })\n }\n return apiJson(dealView(snap), { headers: ctx.headers })\n }\n if (request.method === 'PATCH') {\n const denied = requireScope(ctx, 'crm:write')\n if (denied) return denied\n return updateDeal(request, ctx, ref)\n }\n if (request.method === 'DELETE') {\n const denied = requireScope(ctx, 'crm:write')\n if (denied) return denied\n return deleteDeal(request, ctx, ref)\n }\n return ApiErrors.methodNotAllowed({\n headers: { ...ctx.headers, Allow: 'GET, PATCH, DELETE' },\n })\n}\n"],"names":["CRM_COLLECTIONS","CRM_MEDIA_IDS_MAX","createResourceUid","crmNewRecordListFields","dealStageById","lineItemsTotalCents","normalizeCrmMediaIds","readDealLineItems","apiJson","ApiErrors","restampCrmListFieldsAt","Timestamp","claimWrite","readJsonBody","requireScope","floorContactLifecycleStage","orderedStages","resolvePipeline","CRM_TEXT_MAX","CRM_TITLE_MAX","createPayload","crmCollection","crmCreateStamp","crmCustomUpdate","crmCustomView","crmRecordsBandRefusal","crmRefErrors","crmTimes","crmValidationFailed","isoFromMs","listCrm","memberError","parseIsoInstant","readChoice","readCrmCustomBody","readCrmSite","readEqualityFilters","readOptionalText","readRefId","refuseUnknownKeys","updatePayload","DEAL_STATUSES","lineItemView","item","productId","name","quantity","unitAmountCents","currency","dealView","doc","data","id","object","title","pipelineId","stageId","status","amountCents","lineItems","Array","isArray","map","expectedCloseAt","expectedCloseAtMs","closedAt","closedAtMs","stageChangedAt","stageChangedAtMs","ownerUid","contactId","companyId","lostReason","notes","custom","nextTaskAt","nextTaskAtMs","mediaIds","siteId","hostId","DEAL_WRITABLE","Set","readDealInput","body","partial","errors","values","allowed","add","undefined","length","String","trim","slice","Number","isInteger","toLowerCase","test","ms","Object","keys","resolveStage","pipeline","stages","stage","kind","find","candidate","placeLineItems","stored","fields","read","error","items","floorWonDealContact","ctx","deal","contactRef","firestore","collection","orgId","org","floor","console","stageMove","nowMs","dealRefErrors","owner","refs","Promise","all","createDeal","request","parsed","site","response","refErrors","customValues","deals","claimed","headers","get","replay","claim","placed","rest","placedLines","release","resolved","bandFull","stamp","record","titleLower","createdAt","toMillis","create","view","updateDeal","ref","snap","exists","notFound","message","storedLines","keepsLines","update","now","won","current","allowArchived","assign","updatedAt","deleteDeal","delete","deleted","listDeals","url","rawStatus","searchParams","includes","join","filters","handleDeals","segments","dealId","method","denied","methodNotAllowed","Allow"],"mappings":";;AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyCC,GACD,SACEA,eAAe,EACfC,iBAAiB,EAKjBC,iBAAiB,EACjBC,sBAAsB,EACtBC,aAAa,EACbC,mBAAmB,EACnBC,oBAAoB,EACpBC,iBAAiB,QACZ,sBAAqB;AAC5B,SAASC,OAAO,EAAEC,SAAS,EAAEC,sBAAsB,QAAQ,2BAA0B;AACrF,SAASC,SAAS,QAAQ,2BAA0B;AACpD,SAEEC,UAAU,EACVC,YAAY,EACZC,YAAY,QACP,6CAA4C;AACnD,SAASC,0BAA0B,QAAQ,gCAA4B;AACvE,SAASC,aAAa,EAAyBC,eAAe,QAAQ,qBAAiB;AACvF,SAEEC,YAAY,EACZC,aAAa,EACbC,aAAa,EACbC,aAAa,EACbC,cAAc,EACdC,eAAe,EACfC,aAAa,EACbC,qBAAqB,EACrBC,YAAY,EACZC,QAAQ,EACRC,mBAAmB,EACnBC,SAAS,EACTC,OAAO,EACPC,WAAW,EACXC,eAAe,EACfC,UAAU,EACVC,iBAAiB,EACjBC,WAAW,EACXC,mBAAmB,EACnBC,gBAAgB,EAChBC,SAAS,EACTC,iBAAiB,EACjBC,aAAa,QACR,kBAAc;AAErB,MAAMC,gBAAgB;IAAC;IAAQ;IAAO;CAAO;AAE7C,8EAA8E,GAC9E,SAASC,aAAaC,IAAqB;QAE5BA;IADb,OAAO;QACLC,SAAS,GAAED,kBAAAA,KAAKC,SAAS,YAAdD,kBAAkB;QAC7BE,MAAMF,KAAKE,IAAI;QACfC,UAAUH,KAAKG,QAAQ;QACvBC,iBAAiBJ,KAAKI,eAAe;QACrCC,UAAUL,KAAKK,QAAQ;IACzB;AACF;AAEA,qEAAqE,GACrE,SAASC,SAASC,GAAuC;QACzCA,WAILC,aACKA,kBACHA,eACDA,cAIEA,gBAKAA,gBACCA,iBACAA,iBACCA,kBACLA,aAOCA;IA3BV,MAAMA,QAAQD,YAAAA,IAAIC,IAAI,cAARD,YAAc,CAAC;IAC7B,OAAO;QACLE,IAAIF,IAAIE,EAAE;QACVC,QAAQ;QACRC,KAAK,GAAEH,cAAAA,KAAKG,KAAK,YAAVH,cAAc;QACrBI,UAAU,GAAEJ,mBAAAA,KAAKI,UAAU,YAAfJ,mBAAmB;QAC/BK,OAAO,GAAEL,gBAAAA,KAAKK,OAAO,YAAZL,gBAAgB;QACzBM,MAAM,GAAEN,eAAAA,KAAKM,MAAM,YAAXN,eAAe;QACvBO,aAAa,OAAOP,KAAKO,WAAW,KAAK,WAAWP,KAAKO,WAAW,GAAG;QACvE,wEAAwE;QACxE,+CAA+C;QAC/CV,QAAQ,GAAEG,iBAAAA,KAAKH,QAAQ,YAAbG,iBAAiB;QAC3BQ,WAAWC,MAAMC,OAAO,CAACV,KAAKQ,SAAS,IAAIR,KAAKQ,SAAS,CAACG,GAAG,CAACpB,gBAAgB,EAAE;QAChFqB,iBAAiBlC,UAAUsB,KAAKa,iBAAiB;QACjDC,UAAUpC,UAAUsB,KAAKe,UAAU;QACnCC,gBAAgBtC,UAAUsB,KAAKiB,gBAAgB;QAC/CC,QAAQ,GAAElB,iBAAAA,KAAKkB,QAAQ,YAAblB,iBAAiB;QAC3BmB,SAAS,GAAEnB,kBAAAA,KAAKmB,SAAS,YAAdnB,kBAAkB;QAC7BoB,SAAS,GAAEpB,kBAAAA,KAAKoB,SAAS,YAAdpB,kBAAkB;QAC7BqB,UAAU,GAAErB,mBAAAA,KAAKqB,UAAU,YAAfrB,mBAAmB;QAC/BsB,KAAK,GAAEtB,cAAAA,KAAKsB,KAAK,YAAVtB,cAAc;QACrB,+DAA+D;QAC/DuB,QAAQlD,cAAc2B;QACtB,4DAA4D;QAC5D,sEAAsE;QACtEwB,YAAY9C,UAAUsB,KAAKyB,YAAY;QACvCC,UAAUvE,qBAAqB6C,KAAK0B,QAAQ;QAC5CC,MAAM,GAAE3B,eAAAA,KAAK4B,MAAM,YAAX5B,eAAe;OACpBxB,SAASwB;AAEhB;AAEA,MAAM6B,gBAAgB,IAAIC,IAAI;IAC5B;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD;AAyBD;;;;CAIC,GACD,SAASC,cACPC,IAA6B,EAC7B,EAAEC,OAAO,EAAwB;IAEjC,MAAMC,SAAiC,CAAC;IACxC,MAAMC,SAAoB,CAAC;IAC3B,MAAMC,UAAU,IAAIN,IAAID;IACxB,IAAI,CAACI,SAAS;QACZG,QAAQC,GAAG,CAAC;QACZD,QAAQC,GAAG,CAAC;IACd;IACAjD,kBAAkB4C,MAAMI,SAAS,QAAQF;IACzC,IAAID,WAAWD,KAAK5B,UAAU,KAAKkC,WAAW;QAC5CJ,OAAO9B,UAAU,GAAG;IACtB;IAEA,IAAI4B,KAAKN,QAAQ,KAAKY,WAAW;QAC/B,IAAI,CAAC7B,MAAMC,OAAO,CAACsB,KAAKN,QAAQ,GAAG;YACjCQ,OAAOR,QAAQ,GAAG;QACpB,OAAO,IAAIM,KAAKN,QAAQ,CAACa,MAAM,GAAGzF,mBAAmB;YACnDoF,OAAOR,QAAQ,GAAG,CAAC,QAAQ,EAAE5E,kBAAkB,sBAAsB,CAAC;QACxE,OAAO;YACL,kEAAkE;YAClE,kEAAkE;YAClE,oCAAoC;YACpCqF,OAAOT,QAAQ,GAAGvE,qBAAqB6E,KAAKN,QAAQ;QACtD;IACF;IAEA,IAAIM,KAAK7B,KAAK,KAAKmC,aAAa,CAACL,SAAS;YACnBD;QAArB,MAAM7B,QAAQqC,QAAOR,cAAAA,KAAK7B,KAAK,YAAV6B,cAAc,IAChCS,IAAI,GACJC,KAAK,CAAC,GAAG1E;QACZ,IAAImC,OAAOgC,OAAOhC,KAAK,GAAGA;aACrB+B,OAAO/B,KAAK,GAAG8B,UAAU,sBAAsB;IACtD;IAEA,IAAI,CAACA,WAAWD,KAAK5B,UAAU,KAAKkC,WAAW;QAC7C,MAAMlC,aAAajB,UAAU6C,MAAM,cAAcE;QACjD,IAAI9B,YAAY+B,OAAO/B,UAAU,GAAGA;aAC/B,IAAIA,eAAe,MAAM8B,OAAO9B,UAAU,GAAG;IACpD;IAEA,MAAMC,UAAUlB,UAAU6C,MAAM,WAAWE;IAC3C,IAAI7B,SAAS8B,OAAO9B,OAAO,GAAGA;SACzB,IAAIA,YAAY,MAAM6B,OAAO7B,OAAO,GAAG;IAE5C,MAAMC,SAASxB,WAAWkD,MAAM,UAAU1C,eAAe4C;IACzD,IAAI5B,QAAQ6B,OAAO7B,MAAM,GAAGA;IAE5B,IAAI0B,KAAKzB,WAAW,KAAK+B,WAAW;QAClC,IAAIN,KAAKzB,WAAW,KAAK,MAAM;YAC7B4B,OAAO5B,WAAW,GAAG;QACvB,OAAO,IACL,OAAOyB,KAAKzB,WAAW,KAAK,YAC5B,CAACoC,OAAOC,SAAS,CAACZ,KAAKzB,WAAW,KAClCyB,KAAKzB,WAAW,GAAG,GACnB;YACA2B,OAAO3B,WAAW,GAAG;QACvB,OAAO;YACL4B,OAAO5B,WAAW,GAAGyB,KAAKzB,WAAW;QACvC;IACF;IAEA,IAAIyB,KAAKnC,QAAQ,KAAKyC,WAAW;YACPN;QAAxB,MAAMnC,WAAW2C,QAAOR,iBAAAA,KAAKnC,QAAQ,YAAbmC,iBAAiB,IACtCS,IAAI,GACJI,WAAW;QACd,IAAI,aAAaC,IAAI,CAACjD,WAAWsC,OAAOtC,QAAQ,GAAGA;aAC9CqC,OAAOrC,QAAQ,GAAG;IACzB;IAEA,IAAImC,KAAKxB,SAAS,KAAK8B,WAAW;QAChC,IAAIN,KAAKxB,SAAS,KAAK,QAASC,MAAMC,OAAO,CAACsB,KAAKxB,SAAS,KAAKwB,KAAKxB,SAAS,CAAC+B,MAAM,KAAK,GAAI;YAC7FJ,OAAO3B,SAAS,GAAG,EAAE;QACvB,OAAO,IAAI,CAACC,MAAMC,OAAO,CAACsB,KAAKxB,SAAS,GAAG;YACzC0B,OAAO1B,SAAS,GAAG;QACrB,OAAO;YACL2B,OAAO3B,SAAS,GAAGwB,KAAKxB,SAAS;YACjC,IAAIwB,KAAKzB,WAAW,KAAK+B,WAAW;gBAClCJ,OAAO3B,WAAW,GAAG;YACvB;QACF;IACF;IAEA,IAAIyB,KAAKpB,eAAe,KAAK0B,WAAW;QACtC,IAAIN,KAAKpB,eAAe,KAAK,MAAM;YACjCuB,OAAOtB,iBAAiB,GAAG;QAC7B,OAAO;YACL,MAAMkC,KAAKlE,gBAAgBmD,KAAKpB,eAAe;YAC/C,IAAImC,OAAO,MAAM;gBACfb,OAAOtB,eAAe,GACpB;YACJ,OAAO;gBACLuB,OAAOtB,iBAAiB,GAAGkC;YAC7B;QACF;IACF;IAEA,MAAM7B,WAAWhC,iBAAiB8C,MAAM,YAAYhE,eAAekE;IACnE,IAAIhB,aAAaoB,WAAWH,OAAOjB,QAAQ,GAAGA;IAC9C,MAAMC,YAAYhC,UAAU6C,MAAM,aAAaE;IAC/C,IAAIf,cAAcmB,WAAWH,OAAOhB,SAAS,GAAGA;IAChD,MAAMC,YAAYjC,UAAU6C,MAAM,aAAaE;IAC/C,IAAId,cAAckB,WAAWH,OAAOf,SAAS,GAAGA;IAChD,MAAMC,aAAanC,iBAAiB8C,MAAM,cAAcjE,cAAcmE;IACtE,IAAIb,eAAeiB,WAAWH,OAAOd,UAAU,GAAGA;IAClD,MAAMC,QAAQpC,iBAAiB8C,MAAM,SAASjE,cAAcmE;IAC5D,IAAIZ,UAAUgB,WAAWH,OAAOb,KAAK,GAAGA;IAExC,8DAA8D;IAC9D,+DAA+D;IAC/D,IAAIU,KAAKT,MAAM,KAAKe,WAAW;QAC7B,IAAI,CAACN,KAAKT,MAAM,IAAI,OAAOS,KAAKT,MAAM,KAAK,YAAYd,MAAMC,OAAO,CAACsB,KAAKT,MAAM,GAAG;YACjFW,OAAOX,MAAM,GAAG;QAClB;IACF;IAEA,OAAOyB,OAAOC,IAAI,CAACf,QAAQK,MAAM,GAAG;QAAEL;IAAO,IAAI;QAAEC;IAAO;AAC5D;AAEA;;;;;CAKC,GACD,SAASe,aACPC,QAAsC,EACtChB,MAA6C;IAE7C,MAAMiB,SAASvF,cAAcsF;IAC7B,IAAIhB,OAAO9B,OAAO,EAAE;QAClB,MAAMgD,QAAQpG,cAAckG,UAAUhB,OAAO9B,OAAO;QACpD,IAAI,CAACgD,OAAO,OAAO;YAAEnB,QAAQ;gBAAE7B,SAAS;YAAiC;QAAE;QAC3E,IAAI8B,OAAO7B,MAAM,IAAI6B,OAAO7B,MAAM,KAAK+C,MAAMC,IAAI,EAAE;YACjD,OAAO;gBAAEpB,QAAQ;oBAAE5B,QAAQ,CAAC,+BAA+B,EAAE+C,MAAMC,IAAI,EAAE;gBAAC;YAAE;QAC9E;QACA,OAAO;YAAED;QAAM;IACjB;IACA,IAAIlB,OAAO7B,MAAM,EAAE;QACjB,MAAM+C,QACJlB,OAAO7B,MAAM,KAAK,SACd8C,OAAOG,IAAI,CAAC,CAACC,YAAcA,UAAUF,IAAI,KAAK,UAC9CF,OAAOG,IAAI,CAAC,CAACC,YAAcA,UAAUF,IAAI,KAAKnB,OAAO7B,MAAM;QACjE,IAAI,CAAC+C,OAAO;YACV,OAAO;gBAAEnB,QAAQ;oBAAE5B,QAAQ,CAAC,qBAAqB,EAAE6B,OAAO7B,MAAM,CAAC,MAAM,CAAC;gBAAC;YAAE;QAC7E;QACA,OAAO;YAAE+C;QAAM;IACjB;IACA,OAAO;QAAEA,OAAO;IAAK;AACvB;AAEA;;;;;CAKC,GACD,SAASI,eACPtB,MAAiD,EACjDuB,MAA+B;QAGdvB,MAAAA;IADjB,IAAIA,OAAO3B,SAAS,KAAK8B,WAAW,OAAO;QAAEqB,QAAQ,CAAC;IAAE;IACxD,MAAM9D,YAAWsC,QAAAA,mBAAAA,OAAOtC,QAAQ,YAAfsC,mBAAmBuB,0BAAAA,OAAQ7D,QAAQ,YAAnCsC,OAAuC;IACxD,MAAMyB,OAAOxG,kBAAkB+E,OAAO3B,SAAS,EAAEX;IACjD,IAAI,WAAW+D,MAAM,OAAO;QAAE1B,QAAQ;YAAE1B,WAAWoD,KAAKC,KAAK;QAAC;IAAE;IAChE,OAAO;QACLF,QAAQ;YACNnD,WAAWoD,KAAKE,KAAK;WACjBF,KAAKE,KAAK,CAACvB,MAAM,GAAG;YAAEhC,aAAarD,oBAAoB0G,KAAKE,KAAK;QAAE,IAAI,CAAC;IAEhF;AACF;AAEA;;;;;CAKC,GACD,eAAeC,oBACbC,GAAiB,EACjBC,IAA2D;QAElCA;IAAzB,MAAM9C,YAAYqB,QAAOyB,kBAAAA,KAAK9C,SAAS,YAAd8C,kBAAkB,IAAIxB,IAAI;IACnD,IAAI,CAACtB,WAAW;IAChB,IAAI;YAQQ8C;QAPV,MAAMrG,2BAA2B;YAC/BsG,YAAYF,IAAIG,SAAS,CACtBC,UAAU,CAAC,QACXrE,GAAG,CAACiE,IAAIK,KAAK,EACbD,UAAU,CAAC,YACXrE,GAAG,CAACoB;YACPmD,KAAKN,IAAIM,GAAG;YACZ1C,MAAM,GAAEqC,eAAAA,KAAKrC,MAAM,YAAXqC,eAAe;YACvBM,OAAO;QACT;IACF,EAAE,OAAOV,OAAO;QACdW,QAAQX,KAAK,CAAC,6CAA6C1C,WAAW0C;IACxE;AACF;AAEA,6DAA6D,GAC7D,SAASY,UAAUpB,KAAmB,EAAEqB,KAAa;IACnD,OAAO;QACLrE,SAASgD,MAAMpD,EAAE;QACjBK,QAAQ+C,MAAMC,IAAI;QAClBrC,kBAAkByD;QAClB3D,YAAYsC,MAAMC,IAAI,KAAK,SAAS,OAAOoB;IAC7C;AACF;AAEA,oEAAoE,GACpE,eAAeC,cACbX,GAAiB,EACjB7B,MAAiB;QAKFA,mBACAA;IAJf,MAAM,CAACyC,OAAOC,KAAK,GAAG,MAAMC,QAAQC,GAAG,CAAC;QACtCnG,YAAYoF,KAAK,YAAY7B,OAAOjB,QAAQ;QAC5C3C,aAAayF,KAAK;YAChB7C,SAAS,GAAEgB,oBAAAA,OAAOhB,SAAS,YAAhBgB,oBAAoBG;YAC/BlB,SAAS,GAAEe,oBAAAA,OAAOf,SAAS,YAAhBe,oBAAoBG;QACjC;KACD;IACD,OAAO,aAAKsC,OAAUC;AACxB;AAEA;;;;CAIC,GACD,eAAeG,WAAWC,OAAgB,EAAEjB,GAAiB;IAC3D,MAAMhC,OAAO,MAAMtE,aAAauH;IAChC,MAAMC,SAASnD,cAAcC,MAAM;QAAEC,SAAS;IAAM;IACpD,IAAI,YAAYiD,QAAQ,OAAOzG,oBAAoBuF,KAAK,QAAQkB,OAAOhD,MAAM;IAC7E,MAAMiD,OAAOnG,YAAYgF,KAAK,QAAQhC;IACtC,IAAI,cAAcmD,MAAM,OAAOA,KAAKC,QAAQ;IAC5C,MAAMC,YAAY,MAAMV,cAAcX,KAAKkB,OAAO/C,MAAM;IACxD,IAAIa,OAAOC,IAAI,CAACoC,WAAW9C,MAAM,EAAE,OAAO9D,oBAAoBuF,KAAK,QAAQqB;IAC3E,yEAAyE;IACzE,MAAM9D,SAAS,MAAMxC,kBAAkBiF,KAAKhC,MAAM;IAClD,IAAIT,UAAU,YAAYA,QAAQ,OAAO9C,oBAAoBuF,KAAK,QAAQzC,OAAOW,MAAM;IACvF,MAAMoD,eAAe/D,UAAU,YAAYA,SAASA,OAAOY,MAAM,GAAG,CAAC;IAErE,MAAMiC,aAAalG,cAAc8F,KAAKnH,gBAAgB0I,KAAK;IAC3D,MAAMC,UAAU,MAAM/H,WACpBuG,KACA,KACAiB,QAAQQ,OAAO,CAACC,GAAG,CAAC,oBACpB;IAEF,IAAI,YAAYF,SAAS,OAAOA,QAAQG,MAAM;IAC9C,MAAM,EAAEC,KAAK,EAAE,GAAGJ;IAElB,IAAI;YAiBYK;QAhBd,MAAmEX,iBAAAA,OAAO/C,MAAM,EAA1E,EAAEhC,KAAK,EAAEC,UAAU,EAAEC,OAAO,EAAEC,MAAM,EAAEE,SAAS,EAAW,GAAG0E,gBAATY,wCAASZ;;;;;;;QACnE,MAAMa,cAActC,eAAe;YAAEjD;YAAWX,UAAUiG,KAAKjG,QAAQ;QAAC,GAAG;QAC3E,IAAI,YAAYkG,aAAa;YAC3B,MAAMH,MAAMI,OAAO;YACnB,OAAOvH,oBAAoBuF,KAAK,QAAQ+B,YAAY7D,MAAM;QAC5D;QACA,MAAM+D,WAAW,MAAMnI,gBAAgBkG,KAAKmB,KAAKxD,MAAM,EAAEvB;QACzD,IAAI,WAAW6F,UAAU;YACvB,MAAML,MAAMI,OAAO;YACnB,OAAOvH,oBAAoBuF,KAAK,QAAQ;gBAAE5D,YAAY6F,SAASpC,KAAK;YAAC;QACvE;QACA,MAAMgC,SAAS3C,aAAa+C,SAAS9C,QAAQ,EAAE;YAAE9C;YAASC;QAAO;QACjE,IAAI,YAAYuF,QAAQ;YACtB,MAAMD,MAAMI,OAAO;YACnB,OAAOvH,oBAAoBuF,KAAK,QAAQ6B,OAAO3D,MAAM;QACvD;QACA,MAAMmB,SAAQwC,gBAAAA,OAAOxC,KAAK,YAAZwC,gBAAgBhI,cAAcoI,SAAS9C,QAAQ,CAAC,CAAC,EAAE;QACjE,IAAI,CAACE,OAAO;YACV,MAAMuC,MAAMI,OAAO;YACnB,OAAOvH,oBAAoBuF,KAAK,QAAQ;gBACtC5D,YAAY;YACd;QACF;QACA,yEAAyE;QACzE,2DAA2D;QAC3D,MAAM8F,WAAW,MAAM5H,sBAAsB0F;QAC7C,IAAIkC,UAAU;YACZ,MAAMN,MAAMI,OAAO;YACnB,OAAOE;QACT;QACA,MAAMjG,KAAKlD;QACX,yEAAyE;QACzE,yEAAyE;QACzE,MAAMoJ,QAAQhI,eAAe6F,KAAKmB,KAAKxD,MAAM;QAC7C,MAAMyE,SAAkC;YACtCjG;YACAkG,YAAY,CAAClG,gBAAAA,QAAS,IAAI0C,WAAW;YACrCzC,YAAY6F,SAAShG,EAAE;WACpBhC,cAAc,aACZ6H,MACAC,YAAYpC,MAAM,EAClBc,UAAUpB,OAAO8C,MAAMG,SAAS,CAACC,QAAQ,OAE1CvD,OAAOC,IAAI,CAACqC,cAAc/C,MAAM,GAChC;YAAEhB,QAAQtD,cAAcqH;QAAc,IACtC,CAAC,GACFa;QAEL,oEAAoE;QACpE,MAAM/B,WAAWrE,GAAG,CAACE,IAAIuG,MAAM,CAAC,aAAKJ,QAAWpJ,uBAAuB,SAASoJ;QAChF,0EAA0E;QAC1E,IAAI/C,MAAMC,IAAI,KAAK,OAAO;YACxB,MAAMS,oBAAoBC,KAAK;gBAAE7C,WAAW2E,KAAK3E,SAAS;gBAAES,QAAQuD,KAAKxD,MAAM;YAAC;QAClF;QACA,MAAM8E,OAAO3G,SAAS,MAAMsE,WAAWrE,GAAG,CAACE,IAAIyF,GAAG;QAClD,MAAME,MAAMQ,MAAM,CAAC,KAAKK;QACxB,OAAOpJ,QAAQoJ,MAAM;YAAEnG,QAAQ;YAAKmF,SAASzB,IAAIyB,OAAO;QAAC;IAC3D,EAAE,OAAO5B,OAAO;QACd,MAAM+B,MAAMI,OAAO;QACnB,MAAMnC;IACR;AACF;AAEA,4BAA4B,GAC5B,eAAe6C,WACbzB,OAAgB,EAChBjB,GAAiB,EACjB2C,GAAwC;QAuB4BjD;IArBpE,MAAM1B,OAAO,MAAMtE,aAAauH;IAChC,MAAMC,SAASnD,cAAcC,MAAM;QAAEC,SAAS;IAAK;IACnD,IAAI,YAAYiD,QAAQ,OAAOzG,oBAAoBuF,KAAK,QAAQkB,OAAOhD,MAAM;IAC7E,MAAM0E,OAAO,MAAMD,IAAIjB,GAAG;IAC1B,IAAI,CAACkB,KAAKC,MAAM,EAAE;QAChB,OAAOvJ,UAAUwJ,QAAQ,CAAC;YAAEC,SAAS;YAAgBtB,SAASzB,IAAIyB,OAAO;QAAC;IAC5E;IACA,MAAMJ,YAAY,MAAMV,cAAcX,KAAKkB,OAAO/C,MAAM;IACxD,IAAIa,OAAOC,IAAI,CAACoC,WAAW9C,MAAM,EAAE,OAAO9D,oBAAoBuF,KAAK,QAAQqB;IAC3E,MAAM9D,SAAS,MAAMxC,kBAAkBiF,KAAKhC,MAAM;IAClD,IAAIT,UAAU,YAAYA,QAAQ,OAAO9C,oBAAoBuF,KAAK,QAAQzC,OAAOW,MAAM;IAEvF,MAAuDgD,iBAAAA,OAAO/C,MAAM,EAA9D,EAAEhC,KAAK,EAAEE,OAAO,EAAEC,MAAM,EAAEE,SAAS,EAAW,GAAG0E,gBAATY,wCAASZ;;;;;;IACvD,MAAMxB,SAASkD,KAAK5G,IAAI;IACxB,MAAMgH,cAAcvG,MAAMC,OAAO,CAACgD,OAAOlD,SAAS,KAAKkD,OAAOlD,SAAS,CAAC+B,MAAM,GAAG;IACjF,MAAM0E,aAAaD,eAAexG,cAAc8B;IAChD,IAAI2E,cAAcnB,KAAKvF,WAAW,KAAK+B,WAAW;QAChD,OAAO7D,oBAAoBuF,KAAK,QAAQ;YACtCzD,aAAa;QACf;IACF;IACA,IAAI0G,cAAcnB,KAAKjG,QAAQ,KAAKyC,aAAawD,KAAKjG,QAAQ,OAAM6D,mBAAAA,OAAO7D,QAAQ,YAAf6D,mBAAmB,QAAQ;QAC7F,OAAOjF,oBAAoBuF,KAAK,QAAQ;YACtCnE,UAAU;QACZ;IACF;IACA,MAAMkG,cAActC,eAAe;QAAEjD;QAAWX,UAAUiG,KAAKjG,QAAQ;IAAC,GAAG6D;IAC3E,IAAI,YAAYqC,aAAa,OAAOtH,oBAAoBuF,KAAK,QAAQ+B,YAAY7D,MAAM;IACvF,MAAMgF,SAAkC,aAClC/G,UAAUmC,YAAY;QAAEnC;QAAOkG,YAAYlG,MAAM0C,WAAW;IAAG,IAAI,CAAC,GACrExD,cAAc,aAAKyG,MAASC,YAAYpC,MAAM,IAC7CpC,UAAU,YAAYA,SAASnD,gBAAgBmD,OAAOY,MAAM,IAAI,CAAC;IAEvE,4EAA4E;IAC5E,4CAA4C;IAC5C,MAAMgF,MAAM3J,UAAU2J,GAAG;IACzB,IAAIC,MAAM;IACV,IAAI/G,YAAYiC,aAAahC,WAAWgC,WAAW;QACjD,MAAM+E,UAAUT,KAAK5G,IAAI;QACzB,MAAMiG,WAAW,MAAMnI,gBAAgBkG,KAAKqD,QAAQzF,MAAM,EAAEyF,QAAQjH,UAAU,EAAE;YAC9EkH,eAAe;QACjB;QACA,IAAI,WAAWrB,UAAU;YACvB,OAAOxH,oBAAoBuF,KAAK,QAAQ;gBACtC3D,SAAS;YACX;QACF;QACA,MAAMwF,SAAS3C,aAAa+C,SAAS9C,QAAQ,EAAE;YAAE9C;YAASC;QAAO;QACjE,IAAI,YAAYuF,QAAQ,OAAOpH,oBAAoBuF,KAAK,QAAQ6B,OAAO3D,MAAM;QAC7E,IAAI2D,OAAOxC,KAAK,IAAIwC,OAAOxC,KAAK,CAACpD,EAAE,KAAKoH,QAAQhH,OAAO,EAAE;YACvD2C,OAAOuE,MAAM,CAACL,QAAQzC,UAAUoB,OAAOxC,KAAK,EAAE8D,IAAIZ,QAAQ;YAC1D,iEAAiE;YACjE,iDAAiD;YACjDa,MAAMvB,OAAOxC,KAAK,CAACC,IAAI,KAAK,SAAS+D,QAAQ/G,MAAM,KAAK;QAC1D;IACF;IACA,IAAI0C,OAAOC,IAAI,CAACiE,QAAQ3E,MAAM,GAAG,GAAG;QAClC,MAAMoE,IAAIO,MAAM,CAAC,aAAKA;YAAQM,WAAWL;;QACzC,qDAAqD;QACrD,IAAI,WAAWD,QAAQ,MAAM3J,uBAAuBoJ,KAAK;IAC3D;IACA,IAAIS,KAAK;QACP,MAAMrD,oBAAoBC,KAAK;YAC7B7C,WAAW2E,KAAK3E,SAAS,KAAKmB,YAAYwD,KAAK3E,SAAS,GAAGuC,OAAOvC,SAAS;YAC3ES,QAAQ8B,OAAO9B,MAAM;QACvB;IACF;IACA,OAAOvE,QAAQyC,SAAS,MAAM6G,IAAIjB,GAAG,KAAK;QAAED,SAASzB,IAAIyB,OAAO;IAAC;AACnE;AAEA,6EAA6E,GAC7E,eAAegC,WACbxC,OAAgB,EAChBjB,GAAiB,EACjB2C,GAAwC;IAExC,MAAMnB,UAAU,MAAM/H,WACpBuG,KACA,KACAiB,QAAQQ,OAAO,CAACC,GAAG,CAAC,oBACpB;IAEF,IAAI,YAAYF,SAAS,OAAOA,QAAQG,MAAM;IAC9C,MAAM,EAAEC,KAAK,EAAE,GAAGJ;IAClB,IAAI;QACF,MAAMoB,OAAO,MAAMD,IAAIjB,GAAG;QAC1B,IAAI,CAACkB,KAAKC,MAAM,EAAE;YAChB,MAAMjB,MAAMI,OAAO;YACnB,OAAO1I,UAAUwJ,QAAQ,CAAC;gBAAEC,SAAS;gBAAgBtB,SAASzB,IAAIyB,OAAO;YAAC;QAC5E;QACA,MAAMkB,IAAIe,MAAM;QAChB,MAAMjB,OAAO;YAAExG,IAAI0G,IAAI1G,EAAE;YAAEC,QAAQ;YAAQyH,SAAS;QAAK;QACzD,MAAM/B,MAAMQ,MAAM,CAAC,KAAKK;QACxB,OAAOpJ,QAAQoJ,MAAM;YAAEhB,SAASzB,IAAIyB,OAAO;QAAC;IAC9C,EAAE,OAAO5B,OAAO;QACd,MAAM+B,MAAMI,OAAO;QACnB,MAAMnC;IACR;AACF;AAEA;;;;;CAKC,GACD,eAAe+D,UACb5D,GAAiB,EACjBI,UAAiD,EACjDyD,GAAQ;IAER,MAAMC,YAAYD,IAAIE,YAAY,CAACrC,GAAG,CAAC;IACvC,IAAIoC,cAAc,QAAQA,UAAUrF,IAAI,OAAO,MAAM,CAAC,AAACnD,cAAoC0I,QAAQ,CAACF,UAAUrF,IAAI,KAAK;QACrH,OAAOhE,oBAAoBuF,KAAK,eAAe;YAC7C1D,QAAQ,CAAC,gBAAgB,EAAEhB,cAAc2I,IAAI,CAAC,OAAO;QACvD;IACF;IACA,MAAMC,UAAUjJ,oBAAoB4I,KAAK;QACvC;QACA;QACA;QACA;QACA;KACD;IACD,OAAOlJ,QAAQqF,KAAKI,YAAYyD,KAAKK,SAASpI;AAChD;AAEA,OAAO,eAAeqI,YACpBlD,OAAgB,EAChBjB,GAAiB,EACjBoE,QAAkB,EAClBP,GAAQ;IAER,MAAMzD,aAAalG,cAAc8F,KAAKnH,gBAAgB0I,KAAK;IAC3D,MAAM,GAAG8C,OAAO,GAAGD;IAEnB,IAAI,CAACC,QAAQ;QACX,IAAIpD,QAAQqD,MAAM,KAAK,OAAO;YAC5B,MAAMC,SAAS5K,aAAaqG,KAAK;YACjC,IAAIuE,QAAQ,OAAOA;YACnB,OAAOX,UAAU5D,KAAKI,YAAYyD;QACpC;QACA,IAAI5C,QAAQqD,MAAM,KAAK,QAAQ;YAC7B,MAAMC,SAAS5K,aAAaqG,KAAK;YACjC,IAAIuE,QAAQ,OAAOA;YACnB,OAAOvD,WAAWC,SAASjB;QAC7B;QACA,OAAO1G,UAAUkL,gBAAgB,CAAC;YAChC/C,SAAS,aAAKzB,IAAIyB,OAAO;gBAAEgD,OAAO;;QACpC;IACF;IAEA,MAAM9B,MAAMvC,WAAWrE,GAAG,CAACsI;IAC3B,IAAIpD,QAAQqD,MAAM,KAAK,OAAO;QAC5B,MAAMC,SAAS5K,aAAaqG,KAAK;QACjC,IAAIuE,QAAQ,OAAOA;QACnB,MAAM3B,OAAO,MAAMD,IAAIjB,GAAG;QAC1B,IAAI,CAACkB,KAAKC,MAAM,EAAE;YAChB,OAAOvJ,UAAUwJ,QAAQ,CAAC;gBAAEC,SAAS;gBAAgBtB,SAASzB,IAAIyB,OAAO;YAAC;QAC5E;QACA,OAAOpI,QAAQyC,SAAS8G,OAAO;YAAEnB,SAASzB,IAAIyB,OAAO;QAAC;IACxD;IACA,IAAIR,QAAQqD,MAAM,KAAK,SAAS;QAC9B,MAAMC,SAAS5K,aAAaqG,KAAK;QACjC,IAAIuE,QAAQ,OAAOA;QACnB,OAAO7B,WAAWzB,SAASjB,KAAK2C;IAClC;IACA,IAAI1B,QAAQqD,MAAM,KAAK,UAAU;QAC/B,MAAMC,SAAS5K,aAAaqG,KAAK;QACjC,IAAIuE,QAAQ,OAAOA;QACnB,OAAOd,WAAWxC,SAASjB,KAAK2C;IAClC;IACA,OAAOrJ,UAAUkL,gBAAgB,CAAC;QAChC/C,SAAS,aAAKzB,IAAIyB,OAAO;YAAEgD,OAAO;;IACpC;AACF"}
1
+ {"version":3,"sources":["../../../../../../../../libs/plugins/crm/src/lib/server/api-v1/crm-deals.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * `/v1/deals` (AGL-2606) — the most commercially sensitive row in the CRM.\n *\n * ## The stage owns the status\n *\n * `status` is denormalized from the stage's `kind` (`crm.ts`), so the two\n * can never disagree on a stored deal. A client may move a deal by either\n * name: `stageId` picks a stage and the status follows; `status` alone picks\n * the pipeline's one `won` or `lost` stage, or its FIRST open stage for\n * `open` — a reopen has to land somewhere, and the top of the pipeline is\n * the only somewhere that needs no second field. Both together must agree,\n * and a pair that does not is refused rather than resolved in favor of\n * either, because whichever one we picked would be the one the client did\n * not mean.\n *\n * Every stage move stamps `stageChangedAtMs`, which is what \"stuck in\n * stage\" reports read, and a move into or out of a closed stage sets or\n * clears `closedAtMs`.\n *\n * ## A won deal makes its contact a customer\n *\n * The console's stage route floors the linked contact's lifecycle stage at\n * `customer` when a deal is won (AGL-2641), and this resource is the same\n * writer with a different door: a `PATCH` that moves a deal into its `won`\n * stage, or a `POST` that creates one there, applies the same floor to the\n * contact the deal names, in the facet of the deal's site — filling an\n * empty stage, advancing an earlier one, never moving anybody back. The\n * deal's own write is not undone by a contact write that fails; the deal\n * is what the integrator asked for, and the floor is what the win implies.\n *\n * ## The line items own the amount\n *\n * A deal may carry `lineItems` (AGL-2620) — the products behind its value,\n * each in the deal's currency. With one or more lines the stored\n * `amountCents` IS their sum, written beside them, so a typed `amountCents`\n * in the same body, or alone on a deal that has lines, is refused rather\n * than reconciled: whichever number we kept would be the one the client did\n * not mean. `lineItems: []` clears the lines and hands the amount back to\n * the client; the last sum stays until it is retyped. Changing the currency\n * of a deal with lines needs the lines resent in that currency, because\n * their sum is one number in one unit.\n *\n * ## Salesforce's Opportunity fields (AGL-3516)\n *\n * `type` and `leadSource` are judged against the org's `opportunityType`\n * and `leadSource` picklists, as every door judges them: an active value\n * is stored as the list spells it, a deal's own current value is kept, and\n * anything else is a `400` naming the values allowed. A create with no\n * `type` takes the list's default; `leadSource` is never defaulted.\n * `forecastCategory` is one of a FIXED set. Every stage move stamps the new\n * stage's `forecastCategory` and clears the `probability` override — a\n * body that sets either beside the move wins. `campaignId` names one of the\n * org's live campaigns.\n *\n * ## Contact roles (AGL-3521)\n *\n * `contactRoles` is the whole list of the deal's contacts — `{ contactId,\n * role, primary }` — replaced as sent. Each contact must exist, none twice,\n * at most one Primary, and each `role` is judged against the org's\n * `opportunityContactRole` list (a contact's current role kept). The\n * Primary IS `contactId`: a body that sends both must agree, and a body\n * that sends `contactId` alone makes that contact Primary — added with no\n * role when the deal did not name them — so an integration written before\n * roles keeps meaning what it meant.\n */\nimport {\n CRM_COLLECTIONS,\n CRM_MEDIA_IDS_MAX,\n type CrmDeal,\n type CrmDealContactRole,\n type CrmDealLineItem,\n type CrmDealStage,\n type CrmDealStatus,\n createResourceUid,\n CRM_FORECAST_CATEGORIES,\n type CrmPicklistId,\n crmListFieldsTouched,\n crmNewRecordListFields,\n DEAL_CONTACT_ROLES_MAX,\n DEAL_NEXT_STEP_MAX,\n dealContactRoleFields,\n dealContactRolesOf,\n dealContactRolesWithPrimary,\n dealPrimaryContactId,\n dealStageById,\n judgeDealContactRoles,\n dealStageMoveFields,\n lineItemsTotalCents,\n normalizeCrmMediaIds,\n readDealLineItems,\n} from '@aglyn/aglyn/server'\nimport { apiJson, ApiErrors, restampCrmListFieldsAt } from '@aglyn/tenant-data-admin'\nimport { FieldValue, Timestamp } from 'firebase-admin/firestore'\nimport {\n type ApiV1Context,\n claimWrite,\n readJsonBody,\n requireScope,\n} from '@aglyn/tenant-data-admin/server/api-v1-kit'\nimport { readOrgContainers } from '@aglyn/tenant-data-admin/server/org-containers'\nimport { floorContactLifecycleStage } from '../contact-lifecycle-floor'\nimport { readCrmPicklist, resolveCrmPicklistWrite } from '../read-picklist'\nimport { orderedStages, type ResolvedPipeline, resolvePipeline } from './crm-pipelines'\nimport {\n type Clearable,\n CRM_TEXT_MAX,\n CRM_TITLE_MAX,\n createPayload,\n crmCollection,\n crmCreateStamp,\n crmCustomUpdate,\n crmCustomView,\n crmRecordsBandRefusal,\n crmRefErrors,\n crmTimes,\n crmValidationFailed,\n isoFromMs,\n listCrm,\n memberError,\n parseIsoInstant,\n readChoice,\n readCrmCustomBody,\n readCrmSite,\n readEqualityFilters,\n readOptionalText,\n readRefId,\n refuseUnknownKeys,\n updatePayload,\n} from './crm-shared'\n\nconst DEAL_STATUSES = ['open', 'won', 'lost'] as const\n\n/** One line as published: the stored shape, with `productId` always present. */\nfunction lineItemView(item: CrmDealLineItem) {\n return {\n productId: item.productId ?? null,\n name: item.name,\n quantity: item.quantity,\n unitAmountCents: item.unitAmountCents,\n currency: item.currency,\n }\n}\n\n/** The deal object as published. Every writable field appears here. */\nfunction dealView(doc: FirebaseFirestore.DocumentSnapshot) {\n const data = (doc.data() ?? {}) as Partial<CrmDeal>\n return {\n id: doc.id,\n object: 'deal',\n title: data.title ?? null,\n pipelineId: data.pipelineId ?? null,\n stageId: data.stageId ?? null,\n status: data.status ?? null,\n amountCents: typeof data.amountCents === 'number' ? data.amountCents : null,\n // `'usd'` when absent, as the model says — a deal with no currency is a\n // dollar deal, not a deal with an unknown one.\n currency: data.currency ?? 'usd',\n lineItems: Array.isArray(data.lineItems) ? data.lineItems.map(lineItemView) : [],\n expectedCloseAt: isoFromMs(data.expectedCloseAtMs),\n closedAt: isoFromMs(data.closedAtMs),\n stageChangedAt: isoFromMs(data.stageChangedAtMs),\n ownerUid: data.ownerUid ?? null,\n contactId: data.contactId ?? null,\n // Every contact on the deal and the part each plays (AGL-3521); the\n // Primary is `contactId`.\n contactRoles: dealContactRolesOf(data).map((row) => ({\n contactId: row.contactId,\n role: row.role ?? null,\n primary: row.primary,\n })),\n companyId: data.companyId ?? null,\n lostReason: data.lostReason ?? null,\n notes: data.notes ?? null,\n // Salesforce's Opportunity fields (AGL-3516).\n type: data.type ?? null,\n leadSource: data.leadSource ?? null,\n nextStep: data.nextStep ?? null,\n probability: typeof data.probability === 'number' ? data.probability : null,\n forecastCategory: data.forecastCategory ?? null,\n campaignId: data.campaignId ?? null,\n // The org's deal custom fields, keyed by field key (AGL-2661).\n custom: crmCustomView(data as FirebaseFirestore.DocumentData),\n // When the earliest open task against the deal is due — see\n // `CrmDeal.nextTaskAtMs`. Read-only: the tasks resource maintains it.\n nextTaskAt: isoFromMs(data.nextTaskAtMs),\n mediaIds: normalizeCrmMediaIds(data.mediaIds),\n siteId: data.hostId ?? null,\n ...crmTimes(data as FirebaseFirestore.DocumentData),\n }\n}\n\nconst DEAL_WRITABLE = new Set([\n 'title',\n 'stageId',\n 'status',\n 'amountCents',\n 'currency',\n 'lineItems',\n 'expectedCloseAt',\n 'ownerUid',\n 'contactId',\n 'companyId',\n 'lostReason',\n 'notes',\n 'custom',\n 'mediaIds',\n 'type',\n 'leadSource',\n 'nextStep',\n 'probability',\n 'forecastCategory',\n 'campaignId',\n 'contactRoles',\n])\n\n/** The keys one contact role takes. */\nconst CONTACT_ROLE_KEYS = new Set(['contactId', 'role', 'primary'])\n\ninterface DealInput {\n title?: string\n pipelineId?: string\n stageId?: string\n status?: CrmDealStatus\n amountCents?: Clearable<number>\n currency?: string\n /**\n * The lines as sent, validated only for shape here; the currency check\n * and the sum wait for `placeLineItems`, which knows the deal's currency\n * on a PATCH that did not send one. `[]` means \"clear them\".\n */\n lineItems?: unknown[]\n expectedCloseAtMs?: Clearable<number>\n ownerUid?: Clearable<string>\n contactId?: Clearable<string>\n companyId?: Clearable<string>\n lostReason?: Clearable<string>\n notes?: Clearable<string>\n /** Org-library files attached to the deal (AGL-2662), by media id. */\n mediaIds?: string[]\n /** As sent; judged against the org's picklist by the writer, which pays the read. */\n type?: Clearable<string>\n leadSource?: Clearable<string>\n nextStep?: Clearable<string>\n probability?: Clearable<number>\n forecastCategory?: (typeof CRM_FORECAST_CATEGORIES)[number]\n campaignId?: Clearable<string>\n /** The whole list as sent, shape-checked; roles judged by the writer, which pays the read. */\n contactRoles?: CrmDealContactRole[]\n}\n\n/**\n * `contactRoles` as sent, shape-checked: a list of at most\n * {@link DEAL_CONTACT_ROLES_MAX} entries, each naming a contact once, and\n * at most one of them Primary. `null` is the empty list.\n */\nfunction readContactRolesBody(\n raw: unknown,\n errors: Record<string, string>,\n): CrmDealContactRole[] | undefined {\n if (raw === undefined) return undefined\n if (raw === null) return []\n if (!Array.isArray(raw)) {\n errors.contactRoles = 'Must be a list of { contactId, role, primary }'\n return undefined\n }\n if (raw.length > DEAL_CONTACT_ROLES_MAX) {\n errors.contactRoles = `At most ${DEAL_CONTACT_ROLES_MAX} contacts per deal`\n return undefined\n }\n const seen = new Set<string>()\n let primaries = 0\n for (const [at, entry] of raw.entries()) {\n const row = entry && typeof entry === 'object' && !Array.isArray(entry) ? (entry as Record<string, unknown>) : null\n const contactId = typeof row?.['contactId'] === 'string' ? row['contactId'].trim() : ''\n const unknownKey = row ? Object.keys(row).find((key) => !CONTACT_ROLE_KEYS.has(key)) : undefined\n if (!row || unknownKey) {\n errors.contactRoles = unknownKey\n ? `Entry ${at}: unknown field ${unknownKey}`\n : `Entry ${at}: must be { contactId, role, primary }`\n return undefined\n }\n if (!contactId || contactId.length > 200 || contactId.includes('/')) {\n errors.contactRoles = `Entry ${at}: contactId must be a contact id`\n return undefined\n }\n if (seen.has(contactId)) {\n errors.contactRoles = `Entry ${at}: ${contactId} is on the list twice`\n return undefined\n }\n seen.add(contactId)\n if (row['role'] !== undefined && row['role'] !== null && typeof row['role'] !== 'string') {\n errors.contactRoles = `Entry ${at}: role must be a contact role, or null`\n return undefined\n }\n if (row['primary'] !== undefined && typeof row['primary'] !== 'boolean') {\n errors.contactRoles = `Entry ${at}: primary must be true or false`\n return undefined\n }\n if (row['primary'] === true) primaries += 1\n }\n if (primaries > 1) {\n errors.contactRoles = 'At most one contact may be Primary'\n return undefined\n }\n return raw.map((entry) => {\n const row = entry as Record<string, unknown>\n const role = typeof row['role'] === 'string' ? row['role'].trim() : ''\n return {\n contactId: String(row['contactId']).trim(),\n ...(role ? { role } : {}),\n primary: row['primary'] === true,\n }\n })\n}\n\n/**\n * The writable half of a deal, validated. `pipelineId` is accepted on a\n * create only: a deal's stages are its pipeline's, and moving one between\n * pipelines is a new deal in the other pipeline, not an edit.\n */\nfunction readDealInput(\n body: Record<string, unknown>,\n { partial }: { partial: boolean },\n): { values: DealInput } | { errors: Record<string, string> } {\n const errors: Record<string, string> = {}\n const values: DealInput = {}\n const allowed = new Set(DEAL_WRITABLE)\n if (!partial) {\n allowed.add('consentSiteId')\n allowed.add('pipelineId')\n }\n refuseUnknownKeys(body, allowed, 'deal', errors)\n if (partial && body.pipelineId !== undefined) {\n errors.pipelineId = 'Not writable — create the deal in the other pipeline'\n }\n\n if (body.mediaIds !== undefined) {\n if (!Array.isArray(body.mediaIds)) {\n errors.mediaIds = 'Must be an array of media ids'\n } else if (body.mediaIds.length > CRM_MEDIA_IDS_MAX) {\n errors.mediaIds = `At most ${CRM_MEDIA_IDS_MAX} files may be attached`\n } else {\n // The SAME normalizer the console card writes through, so the API\n // cannot store a list the console would refuse. An empty array is\n // legal and clears the attachments.\n values.mediaIds = normalizeCrmMediaIds(body.mediaIds)\n }\n }\n\n if (body.title !== undefined || !partial) {\n const title = String(body.title ?? '')\n .trim()\n .slice(0, CRM_TITLE_MAX)\n if (title) values.title = title\n else errors.title = partial ? 'Must not be empty' : 'A title is required'\n }\n\n if (!partial && body.pipelineId !== undefined) {\n const pipelineId = readRefId(body, 'pipelineId', errors)\n if (pipelineId) values.pipelineId = pipelineId\n else if (pipelineId === null) errors.pipelineId = 'Must be an id'\n }\n\n const stageId = readRefId(body, 'stageId', errors)\n if (stageId) values.stageId = stageId\n else if (stageId === null) errors.stageId = 'Must be a stage id'\n\n const status = readChoice(body, 'status', DEAL_STATUSES, errors)\n if (status) values.status = status\n\n if (body.amountCents !== undefined) {\n if (body.amountCents === null) {\n values.amountCents = null\n } else if (\n typeof body.amountCents !== 'number' ||\n !Number.isInteger(body.amountCents) ||\n body.amountCents < 0\n ) {\n errors.amountCents = 'Must be a whole number of cents, 0 or more'\n } else {\n values.amountCents = body.amountCents\n }\n }\n\n if (body.currency !== undefined) {\n const currency = String(body.currency ?? '')\n .trim()\n .toLowerCase()\n if (/^[a-z]{3}$/.test(currency)) values.currency = currency\n else errors.currency = 'Must be a three-letter ISO 4217 code, like usd'\n }\n\n if (body.lineItems !== undefined) {\n if (body.lineItems === null || (Array.isArray(body.lineItems) && body.lineItems.length === 0)) {\n values.lineItems = []\n } else if (!Array.isArray(body.lineItems)) {\n errors.lineItems = 'Must be a list of line items'\n } else {\n values.lineItems = body.lineItems\n if (body.amountCents !== undefined) {\n errors.amountCents = 'Derived from lineItems — omit it, or send lineItems: [] to type an amount'\n }\n }\n }\n\n if (body.expectedCloseAt !== undefined) {\n if (body.expectedCloseAt === null) {\n values.expectedCloseAtMs = null\n } else {\n const ms = parseIsoInstant(body.expectedCloseAt)\n if (ms === null) {\n errors.expectedCloseAt =\n 'Must be an ISO 8601 instant, like 2026-12-31T00:00:00Z'\n } else {\n values.expectedCloseAtMs = ms\n }\n }\n }\n\n const ownerUid = readOptionalText(body, 'ownerUid', CRM_TITLE_MAX, errors)\n if (ownerUid !== undefined) values.ownerUid = ownerUid\n const contactId = readRefId(body, 'contactId', errors)\n if (contactId !== undefined) values.contactId = contactId\n const companyId = readRefId(body, 'companyId', errors)\n if (companyId !== undefined) values.companyId = companyId\n const lostReason = readOptionalText(body, 'lostReason', CRM_TEXT_MAX, errors)\n if (lostReason !== undefined) values.lostReason = lostReason\n const notes = readOptionalText(body, 'notes', CRM_TEXT_MAX, errors)\n if (notes !== undefined) values.notes = notes\n\n for (const key of ['type', 'leadSource'] as const) {\n const label = readOptionalText(body, key, CRM_TITLE_MAX, errors)\n if (label !== undefined) values[key] = label\n }\n const nextStep = readOptionalText(body, 'nextStep', DEAL_NEXT_STEP_MAX, errors)\n if (nextStep !== undefined) values.nextStep = nextStep\n if (body.probability !== undefined) {\n if (body.probability === null) {\n values.probability = null\n } else if (\n typeof body.probability !== 'number' ||\n !Number.isInteger(body.probability) ||\n body.probability < 0 ||\n body.probability > 100\n ) {\n errors.probability = 'Must be a whole number from 0 to 100, or null for the stage’s'\n } else {\n values.probability = body.probability\n }\n }\n const forecastCategory = readChoice(body, 'forecastCategory', CRM_FORECAST_CATEGORIES, errors)\n if (forecastCategory) values.forecastCategory = forecastCategory\n const campaignId = readRefId(body, 'campaignId', errors)\n if (campaignId !== undefined) values.campaignId = campaignId\n const contactRoles = readContactRolesBody(body.contactRoles, errors)\n if (contactRoles !== undefined) {\n values.contactRoles = contactRoles\n // The Primary IS `contactId`, so a body naming both says one thing twice.\n if (values.contactId !== undefined && values.contactId !== dealPrimaryContactId(contactRoles)) {\n errors.contactId = 'Must name the Primary in contactRoles, or be left out'\n }\n }\n\n // `custom` is shape-checked here and judged against the org's\n // definitions by the writers, which is where the read is paid.\n if (body.custom !== undefined) {\n if (!body.custom || typeof body.custom !== 'object' || Array.isArray(body.custom)) {\n errors.custom = 'Must be an object of field values keyed by field key'\n }\n }\n\n return Object.keys(errors).length ? { errors } : { values }\n}\n\n/**\n * The stage a write lands the deal in, from `stageId` and/or `status` — see\n * the module header for the rule. `null` when neither was sent, which on a\n * PATCH means \"leave the stage alone\" and on a create means the first open\n * stage.\n */\nfunction resolveStage(\n pipeline: ResolvedPipeline['pipeline'],\n values: Pick<DealInput, 'stageId' | 'status'>,\n): { stage: CrmDealStage | null } | { errors: Record<string, string> } {\n const stages = orderedStages(pipeline)\n if (values.stageId) {\n const stage = dealStageById(pipeline, values.stageId)\n if (!stage) return { errors: { stageId: 'No such stage in this pipeline' } }\n if (values.status && values.status !== stage.kind) {\n return { errors: { status: `Must match the stage, which is ${stage.kind}` } }\n }\n return { stage }\n }\n if (values.status) {\n const stage =\n values.status === 'open'\n ? stages.find((candidate) => candidate.kind === 'open')\n : stages.find((candidate) => candidate.kind === values.status)\n if (!stage) {\n return { errors: { status: `This pipeline has no ${values.status} stage` } }\n }\n return { stage }\n }\n return { stage: null }\n}\n\n/**\n * The stored lines and the amount they derive, for a write that sent\n * `lineItems`, validated against the currency the deal WILL have — the\n * body's, else the stored one, else `usd`. Returns nothing to write when\n * the body carried no lines.\n */\nfunction placeLineItems(\n values: Pick<DealInput, 'lineItems' | 'currency'>,\n stored: Partial<CrmDeal> | null,\n): { fields: Record<string, unknown> } | { errors: Record<string, string> } {\n if (values.lineItems === undefined) return { fields: {} }\n const currency = values.currency ?? stored?.currency ?? 'usd'\n const read = readDealLineItems(values.lineItems, currency)\n if ('error' in read) return { errors: { lineItems: read.error } }\n return {\n fields: {\n lineItems: read.items,\n ...(read.items.length ? { amountCents: lineItemsTotalCents(read.items) } : {}),\n },\n }\n}\n\n/**\n * The customer floor a win applies to the deal's contact (AGL-2641), after\n * the deal itself is written. A contact write that fails is logged and\n * swallowed: the deal is already won, and a `500` would tell the integrator\n * the move they can see in the console did not happen.\n */\nasync function floorWonDealContact(\n ctx: ApiV1Context,\n deal: { contactId?: string | null; hostId?: string | null },\n): Promise<void> {\n const contactId = String(deal.contactId ?? '').trim()\n if (!contactId) return\n try {\n await floorContactLifecycleStage({\n contactRef: ctx.firestore\n .collection('orgs')\n .doc(ctx.orgId)\n .collection('contacts')\n .doc(contactId),\n org: ctx.org as Record<string, unknown>,\n hostId: deal.hostId ?? null,\n floor: 'customer',\n })\n } catch (error) {\n console.error('[api-v1] deals: the customer floor failed', contactId, error)\n }\n}\n\n/**\n * The fields a stage move writes, beside the stage itself — and the new\n * stage's forecast category with the probability override cleared\n * (`dealStageMoveFields`, AGL-3516).\n */\nfunction stageMove(stage: CrmDealStage, nowMs: number) {\n return {\n stageId: stage.id,\n status: stage.kind,\n stageChangedAtMs: nowMs,\n closedAtMs: stage.kind === 'open' ? null : nowMs,\n ...dealStageMoveFields(stage),\n }\n}\n\n/**\n * The membership and reference checks a deal write makes, merged. A\n * campaign is checked against the org's live campaigns, except the one the\n * deal already names, which it keeps even once the campaign is retired.\n */\nasync function dealRefErrors(\n ctx: ApiV1Context,\n values: DealInput,\n stored?: Partial<CrmDeal> | null,\n): Promise<Record<string, string>> {\n const campaignId = values.campaignId ?? undefined\n const [owner, refs, campaign, roles] = await Promise.all([\n memberError(ctx, 'ownerUid', values.ownerUid),\n crmRefErrors(ctx, {\n contactId: values.contactId ?? undefined,\n companyId: values.companyId ?? undefined,\n }),\n campaignId && campaignId !== stored?.campaignId\n ? readOrgContainers(ctx.firestore, 'campaign', ctx.orgId, [campaignId]).then(\n ([record]): Record<string, string> =>\n record?.live ? {} : { campaignId: 'No such campaign in this organization' },\n )\n : Promise.resolve({}),\n contactRoleRefErrors(ctx, values.contactRoles, stored),\n ])\n return { ...owner, ...refs, ...campaign, ...roles }\n}\n\n/**\n * Every contact a sent `contactRoles` adds to the deal must exist; one the\n * deal already names is kept as it is, as a campaign is.\n */\nasync function contactRoleRefErrors(\n ctx: ApiV1Context,\n roles: readonly CrmDealContactRole[] | undefined,\n stored?: Partial<CrmDeal> | null,\n): Promise<Record<string, string>> {\n const held = new Set(stored ? dealContactRolesOf(stored).map((row) => row.contactId) : [])\n const added = (roles ?? []).map((row) => row.contactId).filter((id) => !held.has(id))\n if (!added.length) return {}\n const contacts = ctx.firestore.collection('orgs').doc(ctx.orgId).collection('contacts')\n const snapshots = await ctx.firestore.getAll(...added.map((id) => contacts.doc(id)))\n const missing = snapshots.find((snapshot) => !snapshot.exists)\n return missing ? { contactRoles: `No such contact in this organization: ${missing.id}` } : {}\n}\n\n/**\n * What a write stores for the deal's contacts (AGL-3521): `contactRoles`\n * judged and `contactId` beside its Primary when the body sent the list;\n * when it sent `contactId` alone, the stored roles with that contact as the\n * Primary. Nothing, when it sent neither.\n */\nasync function dealContactRoleWrites(\n ctx: ApiV1Context,\n values: Pick<DealInput, 'contactRoles' | 'contactId'>,\n stored: Partial<CrmDeal> | null,\n): Promise<\n { values: { contactRoles?: CrmDealContactRole[]; contactId?: string | null } } | { errors: Record<string, string> }\n> {\n const current = stored ? dealContactRolesOf(stored) : []\n if (values.contactRoles !== undefined) {\n const judged = judgeDealContactRoles(\n await readCrmPicklist(ctx.firestore, ctx.orgId, 'opportunityContactRole'),\n values.contactRoles,\n current,\n )\n if (judged.ok === false) return { errors: { contactRoles: judged.error } }\n return { values: dealContactRoleFields(judged.roles) }\n }\n if (values.contactId !== undefined) {\n return { values: dealContactRoleFields(dealContactRolesWithPrimary(current, values.contactId)) }\n }\n return { values: {} }\n}\n\n/**\n * `type` and `leadSource` as the deal will store them, judged against the\n * org's lists (AGL-3510's `resolveCrmPicklistWrite`): the values to write,\n * or the refusals by field. Only a list the write touches is read — and the\n * type list on every create, for its default.\n */\nasync function dealPicklistWrites(\n ctx: ApiV1Context,\n values: Pick<DealInput, 'type' | 'leadSource'>,\n stored: Partial<CrmDeal> | null,\n): Promise<{ values: Partial<Record<'type' | 'leadSource', string | null>> } | { errors: Record<string, string> }> {\n const created = stored === null\n const fields: Array<{ key: 'type' | 'leadSource'; id: CrmPicklistId; defaulted: boolean }> = [\n { key: 'type', id: 'opportunityType', defaulted: created },\n { key: 'leadSource', id: 'leadSource', defaulted: false },\n ]\n const written: Partial<Record<'type' | 'leadSource', string | null>> = {}\n const errors: Record<string, string> = {}\n for (const { key, id, defaulted } of fields) {\n if (values[key] === undefined && !defaulted) continue\n const judged = resolveCrmPicklistWrite(\n id,\n await readCrmPicklist(ctx.firestore, ctx.orgId, id),\n values[key],\n { current: stored?.[key], created: defaulted },\n )\n if (judged.ok === false) errors[key] = judged.error\n else if (judged.write !== undefined) written[key] = judged.write\n }\n return Object.keys(errors).length ? { errors } : { values: written }\n}\n\n/**\n * `POST /v1/deals`. The pipeline is resolved AFTER the claim because\n * resolving it can create one (`resolvePipeline`), and a refusal past that\n * point releases the key so the retry that names a real stage still can.\n */\nasync function createDeal(request: Request, ctx: ApiV1Context): Promise<Response> {\n const body = await readJsonBody(request)\n const parsed = readDealInput(body, { partial: false })\n if ('errors' in parsed) return crmValidationFailed(ctx, 'deal', parsed.errors)\n const site = readCrmSite(ctx, 'deal', body)\n if ('response' in site) return site.response\n const refErrors = await dealRefErrors(ctx, parsed.values)\n if (Object.keys(refErrors).length) return crmValidationFailed(ctx, 'deal', refErrors)\n // Judged against the org's deal definitions, above the claim (AGL-2661).\n const custom = await readCrmCustomBody(ctx, body, 'deal')\n if (custom && 'errors' in custom) return crmValidationFailed(ctx, 'deal', custom.errors)\n const customValues = custom && 'values' in custom ? custom.values : {}\n // And against the org's picklists (AGL-3516), above the claim too.\n const picklists = await dealPicklistWrites(ctx, parsed.values, null)\n if ('errors' in picklists) return crmValidationFailed(ctx, 'deal', picklists.errors)\n const roles = await dealContactRoleWrites(ctx, parsed.values, null)\n if ('errors' in roles) return crmValidationFailed(ctx, 'deal', roles.errors)\n\n const collection = crmCollection(ctx, CRM_COLLECTIONS.deals)\n const claimed = await claimWrite(\n ctx,\n '*',\n request.headers.get('Idempotency-Key'),\n 'deals',\n )\n if ('replay' in claimed) return claimed.replay\n const { claim } = claimed\n\n try {\n const { title, pipelineId, stageId, status, lineItems, probability, forecastCategory, ...rest } =\n parsed.values\n const placedLines = placeLineItems({ lineItems, currency: rest.currency }, null)\n if ('errors' in placedLines) {\n await claim.release()\n return crmValidationFailed(ctx, 'deal', placedLines.errors)\n }\n const resolved = await resolvePipeline(ctx, site.siteId, pipelineId)\n if ('error' in resolved) {\n await claim.release()\n return crmValidationFailed(ctx, 'deal', { pipelineId: resolved.error })\n }\n const placed = resolveStage(resolved.pipeline, { stageId, status })\n if ('errors' in placed) {\n await claim.release()\n return crmValidationFailed(ctx, 'deal', placed.errors)\n }\n const stage = placed.stage ?? orderedStages(resolved.pipeline)[0]\n if (!stage) {\n await claim.release()\n return crmValidationFailed(ctx, 'deal', {\n pipelineId: 'This pipeline has no stages',\n })\n }\n // The records band (AGL-2611), asked last so a refusal past the pipeline\n // resolution releases the key exactly as a bad stage does.\n const bandFull = await crmRecordsBandRefusal(ctx)\n if (bandFull) {\n await claim.release()\n return bandFull\n }\n const id = createResourceUid()\n // One clock: the stage move is stamped with the instant the record's own\n // `createdAt` carries, so a deal created won closed the moment it began.\n const stamp = crmCreateStamp(ctx, site.siteId)\n const record: Record<string, unknown> = {\n title,\n titleLower: (title ?? '').toLowerCase(),\n pipelineId: resolved.id,\n ...createPayload({\n ...rest,\n ...picklists.values,\n // The roles as judged, and `contactId` as their Primary (AGL-3521).\n ...roles.values,\n ...placedLines.fields,\n ...stageMove(stage, stamp.createdAt.toMillis()),\n // What the body set beside the stage wins over what the stage stamps.\n ...(probability !== undefined ? { probability } : {}),\n ...(forecastCategory ? { forecastCategory } : {}),\n }),\n ...(Object.keys(customValues).length\n ? { custom: createPayload(customValues) }\n : {}),\n ...stamp,\n }\n // What the console's Deals list searches and filters by (AGL-3321).\n await collection.doc(id).create({ ...record, ...crmNewRecordListFields('deals', record) })\n // A deal created won is a won deal: its contact is a customer from birth.\n if (stage.kind === 'won') {\n await floorWonDealContact(ctx, {\n contactId: roles.values.contactId ?? rest.contactId,\n hostId: site.siteId,\n })\n }\n const view = dealView(await collection.doc(id).get())\n await claim.record(200, view)\n return apiJson(view, { status: 201, headers: ctx.headers })\n } catch (error) {\n await claim.release()\n throw error\n }\n}\n\n/** `PATCH /v1/deals/{id}`. */\nasync function updateDeal(\n request: Request,\n ctx: ApiV1Context,\n ref: FirebaseFirestore.DocumentReference,\n): Promise<Response> {\n const body = await readJsonBody(request)\n const parsed = readDealInput(body, { partial: true })\n if ('errors' in parsed) return crmValidationFailed(ctx, 'deal', parsed.errors)\n const snap = await ref.get()\n if (!snap.exists) {\n return ApiErrors.notFound({ message: 'No such deal', headers: ctx.headers })\n }\n const stored = snap.data() as Partial<CrmDeal>\n const refErrors = await dealRefErrors(ctx, parsed.values, stored)\n if (Object.keys(refErrors).length) return crmValidationFailed(ctx, 'deal', refErrors)\n const custom = await readCrmCustomBody(ctx, body, 'deal')\n if (custom && 'errors' in custom) return crmValidationFailed(ctx, 'deal', custom.errors)\n const picklists = await dealPicklistWrites(ctx, parsed.values, stored)\n if ('errors' in picklists) return crmValidationFailed(ctx, 'deal', picklists.errors)\n const roles = await dealContactRoleWrites(ctx, parsed.values, stored)\n if ('errors' in roles) return crmValidationFailed(ctx, 'deal', roles.errors)\n\n const { title, stageId, status, lineItems, probability, forecastCategory, ...rest } = parsed.values\n const storedLines = Array.isArray(stored.lineItems) && stored.lineItems.length > 0\n const keepsLines = storedLines && lineItems === undefined\n if (keepsLines && rest.amountCents !== undefined) {\n return crmValidationFailed(ctx, 'deal', {\n amountCents: \"This deal's amount is the sum of its line items — edit lineItems instead\",\n })\n }\n if (keepsLines && rest.currency !== undefined && rest.currency !== (stored.currency ?? 'usd')) {\n return crmValidationFailed(ctx, 'deal', {\n currency: \"Every line item is in the deal's currency — send lineItems in the new currency with it\",\n })\n }\n const placedLines = placeLineItems({ lineItems, currency: rest.currency }, stored)\n if ('errors' in placedLines) return crmValidationFailed(ctx, 'deal', placedLines.errors)\n const update: Record<string, unknown> = {\n ...(title !== undefined ? { title, titleLower: title.toLowerCase() } : {}),\n ...updatePayload({ ...rest, ...picklists.values, ...roles.values, ...placedLines.fields }),\n ...(custom && 'values' in custom ? crmCustomUpdate(custom.values) : {}),\n // The name the console copied beside a Primary that is no longer it.\n ...(roles.values.contactId !== undefined && roles.values.contactId !== (stored.contactId ?? null)\n ? { contactName: FieldValue.delete() }\n : {}),\n }\n // The write's one instant: `updatedAt`, and the stage move if there is one,\n // so a deal closed at T reads updated at T.\n const now = Timestamp.now()\n let won = false\n if (stageId !== undefined || status !== undefined) {\n const current = snap.data() as CrmDeal\n const resolved = await resolvePipeline(ctx, current.hostId, current.pipelineId, {\n allowArchived: true,\n })\n if ('error' in resolved) {\n return crmValidationFailed(ctx, 'deal', {\n stageId: \"This deal's pipeline no longer exists\",\n })\n }\n const placed = resolveStage(resolved.pipeline, { stageId, status })\n if ('errors' in placed) return crmValidationFailed(ctx, 'deal', placed.errors)\n if (placed.stage && placed.stage.id !== current.stageId) {\n Object.assign(update, stageMove(placed.stage, now.toMillis()))\n // The transition INTO won, not a won deal edited: a deal already\n // closed won floored its contact when it closed.\n won = placed.stage.kind === 'won' && current.status !== 'won'\n }\n }\n // What the body set beside a stage move wins over what the stage stamps\n // (AGL-3516); without a move, they are plain edits. `null` clears the\n // override back to the stage's.\n if (probability !== undefined) update['probability'] = probability\n if (forecastCategory) update['forecastCategory'] = forecastCategory\n if (Object.keys(update).length > 0) {\n await ref.update({ ...update, updatedAt: now })\n // What the console's Deals list searches and filters by (AGL-3321, AGL-3516).\n if (crmListFieldsTouched('deals', update)) await restampCrmListFieldsAt(ref, 'deals')\n }\n if (won) {\n await floorWonDealContact(ctx, {\n contactId: roles.values.contactId !== undefined ? roles.values.contactId : stored.contactId,\n hostId: stored.hostId,\n })\n }\n return apiJson(dealView(await ref.get()), { headers: ctx.headers })\n}\n\n/** `DELETE /v1/deals/{id}` — the deal alone; its tasks and activities stay. */\nasync function deleteDeal(\n request: Request,\n ctx: ApiV1Context,\n ref: FirebaseFirestore.DocumentReference,\n): Promise<Response> {\n const claimed = await claimWrite(\n ctx,\n '*',\n request.headers.get('Idempotency-Key'),\n 'deal-deletes',\n )\n if ('replay' in claimed) return claimed.replay\n const { claim } = claimed\n try {\n const snap = await ref.get()\n if (!snap.exists) {\n await claim.release()\n return ApiErrors.notFound({ message: 'No such deal', headers: ctx.headers })\n }\n await ref.delete()\n const view = { id: ref.id, object: 'deal', deleted: true }\n await claim.record(200, view)\n return apiJson(view, { headers: ctx.headers })\n } catch (error) {\n await claim.release()\n throw error\n }\n}\n\n/**\n * `GET /v1/deals` filters, most selective first — the order `listCrm`\n * indexes them in. `status` is validated against the three values a deal\n * can hold, because `?status=closed` matching nothing is the plausible empty\n * page the conventions refuse to serve.\n */\nasync function listDeals(\n ctx: ApiV1Context,\n collection: FirebaseFirestore.CollectionReference,\n url: URL,\n): Promise<Response> {\n const rawStatus = url.searchParams.get('status')\n if (rawStatus !== null && rawStatus.trim() !== '' && !(DEAL_STATUSES as readonly string[]).includes(rawStatus.trim())) {\n return crmValidationFailed(ctx, 'deal filter', {\n status: `Must be one of: ${DEAL_STATUSES.join(', ')}`,\n })\n }\n const filters = readEqualityFilters(url, [\n 'contactId',\n 'companyId',\n 'pipelineId',\n 'ownerUid',\n 'status',\n 'type',\n 'leadSource',\n 'forecastCategory',\n 'campaignId',\n ])\n return listCrm(ctx, collection, url, filters, dealView)\n}\n\nexport async function handleDeals(\n request: Request,\n ctx: ApiV1Context,\n segments: string[],\n url: URL,\n): Promise<Response> {\n const collection = crmCollection(ctx, CRM_COLLECTIONS.deals)\n const [, dealId] = segments\n\n if (!dealId) {\n if (request.method === 'GET') {\n const denied = requireScope(ctx, 'crm:read')\n if (denied) return denied\n return listDeals(ctx, collection, url)\n }\n if (request.method === 'POST') {\n const denied = requireScope(ctx, 'crm:write')\n if (denied) return denied\n return createDeal(request, ctx)\n }\n return ApiErrors.methodNotAllowed({\n headers: { ...ctx.headers, Allow: 'GET, POST' },\n })\n }\n\n const ref = collection.doc(dealId)\n if (request.method === 'GET') {\n const denied = requireScope(ctx, 'crm:read')\n if (denied) return denied\n const snap = await ref.get()\n if (!snap.exists) {\n return ApiErrors.notFound({ message: 'No such deal', headers: ctx.headers })\n }\n return apiJson(dealView(snap), { headers: ctx.headers })\n }\n if (request.method === 'PATCH') {\n const denied = requireScope(ctx, 'crm:write')\n if (denied) return denied\n return updateDeal(request, ctx, ref)\n }\n if (request.method === 'DELETE') {\n const denied = requireScope(ctx, 'crm:write')\n if (denied) return denied\n return deleteDeal(request, ctx, ref)\n }\n return ApiErrors.methodNotAllowed({\n headers: { ...ctx.headers, Allow: 'GET, PATCH, DELETE' },\n })\n}\n"],"names":["CRM_COLLECTIONS","CRM_MEDIA_IDS_MAX","createResourceUid","CRM_FORECAST_CATEGORIES","crmListFieldsTouched","crmNewRecordListFields","DEAL_CONTACT_ROLES_MAX","DEAL_NEXT_STEP_MAX","dealContactRoleFields","dealContactRolesOf","dealContactRolesWithPrimary","dealPrimaryContactId","dealStageById","judgeDealContactRoles","dealStageMoveFields","lineItemsTotalCents","normalizeCrmMediaIds","readDealLineItems","apiJson","ApiErrors","restampCrmListFieldsAt","FieldValue","Timestamp","claimWrite","readJsonBody","requireScope","readOrgContainers","floorContactLifecycleStage","readCrmPicklist","resolveCrmPicklistWrite","orderedStages","resolvePipeline","CRM_TEXT_MAX","CRM_TITLE_MAX","createPayload","crmCollection","crmCreateStamp","crmCustomUpdate","crmCustomView","crmRecordsBandRefusal","crmRefErrors","crmTimes","crmValidationFailed","isoFromMs","listCrm","memberError","parseIsoInstant","readChoice","readCrmCustomBody","readCrmSite","readEqualityFilters","readOptionalText","readRefId","refuseUnknownKeys","updatePayload","DEAL_STATUSES","lineItemView","item","productId","name","quantity","unitAmountCents","currency","dealView","doc","data","id","object","title","pipelineId","stageId","status","amountCents","lineItems","Array","isArray","map","expectedCloseAt","expectedCloseAtMs","closedAt","closedAtMs","stageChangedAt","stageChangedAtMs","ownerUid","contactId","contactRoles","row","role","primary","companyId","lostReason","notes","type","leadSource","nextStep","probability","forecastCategory","campaignId","custom","nextTaskAt","nextTaskAtMs","mediaIds","siteId","hostId","DEAL_WRITABLE","Set","CONTACT_ROLE_KEYS","readContactRolesBody","raw","errors","undefined","length","seen","primaries","at","entry","entries","trim","unknownKey","Object","keys","find","key","has","includes","add","String","readDealInput","body","partial","values","allowed","slice","Number","isInteger","toLowerCase","test","ms","label","resolveStage","pipeline","stages","stage","kind","candidate","placeLineItems","stored","fields","read","error","items","floorWonDealContact","ctx","deal","contactRef","firestore","collection","orgId","org","floor","console","stageMove","nowMs","dealRefErrors","owner","refs","campaign","roles","Promise","all","then","record","live","resolve","contactRoleRefErrors","held","added","filter","contacts","snapshots","getAll","missing","snapshot","exists","dealContactRoleWrites","current","judged","ok","dealPicklistWrites","created","defaulted","written","write","createDeal","request","parsed","site","response","refErrors","customValues","picklists","deals","claimed","headers","get","replay","claim","placed","rest","placedLines","release","resolved","bandFull","stamp","titleLower","createdAt","toMillis","create","view","updateDeal","ref","snap","notFound","message","storedLines","keepsLines","update","contactName","delete","now","won","allowArchived","assign","updatedAt","deleteDeal","deleted","listDeals","url","rawStatus","searchParams","join","filters","handleDeals","segments","dealId","method","denied","methodNotAllowed","Allow"],"mappings":"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"}