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

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 (541) 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-next-activity-column.js +1 -1
  34. package/src/lib/components/crm-next-activity-column.js.map +1 -1
  35. package/src/lib/components/crm-record-picker.d.ts +15 -0
  36. package/src/lib/components/crm-record-picker.js +16 -10
  37. package/src/lib/components/crm-record-picker.js.map +1 -1
  38. package/src/lib/components/crm-transfer-buttons.d.ts +54 -0
  39. package/src/lib/components/crm-transfer-buttons.js +167 -0
  40. package/src/lib/components/crm-transfer-buttons.js.map +1 -0
  41. package/src/lib/components/deal-contact-roles-card.d.ts +46 -0
  42. package/src/lib/components/deal-contact-roles-card.js +368 -0
  43. package/src/lib/components/deal-contact-roles-card.js.map +1 -0
  44. package/src/lib/components/deal-detail-page.d.ts +3 -2
  45. package/src/lib/components/deal-detail-page.js +25 -6
  46. package/src/lib/components/deal-detail-page.js.map +1 -1
  47. package/src/lib/components/deal-edit-drawer.d.ts +10 -0
  48. package/src/lib/components/deal-edit-drawer.js +219 -10
  49. package/src/lib/components/deal-edit-drawer.js.map +1 -1
  50. package/src/lib/components/deal-properties-card.d.ts +7 -0
  51. package/src/lib/components/deal-properties-card.js +34 -3
  52. package/src/lib/components/deal-properties-card.js.map +1 -1
  53. package/src/lib/components/deal-stage-card.d.ts +4 -0
  54. package/src/lib/components/deal-stage-card.js +10 -2
  55. package/src/lib/components/deal-stage-card.js.map +1 -1
  56. package/src/lib/components/deals-bulk-bar.d.ts +0 -3
  57. package/src/lib/components/deals-bulk-bar.js +7 -20
  58. package/src/lib/components/deals-bulk-bar.js.map +1 -1
  59. package/src/lib/components/deals-section.d.ts +3 -3
  60. package/src/lib/components/deals-section.js +123 -63
  61. package/src/lib/components/deals-section.js.map +1 -1
  62. package/src/lib/components/fields-section.js +31 -17
  63. package/src/lib/components/fields-section.js.map +1 -1
  64. package/src/lib/components/lead-convert-dialog.d.ts +4 -0
  65. package/src/lib/components/lead-convert-dialog.js +23 -1
  66. package/src/lib/components/lead-convert-dialog.js.map +1 -1
  67. package/src/lib/components/lead-detail-page.js +8 -2
  68. package/src/lib/components/lead-detail-page.js.map +1 -1
  69. package/src/lib/components/lead-profile-fields.d.ts +71 -0
  70. package/src/lib/components/lead-profile-fields.js +386 -0
  71. package/src/lib/components/lead-profile-fields.js.map +1 -0
  72. package/src/lib/components/lead-properties-card.d.ts +2 -1
  73. package/src/lib/components/lead-properties-card.js +85 -176
  74. package/src/lib/components/lead-properties-card.js.map +1 -1
  75. package/src/lib/components/lead-source-select.d.ts +4 -23
  76. package/src/lib/components/lead-source-select.js +9 -73
  77. package/src/lib/components/lead-source-select.js.map +1 -1
  78. package/src/lib/components/lead-status-chip.d.ts +9 -3
  79. package/src/lib/components/lead-status-chip.js +8 -4
  80. package/src/lib/components/lead-status-chip.js.map +1 -1
  81. package/src/lib/components/lead-status-options.d.ts +20 -0
  82. package/src/lib/components/lead-status-options.js +51 -0
  83. package/src/lib/components/lead-status-options.js.map +1 -0
  84. package/src/lib/components/lead-unqualify-dialog.d.ts +5 -0
  85. package/src/lib/components/lead-unqualify-dialog.js +50 -18
  86. package/src/lib/components/lead-unqualify-dialog.js.map +1 -1
  87. package/src/lib/components/leads-bulk-bar.d.ts +0 -3
  88. package/src/lib/components/leads-bulk-bar.js +29 -29
  89. package/src/lib/components/leads-bulk-bar.js.map +1 -1
  90. package/src/lib/components/leads-section.js +120 -68
  91. package/src/lib/components/leads-section.js.map +1 -1
  92. package/src/lib/components/linked-deals-card.d.ts +4 -0
  93. package/src/lib/components/linked-deals-card.js +47 -3
  94. package/src/lib/components/linked-deals-card.js.map +1 -1
  95. package/src/lib/components/log-activity-dialog.js +43 -3
  96. package/src/lib/components/log-activity-dialog.js.map +1 -1
  97. package/src/lib/components/new-contact-drawer.d.ts +8 -0
  98. package/src/lib/components/new-contact-drawer.js +108 -6
  99. package/src/lib/components/new-contact-drawer.js.map +1 -1
  100. package/src/lib/components/new-lead-drawer.d.ts +9 -2
  101. package/src/lib/components/new-lead-drawer.js +88 -121
  102. package/src/lib/components/new-lead-drawer.js.map +1 -1
  103. package/src/lib/components/picklist-select.d.ts +36 -0
  104. package/src/lib/components/picklist-select.js +114 -0
  105. package/src/lib/components/picklist-select.js.map +1 -0
  106. package/src/lib/components/picklist-values-card.d.ts +34 -0
  107. package/src/lib/components/{lead-source-values-card.js → picklist-values-card.js} +241 -58
  108. package/src/lib/components/picklist-values-card.js.map +1 -0
  109. package/src/lib/components/pipeline-stages-dialog.d.ts +7 -0
  110. package/src/lib/components/pipeline-stages-dialog.js +26 -4
  111. package/src/lib/components/pipeline-stages-dialog.js.map +1 -1
  112. package/src/lib/components/pipelines-dialog.js +15 -6
  113. package/src/lib/components/pipelines-dialog.js.map +1 -1
  114. package/src/lib/components/recent-activity-feed.js +20 -5
  115. package/src/lib/components/recent-activity-feed.js.map +1 -1
  116. package/src/lib/components/recipes-card.js +4 -2
  117. package/src/lib/components/recipes-card.js.map +1 -1
  118. package/src/lib/components/record-tasks-card.js +15 -8
  119. package/src/lib/components/record-tasks-card.js.map +1 -1
  120. package/src/lib/components/reports/forecast-card.d.ts +6 -0
  121. package/src/lib/components/reports/forecast-card.js +101 -3
  122. package/src/lib/components/reports/forecast-card.js.map +1 -1
  123. package/src/lib/components/reports/lead-funnel-card.d.ts +12 -0
  124. package/src/lib/components/reports/lead-funnel-card.js +9 -5
  125. package/src/lib/components/reports/lead-funnel-card.js.map +1 -1
  126. package/src/lib/components/reports/lead-source-card.d.ts +23 -0
  127. package/src/lib/components/reports/lead-source-card.js +318 -0
  128. package/src/lib/components/reports/lead-source-card.js.map +1 -0
  129. package/src/lib/components/reports/pipeline-card.js +2 -1
  130. package/src/lib/components/reports/pipeline-card.js.map +1 -1
  131. package/src/lib/components/reports/report-export.js +1 -1
  132. package/src/lib/components/reports/report-export.js.map +1 -1
  133. package/src/lib/components/reports-section.js +8 -0
  134. package/src/lib/components/reports-section.js.map +1 -1
  135. package/src/lib/components/sharing-rule-drawer.d.ts +5 -0
  136. package/src/lib/components/sharing-rule-drawer.js +108 -19
  137. package/src/lib/components/sharing-rule-drawer.js.map +1 -1
  138. package/src/lib/components/sharing-rules-card.js +11 -3
  139. package/src/lib/components/sharing-rules-card.js.map +1 -1
  140. package/src/lib/components/task-cells.d.ts +9 -1
  141. package/src/lib/components/task-cells.js +9 -4
  142. package/src/lib/components/task-cells.js.map +1 -1
  143. package/src/lib/components/task-edit-drawer.js +111 -43
  144. package/src/lib/components/task-edit-drawer.js.map +1 -1
  145. package/src/lib/components/tasks-bulk-bar.d.ts +0 -3
  146. package/src/lib/components/tasks-bulk-bar.js +7 -20
  147. package/src/lib/components/tasks-bulk-bar.js.map +1 -1
  148. package/src/lib/components/tasks-calendar.d.ts +3 -0
  149. package/src/lib/components/tasks-calendar.js +8 -1
  150. package/src/lib/components/tasks-calendar.js.map +1 -1
  151. package/src/lib/components/tasks-section.d.ts +3 -3
  152. package/src/lib/components/tasks-section.js +58 -43
  153. package/src/lib/components/tasks-section.js.map +1 -1
  154. package/src/lib/constants/api-routes.d.ts +2 -9
  155. package/src/lib/constants/api-routes.js +1 -7
  156. package/src/lib/constants/api-routes.js.map +1 -1
  157. package/src/lib/constants/bundle-common.d.ts +6 -0
  158. package/src/lib/constants/bundle-common.js +11 -0
  159. package/src/lib/constants/bundle-common.js.map +1 -1
  160. package/src/lib/constants/company-filters.d.ts +14 -0
  161. package/src/lib/constants/company-filters.js +51 -1
  162. package/src/lib/constants/company-filters.js.map +1 -1
  163. package/src/lib/constants/contact-filters.d.ts +2 -0
  164. package/src/lib/constants/contact-filters.js +18 -1
  165. package/src/lib/constants/contact-filters.js.map +1 -1
  166. package/src/lib/constants/deal-filters.d.ts +22 -1
  167. package/src/lib/constants/deal-filters.js +67 -4
  168. package/src/lib/constants/deal-filters.js.map +1 -1
  169. package/src/lib/declarations.console-server.d.ts +3 -0
  170. package/src/lib/declarations.console-server.js +35 -0
  171. package/src/lib/declarations.console-server.js.map +1 -1
  172. package/src/lib/declarations.d.ts +26 -0
  173. package/src/lib/declarations.js +35 -0
  174. package/src/lib/declarations.js.map +1 -0
  175. package/src/lib/declarations.server.d.ts +11 -0
  176. package/src/lib/declarations.server.js +97 -1
  177. package/src/lib/declarations.server.js.map +1 -1
  178. package/src/lib/hooks/use-company-picklists.d.ts +15 -0
  179. package/src/lib/hooks/use-company-picklists.js +55 -0
  180. package/src/lib/hooks/use-company-picklists.js.map +1 -0
  181. package/src/lib/hooks/use-crm-picklist.d.ts +25 -0
  182. package/src/lib/hooks/use-crm-picklist.js +53 -0
  183. package/src/lib/hooks/use-crm-picklist.js.map +1 -0
  184. package/src/lib/hooks/use-crm-record-names.d.ts +16 -0
  185. package/src/lib/hooks/use-crm-record-names.js +45 -19
  186. package/src/lib/hooks/use-crm-record-names.js.map +1 -1
  187. package/src/lib/hooks/use-crm-task-picklists.d.ts +11 -0
  188. package/src/lib/hooks/use-crm-task-picklists.js +45 -0
  189. package/src/lib/hooks/use-crm-task-picklists.js.map +1 -0
  190. package/src/lib/hooks/use-deals.d.ts +14 -0
  191. package/src/lib/hooks/use-deals.js +29 -0
  192. package/src/lib/hooks/use-deals.js.map +1 -1
  193. package/src/lib/hooks/use-lead-picklists.d.ts +14 -0
  194. package/src/lib/hooks/use-lead-picklists.js +46 -0
  195. package/src/lib/hooks/use-lead-picklists.js.map +1 -0
  196. package/src/lib/hooks/use-lead-source-picklist.d.ts +5 -19
  197. package/src/lib/hooks/use-lead-source-picklist.js +12 -22
  198. package/src/lib/hooks/use-lead-source-picklist.js.map +1 -1
  199. package/src/lib/hooks/use-lead-status-picklist.d.ts +9 -0
  200. package/src/lib/hooks/use-lead-status-picklist.js +40 -0
  201. package/src/lib/hooks/use-lead-status-picklist.js.map +1 -0
  202. package/src/lib/model/companies.d.ts +32 -3
  203. package/src/lib/model/companies.js +133 -16
  204. package/src/lib/model/companies.js.map +1 -1
  205. package/src/lib/model/contact-merge.d.ts +27 -3
  206. package/src/lib/model/contact-merge.js +81 -7
  207. package/src/lib/model/contact-merge.js.map +1 -1
  208. package/src/lib/model/contact-record.d.ts +17 -0
  209. package/src/lib/model/contact-record.js +17 -2
  210. package/src/lib/model/contact-record.js.map +1 -1
  211. package/src/lib/model/contact-update.d.ts +31 -2
  212. package/src/lib/model/contact-update.js +14 -0
  213. package/src/lib/model/contact-update.js.map +1 -1
  214. package/src/lib/model/crm-list-query.d.ts +5 -0
  215. package/src/lib/model/crm-list-query.js +8 -0
  216. package/src/lib/model/crm-list-query.js.map +1 -1
  217. package/src/lib/model/crm-next-activity.d.ts +107 -0
  218. package/src/lib/model/crm-next-activity.js +140 -0
  219. package/src/lib/model/crm-next-activity.js.map +1 -0
  220. package/src/lib/model/crm-recipes.d.ts +40 -0
  221. package/src/lib/model/crm-recipes.js +259 -0
  222. package/src/lib/model/crm-recipes.js.map +1 -0
  223. package/src/lib/model/crm-record-counts.d.ts +36 -0
  224. package/src/lib/model/crm-record-counts.js +54 -0
  225. package/src/lib/model/crm-record-counts.js.map +1 -0
  226. package/src/lib/model/crm-record-lists.d.ts +23 -0
  227. package/src/lib/model/crm-record-lists.js +161 -0
  228. package/src/lib/model/crm-record-lists.js.map +1 -0
  229. package/src/lib/model/crm-reports.d.ts +73 -3
  230. package/src/lib/model/crm-reports.js +120 -1
  231. package/src/lib/model/crm-reports.js.map +1 -1
  232. package/src/lib/model/crm-sharing.d.ts +21 -3
  233. package/src/lib/model/crm-sharing.js +27 -6
  234. package/src/lib/model/crm-sharing.js.map +1 -1
  235. package/src/lib/model/crm-task-reminders.d.ts +152 -0
  236. package/src/lib/model/crm-task-reminders.js +161 -0
  237. package/src/lib/model/crm-task-reminders.js.map +1 -0
  238. package/src/lib/model/deal-board-model.d.ts +8 -2
  239. package/src/lib/model/deal-board-model.js +15 -2
  240. package/src/lib/model/deal-board-model.js.map +1 -1
  241. package/src/lib/model/deal-contact-roles.d.ts +45 -0
  242. package/src/lib/model/deal-contact-roles.js +73 -0
  243. package/src/lib/model/deal-contact-roles.js.map +1 -0
  244. package/src/lib/model/deal-form-model.d.ts +56 -0
  245. package/src/lib/model/deal-form-model.js +79 -7
  246. package/src/lib/model/deal-form-model.js.map +1 -1
  247. package/src/lib/model/download-text-file.d.ts +23 -0
  248. package/src/lib/model/download-text-file.js +34 -0
  249. package/src/lib/model/download-text-file.js.map +1 -0
  250. package/src/lib/model/lead-filters.d.ts +36 -2
  251. package/src/lib/model/lead-filters.js +123 -2
  252. package/src/lib/model/lead-filters.js.map +1 -1
  253. package/src/lib/model/lead-source-direction.d.ts +38 -0
  254. package/src/lib/model/lead-source-direction.js +52 -0
  255. package/src/lib/model/lead-source-direction.js.map +1 -0
  256. package/src/lib/model/next-activity.d.ts +1 -1
  257. package/src/lib/model/next-activity.js.map +1 -1
  258. package/src/lib/model/picklist-values.d.ts +119 -0
  259. package/src/lib/model/picklist-values.js +256 -0
  260. package/src/lib/model/picklist-values.js.map +1 -0
  261. package/src/lib/model/record-facts-disclosed.d.ts +81 -0
  262. package/src/lib/model/record-facts-disclosed.js +281 -0
  263. package/src/lib/model/record-facts-disclosed.js.map +1 -0
  264. package/src/lib/model/record-facts.d.ts +215 -34
  265. package/src/lib/model/record-facts.js +307 -128
  266. package/src/lib/model/record-facts.js.map +1 -1
  267. package/src/lib/model/task-picklists.d.ts +52 -0
  268. package/src/lib/model/task-picklists.js +83 -0
  269. package/src/lib/model/task-picklists.js.map +1 -0
  270. package/src/lib/model/task-routes.d.ts +13 -0
  271. package/src/lib/model/task-routes.js +23 -4
  272. package/src/lib/model/task-routes.js.map +1 -1
  273. package/src/lib/plan-entitlements.js +6 -4
  274. package/src/lib/plan-entitlements.js.map +1 -1
  275. package/src/lib/plugin.js +17 -0
  276. package/src/lib/plugin.js.map +1 -1
  277. package/src/lib/server/api-v1/contacts.js +220 -14
  278. package/src/lib/server/api-v1/contacts.js.map +1 -1
  279. package/src/lib/server/api-v1/crm-activities.js +14 -1
  280. package/src/lib/server/api-v1/crm-activities.js.map +1 -1
  281. package/src/lib/server/api-v1/crm-companies.js +123 -14
  282. package/src/lib/server/api-v1/crm-companies.js.map +1 -1
  283. package/src/lib/server/api-v1/crm-deals.js +291 -26
  284. package/src/lib/server/api-v1/crm-deals.js.map +1 -1
  285. package/src/lib/server/api-v1/crm-leads.js +144 -38
  286. package/src/lib/server/api-v1/crm-leads.js.map +1 -1
  287. package/src/lib/server/api-v1/crm-pipelines.d.ts +6 -0
  288. package/src/lib/server/api-v1/crm-pipelines.js +8 -2
  289. package/src/lib/server/api-v1/crm-pipelines.js.map +1 -1
  290. package/src/lib/server/api-v1/crm-tasks.js +78 -34
  291. package/src/lib/server/api-v1/crm-tasks.js.map +1 -1
  292. package/src/lib/server/api-v1/openapi.d.ts +0 -11
  293. package/src/lib/server/api-v1/openapi.js +171 -16
  294. package/src/lib/server/api-v1/openapi.js.map +1 -1
  295. package/src/lib/server/assign-contact-owner.d.ts +188 -0
  296. package/src/lib/server/assign-contact-owner.js +446 -0
  297. package/src/lib/server/assign-contact-owner.js.map +1 -0
  298. package/src/lib/server/associate-company-by-domain.d.ts +70 -0
  299. package/src/lib/server/associate-company-by-domain.js +153 -0
  300. package/src/lib/server/associate-company-by-domain.js.map +1 -0
  301. package/src/lib/server/automation-steps.d.ts +140 -0
  302. package/src/lib/server/automation-steps.js +669 -0
  303. package/src/lib/server/automation-steps.js.map +1 -0
  304. package/src/lib/server/capture-contact.d.ts +17 -0
  305. package/src/lib/server/capture-contact.js +95 -26
  306. package/src/lib/server/capture-contact.js.map +1 -1
  307. package/src/lib/server/capture-host-contact.d.ts +104 -0
  308. package/src/lib/server/capture-host-contact.js +151 -0
  309. package/src/lib/server/capture-host-contact.js.map +1 -0
  310. package/src/lib/server/company-children.d.ts +25 -0
  311. package/src/lib/server/company-children.js +42 -0
  312. package/src/lib/server/company-children.js.map +1 -0
  313. package/src/lib/server/company-delete.d.ts +18 -0
  314. package/src/lib/server/company-delete.js +44 -21
  315. package/src/lib/server/company-delete.js.map +1 -1
  316. package/src/lib/server/contact-email-history.js +21 -19
  317. package/src/lib/server/contact-email-history.js.map +1 -1
  318. package/src/lib/server/contact-remove.js +27 -2
  319. package/src/lib/server/contact-remove.js.map +1 -1
  320. package/src/lib/server/contact-reports-to.d.ts +61 -0
  321. package/src/lib/server/contact-reports-to.js +114 -0
  322. package/src/lib/server/contact-reports-to.js.map +1 -0
  323. package/src/lib/server/contact-update.d.ts +42 -1
  324. package/src/lib/server/contact-update.js +204 -23
  325. package/src/lib/server/contact-update.js.map +1 -1
  326. package/src/lib/server/convert-host-lead.d.ts +46 -1
  327. package/src/lib/server/convert-host-lead.js +173 -15
  328. package/src/lib/server/convert-host-lead.js.map +1 -1
  329. package/src/lib/server/convert-open-lead.js +12 -5
  330. package/src/lib/server/convert-open-lead.js.map +1 -1
  331. package/src/lib/server/crm-email-activity.d.ts +118 -0
  332. package/src/lib/server/crm-email-activity.js +148 -0
  333. package/src/lib/server/crm-email-activity.js.map +1 -0
  334. package/src/lib/server/crm-inbound-email.js +1 -1
  335. package/src/lib/server/crm-inbound-email.js.map +1 -1
  336. package/src/lib/server/crm-next-activity.d.ts +74 -0
  337. package/src/lib/server/crm-next-activity.js +194 -0
  338. package/src/lib/server/crm-next-activity.js.map +1 -0
  339. package/src/lib/server/crm-record-indexes.d.ts +45 -0
  340. package/src/lib/server/crm-record-indexes.js +78 -0
  341. package/src/lib/server/crm-record-indexes.js.map +1 -0
  342. package/src/lib/server/crm-sharing.d.ts +9 -1
  343. package/src/lib/server/crm-sharing.js +23 -3
  344. package/src/lib/server/crm-sharing.js.map +1 -1
  345. package/src/lib/server/deal-contact-roles.d.ts +27 -0
  346. package/src/lib/server/deal-contact-roles.js +89 -0
  347. package/src/lib/server/deal-contact-roles.js.map +1 -0
  348. package/src/lib/server/email-send.js +2 -1
  349. package/src/lib/server/email-send.js.map +1 -1
  350. package/src/lib/server/lead-convert.d.ts +5 -0
  351. package/src/lib/server/lead-convert.js +19 -3
  352. package/src/lib/server/lead-convert.js.map +1 -1
  353. package/src/lib/server/lead-create.d.ts +17 -2
  354. package/src/lib/server/lead-create.js +46 -14
  355. package/src/lib/server/lead-create.js.map +1 -1
  356. package/src/lib/server/lead-nurturing.d.ts +6 -0
  357. package/src/lib/server/lead-nurturing.js +57 -20
  358. package/src/lib/server/lead-nurturing.js.map +1 -1
  359. package/src/lib/server/lead-picklists.d.ts +35 -0
  360. package/src/lib/server/lead-picklists.js +52 -0
  361. package/src/lib/server/lead-picklists.js.map +1 -0
  362. package/src/lib/server/lead-source-picklist.d.ts +1 -13
  363. package/src/lib/server/lead-source-picklist.js +6 -33
  364. package/src/lib/server/lead-source-picklist.js.map +1 -1
  365. package/src/lib/server/merge-contacts.js +23 -5
  366. package/src/lib/server/merge-contacts.js.map +1 -1
  367. package/src/lib/server/next-activity-routes.js +2 -1
  368. package/src/lib/server/next-activity-routes.js.map +1 -1
  369. package/src/lib/server/person-eraser.d.ts +53 -0
  370. package/src/lib/server/person-eraser.js +149 -0
  371. package/src/lib/server/person-eraser.js.map +1 -0
  372. package/src/lib/server/person-records.d.ts +69 -0
  373. package/src/lib/server/person-records.js +317 -0
  374. package/src/lib/server/person-records.js.map +1 -0
  375. package/src/lib/server/person-refund.d.ts +97 -0
  376. package/src/lib/server/person-refund.js +221 -0
  377. package/src/lib/server/person-refund.js.map +1 -0
  378. package/src/lib/server/picklist-values.d.ts +21 -0
  379. package/src/lib/server/picklist-values.js +308 -0
  380. package/src/lib/server/picklist-values.js.map +1 -0
  381. package/src/lib/server/read-picklist.d.ts +44 -0
  382. package/src/lib/server/read-picklist.js +65 -0
  383. package/src/lib/server/read-picklist.js.map +1 -0
  384. package/src/lib/server/recipe-routes.js +22 -8
  385. package/src/lib/server/recipe-routes.js.map +1 -1
  386. package/src/lib/server/record-email-state.js +7 -1
  387. package/src/lib/server/record-email-state.js.map +1 -1
  388. package/src/lib/server/record-facts.d.ts +3 -0
  389. package/src/lib/server/record-facts.js +233 -31
  390. package/src/lib/server/record-facts.js.map +1 -1
  391. package/src/lib/server/record-origin.d.ts +27 -0
  392. package/src/lib/server/record-origin.js +104 -0
  393. package/src/lib/server/record-origin.js.map +1 -0
  394. package/src/lib/server/record-timeline.js +40 -3
  395. package/src/lib/server/record-timeline.js.map +1 -1
  396. package/src/lib/server/suite-gate.js +4 -3
  397. package/src/lib/server/suite-gate.js.map +1 -1
  398. package/src/lib/server/task-reminders-route.js +2 -1
  399. package/src/lib/server/task-reminders-route.js.map +1 -1
  400. package/src/lib/server/task-routes.js +33 -17
  401. package/src/lib/server/task-routes.js.map +1 -1
  402. package/src/lib/server-deal-stage.d.ts +5 -1
  403. package/src/lib/server-deal-stage.js +10 -5
  404. package/src/lib/server-deal-stage.js.map +1 -1
  405. package/src/lib/server.d.ts +8 -3
  406. package/src/lib/server.js +47 -43
  407. package/src/lib/server.js.map +1 -1
  408. package/src/lib/testing/memory-firestore.d.ts +55 -0
  409. package/src/lib/testing/memory-firestore.js +335 -0
  410. package/src/lib/testing/memory-firestore.js.map +1 -0
  411. package/src/lib/testing/stand-in-email-send-index.d.ts +25 -0
  412. package/src/lib/testing/stand-in-email-send-index.js +49 -0
  413. package/src/lib/testing/stand-in-email-send-index.js.map +1 -0
  414. package/src/lib/transfer/activities.d.ts +30 -0
  415. package/src/lib/transfer/activities.js +132 -0
  416. package/src/lib/transfer/activities.js.map +1 -0
  417. package/src/lib/transfer/aliases.d.ts +22 -0
  418. package/src/lib/transfer/aliases.js +1342 -0
  419. package/src/lib/transfer/aliases.js.map +1 -0
  420. package/src/lib/transfer/common.d.ts +222 -0
  421. package/src/lib/transfer/common.js +832 -0
  422. package/src/lib/transfer/common.js.map +1 -0
  423. package/src/lib/transfer/companies.d.ts +43 -0
  424. package/src/lib/transfer/companies.js +549 -0
  425. package/src/lib/transfer/companies.js.map +1 -0
  426. package/src/lib/transfer/contacts.d.ts +31 -0
  427. package/src/lib/transfer/contacts.js +727 -0
  428. package/src/lib/transfer/contacts.js.map +1 -0
  429. package/src/lib/transfer/deals.d.ts +66 -0
  430. package/src/lib/transfer/deals.js +698 -0
  431. package/src/lib/transfer/deals.js.map +1 -0
  432. package/src/lib/transfer/email-templates-package.d.ts +40 -0
  433. package/src/lib/transfer/email-templates-package.js +76 -0
  434. package/src/lib/transfer/email-templates-package.js.map +1 -0
  435. package/src/lib/transfer/email-templates-package.server.d.ts +32 -0
  436. package/src/lib/transfer/email-templates-package.server.js +176 -0
  437. package/src/lib/transfer/email-templates-package.server.js.map +1 -0
  438. package/src/lib/transfer/fields.d.ts +102 -0
  439. package/src/lib/transfer/fields.js +1755 -0
  440. package/src/lib/transfer/fields.js.map +1 -0
  441. package/src/lib/transfer/leads.d.ts +30 -0
  442. package/src/lib/transfer/leads.js +582 -0
  443. package/src/lib/transfer/leads.js.map +1 -0
  444. package/src/lib/transfer/pipelines.d.ts +21 -0
  445. package/src/lib/transfer/pipelines.js +172 -0
  446. package/src/lib/transfer/pipelines.js.map +1 -0
  447. package/src/lib/transfer/register.d.ts +47 -0
  448. package/src/lib/transfer/register.js +277 -0
  449. package/src/lib/transfer/register.js.map +1 -0
  450. package/src/lib/transfer/tasks.d.ts +30 -0
  451. package/src/lib/transfer/tasks.js +418 -0
  452. package/src/lib/transfer/tasks.js.map +1 -0
  453. package/src/lib/transfer/ui.d.ts +20 -0
  454. package/src/lib/transfer/ui.js +42 -0
  455. package/src/lib/transfer/ui.js.map +1 -0
  456. package/src/lib/components/company-import-drawer.d.ts +0 -42
  457. package/src/lib/components/company-import-drawer.js +0 -99
  458. package/src/lib/components/company-import-drawer.js.map +0 -1
  459. package/src/lib/components/contact-import-drawer.d.ts +0 -46
  460. package/src/lib/components/contact-import-drawer.js +0 -149
  461. package/src/lib/components/contact-import-drawer.js.map +0 -1
  462. package/src/lib/components/crm-export-all-button.d.ts +0 -39
  463. package/src/lib/components/crm-export-all-button.js +0 -98
  464. package/src/lib/components/crm-export-all-button.js.map +0 -1
  465. package/src/lib/components/csv-import-drawer.d.ts +0 -139
  466. package/src/lib/components/csv-import-drawer.js +0 -757
  467. package/src/lib/components/csv-import-drawer.js.map +0 -1
  468. package/src/lib/components/deal-import-drawer.d.ts +0 -24
  469. package/src/lib/components/deal-import-drawer.js +0 -83
  470. package/src/lib/components/deal-import-drawer.js.map +0 -1
  471. package/src/lib/components/lead-import-drawer.d.ts +0 -27
  472. package/src/lib/components/lead-import-drawer.js +0 -118
  473. package/src/lib/components/lead-import-drawer.js.map +0 -1
  474. package/src/lib/components/lead-source-values-card.d.ts +0 -27
  475. package/src/lib/components/lead-source-values-card.js.map +0 -1
  476. package/src/lib/components/task-import-drawer.d.ts +0 -24
  477. package/src/lib/components/task-import-drawer.js +0 -82
  478. package/src/lib/components/task-import-drawer.js.map +0 -1
  479. package/src/lib/model/companies-csv.d.ts +0 -36
  480. package/src/lib/model/companies-csv.js +0 -38
  481. package/src/lib/model/companies-csv.js.map +0 -1
  482. package/src/lib/model/contacts-csv.d.ts +0 -54
  483. package/src/lib/model/contacts-csv.js +0 -67
  484. package/src/lib/model/contacts-csv.js.map +0 -1
  485. package/src/lib/model/crm-company-import.d.ts +0 -154
  486. package/src/lib/model/crm-company-import.js +0 -331
  487. package/src/lib/model/crm-company-import.js.map +0 -1
  488. package/src/lib/model/crm-csv.d.ts +0 -239
  489. package/src/lib/model/crm-csv.js +0 -467
  490. package/src/lib/model/crm-csv.js.map +0 -1
  491. package/src/lib/model/crm-deal-import.d.ts +0 -112
  492. package/src/lib/model/crm-deal-import.js +0 -263
  493. package/src/lib/model/crm-deal-import.js.map +0 -1
  494. package/src/lib/model/crm-import.d.ts +0 -250
  495. package/src/lib/model/crm-import.js +0 -467
  496. package/src/lib/model/crm-import.js.map +0 -1
  497. package/src/lib/model/crm-lead-import.d.ts +0 -138
  498. package/src/lib/model/crm-lead-import.js +0 -446
  499. package/src/lib/model/crm-lead-import.js.map +0 -1
  500. package/src/lib/model/crm-task-import.d.ts +0 -94
  501. package/src/lib/model/crm-task-import.js +0 -275
  502. package/src/lib/model/crm-task-import.js.map +0 -1
  503. package/src/lib/model/deals-csv.d.ts +0 -32
  504. package/src/lib/model/deals-csv.js +0 -36
  505. package/src/lib/model/deals-csv.js.map +0 -1
  506. package/src/lib/model/import-column-shapes.d.ts +0 -36
  507. package/src/lib/model/import-column-shapes.js +0 -76
  508. package/src/lib/model/import-column-shapes.js.map +0 -1
  509. package/src/lib/model/lead-source-values.d.ts +0 -82
  510. package/src/lib/model/lead-source-values.js +0 -149
  511. package/src/lib/model/lead-source-values.js.map +0 -1
  512. package/src/lib/model/leads-csv.d.ts +0 -40
  513. package/src/lib/model/leads-csv.js +0 -40
  514. package/src/lib/model/leads-csv.js.map +0 -1
  515. package/src/lib/model/tasks-csv.d.ts +0 -28
  516. package/src/lib/model/tasks-csv.js +0 -28
  517. package/src/lib/model/tasks-csv.js.map +0 -1
  518. package/src/lib/server/companies-import.d.ts +0 -57
  519. package/src/lib/server/companies-import.js +0 -242
  520. package/src/lib/server/companies-import.js.map +0 -1
  521. package/src/lib/server/contacts-import.d.ts +0 -109
  522. package/src/lib/server/contacts-import.js +0 -393
  523. package/src/lib/server/contacts-import.js.map +0 -1
  524. package/src/lib/server/deals-import.d.ts +0 -76
  525. package/src/lib/server/deals-import.js +0 -248
  526. package/src/lib/server/deals-import.js.map +0 -1
  527. package/src/lib/server/export-route.d.ts +0 -60
  528. package/src/lib/server/export-route.js +0 -447
  529. package/src/lib/server/export-route.js.map +0 -1
  530. package/src/lib/server/import-context.d.ts +0 -87
  531. package/src/lib/server/import-context.js +0 -182
  532. package/src/lib/server/import-context.js.map +0 -1
  533. package/src/lib/server/lead-source-values.d.ts +0 -50
  534. package/src/lib/server/lead-source-values.js +0 -191
  535. package/src/lib/server/lead-source-values.js.map +0 -1
  536. package/src/lib/server/leads-import.d.ts +0 -84
  537. package/src/lib/server/leads-import.js +0 -367
  538. package/src/lib/server/leads-import.js.map +0 -1
  539. package/src/lib/server/tasks-import.d.ts +0 -54
  540. package/src/lib/server/tasks-import.js +0 -160
  541. package/src/lib/server/tasks-import.js.map +0 -1
@@ -30,37 +30,40 @@ import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_wi
30
30
  * it behind, and cleared by completion while it is still owed — the rule
31
31
  * in `crmTaskReminderAfterEdit`, the same one the console's drawer keeps.
32
32
  * `reminderSentAt` is read-only: when the hourly runner handled it.
33
- */ import { CRM_COLLECTIONS, crmTaskReminderAfterEdit, crmTaskReminderPending, createResourceUid, crmTaskListFields } from "@aglyn/aglyn/server";
34
- import { apiJson, ApiErrors, crmNextActivityLinksOf, recomputeCrmNextTaskAt, restampCrmListFieldsAt } from "@aglyn/tenant-data-admin";
33
+ *
34
+ * `kind`, `priority` and `status` (AGL-3517) take a value of the org's
35
+ * Type, Priority or Status picklist — its label, "In Progress" — or the
36
+ * meaning behind it, `open`; the task stores both, and answers the meaning
37
+ * under the field's own name with the label beside it as `typeLabel`,
38
+ * `priorityLabel` and `statusLabel`.
39
+ */ import { CRM_COLLECTIONS, CRM_TASK_PICKLIST_IDS, crmPicklistLabelForNew, crmTaskPicklistLabels, createResourceUid, crmTaskListFields, resolveCrmSemanticPicklistWrite } from "@aglyn/aglyn/server";
40
+ import { apiJson, ApiErrors, restampCrmListFieldsAt } from "@aglyn/tenant-data-admin";
35
41
  import { FieldValue, Timestamp } from "firebase-admin/firestore";
36
42
  import { claimWrite, readJsonBody, requireScope } from "@aglyn/tenant-data-admin/server/api-v1-kit";
37
- import { CRM_TEXT_MAX, CRM_TITLE_MAX, createPayload, crmCollection, crmCreateStamp, crmRefErrors, crmTimes, crmValidationFailed, isoFromMs, listCrm, memberError, parseIsoInstant, readChoice, readCrmSite, readEqualityFilters, readOptionalText, readRefId, refuseUnknownKeys, updatePayload } from "./crm-shared.js";
38
- const TASK_KINDS = [
39
- 'call',
40
- 'email',
41
- 'meeting',
42
- 'todo'
43
- ];
44
- const TASK_PRIORITIES = [
45
- 'low',
46
- 'normal',
47
- 'high'
48
- ];
43
+ import { CRM_TEXT_MAX, CRM_TITLE_MAX, createPayload, crmCollection, crmCreateStamp, crmRefErrors, crmTimes, crmValidationFailed, isoFromMs, listCrm, memberError, parseIsoInstant, readCrmSite, readEqualityFilters, readOptionalText, readRefId, refuseUnknownKeys, updatePayload } from "./crm-shared.js";
44
+ import { readCrmTaskPicklists } from "../read-picklist.js";
45
+ import { crmTaskReminderAfterEdit, crmTaskReminderPending } from "../../model/crm-task-reminders.js";
46
+ import { crmNextActivityLinksOf, recomputeCrmNextTaskAt } from "../crm-next-activity.js";
49
47
  const TASK_STATUSES = [
50
48
  'open',
51
49
  'done'
52
50
  ];
53
- /** The task object as published. Every writable field appears here. */ function taskView(doc) {
51
+ /** The org's task picklists, read once for a request. */ const taskPicklistsOf = (ctx)=>readCrmTaskPicklists(ctx.firestore, ctx.orgId);
52
+ /** The task object as published. Every writable field appears here. */ function taskView(doc, picklists) {
54
53
  var _doc_data, _data_title, _data_notes, _data_kind, _data_priority, _data_status, _data_assigneeUid, _data_contactId, _data_companyId, _data_dealId, _data_hostId;
55
54
  const data = (_doc_data = doc.data()) != null ? _doc_data : {};
55
+ const labels = crmTaskPicklistLabels(data, picklists);
56
56
  return _extends({
57
57
  id: doc.id,
58
58
  object: 'task',
59
59
  title: (_data_title = data.title) != null ? _data_title : null,
60
60
  notes: (_data_notes = data.notes) != null ? _data_notes : null,
61
61
  kind: (_data_kind = data.kind) != null ? _data_kind : 'todo',
62
+ typeLabel: labels.type,
62
63
  priority: (_data_priority = data.priority) != null ? _data_priority : 'normal',
64
+ priorityLabel: labels.priority,
63
65
  status: (_data_status = data.status) != null ? _data_status : 'open',
66
+ statusLabel: labels.status,
64
67
  dueAt: isoFromMs(data.dueAtMs),
65
68
  remindAt: isoFromMs(data.remindAtMs),
66
69
  reminderSentAt: isoFromMs(data.reminderSentAtMs),
@@ -85,7 +88,24 @@ const TASK_WRITABLE = new Set([
85
88
  'companyId',
86
89
  'dealId'
87
90
  ]);
88
- function readTaskInput(body, { partial }) {
91
+ /**
92
+ * A Type, Priority or Status as the body names it — a label or a meaning —
93
+ * against the org's list; the stored label is kept when the body names it
94
+ * again. Absent answers `undefined`; anything the list does not hold is an
95
+ * error naming the values it does.
96
+ */ function readPicklistField(body, key, id, picklists, stored, errors) {
97
+ const value = body[key];
98
+ if (value === undefined) return undefined;
99
+ const list = key === 'kind' ? picklists.type : key === 'priority' ? picklists.priority : picklists.status;
100
+ const resolved = typeof value === 'string' ? resolveCrmSemanticPicklistWrite(id, list, value, stored) : null;
101
+ if (resolved == null ? void 0 : resolved.ok) return {
102
+ meaning: resolved.meaning,
103
+ label: resolved.label
104
+ };
105
+ errors[key] = (resolved == null ? void 0 : resolved.ok) === false ? resolved.error : 'Must be a value of the list, or its meaning';
106
+ return undefined;
107
+ }
108
+ function readTaskInput(body, { partial }, picklists, stored = null) {
89
109
  const errors = {};
90
110
  const values = {};
91
111
  const allowed = new Set(TASK_WRITABLE);
@@ -99,11 +119,11 @@ function readTaskInput(body, { partial }) {
99
119
  }
100
120
  const notes = readOptionalText(body, 'notes', CRM_TEXT_MAX, errors);
101
121
  if (notes !== undefined) values.notes = notes;
102
- const kind = readChoice(body, 'kind', TASK_KINDS, errors);
122
+ const kind = readPicklistField(body, 'kind', CRM_TASK_PICKLIST_IDS.type, picklists, stored == null ? void 0 : stored.typeLabel, errors);
103
123
  if (kind) values.kind = kind;
104
- const priority = readChoice(body, 'priority', TASK_PRIORITIES, errors);
124
+ const priority = readPicklistField(body, 'priority', CRM_TASK_PICKLIST_IDS.priority, picklists, stored == null ? void 0 : stored.priorityLabel, errors);
105
125
  if (priority) values.priority = priority;
106
- const status = readChoice(body, 'status', TASK_STATUSES, errors);
126
+ const status = readPicklistField(body, 'status', CRM_TASK_PICKLIST_IDS.status, picklists, stored == null ? void 0 : stored.statusLabel, errors);
107
127
  if (status) values.status = status;
108
128
  if (body.dueAt !== undefined) {
109
129
  if (body.dueAt === null) {
@@ -171,9 +191,10 @@ async function taskRefErrors(ctx, values) {
171
191
  }
172
192
  /** `POST /v1/tasks`. */ async function createTask(request, ctx) {
173
193
  const body = await readJsonBody(request);
194
+ const picklists = await taskPicklistsOf(ctx);
174
195
  const parsed = readTaskInput(body, {
175
196
  partial: false
176
- });
197
+ }, picklists);
177
198
  if ('errors' in parsed) return crmValidationFailed(ctx, 'task', parsed.errors);
178
199
  const site = readCrmSite(ctx, 'task', body);
179
200
  if ('response' in site) return site.response;
@@ -184,21 +205,28 @@ async function taskRefErrors(ctx, values) {
184
205
  if ('replay' in claimed) return claimed.replay;
185
206
  const { claim } = claimed;
186
207
  try {
187
- var _rest_dueAtMs, _rest_dueAtMs1;
188
- const _parsed_values = parsed.values, { title, kind, priority, status, remindAtMs } = _parsed_values, rest = _object_without_properties_loose(_parsed_values, [
208
+ var _ref, _ref1, _ref2, _rest_dueAtMs, _rest_dueAtMs1;
209
+ const _parsed_values = parsed.values, { title, kind: pickedKind, priority: pickedPriority, status: pickedStatus, remindAtMs } = _parsed_values, rest = _object_without_properties_loose(_parsed_values, [
189
210
  "title",
190
211
  "kind",
191
212
  "priority",
192
213
  "status",
193
214
  "remindAtMs"
194
215
  ]);
216
+ const kind = (_ref = pickedKind == null ? void 0 : pickedKind.meaning) != null ? _ref : 'todo';
217
+ const priority = (_ref1 = pickedPriority == null ? void 0 : pickedPriority.meaning) != null ? _ref1 : 'normal';
218
+ const status = (_ref2 = pickedStatus == null ? void 0 : pickedStatus.meaning) != null ? _ref2 : 'open';
195
219
  const id = createResourceUid();
196
220
  const stamp = crmCreateStamp(ctx, site.siteId);
197
221
  const record = _extends({
198
222
  title,
199
- kind: kind != null ? kind : 'todo',
200
- priority: priority != null ? priority : 'normal',
201
- status: status != null ? status : 'open'
223
+ // Each meaning with the org's label beside it (AGL-3517).
224
+ kind,
225
+ typeLabel: pickedKind ? pickedKind.label : crmPicklistLabelForNew(picklists.type, kind),
226
+ priority,
227
+ priorityLabel: pickedPriority ? pickedPriority.label : crmPicklistLabelForNew(picklists.priority, priority),
228
+ status,
229
+ statusLabel: pickedStatus ? pickedStatus.label : crmPicklistLabelForNew(picklists.status, status)
202
230
  }, status === 'done' ? {
203
231
  completedAtMs: stamp.createdAt.toMillis()
204
232
  } : {}, createPayload(_extends({}, rest, {
@@ -220,7 +248,7 @@ async function taskRefErrors(ctx, values) {
220
248
  await settleNextActivity(ctx, [
221
249
  rest
222
250
  ]);
223
- const view = taskView(await collection.doc(id).get());
251
+ const view = taskView(await collection.doc(id).get(), picklists);
224
252
  await claim.record(200, view);
225
253
  return apiJson(view, {
226
254
  status: 201,
@@ -232,10 +260,7 @@ async function taskRefErrors(ctx, values) {
232
260
  }
233
261
  }
234
262
  /** `PATCH /v1/tasks/{id}`. */ async function updateTask(request, ctx, ref) {
235
- const parsed = readTaskInput(await readJsonBody(request), {
236
- partial: true
237
- });
238
- if ('errors' in parsed) return crmValidationFailed(ctx, 'task', parsed.errors);
263
+ const body = await readJsonBody(request);
239
264
  const snap = await ref.get();
240
265
  if (!snap.exists) {
241
266
  return ApiErrors.notFound({
@@ -243,18 +268,36 @@ async function taskRefErrors(ctx, values) {
243
268
  headers: ctx.headers
244
269
  });
245
270
  }
271
+ const picklists = await taskPicklistsOf(ctx);
272
+ const parsed = readTaskInput(body, {
273
+ partial: true
274
+ }, picklists, snap.data());
275
+ if ('errors' in parsed) return crmValidationFailed(ctx, 'task', parsed.errors);
246
276
  const refErrors = await taskRefErrors(ctx, parsed.values);
247
277
  if (Object.keys(refErrors).length) return crmValidationFailed(ctx, 'task', refErrors);
248
- const _parsed_values = parsed.values, { status, remindAtMs } = _parsed_values, rest = _object_without_properties_loose(_parsed_values, [
278
+ const _parsed_values = parsed.values, { status: pickedStatus, kind: pickedKind, priority: pickedPriority, remindAtMs } = _parsed_values, rest = _object_without_properties_loose(_parsed_values, [
249
279
  "status",
280
+ "kind",
281
+ "priority",
250
282
  "remindAtMs"
251
283
  ]);
252
284
  const update = updatePayload(rest);
285
+ // Each meaning with the org's label beside it (AGL-3517).
286
+ if (pickedKind) {
287
+ update.kind = pickedKind.meaning;
288
+ update.typeLabel = pickedKind.label;
289
+ }
290
+ if (pickedPriority) {
291
+ update.priority = pickedPriority.meaning;
292
+ update.priorityLabel = pickedPriority.label;
293
+ }
253
294
  // A cleared due date is stored `null`, not deleted — see the create.
254
295
  if (rest.dueAtMs === null) update.dueAtMs = null;
255
296
  // One instant for the write: a task completed at T reads updated at T.
256
297
  const now = Timestamp.now();
298
+ const status = pickedStatus == null ? void 0 : pickedStatus.meaning;
257
299
  const completing = status === 'done' && status !== snap.get('status');
300
+ if (pickedStatus) update.statusLabel = pickedStatus.label;
258
301
  if (status !== undefined && status !== snap.get('status')) {
259
302
  update.status = status;
260
303
  update.completedAtMs = status === 'done' ? now.toMillis() : null;
@@ -290,7 +333,7 @@ async function taskRefErrors(ctx, values) {
290
333
  // What the console's Tasks list searches (AGL-3321).
291
334
  if ('title' in update) await restampCrmListFieldsAt(ref, 'crmTasks');
292
335
  }
293
- return apiJson(taskView(await ref.get()), {
336
+ return apiJson(taskView(await ref.get(), picklists), {
294
337
  headers: ctx.headers
295
338
  });
296
339
  }
@@ -341,7 +384,8 @@ async function taskRefErrors(ctx, values) {
341
384
  'assigneeUid',
342
385
  'status'
343
386
  ]);
344
- return listCrm(ctx, collection, url, filters, taskView);
387
+ const picklists = await taskPicklistsOf(ctx);
388
+ return listCrm(ctx, collection, url, filters, (doc)=>taskView(doc, picklists));
345
389
  }
346
390
  export async function handleTasks(request, ctx, segments, url) {
347
391
  const collection = crmCollection(ctx, CRM_COLLECTIONS.tasks);
@@ -374,7 +418,7 @@ export async function handleTasks(request, ctx, segments, url) {
374
418
  headers: ctx.headers
375
419
  });
376
420
  }
377
- return apiJson(taskView(snap), {
421
+ return apiJson(taskView(snap, await taskPicklistsOf(ctx)), {
378
422
  headers: ctx.headers
379
423
  });
380
424
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../libs/plugins/crm/src/lib/server/api-v1/crm-tasks.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/tasks` (AGL-2606) — what the team owes a person: a call, an email, a\n * meeting or a to-do, with a due date, pointing at the contact, company or\n * deal it is for. A task may point at nothing — a plain to-do is still a\n * task — which is the one place it differs from an activity.\n *\n * `status` is the only state machine here and it has two states. Marking a\n * task `done` stamps `completedAtMs`; marking it `open` again clears it, so\n * a reopened task never reads as completed on the date it was first closed.\n *\n * `remindAt` (AGL-2659) is the task's reminder: the due time unless the\n * body names a time or `null`, carried along when a moved due date leaves\n * it behind, and cleared by completion while it is still owed — the rule\n * in `crmTaskReminderAfterEdit`, the same one the console's drawer keeps.\n * `reminderSentAt` is read-only: when the hourly runner handled it.\n */\nimport {\n CRM_COLLECTIONS,\n type CrmTask,\n type CrmTaskKind,\n type CrmTaskPriority,\n crmTaskReminderAfterEdit,\n crmTaskReminderPending,\n type CrmTaskStatus,\n createResourceUid,\n crmTaskListFields,\n} from '@aglyn/aglyn/server'\nimport {\n apiJson,\n ApiErrors,\n crmNextActivityLinksOf,\n recomputeCrmNextTaskAt,\n restampCrmListFieldsAt,\n} 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 {\n type Clearable,\n CRM_TEXT_MAX,\n CRM_TITLE_MAX,\n createPayload,\n crmCollection,\n crmCreateStamp,\n crmRefErrors,\n crmTimes,\n crmValidationFailed,\n isoFromMs,\n listCrm,\n memberError,\n parseIsoInstant,\n readChoice,\n readCrmSite,\n readEqualityFilters,\n readOptionalText,\n readRefId,\n refuseUnknownKeys,\n updatePayload,\n} from './crm-shared'\n\nconst TASK_KINDS = ['call', 'email', 'meeting', 'todo'] as const\nconst TASK_PRIORITIES = ['low', 'normal', 'high'] as const\nconst TASK_STATUSES = ['open', 'done'] as const\n\n/** The task object as published. Every writable field appears here. */\nfunction taskView(doc: FirebaseFirestore.DocumentSnapshot) {\n const data = (doc.data() ?? {}) as Partial<CrmTask>\n return {\n id: doc.id,\n object: 'task',\n title: data.title ?? null,\n notes: data.notes ?? null,\n kind: data.kind ?? 'todo',\n priority: data.priority ?? 'normal',\n status: data.status ?? 'open',\n dueAt: isoFromMs(data.dueAtMs),\n remindAt: isoFromMs(data.remindAtMs),\n reminderSentAt: isoFromMs(data.reminderSentAtMs),\n completedAt: isoFromMs(data.completedAtMs),\n assigneeUid: data.assigneeUid ?? null,\n contactId: data.contactId ?? null,\n companyId: data.companyId ?? null,\n dealId: data.dealId ?? null,\n siteId: data.hostId ?? null,\n ...crmTimes(data as FirebaseFirestore.DocumentData),\n }\n}\n\nconst TASK_WRITABLE = new Set([\n 'title',\n 'notes',\n 'kind',\n 'priority',\n 'status',\n 'dueAt',\n 'remindAt',\n 'assigneeUid',\n 'contactId',\n 'companyId',\n 'dealId',\n])\n\ninterface TaskInput {\n title?: string\n notes?: Clearable<string>\n kind?: CrmTaskKind\n priority?: CrmTaskPriority\n status?: CrmTaskStatus\n dueAtMs?: Clearable<number>\n remindAtMs?: Clearable<number>\n assigneeUid?: Clearable<string>\n contactId?: Clearable<string>\n companyId?: Clearable<string>\n dealId?: Clearable<string>\n}\n\nfunction readTaskInput(\n body: Record<string, unknown>,\n { partial }: { partial: boolean },\n): { values: TaskInput } | { errors: Record<string, string> } {\n const errors: Record<string, string> = {}\n const values: TaskInput = {}\n const allowed = new Set(TASK_WRITABLE)\n if (!partial) allowed.add('consentSiteId')\n refuseUnknownKeys(body, allowed, 'task', errors)\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 const notes = readOptionalText(body, 'notes', CRM_TEXT_MAX, errors)\n if (notes !== undefined) values.notes = notes\n const kind = readChoice(body, 'kind', TASK_KINDS, errors)\n if (kind) values.kind = kind\n const priority = readChoice(body, 'priority', TASK_PRIORITIES, errors)\n if (priority) values.priority = priority\n const status = readChoice(body, 'status', TASK_STATUSES, errors)\n if (status) values.status = status\n\n if (body.dueAt !== undefined) {\n if (body.dueAt === null) {\n values.dueAtMs = null\n } else {\n const ms = parseIsoInstant(body.dueAt)\n if (ms === null) {\n errors.dueAt = 'Must be an ISO 8601 instant, like 2026-09-10T15:00:00Z'\n } else {\n values.dueAtMs = ms\n }\n }\n }\n\n if (body.remindAt !== undefined) {\n if (body.remindAt === null) {\n values.remindAtMs = null\n } else {\n const ms = parseIsoInstant(body.remindAt)\n if (ms === null) {\n errors.remindAt = 'Must be an ISO 8601 instant, like 2026-09-10T14:00:00Z'\n } else {\n values.remindAtMs = ms\n }\n }\n }\n\n const assigneeUid = readOptionalText(body, 'assigneeUid', CRM_TITLE_MAX, errors)\n if (assigneeUid !== undefined) values.assigneeUid = assigneeUid\n for (const field of ['contactId', 'companyId', 'dealId'] as const) {\n const id = readRefId(body, field, errors)\n if (id !== undefined) values[field] = id\n }\n\n return Object.keys(errors).length ? { errors } : { values }\n}\n\nasync function taskRefErrors(\n ctx: ApiV1Context,\n values: TaskInput,\n): Promise<Record<string, string>> {\n const [assignee, refs] = await Promise.all([\n memberError(ctx, 'assigneeUid', values.assigneeUid),\n crmRefErrors(ctx, {\n contactId: values.contactId ?? undefined,\n companyId: values.companyId ?? undefined,\n dealId: values.dealId ?? undefined,\n }),\n ])\n return { ...assignee, ...refs }\n}\n\n/**\n * The records the task names carry `nextTaskAtMs` (AGL-2661), recomputed\n * after every write here from BOTH sides of the change. Its own catch: the\n * task write is done, and a figure that did not move is what the Fields\n * section's recompute is for, not a failed request.\n */\nasync function settleNextActivity(\n ctx: ApiV1Context,\n links: readonly (Record<string, unknown> | null | undefined)[],\n): Promise<void> {\n try {\n await recomputeCrmNextTaskAt(\n ctx.firestore,\n ctx.orgId,\n links.map((link) => crmNextActivityLinksOf(link)),\n )\n } catch (error) {\n console.error('[api-v1] next activity could not be recomputed', ctx.orgId, error)\n }\n}\n\n/** `POST /v1/tasks`. */\nasync function createTask(request: Request, ctx: ApiV1Context): Promise<Response> {\n const body = await readJsonBody(request)\n const parsed = readTaskInput(body, { partial: false })\n if ('errors' in parsed) return crmValidationFailed(ctx, 'task', parsed.errors)\n const site = readCrmSite(ctx, 'task', body)\n if ('response' in site) return site.response\n const refErrors = await taskRefErrors(ctx, parsed.values)\n if (Object.keys(refErrors).length) return crmValidationFailed(ctx, 'task', refErrors)\n\n const collection = crmCollection(ctx, CRM_COLLECTIONS.tasks)\n const claimed = await claimWrite(\n ctx,\n '*',\n request.headers.get('Idempotency-Key'),\n 'tasks',\n )\n if ('replay' in claimed) return claimed.replay\n const { claim } = claimed\n\n try {\n const { title, kind, priority, status, remindAtMs, ...rest } = parsed.values\n const id = createResourceUid()\n const stamp = crmCreateStamp(ctx, site.siteId)\n const record: Record<string, unknown> = {\n title,\n kind: kind ?? 'todo',\n priority: priority ?? 'normal',\n status: status ?? 'open',\n // A task created done was completed the instant it was created — the\n // same instant its `createdAt` carries.\n ...(status === 'done' ? { completedAtMs: stamp.createdAt.toMillis() } : {}),\n ...createPayload({\n ...rest,\n // A reminder on a task created done is owed to nobody.\n remindAtMs:\n status === 'done'\n ? null\n : crmTaskReminderAfterEdit({\n dueAtMs: rest.dueAtMs ?? null,\n remindAtMs,\n previous: null,\n }),\n }),\n /*\n * Stored as `null` when the body names none, never left absent: every\n * tasks list orders by `dueAtMs`, and Firestore leaves a document\n * without the ordered field out of the answer (AGL-3321).\n */\n dueAtMs: rest.dueAtMs ?? null,\n ...stamp,\n }\n // What the console's Tasks list searches by (AGL-3321).\n await collection.doc(id).create({ ...record, ...crmTaskListFields(record) })\n await settleNextActivity(ctx, [rest as Record<string, unknown>])\n const view = taskView(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/tasks/{id}`. */\nasync function updateTask(\n request: Request,\n ctx: ApiV1Context,\n ref: FirebaseFirestore.DocumentReference,\n): Promise<Response> {\n const parsed = readTaskInput(await readJsonBody(request), { partial: true })\n if ('errors' in parsed) return crmValidationFailed(ctx, 'task', parsed.errors)\n const snap = await ref.get()\n if (!snap.exists) {\n return ApiErrors.notFound({ message: 'No such task', headers: ctx.headers })\n }\n const refErrors = await taskRefErrors(ctx, parsed.values)\n if (Object.keys(refErrors).length) return crmValidationFailed(ctx, 'task', refErrors)\n\n const { status, remindAtMs, ...rest } = parsed.values\n const update: Record<string, unknown> = updatePayload(rest)\n // A cleared due date is stored `null`, not deleted — see the create.\n if (rest.dueAtMs === null) update.dueAtMs = null\n // One instant for the write: a task completed at T reads updated at T.\n const now = Timestamp.now()\n const completing = status === 'done' && status !== snap.get('status')\n if (status !== undefined && status !== snap.get('status')) {\n update.status = status\n update.completedAtMs = status === 'done' ? now.toMillis() : null\n }\n /*\n * The reminder the edit leaves: what the body said, else the rule over\n * the stored task and the due date this PATCH moves it to. Completion\n * clears one still owed. A reminder that MOVED — to a time or to none —\n * is one not yet sent, so the runner's mark comes off with it; one that\n * stayed keeps its mark.\n */\n const stored = snap.data() as Partial<CrmTask>\n const previous = {\n dueAtMs: typeof stored.dueAtMs === 'number' ? stored.dueAtMs : null,\n remindAtMs: typeof stored.remindAtMs === 'number' ? stored.remindAtMs : null,\n }\n const nextRemindAtMs =\n completing && crmTaskReminderPending(stored)\n ? null\n : crmTaskReminderAfterEdit({\n dueAtMs: rest.dueAtMs === undefined ? previous.dueAtMs : rest.dueAtMs,\n remindAtMs,\n previous,\n })\n if (nextRemindAtMs !== previous.remindAtMs) {\n update.remindAtMs = nextRemindAtMs === null ? FieldValue.delete() : nextRemindAtMs\n update.reminderSentAtMs = FieldValue.delete()\n }\n if (Object.keys(update).length > 0) {\n await ref.update({ ...update, updatedAt: now })\n await settleNextActivity(ctx, [snap.data(), rest as Record<string, unknown>])\n // What the console's Tasks list searches (AGL-3321).\n if ('title' in update) await restampCrmListFieldsAt(ref, 'crmTasks')\n }\n return apiJson(taskView(await ref.get()), { headers: ctx.headers })\n}\n\n/** `DELETE /v1/tasks/{id}`. */\nasync function deleteTask(\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 'task-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 task', headers: ctx.headers })\n }\n // Read before the delete: the records it named are recomputed without it.\n const named = snap.data()\n await ref.delete()\n await settleNextActivity(ctx, [named])\n const view = { id: ref.id, object: 'task', 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/** `GET /v1/tasks` filters, most selective first. */\nasync function listTasks(\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() !== '' && !(TASK_STATUSES as readonly string[]).includes(rawStatus.trim())) {\n return crmValidationFailed(ctx, 'task filter', {\n status: `Must be one of: ${TASK_STATUSES.join(', ')}`,\n })\n }\n const filters = readEqualityFilters(url, [\n 'dealId',\n 'contactId',\n 'companyId',\n 'assigneeUid',\n 'status',\n ])\n return listCrm(ctx, collection, url, filters, taskView)\n}\n\nexport async function handleTasks(\n request: Request,\n ctx: ApiV1Context,\n segments: string[],\n url: URL,\n): Promise<Response> {\n const collection = crmCollection(ctx, CRM_COLLECTIONS.tasks)\n const [, taskId] = segments\n\n if (!taskId) {\n if (request.method === 'GET') {\n const denied = requireScope(ctx, 'crm:read')\n if (denied) return denied\n return listTasks(ctx, collection, url)\n }\n if (request.method === 'POST') {\n const denied = requireScope(ctx, 'crm:write')\n if (denied) return denied\n return createTask(request, ctx)\n }\n return ApiErrors.methodNotAllowed({\n headers: { ...ctx.headers, Allow: 'GET, POST' },\n })\n }\n\n const ref = collection.doc(taskId)\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 task', headers: ctx.headers })\n }\n return apiJson(taskView(snap), { headers: ctx.headers })\n }\n if (request.method === 'PATCH') {\n const denied = requireScope(ctx, 'crm:write')\n if (denied) return denied\n return updateTask(request, ctx, ref)\n }\n if (request.method === 'DELETE') {\n const denied = requireScope(ctx, 'crm:write')\n if (denied) return denied\n return deleteTask(request, ctx, ref)\n }\n return ApiErrors.methodNotAllowed({\n headers: { ...ctx.headers, Allow: 'GET, PATCH, DELETE' },\n })\n}\n"],"names":["CRM_COLLECTIONS","crmTaskReminderAfterEdit","crmTaskReminderPending","createResourceUid","crmTaskListFields","apiJson","ApiErrors","crmNextActivityLinksOf","recomputeCrmNextTaskAt","restampCrmListFieldsAt","FieldValue","Timestamp","claimWrite","readJsonBody","requireScope","CRM_TEXT_MAX","CRM_TITLE_MAX","createPayload","crmCollection","crmCreateStamp","crmRefErrors","crmTimes","crmValidationFailed","isoFromMs","listCrm","memberError","parseIsoInstant","readChoice","readCrmSite","readEqualityFilters","readOptionalText","readRefId","refuseUnknownKeys","updatePayload","TASK_KINDS","TASK_PRIORITIES","TASK_STATUSES","taskView","doc","data","id","object","title","notes","kind","priority","status","dueAt","dueAtMs","remindAt","remindAtMs","reminderSentAt","reminderSentAtMs","completedAt","completedAtMs","assigneeUid","contactId","companyId","dealId","siteId","hostId","TASK_WRITABLE","Set","readTaskInput","body","partial","errors","values","allowed","add","undefined","String","trim","slice","ms","field","Object","keys","length","taskRefErrors","ctx","assignee","refs","Promise","all","settleNextActivity","links","firestore","orgId","map","link","error","console","createTask","request","parsed","site","response","refErrors","collection","tasks","claimed","headers","get","replay","claim","rest","stamp","record","createdAt","toMillis","previous","create","view","release","updateTask","ref","snap","exists","notFound","message","update","now","completing","stored","nextRemindAtMs","delete","updatedAt","deleteTask","named","deleted","listTasks","url","rawStatus","searchParams","includes","join","filters","handleTasks","segments","taskId","method","denied","methodNotAllowed","Allow"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../../libs/plugins/crm/src/lib/server/api-v1/crm-tasks.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/tasks` (AGL-2606) — what the team owes a person: a call, an email, a\n * meeting or a to-do, with a due date, pointing at the contact, company or\n * deal it is for. A task may point at nothing — a plain to-do is still a\n * task — which is the one place it differs from an activity.\n *\n * `status` is the only state machine here and it has two states. Marking a\n * task `done` stamps `completedAtMs`; marking it `open` again clears it, so\n * a reopened task never reads as completed on the date it was first closed.\n *\n * `remindAt` (AGL-2659) is the task's reminder: the due time unless the\n * body names a time or `null`, carried along when a moved due date leaves\n * it behind, and cleared by completion while it is still owed — the rule\n * in `crmTaskReminderAfterEdit`, the same one the console's drawer keeps.\n * `reminderSentAt` is read-only: when the hourly runner handled it.\n *\n * `kind`, `priority` and `status` (AGL-3517) take a value of the org's\n * Type, Priority or Status picklist — its label, \"In Progress\" — or the\n * meaning behind it, `open`; the task stores both, and answers the meaning\n * under the field's own name with the label beside it as `typeLabel`,\n * `priorityLabel` and `statusLabel`.\n */\nimport {\n CRM_COLLECTIONS,\n CRM_TASK_PICKLIST_IDS,\n type CrmPicklistId,\n crmPicklistLabelForNew,\n type CrmTask,\n type CrmTaskKind,\n type CrmTaskPicklists,\n crmTaskPicklistLabels,\n type CrmTaskPriority,\n type CrmTaskStatus,\n createResourceUid,\n crmTaskListFields,\n resolveCrmSemanticPicklistWrite,\n} from '@aglyn/aglyn/server'\nimport {\n apiJson,\n ApiErrors,\n restampCrmListFieldsAt,\n} 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 {\n type Clearable,\n CRM_TEXT_MAX,\n CRM_TITLE_MAX,\n createPayload,\n crmCollection,\n crmCreateStamp,\n crmRefErrors,\n crmTimes,\n crmValidationFailed,\n isoFromMs,\n listCrm,\n memberError,\n parseIsoInstant,\n readCrmSite,\n readEqualityFilters,\n readOptionalText,\n readRefId,\n refuseUnknownKeys,\n updatePayload,\n} from './crm-shared'\nimport { readCrmTaskPicklists } from '../read-picklist'\nimport { crmTaskReminderAfterEdit, crmTaskReminderPending } from '../../model/crm-task-reminders'\nimport { crmNextActivityLinksOf, recomputeCrmNextTaskAt } from '../crm-next-activity'\n\nconst TASK_STATUSES = ['open', 'done'] as const\n\n/** The org's task picklists, read once for a request. */\nconst taskPicklistsOf = (ctx: ApiV1Context): Promise<CrmTaskPicklists> =>\n readCrmTaskPicklists(ctx.firestore, ctx.orgId)\n\n/** The task object as published. Every writable field appears here. */\nfunction taskView(doc: FirebaseFirestore.DocumentSnapshot, picklists: CrmTaskPicklists) {\n const data = (doc.data() ?? {}) as Partial<CrmTask>\n const labels = crmTaskPicklistLabels(data, picklists)\n return {\n id: doc.id,\n object: 'task',\n title: data.title ?? null,\n notes: data.notes ?? null,\n kind: data.kind ?? 'todo',\n typeLabel: labels.type,\n priority: data.priority ?? 'normal',\n priorityLabel: labels.priority,\n status: data.status ?? 'open',\n statusLabel: labels.status,\n dueAt: isoFromMs(data.dueAtMs),\n remindAt: isoFromMs(data.remindAtMs),\n reminderSentAt: isoFromMs(data.reminderSentAtMs),\n completedAt: isoFromMs(data.completedAtMs),\n assigneeUid: data.assigneeUid ?? null,\n contactId: data.contactId ?? null,\n companyId: data.companyId ?? null,\n dealId: data.dealId ?? null,\n siteId: data.hostId ?? null,\n ...crmTimes(data as FirebaseFirestore.DocumentData),\n }\n}\n\nconst TASK_WRITABLE = new Set([\n 'title',\n 'notes',\n 'kind',\n 'priority',\n 'status',\n 'dueAt',\n 'remindAt',\n 'assigneeUid',\n 'contactId',\n 'companyId',\n 'dealId',\n])\n\n/** A picklist field as resolved: the meaning stored under its name, the label beside it. */\ninterface Picked<T extends string> {\n meaning: T\n label: string | null\n}\n\ninterface TaskInput {\n title?: string\n notes?: Clearable<string>\n kind?: Picked<CrmTaskKind>\n priority?: Picked<CrmTaskPriority>\n status?: Picked<CrmTaskStatus>\n dueAtMs?: Clearable<number>\n remindAtMs?: Clearable<number>\n assigneeUid?: Clearable<string>\n contactId?: Clearable<string>\n companyId?: Clearable<string>\n dealId?: Clearable<string>\n}\n\n/**\n * A Type, Priority or Status as the body names it — a label or a meaning —\n * against the org's list; the stored label is kept when the body names it\n * again. Absent answers `undefined`; anything the list does not hold is an\n * error naming the values it does.\n */\nfunction readPicklistField<T extends string>(\n body: Record<string, unknown>,\n key: 'kind' | 'priority' | 'status',\n id: CrmPicklistId,\n picklists: CrmTaskPicklists,\n stored: string | null | undefined,\n errors: Record<string, string>,\n): Picked<T> | undefined {\n const value = body[key]\n if (value === undefined) return undefined\n const list =\n key === 'kind' ? picklists.type : key === 'priority' ? picklists.priority : picklists.status\n const resolved =\n typeof value === 'string' ? resolveCrmSemanticPicklistWrite(id, list, value, stored) : null\n if (resolved?.ok) return { meaning: resolved.meaning as T, label: resolved.label }\n errors[key] =\n resolved?.ok === false ? resolved.error : 'Must be a value of the list, or its meaning'\n return undefined\n}\n\nfunction readTaskInput(\n body: Record<string, unknown>,\n { partial }: { partial: boolean },\n picklists: CrmTaskPicklists,\n stored: Partial<CrmTask> | null = null,\n): { values: TaskInput } | { errors: Record<string, string> } {\n const errors: Record<string, string> = {}\n const values: TaskInput = {}\n const allowed = new Set(TASK_WRITABLE)\n if (!partial) allowed.add('consentSiteId')\n refuseUnknownKeys(body, allowed, 'task', errors)\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 const notes = readOptionalText(body, 'notes', CRM_TEXT_MAX, errors)\n if (notes !== undefined) values.notes = notes\n const kind = readPicklistField<CrmTaskKind>(\n body, 'kind', CRM_TASK_PICKLIST_IDS.type, picklists, stored?.typeLabel, errors,\n )\n if (kind) values.kind = kind\n const priority = readPicklistField<CrmTaskPriority>(\n body, 'priority', CRM_TASK_PICKLIST_IDS.priority, picklists, stored?.priorityLabel, errors,\n )\n if (priority) values.priority = priority\n const status = readPicklistField<CrmTaskStatus>(\n body, 'status', CRM_TASK_PICKLIST_IDS.status, picklists, stored?.statusLabel, errors,\n )\n if (status) values.status = status\n\n if (body.dueAt !== undefined) {\n if (body.dueAt === null) {\n values.dueAtMs = null\n } else {\n const ms = parseIsoInstant(body.dueAt)\n if (ms === null) {\n errors.dueAt = 'Must be an ISO 8601 instant, like 2026-09-10T15:00:00Z'\n } else {\n values.dueAtMs = ms\n }\n }\n }\n\n if (body.remindAt !== undefined) {\n if (body.remindAt === null) {\n values.remindAtMs = null\n } else {\n const ms = parseIsoInstant(body.remindAt)\n if (ms === null) {\n errors.remindAt = 'Must be an ISO 8601 instant, like 2026-09-10T14:00:00Z'\n } else {\n values.remindAtMs = ms\n }\n }\n }\n\n const assigneeUid = readOptionalText(body, 'assigneeUid', CRM_TITLE_MAX, errors)\n if (assigneeUid !== undefined) values.assigneeUid = assigneeUid\n for (const field of ['contactId', 'companyId', 'dealId'] as const) {\n const id = readRefId(body, field, errors)\n if (id !== undefined) values[field] = id\n }\n\n return Object.keys(errors).length ? { errors } : { values }\n}\n\nasync function taskRefErrors(\n ctx: ApiV1Context,\n values: TaskInput,\n): Promise<Record<string, string>> {\n const [assignee, refs] = await Promise.all([\n memberError(ctx, 'assigneeUid', values.assigneeUid),\n crmRefErrors(ctx, {\n contactId: values.contactId ?? undefined,\n companyId: values.companyId ?? undefined,\n dealId: values.dealId ?? undefined,\n }),\n ])\n return { ...assignee, ...refs }\n}\n\n/**\n * The records the task names carry `nextTaskAtMs` (AGL-2661), recomputed\n * after every write here from BOTH sides of the change. Its own catch: the\n * task write is done, and a figure that did not move is what the Fields\n * section's recompute is for, not a failed request.\n */\nasync function settleNextActivity(\n ctx: ApiV1Context,\n links: readonly (Record<string, unknown> | null | undefined)[],\n): Promise<void> {\n try {\n await recomputeCrmNextTaskAt(\n ctx.firestore,\n ctx.orgId,\n links.map((link) => crmNextActivityLinksOf(link)),\n )\n } catch (error) {\n console.error('[api-v1] next activity could not be recomputed', ctx.orgId, error)\n }\n}\n\n/** `POST /v1/tasks`. */\nasync function createTask(request: Request, ctx: ApiV1Context): Promise<Response> {\n const body = await readJsonBody(request)\n const picklists = await taskPicklistsOf(ctx)\n const parsed = readTaskInput(body, { partial: false }, picklists)\n if ('errors' in parsed) return crmValidationFailed(ctx, 'task', parsed.errors)\n const site = readCrmSite(ctx, 'task', body)\n if ('response' in site) return site.response\n const refErrors = await taskRefErrors(ctx, parsed.values)\n if (Object.keys(refErrors).length) return crmValidationFailed(ctx, 'task', refErrors)\n\n const collection = crmCollection(ctx, CRM_COLLECTIONS.tasks)\n const claimed = await claimWrite(\n ctx,\n '*',\n request.headers.get('Idempotency-Key'),\n 'tasks',\n )\n if ('replay' in claimed) return claimed.replay\n const { claim } = claimed\n\n try {\n const { title, kind: pickedKind, priority: pickedPriority, status: pickedStatus, remindAtMs, ...rest } =\n parsed.values\n const kind = pickedKind?.meaning ?? 'todo'\n const priority = pickedPriority?.meaning ?? 'normal'\n const status = pickedStatus?.meaning ?? 'open'\n const id = createResourceUid()\n const stamp = crmCreateStamp(ctx, site.siteId)\n const record: Record<string, unknown> = {\n title,\n // Each meaning with the org's label beside it (AGL-3517).\n kind,\n typeLabel: pickedKind ? pickedKind.label : crmPicklistLabelForNew(picklists.type, kind),\n priority,\n priorityLabel: pickedPriority\n ? pickedPriority.label\n : crmPicklistLabelForNew(picklists.priority, priority),\n status,\n statusLabel: pickedStatus\n ? pickedStatus.label\n : crmPicklistLabelForNew(picklists.status, status),\n // A task created done was completed the instant it was created — the\n // same instant its `createdAt` carries.\n ...(status === 'done' ? { completedAtMs: stamp.createdAt.toMillis() } : {}),\n ...createPayload({\n ...rest,\n // A reminder on a task created done is owed to nobody.\n remindAtMs:\n status === 'done'\n ? null\n : crmTaskReminderAfterEdit({\n dueAtMs: rest.dueAtMs ?? null,\n remindAtMs,\n previous: null,\n }),\n }),\n /*\n * Stored as `null` when the body names none, never left absent: every\n * tasks list orders by `dueAtMs`, and Firestore leaves a document\n * without the ordered field out of the answer (AGL-3321).\n */\n dueAtMs: rest.dueAtMs ?? null,\n ...stamp,\n }\n // What the console's Tasks list searches by (AGL-3321).\n await collection.doc(id).create({ ...record, ...crmTaskListFields(record) })\n await settleNextActivity(ctx, [rest as Record<string, unknown>])\n const view = taskView(await collection.doc(id).get(), picklists)\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/tasks/{id}`. */\nasync function updateTask(\n request: Request,\n ctx: ApiV1Context,\n ref: FirebaseFirestore.DocumentReference,\n): Promise<Response> {\n const body = await readJsonBody(request)\n const snap = await ref.get()\n if (!snap.exists) {\n return ApiErrors.notFound({ message: 'No such task', headers: ctx.headers })\n }\n const picklists = await taskPicklistsOf(ctx)\n const parsed = readTaskInput(body, { partial: true }, picklists, snap.data() as Partial<CrmTask>)\n if ('errors' in parsed) return crmValidationFailed(ctx, 'task', parsed.errors)\n const refErrors = await taskRefErrors(ctx, parsed.values)\n if (Object.keys(refErrors).length) return crmValidationFailed(ctx, 'task', refErrors)\n\n const { status: pickedStatus, kind: pickedKind, priority: pickedPriority, remindAtMs, ...rest } =\n parsed.values\n const update: Record<string, unknown> = updatePayload(rest)\n // Each meaning with the org's label beside it (AGL-3517).\n if (pickedKind) {\n update.kind = pickedKind.meaning\n update.typeLabel = pickedKind.label\n }\n if (pickedPriority) {\n update.priority = pickedPriority.meaning\n update.priorityLabel = pickedPriority.label\n }\n // A cleared due date is stored `null`, not deleted — see the create.\n if (rest.dueAtMs === null) update.dueAtMs = null\n // One instant for the write: a task completed at T reads updated at T.\n const now = Timestamp.now()\n const status = pickedStatus?.meaning\n const completing = status === 'done' && status !== snap.get('status')\n if (pickedStatus) update.statusLabel = pickedStatus.label\n if (status !== undefined && status !== snap.get('status')) {\n update.status = status\n update.completedAtMs = status === 'done' ? now.toMillis() : null\n }\n /*\n * The reminder the edit leaves: what the body said, else the rule over\n * the stored task and the due date this PATCH moves it to. Completion\n * clears one still owed. A reminder that MOVED — to a time or to none —\n * is one not yet sent, so the runner's mark comes off with it; one that\n * stayed keeps its mark.\n */\n const stored = snap.data() as Partial<CrmTask>\n const previous = {\n dueAtMs: typeof stored.dueAtMs === 'number' ? stored.dueAtMs : null,\n remindAtMs: typeof stored.remindAtMs === 'number' ? stored.remindAtMs : null,\n }\n const nextRemindAtMs =\n completing && crmTaskReminderPending(stored)\n ? null\n : crmTaskReminderAfterEdit({\n dueAtMs: rest.dueAtMs === undefined ? previous.dueAtMs : rest.dueAtMs,\n remindAtMs,\n previous,\n })\n if (nextRemindAtMs !== previous.remindAtMs) {\n update.remindAtMs = nextRemindAtMs === null ? FieldValue.delete() : nextRemindAtMs\n update.reminderSentAtMs = FieldValue.delete()\n }\n if (Object.keys(update).length > 0) {\n await ref.update({ ...update, updatedAt: now })\n await settleNextActivity(ctx, [snap.data(), rest as Record<string, unknown>])\n // What the console's Tasks list searches (AGL-3321).\n if ('title' in update) await restampCrmListFieldsAt(ref, 'crmTasks')\n }\n return apiJson(taskView(await ref.get(), picklists), { headers: ctx.headers })\n}\n\n/** `DELETE /v1/tasks/{id}`. */\nasync function deleteTask(\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 'task-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 task', headers: ctx.headers })\n }\n // Read before the delete: the records it named are recomputed without it.\n const named = snap.data()\n await ref.delete()\n await settleNextActivity(ctx, [named])\n const view = { id: ref.id, object: 'task', 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/** `GET /v1/tasks` filters, most selective first. */\nasync function listTasks(\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() !== '' && !(TASK_STATUSES as readonly string[]).includes(rawStatus.trim())) {\n return crmValidationFailed(ctx, 'task filter', {\n status: `Must be one of: ${TASK_STATUSES.join(', ')}`,\n })\n }\n const filters = readEqualityFilters(url, [\n 'dealId',\n 'contactId',\n 'companyId',\n 'assigneeUid',\n 'status',\n ])\n const picklists = await taskPicklistsOf(ctx)\n return listCrm(ctx, collection, url, filters, (doc) => taskView(doc, picklists))\n}\n\nexport async function handleTasks(\n request: Request,\n ctx: ApiV1Context,\n segments: string[],\n url: URL,\n): Promise<Response> {\n const collection = crmCollection(ctx, CRM_COLLECTIONS.tasks)\n const [, taskId] = segments\n\n if (!taskId) {\n if (request.method === 'GET') {\n const denied = requireScope(ctx, 'crm:read')\n if (denied) return denied\n return listTasks(ctx, collection, url)\n }\n if (request.method === 'POST') {\n const denied = requireScope(ctx, 'crm:write')\n if (denied) return denied\n return createTask(request, ctx)\n }\n return ApiErrors.methodNotAllowed({\n headers: { ...ctx.headers, Allow: 'GET, POST' },\n })\n }\n\n const ref = collection.doc(taskId)\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 task', headers: ctx.headers })\n }\n return apiJson(taskView(snap, await taskPicklistsOf(ctx)), { headers: ctx.headers })\n }\n if (request.method === 'PATCH') {\n const denied = requireScope(ctx, 'crm:write')\n if (denied) return denied\n return updateTask(request, ctx, ref)\n }\n if (request.method === 'DELETE') {\n const denied = requireScope(ctx, 'crm:write')\n if (denied) return denied\n return deleteTask(request, ctx, ref)\n }\n return ApiErrors.methodNotAllowed({\n headers: { ...ctx.headers, Allow: 'GET, PATCH, DELETE' },\n })\n}\n"],"names":["CRM_COLLECTIONS","CRM_TASK_PICKLIST_IDS","crmPicklistLabelForNew","crmTaskPicklistLabels","createResourceUid","crmTaskListFields","resolveCrmSemanticPicklistWrite","apiJson","ApiErrors","restampCrmListFieldsAt","FieldValue","Timestamp","claimWrite","readJsonBody","requireScope","CRM_TEXT_MAX","CRM_TITLE_MAX","createPayload","crmCollection","crmCreateStamp","crmRefErrors","crmTimes","crmValidationFailed","isoFromMs","listCrm","memberError","parseIsoInstant","readCrmSite","readEqualityFilters","readOptionalText","readRefId","refuseUnknownKeys","updatePayload","readCrmTaskPicklists","crmTaskReminderAfterEdit","crmTaskReminderPending","crmNextActivityLinksOf","recomputeCrmNextTaskAt","TASK_STATUSES","taskPicklistsOf","ctx","firestore","orgId","taskView","doc","picklists","data","labels","id","object","title","notes","kind","typeLabel","type","priority","priorityLabel","status","statusLabel","dueAt","dueAtMs","remindAt","remindAtMs","reminderSentAt","reminderSentAtMs","completedAt","completedAtMs","assigneeUid","contactId","companyId","dealId","siteId","hostId","TASK_WRITABLE","Set","readPicklistField","body","key","stored","errors","value","undefined","list","resolved","ok","meaning","label","error","readTaskInput","partial","values","allowed","add","String","trim","slice","ms","field","Object","keys","length","taskRefErrors","assignee","refs","Promise","all","settleNextActivity","links","map","link","console","createTask","request","parsed","site","response","refErrors","collection","tasks","claimed","headers","get","replay","claim","rest","pickedKind","pickedPriority","pickedStatus","stamp","record","createdAt","toMillis","previous","create","view","release","updateTask","ref","snap","exists","notFound","message","update","now","completing","nextRemindAtMs","delete","updatedAt","deleteTask","named","deleted","listTasks","url","rawStatus","searchParams","includes","join","filters","handleTasks","segments","taskId","method","denied","methodNotAllowed","Allow"],"mappings":"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"}
@@ -15,15 +15,4 @@
15
15
  * limitations under the License.
16
16
  */
17
17
  import { type ApiV1ResourceDescription } from '@aglyn/tenant-data-admin/server/api-v1-description';
18
- /**
19
- * The CRM's resources as the customer API's OpenAPI document describes them
20
- * (AGL-2733), keyed by the resource each describes — what the console's
21
- * builder turns into their paths, tags and schemas, and the MCP tools derive
22
- * from.
23
- *
24
- * Transcribed from the response examples in `apps/docs/api/resources/*.md`,
25
- * the customer-facing contract, as the platform's own resources are; each
26
- * write body lists its handler's own writable set. `api-v1-openapi.spec.ts`
27
- * holds the document to every endpoint the documentation promises.
28
- */
29
18
  export declare const CRM_API_V1_DESCRIPTIONS: Readonly<Record<string, ApiV1ResourceDescription>>;