@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
@@ -56,11 +56,36 @@ import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_wi
56
56
  * the client; the last sum stays until it is retyped. Changing the currency
57
57
  * of a deal with lines needs the lines resent in that currency, because
58
58
  * their sum is one number in one unit.
59
- */ import { CRM_COLLECTIONS, CRM_MEDIA_IDS_MAX, createResourceUid, crmNewRecordListFields, dealStageById, lineItemsTotalCents, normalizeCrmMediaIds, readDealLineItems } from "@aglyn/aglyn/server";
59
+ *
60
+ * ## Salesforce's Opportunity fields (AGL-3516)
61
+ *
62
+ * `type` and `leadSource` are judged against the org's `opportunityType`
63
+ * and `leadSource` picklists, as every door judges them: an active value
64
+ * is stored as the list spells it, a deal's own current value is kept, and
65
+ * anything else is a `400` naming the values allowed. A create with no
66
+ * `type` takes the list's default; `leadSource` is never defaulted.
67
+ * `forecastCategory` is one of a FIXED set. Every stage move stamps the new
68
+ * stage's `forecastCategory` and clears the `probability` override — a
69
+ * body that sets either beside the move wins. `campaignId` names one of the
70
+ * org's live campaigns.
71
+ *
72
+ * ## Contact roles (AGL-3521)
73
+ *
74
+ * `contactRoles` is the whole list of the deal's contacts — `{ contactId,
75
+ * role, primary }` — replaced as sent. Each contact must exist, none twice,
76
+ * at most one Primary, and each `role` is judged against the org's
77
+ * `opportunityContactRole` list (a contact's current role kept). The
78
+ * Primary IS `contactId`: a body that sends both must agree, and a body
79
+ * that sends `contactId` alone makes that contact Primary — added with no
80
+ * role when the deal did not name them — so an integration written before
81
+ * roles keeps meaning what it meant.
82
+ */ import { 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 } from "@aglyn/aglyn/server";
60
83
  import { apiJson, ApiErrors, restampCrmListFieldsAt } from "@aglyn/tenant-data-admin";
61
- import { Timestamp } from "firebase-admin/firestore";
84
+ import { FieldValue, Timestamp } from "firebase-admin/firestore";
62
85
  import { claimWrite, readJsonBody, requireScope } from "@aglyn/tenant-data-admin/server/api-v1-kit";
86
+ import { readOrgContainers } from "@aglyn/tenant-data-admin/server/org-containers";
63
87
  import { floorContactLifecycleStage } from "../contact-lifecycle-floor.js";
88
+ import { readCrmPicklist, resolveCrmPicklistWrite } from "../read-picklist.js";
64
89
  import { orderedStages, resolvePipeline } from "./crm-pipelines.js";
65
90
  import { 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 } from "./crm-shared.js";
66
91
  const DEAL_STATUSES = [
@@ -79,7 +104,7 @@ const DEAL_STATUSES = [
79
104
  };
80
105
  }
81
106
  /** The deal object as published. Every writable field appears here. */ function dealView(doc) {
82
- var _doc_data, _data_title, _data_pipelineId, _data_stageId, _data_status, _data_currency, _data_ownerUid, _data_contactId, _data_companyId, _data_lostReason, _data_notes, _data_hostId;
107
+ var _doc_data, _data_title, _data_pipelineId, _data_stageId, _data_status, _data_currency, _data_ownerUid, _data_contactId, _data_companyId, _data_lostReason, _data_notes, _data_type, _data_leadSource, _data_nextStep, _data_forecastCategory, _data_campaignId, _data_hostId;
83
108
  const data = (_doc_data = doc.data()) != null ? _doc_data : {};
84
109
  return _extends({
85
110
  id: doc.id,
@@ -98,9 +123,26 @@ const DEAL_STATUSES = [
98
123
  stageChangedAt: isoFromMs(data.stageChangedAtMs),
99
124
  ownerUid: (_data_ownerUid = data.ownerUid) != null ? _data_ownerUid : null,
100
125
  contactId: (_data_contactId = data.contactId) != null ? _data_contactId : null,
126
+ // Every contact on the deal and the part each plays (AGL-3521); the
127
+ // Primary is `contactId`.
128
+ contactRoles: dealContactRolesOf(data).map((row)=>{
129
+ var _row_role;
130
+ return {
131
+ contactId: row.contactId,
132
+ role: (_row_role = row.role) != null ? _row_role : null,
133
+ primary: row.primary
134
+ };
135
+ }),
101
136
  companyId: (_data_companyId = data.companyId) != null ? _data_companyId : null,
102
137
  lostReason: (_data_lostReason = data.lostReason) != null ? _data_lostReason : null,
103
138
  notes: (_data_notes = data.notes) != null ? _data_notes : null,
139
+ // Salesforce's Opportunity fields (AGL-3516).
140
+ type: (_data_type = data.type) != null ? _data_type : null,
141
+ leadSource: (_data_leadSource = data.leadSource) != null ? _data_leadSource : null,
142
+ nextStep: (_data_nextStep = data.nextStep) != null ? _data_nextStep : null,
143
+ probability: typeof data.probability === 'number' ? data.probability : null,
144
+ forecastCategory: (_data_forecastCategory = data.forecastCategory) != null ? _data_forecastCategory : null,
145
+ campaignId: (_data_campaignId = data.campaignId) != null ? _data_campaignId : null,
104
146
  // The org's deal custom fields, keyed by field key (AGL-2661).
105
147
  custom: crmCustomView(data),
106
148
  // When the earliest open task against the deal is due — see
@@ -124,8 +166,80 @@ const DEAL_WRITABLE = new Set([
124
166
  'lostReason',
125
167
  'notes',
126
168
  'custom',
127
- 'mediaIds'
169
+ 'mediaIds',
170
+ 'type',
171
+ 'leadSource',
172
+ 'nextStep',
173
+ 'probability',
174
+ 'forecastCategory',
175
+ 'campaignId',
176
+ 'contactRoles'
177
+ ]);
178
+ /** The keys one contact role takes. */ const CONTACT_ROLE_KEYS = new Set([
179
+ 'contactId',
180
+ 'role',
181
+ 'primary'
128
182
  ]);
183
+ /**
184
+ * `contactRoles` as sent, shape-checked: a list of at most
185
+ * {@link DEAL_CONTACT_ROLES_MAX} entries, each naming a contact once, and
186
+ * at most one of them Primary. `null` is the empty list.
187
+ */ function readContactRolesBody(raw, errors) {
188
+ if (raw === undefined) return undefined;
189
+ if (raw === null) return [];
190
+ if (!Array.isArray(raw)) {
191
+ errors.contactRoles = 'Must be a list of { contactId, role, primary }';
192
+ return undefined;
193
+ }
194
+ if (raw.length > DEAL_CONTACT_ROLES_MAX) {
195
+ errors.contactRoles = `At most ${DEAL_CONTACT_ROLES_MAX} contacts per deal`;
196
+ return undefined;
197
+ }
198
+ const seen = new Set();
199
+ let primaries = 0;
200
+ for (const [at, entry] of raw.entries()){
201
+ const row = entry && typeof entry === 'object' && !Array.isArray(entry) ? entry : null;
202
+ const contactId = typeof (row == null ? void 0 : row['contactId']) === 'string' ? row['contactId'].trim() : '';
203
+ const unknownKey = row ? Object.keys(row).find((key)=>!CONTACT_ROLE_KEYS.has(key)) : undefined;
204
+ if (!row || unknownKey) {
205
+ errors.contactRoles = unknownKey ? `Entry ${at}: unknown field ${unknownKey}` : `Entry ${at}: must be { contactId, role, primary }`;
206
+ return undefined;
207
+ }
208
+ if (!contactId || contactId.length > 200 || contactId.includes('/')) {
209
+ errors.contactRoles = `Entry ${at}: contactId must be a contact id`;
210
+ return undefined;
211
+ }
212
+ if (seen.has(contactId)) {
213
+ errors.contactRoles = `Entry ${at}: ${contactId} is on the list twice`;
214
+ return undefined;
215
+ }
216
+ seen.add(contactId);
217
+ if (row['role'] !== undefined && row['role'] !== null && typeof row['role'] !== 'string') {
218
+ errors.contactRoles = `Entry ${at}: role must be a contact role, or null`;
219
+ return undefined;
220
+ }
221
+ if (row['primary'] !== undefined && typeof row['primary'] !== 'boolean') {
222
+ errors.contactRoles = `Entry ${at}: primary must be true or false`;
223
+ return undefined;
224
+ }
225
+ if (row['primary'] === true) primaries += 1;
226
+ }
227
+ if (primaries > 1) {
228
+ errors.contactRoles = 'At most one contact may be Primary';
229
+ return undefined;
230
+ }
231
+ return raw.map((entry)=>{
232
+ const row = entry;
233
+ const role = typeof row['role'] === 'string' ? row['role'].trim() : '';
234
+ return _extends({
235
+ contactId: String(row['contactId']).trim()
236
+ }, role ? {
237
+ role
238
+ } : {}, {
239
+ primary: row['primary'] === true
240
+ });
241
+ });
242
+ }
129
243
  /**
130
244
  * The writable half of a deal, validated. `pipelineId` is accepted on a
131
245
  * create only: a deal's stages are its pipeline's, and moving one between
@@ -219,6 +333,36 @@ const DEAL_WRITABLE = new Set([
219
333
  if (lostReason !== undefined) values.lostReason = lostReason;
220
334
  const notes = readOptionalText(body, 'notes', CRM_TEXT_MAX, errors);
221
335
  if (notes !== undefined) values.notes = notes;
336
+ for (const key of [
337
+ 'type',
338
+ 'leadSource'
339
+ ]){
340
+ const label = readOptionalText(body, key, CRM_TITLE_MAX, errors);
341
+ if (label !== undefined) values[key] = label;
342
+ }
343
+ const nextStep = readOptionalText(body, 'nextStep', DEAL_NEXT_STEP_MAX, errors);
344
+ if (nextStep !== undefined) values.nextStep = nextStep;
345
+ if (body.probability !== undefined) {
346
+ if (body.probability === null) {
347
+ values.probability = null;
348
+ } else if (typeof body.probability !== 'number' || !Number.isInteger(body.probability) || body.probability < 0 || body.probability > 100) {
349
+ errors.probability = 'Must be a whole number from 0 to 100, or null for the stage’s';
350
+ } else {
351
+ values.probability = body.probability;
352
+ }
353
+ }
354
+ const forecastCategory = readChoice(body, 'forecastCategory', CRM_FORECAST_CATEGORIES, errors);
355
+ if (forecastCategory) values.forecastCategory = forecastCategory;
356
+ const campaignId = readRefId(body, 'campaignId', errors);
357
+ if (campaignId !== undefined) values.campaignId = campaignId;
358
+ const contactRoles = readContactRolesBody(body.contactRoles, errors);
359
+ if (contactRoles !== undefined) {
360
+ values.contactRoles = contactRoles;
361
+ // The Primary IS `contactId`, so a body naming both says one thing twice.
362
+ if (values.contactId !== undefined && values.contactId !== dealPrimaryContactId(contactRoles)) {
363
+ errors.contactId = 'Must name the Primary in contactRoles, or be left out';
364
+ }
365
+ }
222
366
  // `custom` is shape-checked here and judged against the org's
223
367
  // definitions by the writers, which is where the read is paid.
224
368
  if (body.custom !== undefined) {
@@ -320,24 +464,116 @@ const DEAL_WRITABLE = new Set([
320
464
  console.error('[api-v1] deals: the customer floor failed', contactId, error);
321
465
  }
322
466
  }
323
- /** The fields a stage move writes, beside the stage itself. */ function stageMove(stage, nowMs) {
324
- return {
467
+ /**
468
+ * The fields a stage move writes, beside the stage itself — and the new
469
+ * stage's forecast category with the probability override cleared
470
+ * (`dealStageMoveFields`, AGL-3516).
471
+ */ function stageMove(stage, nowMs) {
472
+ return _extends({
325
473
  stageId: stage.id,
326
474
  status: stage.kind,
327
475
  stageChangedAtMs: nowMs,
328
476
  closedAtMs: stage.kind === 'open' ? null : nowMs
329
- };
477
+ }, dealStageMoveFields(stage));
330
478
  }
331
- /** The membership and reference checks a deal write makes, merged. */ async function dealRefErrors(ctx, values) {
332
- var _values_contactId, _values_companyId;
333
- const [owner, refs] = await Promise.all([
479
+ /**
480
+ * The membership and reference checks a deal write makes, merged. A
481
+ * campaign is checked against the org's live campaigns, except the one the
482
+ * deal already names, which it keeps even once the campaign is retired.
483
+ */ async function dealRefErrors(ctx, values, stored) {
484
+ var _values_campaignId, _values_contactId, _values_companyId;
485
+ const campaignId = (_values_campaignId = values.campaignId) != null ? _values_campaignId : undefined;
486
+ const [owner, refs, campaign, roles] = await Promise.all([
334
487
  memberError(ctx, 'ownerUid', values.ownerUid),
335
488
  crmRefErrors(ctx, {
336
489
  contactId: (_values_contactId = values.contactId) != null ? _values_contactId : undefined,
337
490
  companyId: (_values_companyId = values.companyId) != null ? _values_companyId : undefined
338
- })
491
+ }),
492
+ campaignId && campaignId !== (stored == null ? void 0 : stored.campaignId) ? readOrgContainers(ctx.firestore, 'campaign', ctx.orgId, [
493
+ campaignId
494
+ ]).then(([record])=>(record == null ? void 0 : record.live) ? {} : {
495
+ campaignId: 'No such campaign in this organization'
496
+ }) : Promise.resolve({}),
497
+ contactRoleRefErrors(ctx, values.contactRoles, stored)
339
498
  ]);
340
- return _extends({}, owner, refs);
499
+ return _extends({}, owner, refs, campaign, roles);
500
+ }
501
+ /**
502
+ * Every contact a sent `contactRoles` adds to the deal must exist; one the
503
+ * deal already names is kept as it is, as a campaign is.
504
+ */ async function contactRoleRefErrors(ctx, roles, stored) {
505
+ const held = new Set(stored ? dealContactRolesOf(stored).map((row)=>row.contactId) : []);
506
+ const added = (roles != null ? roles : []).map((row)=>row.contactId).filter((id)=>!held.has(id));
507
+ if (!added.length) return {};
508
+ const contacts = ctx.firestore.collection('orgs').doc(ctx.orgId).collection('contacts');
509
+ const snapshots = await ctx.firestore.getAll(...added.map((id)=>contacts.doc(id)));
510
+ const missing = snapshots.find((snapshot)=>!snapshot.exists);
511
+ return missing ? {
512
+ contactRoles: `No such contact in this organization: ${missing.id}`
513
+ } : {};
514
+ }
515
+ /**
516
+ * What a write stores for the deal's contacts (AGL-3521): `contactRoles`
517
+ * judged and `contactId` beside its Primary when the body sent the list;
518
+ * when it sent `contactId` alone, the stored roles with that contact as the
519
+ * Primary. Nothing, when it sent neither.
520
+ */ async function dealContactRoleWrites(ctx, values, stored) {
521
+ const current = stored ? dealContactRolesOf(stored) : [];
522
+ if (values.contactRoles !== undefined) {
523
+ const judged = judgeDealContactRoles(await readCrmPicklist(ctx.firestore, ctx.orgId, 'opportunityContactRole'), values.contactRoles, current);
524
+ if (judged.ok === false) return {
525
+ errors: {
526
+ contactRoles: judged.error
527
+ }
528
+ };
529
+ return {
530
+ values: dealContactRoleFields(judged.roles)
531
+ };
532
+ }
533
+ if (values.contactId !== undefined) {
534
+ return {
535
+ values: dealContactRoleFields(dealContactRolesWithPrimary(current, values.contactId))
536
+ };
537
+ }
538
+ return {
539
+ values: {}
540
+ };
541
+ }
542
+ /**
543
+ * `type` and `leadSource` as the deal will store them, judged against the
544
+ * org's lists (AGL-3510's `resolveCrmPicklistWrite`): the values to write,
545
+ * or the refusals by field. Only a list the write touches is read — and the
546
+ * type list on every create, for its default.
547
+ */ async function dealPicklistWrites(ctx, values, stored) {
548
+ const created = stored === null;
549
+ const fields = [
550
+ {
551
+ key: 'type',
552
+ id: 'opportunityType',
553
+ defaulted: created
554
+ },
555
+ {
556
+ key: 'leadSource',
557
+ id: 'leadSource',
558
+ defaulted: false
559
+ }
560
+ ];
561
+ const written = {};
562
+ const errors = {};
563
+ for (const { key, id, defaulted } of fields){
564
+ if (values[key] === undefined && !defaulted) continue;
565
+ const judged = resolveCrmPicklistWrite(id, await readCrmPicklist(ctx.firestore, ctx.orgId, id), values[key], {
566
+ current: stored == null ? void 0 : stored[key],
567
+ created: defaulted
568
+ });
569
+ if (judged.ok === false) errors[key] = judged.error;
570
+ else if (judged.write !== undefined) written[key] = judged.write;
571
+ }
572
+ return Object.keys(errors).length ? {
573
+ errors
574
+ } : {
575
+ values: written
576
+ };
341
577
  }
342
578
  /**
343
579
  * `POST /v1/deals`. The pipeline is resolved AFTER the claim because
@@ -357,18 +593,25 @@ const DEAL_WRITABLE = new Set([
357
593
  const custom = await readCrmCustomBody(ctx, body, 'deal');
358
594
  if (custom && 'errors' in custom) return crmValidationFailed(ctx, 'deal', custom.errors);
359
595
  const customValues = custom && 'values' in custom ? custom.values : {};
596
+ // And against the org's picklists (AGL-3516), above the claim too.
597
+ const picklists = await dealPicklistWrites(ctx, parsed.values, null);
598
+ if ('errors' in picklists) return crmValidationFailed(ctx, 'deal', picklists.errors);
599
+ const roles = await dealContactRoleWrites(ctx, parsed.values, null);
600
+ if ('errors' in roles) return crmValidationFailed(ctx, 'deal', roles.errors);
360
601
  const collection = crmCollection(ctx, CRM_COLLECTIONS.deals);
361
602
  const claimed = await claimWrite(ctx, '*', request.headers.get('Idempotency-Key'), 'deals');
362
603
  if ('replay' in claimed) return claimed.replay;
363
604
  const { claim } = claimed;
364
605
  try {
365
606
  var _placed_stage;
366
- const _parsed_values = parsed.values, { title, pipelineId, stageId, status, lineItems } = _parsed_values, rest = _object_without_properties_loose(_parsed_values, [
607
+ const _parsed_values = parsed.values, { title, pipelineId, stageId, status, lineItems, probability, forecastCategory } = _parsed_values, rest = _object_without_properties_loose(_parsed_values, [
367
608
  "title",
368
609
  "pipelineId",
369
610
  "stageId",
370
611
  "status",
371
- "lineItems"
612
+ "lineItems",
613
+ "probability",
614
+ "forecastCategory"
372
615
  ]);
373
616
  const placedLines = placeLineItems({
374
617
  lineItems,
@@ -415,15 +658,20 @@ const DEAL_WRITABLE = new Set([
415
658
  title,
416
659
  titleLower: (title != null ? title : '').toLowerCase(),
417
660
  pipelineId: resolved.id
418
- }, createPayload(_extends({}, rest, placedLines.fields, stageMove(stage, stamp.createdAt.toMillis()))), Object.keys(customValues).length ? {
661
+ }, createPayload(_extends({}, rest, picklists.values, roles.values, placedLines.fields, stageMove(stage, stamp.createdAt.toMillis()), probability !== undefined ? {
662
+ probability
663
+ } : {}, forecastCategory ? {
664
+ forecastCategory
665
+ } : {})), Object.keys(customValues).length ? {
419
666
  custom: createPayload(customValues)
420
667
  } : {}, stamp);
421
668
  // What the console's Deals list searches and filters by (AGL-3321).
422
669
  await collection.doc(id).create(_extends({}, record, crmNewRecordListFields('deals', record)));
423
670
  // A deal created won is a won deal: its contact is a customer from birth.
424
671
  if (stage.kind === 'won') {
672
+ var _roles_values_contactId;
425
673
  await floorWonDealContact(ctx, {
426
- contactId: rest.contactId,
674
+ contactId: (_roles_values_contactId = roles.values.contactId) != null ? _roles_values_contactId : rest.contactId,
427
675
  hostId: site.siteId
428
676
  });
429
677
  }
@@ -439,7 +687,7 @@ const DEAL_WRITABLE = new Set([
439
687
  }
440
688
  }
441
689
  /** `PATCH /v1/deals/{id}`. */ async function updateDeal(request, ctx, ref) {
442
- var _stored_currency;
690
+ var _stored_currency, _stored_contactId;
443
691
  const body = await readJsonBody(request);
444
692
  const parsed = readDealInput(body, {
445
693
  partial: true
@@ -452,17 +700,23 @@ const DEAL_WRITABLE = new Set([
452
700
  headers: ctx.headers
453
701
  });
454
702
  }
455
- const refErrors = await dealRefErrors(ctx, parsed.values);
703
+ const stored = snap.data();
704
+ const refErrors = await dealRefErrors(ctx, parsed.values, stored);
456
705
  if (Object.keys(refErrors).length) return crmValidationFailed(ctx, 'deal', refErrors);
457
706
  const custom = await readCrmCustomBody(ctx, body, 'deal');
458
707
  if (custom && 'errors' in custom) return crmValidationFailed(ctx, 'deal', custom.errors);
459
- const _parsed_values = parsed.values, { title, stageId, status, lineItems } = _parsed_values, rest = _object_without_properties_loose(_parsed_values, [
708
+ const picklists = await dealPicklistWrites(ctx, parsed.values, stored);
709
+ if ('errors' in picklists) return crmValidationFailed(ctx, 'deal', picklists.errors);
710
+ const roles = await dealContactRoleWrites(ctx, parsed.values, stored);
711
+ if ('errors' in roles) return crmValidationFailed(ctx, 'deal', roles.errors);
712
+ const _parsed_values = parsed.values, { title, stageId, status, lineItems, probability, forecastCategory } = _parsed_values, rest = _object_without_properties_loose(_parsed_values, [
460
713
  "title",
461
714
  "stageId",
462
715
  "status",
463
- "lineItems"
716
+ "lineItems",
717
+ "probability",
718
+ "forecastCategory"
464
719
  ]);
465
- const stored = snap.data();
466
720
  const storedLines = Array.isArray(stored.lineItems) && stored.lineItems.length > 0;
467
721
  const keepsLines = storedLines && lineItems === undefined;
468
722
  if (keepsLines && rest.amountCents !== undefined) {
@@ -483,7 +737,9 @@ const DEAL_WRITABLE = new Set([
483
737
  const update = _extends({}, title !== undefined ? {
484
738
  title,
485
739
  titleLower: title.toLowerCase()
486
- } : {}, updatePayload(_extends({}, rest, placedLines.fields)), custom && 'values' in custom ? crmCustomUpdate(custom.values) : {});
740
+ } : {}, updatePayload(_extends({}, rest, picklists.values, roles.values, placedLines.fields)), custom && 'values' in custom ? crmCustomUpdate(custom.values) : {}, roles.values.contactId !== undefined && roles.values.contactId !== ((_stored_contactId = stored.contactId) != null ? _stored_contactId : null) ? {
741
+ contactName: FieldValue.delete()
742
+ } : {});
487
743
  // The write's one instant: `updatedAt`, and the stage move if there is one,
488
744
  // so a deal closed at T reads updated at T.
489
745
  const now = Timestamp.now();
@@ -510,16 +766,21 @@ const DEAL_WRITABLE = new Set([
510
766
  won = placed.stage.kind === 'won' && current.status !== 'won';
511
767
  }
512
768
  }
769
+ // What the body set beside a stage move wins over what the stage stamps
770
+ // (AGL-3516); without a move, they are plain edits. `null` clears the
771
+ // override back to the stage's.
772
+ if (probability !== undefined) update['probability'] = probability;
773
+ if (forecastCategory) update['forecastCategory'] = forecastCategory;
513
774
  if (Object.keys(update).length > 0) {
514
775
  await ref.update(_extends({}, update, {
515
776
  updatedAt: now
516
777
  }));
517
- // What the console's Deals list searches (AGL-3321).
518
- if ('title' in update) await restampCrmListFieldsAt(ref, 'deals');
778
+ // What the console's Deals list searches and filters by (AGL-3321, AGL-3516).
779
+ if (crmListFieldsTouched('deals', update)) await restampCrmListFieldsAt(ref, 'deals');
519
780
  }
520
781
  if (won) {
521
782
  await floorWonDealContact(ctx, {
522
- contactId: rest.contactId !== undefined ? rest.contactId : stored.contactId,
783
+ contactId: roles.values.contactId !== undefined ? roles.values.contactId : stored.contactId,
523
784
  hostId: stored.hostId
524
785
  });
525
786
  }
@@ -572,7 +833,11 @@ const DEAL_WRITABLE = new Set([
572
833
  'companyId',
573
834
  'pipelineId',
574
835
  'ownerUid',
575
- 'status'
836
+ 'status',
837
+ 'type',
838
+ 'leadSource',
839
+ 'forecastCategory',
840
+ 'campaignId'
576
841
  ]);
577
842
  return listCrm(ctx, collection, url, filters, dealView);
578
843
  }