@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
@@ -0,0 +1,188 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import { type ContactSource, type CrmAssignmentTarget } from '@aglyn/aglyn/server';
18
+ /**
19
+ * WHO A NEW RECORD BELONGS TO — the one place an owner is decided on the
20
+ * server (AGL-2618).
21
+ *
22
+ * Two entry points over one transaction. `assignOwnerForCapture` is the
23
+ * capture door's pass: it runs the org's assignment rules in order, falls
24
+ * back to the capturing site's default owner, and touches only a record
25
+ * that has NO owner — a door that named one (the console's drawer, an
26
+ * import column, a conversion with a picked owner) has expressed a person's
27
+ * choice. `reassignContactOwner` is the automation's: an author who put
28
+ * "assign an owner" on a stage change means to reassign, and the step hands
29
+ * this either a member or the rotation.
30
+ *
31
+ * ## One transaction, because the pointer is shared
32
+ *
33
+ * The round-robin pool's pointer lives on the org document, and two
34
+ * captures landing together must take two different members. Firestore
35
+ * transactions serialize on what they read, so the org document, the
36
+ * contact and the roster documents are all read inside the transaction and
37
+ * the pointer is advanced in the same commit that writes the owner: a
38
+ * concurrent capture that read the same pointer retries and reads the moved
39
+ * one. The alternative — read the pointer, decide, then write — is exactly
40
+ * the read-then-write shape that lets two captures pick the same person.
41
+ *
42
+ * ## The roster is checked, once per member per attempt
43
+ *
44
+ * A rule may name a member who has since left, and a pool may hold one. A
45
+ * rule naming nobody on the roster is passed over rather than stopping the
46
+ * pass — the next rule may well assign — and a pool member who is gone is
47
+ * skipped for the next in the order. `orgs/{orgId}/members/{uid}` is keyed
48
+ * by uid, so the check is one document read per candidate, and only the
49
+ * roster is consulted: a project-level Auth lookup would admit people who
50
+ * are not on this organization at all (AGL-1122).
51
+ *
52
+ * ## The lead follows the contact
53
+ *
54
+ * The capture doors that file a lead (`addHostLead`: a form routed to leads,
55
+ * a sign-up, a booking) key it by `personKey(email)`, so the lead's document
56
+ * is addressable from the capture alone. When it exists it is given the same
57
+ * owner in the same transaction; two doors write the lead AFTER the contact
58
+ * they `void`ed, so for those sources the mirror is retried a few times over
59
+ * the next seconds, detached, and the person's Leads list shows the owner
60
+ * as soon as the lead is there.
61
+ *
62
+ * ## The owner is told, unless they chose themselves
63
+ *
64
+ * One console notification per assignment, for the record the recipient
65
+ * will open: the lead when the site holds one for this person, the contact
66
+ * otherwise. Not when the actor IS the new owner — a rep who converts a
67
+ * lead into their own contact has not been handed anything.
68
+ *
69
+ * ## Never rejects
70
+ *
71
+ * The capture has already succeeded and a form submission must not fail
72
+ * because the CRM could not decide who follows up; a failure is logged and
73
+ * answered as `none`, and the record is exactly as assignable by hand as it
74
+ * was before this existed. The automation executor turns a `none` into the
75
+ * step's recorded error.
76
+ */
77
+ export interface OwnerAssignmentInput {
78
+ hostId: string;
79
+ /** `orgs/{orgId}/contacts/{contactId}` — the record the owner is written on. */
80
+ contactId: string;
81
+ /** The contact's address, which keys the lead and names the person in the notification. */
82
+ email: string;
83
+ /**
84
+ * The signed-in person making the assignment, when there is one. Never
85
+ * notified about their own choice; absent for a capture and an automation.
86
+ */
87
+ actorUid?: string | null;
88
+ }
89
+ export interface CaptureAssignmentInput extends OwnerAssignmentInput {
90
+ source: ContactSource;
91
+ /** The form the capture came through, for a rule conditioned on it. */
92
+ formId?: string | null;
93
+ /** The tags the capture carried; the contact's own are read from the facet. */
94
+ tags?: readonly string[];
95
+ }
96
+ export interface ReassignmentInput extends OwnerAssignmentInput {
97
+ assign: CrmAssignmentTarget;
98
+ }
99
+ /** Why an assignment assigned nobody — the automation reports these verbatim. */
100
+ export type OwnerAssignmentRefusal = 'no-org' | 'no-contact' | 'no-lead' | 'no-rule' | 'empty-pool' | 'not-a-member' | 'failed';
101
+ /** What decided an assignment: a rule, the site default, the step's member, or the rotation. */
102
+ export type OwnerAssignedBy = 'rule' | 'default' | 'member' | 'roundRobin';
103
+ export type OwnerAssignment = {
104
+ outcome: 'assigned';
105
+ ownerUid: string;
106
+ by: OwnerAssignedBy;
107
+ /** The rule that decided it, when one did. */
108
+ ruleId?: string;
109
+ /** The lead document existed and now carries the owner too. */
110
+ leadMirrored: boolean;
111
+ /** A notification was fanned out to the new owner. */
112
+ notified: boolean;
113
+ }
114
+ /** The record already had this owner (a capture), or the same one was named again (a reassignment). */
115
+ | {
116
+ outcome: 'unchanged';
117
+ ownerUid: string;
118
+ } | {
119
+ outcome: 'none';
120
+ reason: OwnerAssignmentRefusal;
121
+ };
122
+ /** The words the run history and the log give each refusal. */
123
+ export declare const OWNER_ASSIGNMENT_REFUSALS: Record<OwnerAssignmentRefusal, string>;
124
+ /** The record an assignment notification opens. */
125
+ export type AssignedRecord = {
126
+ kind: 'contact';
127
+ id: string;
128
+ } | {
129
+ kind: 'lead';
130
+ id: string;
131
+ };
132
+ /**
133
+ * Tells a member a record is now theirs — one console notification, typed
134
+ * by the record it opens — unless the member handed it to themselves.
135
+ * Shared by the pass above and by the routes where a person picks the
136
+ * owner outright (a lead conversion naming a colleague), so every server
137
+ * path that writes `ownerUid` says so in the same words. Never throws;
138
+ * the fan-out swallows its own failures.
139
+ */
140
+ export declare function notifyRecordAssigned(input: {
141
+ hostId: string;
142
+ orgId: string;
143
+ ownerUid: string;
144
+ actorUid?: string | null;
145
+ record: AssignedRecord;
146
+ /** How the person reads in the message: their name, else their address. */
147
+ who: string;
148
+ }): Promise<boolean>;
149
+ /**
150
+ * The capture door's pass: the org's rules in order, then the capturing
151
+ * site's default owner, on a record that has no owner yet. See the module
152
+ * comment for the whole of it.
153
+ */
154
+ export declare function assignOwnerForCapture(input: CaptureAssignmentInput): Promise<OwnerAssignment>;
155
+ /**
156
+ * The deliberate assignment — the `assignContactOwner` step, and a person
157
+ * handing a record to somebody: a member by uid (verified on the roster) or
158
+ * the next in the round-robin pool, overwriting whoever held it. Naming the
159
+ * owner the record already has changes nothing and tells nobody.
160
+ */
161
+ export declare function reassignContactOwner(input: ReassignmentInput): Promise<OwnerAssignment>;
162
+ /** The deliberate assignment of a LEAD the site holds and no contact has absorbed yet. */
163
+ export interface LeadReassignmentInput {
164
+ hostId: string;
165
+ /** `orgs/{orgId}/leads/{leadId}` — the person's key. */
166
+ leadId: string;
167
+ assign: CrmAssignmentTarget;
168
+ /** As {@link OwnerAssignmentInput.actorUid}: never told about their own choice. */
169
+ actorUid?: string | null;
170
+ }
171
+ /**
172
+ * {@link reassignContactOwner} for a person who is still a LEAD (AGL-3458).
173
+ *
174
+ * A lead-routed form files a lead and no contact (AGL-3232), so an
175
+ * automation welcoming that person — "assign an owner, then book them a
176
+ * call" — has only the lead to act on. The owner is the lead's own
177
+ * `ownerUid`, the field the Leads list's Owner column and filter read and a
178
+ * conversion hands to the contact. Same transaction shape as a contact's:
179
+ * the org document, the lead and every roster candidate are read inside it,
180
+ * and the round-robin pointer moves in the commit that writes the owner, so
181
+ * a lead and a contact assigned at the same moment take two different
182
+ * members of the one rotation.
183
+ *
184
+ * Never rejects; a failure is logged and answered as `none`, which the
185
+ * automation records as the step's error.
186
+ */
187
+ export declare function reassignLeadOwner(input: LeadReassignmentInput): Promise<OwnerAssignment>;
188
+ export default assignOwnerForCapture;
@@ -0,0 +1,446 @@
1
+ import { _ as _extends } from "@swc/helpers/_/_extends";
2
+ /**
3
+ * @license
4
+ * Copyright 2026 Aglyn LLC
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */ import { assignmentRuleMatches, consentGroupForHost, contactFacetPath, CRM_ROUND_ROBIN_LAST_ASSIGNED_PATH, personKey, readContactFacet, readCrmAssignmentSettings, roundRobinOrder } from "@aglyn/aglyn/server";
18
+ import { firebaseAdmin, getHostDocAdmin, getOrgForHost, hostDisplayName, notifyUsers, restampCrmListFieldsAt } from "@aglyn/tenant-data-admin";
19
+ import { FieldValue } from "firebase-admin/firestore";
20
+ /** The words the run history and the log give each refusal. */ export const OWNER_ASSIGNMENT_REFUSALS = {
21
+ 'no-org': 'this site has no organization',
22
+ 'no-contact': 'the contact no longer exists',
23
+ 'no-lead': 'the lead no longer exists',
24
+ 'no-rule': 'no assignment rule matched and the site has no default owner',
25
+ 'empty-pool': 'the round-robin pool has nobody on the roster in it',
26
+ 'not-a-member': 'the owner named is not on the team',
27
+ failed: 'the owner could not be assigned'
28
+ };
29
+ /**
30
+ * The doors whose lead lands after the contact they `void`ed — the ones the
31
+ * mirror is worth retrying for. An order, an import, a manual add and an
32
+ * API call file no lead, and a retry for them would be reads for nothing.
33
+ */ const LEAD_FILING_SOURCES = new Set([
34
+ 'form',
35
+ 'member',
36
+ 'booking'
37
+ ]);
38
+ /** How long the detached lead mirror waits between its looks, in order. */ const LEAD_MIRROR_RETRY_MS = [
39
+ 1000,
40
+ 2000,
41
+ 3000
42
+ ];
43
+ /**
44
+ * The console path the owner's notification opens, in the `/{hostDocId}/rest`
45
+ * shape every host notification uses — the console rewrites it to
46
+ * `/{orgSlug}/hosts/{subdomain}/rest` when the link is followed, which is
47
+ * why `hostId` and `orgId` travel on the document. The same spelling the
48
+ * CRM's task notification uses; the hub's own route builder lives in the
49
+ * plugin, which this layer cannot import.
50
+ */ function recordLink(hostId, record) {
51
+ const section = record.kind === 'contact' ? 'contacts' : 'leads';
52
+ return `/${hostId}/crm/${section}/${encodeURIComponent(record.id)}`;
53
+ }
54
+ /**
55
+ * Tells a member a record is now theirs — one console notification, typed
56
+ * by the record it opens — unless the member handed it to themselves.
57
+ * Shared by the pass above and by the routes where a person picks the
58
+ * owner outright (a lead conversion naming a colleague), so every server
59
+ * path that writes `ownerUid` says so in the same words. Never throws;
60
+ * the fan-out swallows its own failures.
61
+ */ export async function notifyRecordAssigned(input) {
62
+ var _input_actorUid;
63
+ if (!input.ownerUid || input.ownerUid === ((_input_actorUid = input.actorUid) != null ? _input_actorUid : '')) return false;
64
+ const lead = input.record.kind === 'lead';
65
+ /*
66
+ * THE BODY SAYS WHAT HAPPENED, AND ON WHICH SITE (AGL-3432).
67
+ *
68
+ * It was the bare name, so a member who owns records on several sites read
69
+ * "Ada" in an email body and could not tell what Ada was or where. The
70
+ * site's name is one request-cached read of a document most callers have
71
+ * already paid for, taken only when somebody is actually notified; a read
72
+ * that fails drops the "on {site}" clause rather than the notification.
73
+ */ let site = '';
74
+ try {
75
+ const host = await getHostDocAdmin(input.hostId);
76
+ if (host) site = ` on ${hostDisplayName(host, input.hostId)}`;
77
+ } catch (unused) {
78
+ // The clause goes, never the notification.
79
+ }
80
+ await notifyUsers([
81
+ input.ownerUid
82
+ ], {
83
+ type: lead ? 'content.leadAssigned' : 'content.contactAssigned',
84
+ title: lead ? 'Lead assigned to you' : 'Contact assigned to you',
85
+ body: `${input.who} was assigned to you as a ${lead ? 'lead' : 'contact'}${site}.`,
86
+ link: recordLink(input.hostId, input.record),
87
+ orgId: input.orgId,
88
+ hostId: input.hostId
89
+ });
90
+ return true;
91
+ }
92
+ /**
93
+ * The roster checks one assignment transaction makes: whether a uid is on the
94
+ * team, and who a target names — a member as named, or the next member of
95
+ * the round-robin pool who is still on the roster. One read per candidate
96
+ * per attempt; a retried transaction builds a fresh one and reads afresh, as
97
+ * it must.
98
+ */ function rosterResolver(tx, membersRef, settings) {
99
+ const onRoster = new Map();
100
+ const isMember = (uid)=>{
101
+ let known = onRoster.get(uid);
102
+ if (!known) {
103
+ known = tx.get(membersRef.doc(uid)).then((snapshot)=>snapshot.exists);
104
+ onRoster.set(uid, known);
105
+ }
106
+ return known;
107
+ };
108
+ const fromPool = async ()=>{
109
+ for (const uid of roundRobinOrder(settings.pool.memberUids, settings.pool.lastAssignedUid)){
110
+ if (await isMember(uid)) return uid;
111
+ }
112
+ return null;
113
+ };
114
+ const resolveTarget = async (target)=>{
115
+ if ('roundRobin' in target) {
116
+ const uid = await fromPool();
117
+ return uid ? {
118
+ uid,
119
+ advancePointer: true
120
+ } : null;
121
+ }
122
+ return await isMember(target.memberUid) ? {
123
+ uid: target.memberUid,
124
+ advancePointer: false
125
+ } : null;
126
+ };
127
+ return {
128
+ isMember,
129
+ resolveTarget
130
+ };
131
+ }
132
+ async function assignOwner(policy) {
133
+ const { input } = policy;
134
+ try {
135
+ const resolved = await getOrgForHost(input.hostId);
136
+ if (!resolved) return {
137
+ outcome: 'none',
138
+ reason: 'no-org'
139
+ };
140
+ const { orgId } = resolved;
141
+ const firestore = firebaseAdmin.app().firestore();
142
+ const orgRef = firestore.collection('orgs').doc(orgId);
143
+ const contactRef = orgRef.collection('contacts').doc(input.contactId);
144
+ const membersRef = orgRef.collection('members');
145
+ const leadKey = personKey(input.email);
146
+ // Beside the contact on the org, keyed by the same address (AGL-3275).
147
+ const leadRef = leadKey ? orgRef.collection('leads').doc(leadKey) : null;
148
+ let contactName = '';
149
+ const verdict = await firestore.runTransaction(async (tx)=>{
150
+ var _orgSnapshot_data, _contactSnapshot_data, _contact_name, _ref;
151
+ /*
152
+ * ALL READS BEFORE THE WRITE, which Firestore requires. The org
153
+ * document is read here rather than trusted from `getOrgForHost`,
154
+ * because the pointer it carries is the one thing a concurrent
155
+ * capture may have moved, and the rules and the pool are read from
156
+ * the same snapshot so the decision and the pointer agree.
157
+ */ const [orgSnapshot, contactSnapshot, leadSnapshot] = await Promise.all([
158
+ tx.get(orgRef),
159
+ tx.get(contactRef),
160
+ leadRef ? tx.get(leadRef) : Promise.resolve(null)
161
+ ]);
162
+ if (!contactSnapshot.exists) {
163
+ return {
164
+ outcome: 'none',
165
+ reason: 'no-contact'
166
+ };
167
+ }
168
+ const org = (_orgSnapshot_data = orgSnapshot.data()) != null ? _orgSnapshot_data : {};
169
+ const contact = (_contactSnapshot_data = contactSnapshot.data()) != null ? _contactSnapshot_data : {};
170
+ contactName = String((_contact_name = contact['name']) != null ? _contact_name : '');
171
+ const group = consentGroupForHost(org, input.hostId);
172
+ const facet = readContactFacet(contact, group.groupId);
173
+ const current = typeof facet.ownerUid === 'string' ? facet.ownerUid : '';
174
+ if (policy.kind === 'capture' && current) {
175
+ return {
176
+ outcome: 'unchanged',
177
+ ownerUid: current
178
+ };
179
+ }
180
+ const settings = readCrmAssignmentSettings(org);
181
+ const { isMember, resolveTarget } = rosterResolver(tx, membersRef, settings);
182
+ let decision = null;
183
+ let refusal = 'no-rule';
184
+ if (policy.kind === 'capture') {
185
+ var _policy_input_formId, _policy_input_tags, _facet_tags;
186
+ const capture = {
187
+ source: policy.input.source,
188
+ email: input.email,
189
+ formId: (_policy_input_formId = policy.input.formId) != null ? _policy_input_formId : null,
190
+ tags: [
191
+ ...(_policy_input_tags = policy.input.tags) != null ? _policy_input_tags : [],
192
+ ...(_facet_tags = facet.tags) != null ? _facet_tags : []
193
+ ]
194
+ };
195
+ for (const rule of settings.rules){
196
+ if (!assignmentRuleMatches(rule.when, capture)) continue;
197
+ const hit = await resolveTarget(rule.assign);
198
+ if (hit) {
199
+ decision = _extends({}, hit, {
200
+ ownerUid: hit.uid,
201
+ by: 'rule',
202
+ ruleId: rule.id
203
+ });
204
+ break;
205
+ }
206
+ }
207
+ const fallback = settings.hostDefaultOwners[input.hostId];
208
+ if (!decision && fallback && await isMember(fallback)) {
209
+ decision = {
210
+ ownerUid: fallback,
211
+ by: 'default',
212
+ advancePointer: false
213
+ };
214
+ }
215
+ } else {
216
+ const { assign } = policy.input;
217
+ const hit = await resolveTarget(assign);
218
+ if (hit) {
219
+ decision = _extends({}, hit, {
220
+ ownerUid: hit.uid,
221
+ by: 'roundRobin' in assign ? 'roundRobin' : 'member'
222
+ });
223
+ } else {
224
+ refusal = 'roundRobin' in assign ? 'empty-pool' : 'not-a-member';
225
+ }
226
+ }
227
+ if (!decision) return {
228
+ outcome: 'none',
229
+ reason: refusal
230
+ };
231
+ if (decision.ownerUid === current) {
232
+ return {
233
+ outcome: 'unchanged',
234
+ ownerUid: current
235
+ };
236
+ }
237
+ tx.update(contactRef, {
238
+ [contactFacetPath(group.groupId, 'ownerUid')]: decision.ownerUid,
239
+ updatedAt: FieldValue.serverTimestamp()
240
+ });
241
+ if (decision.advancePointer) {
242
+ tx.update(orgRef, {
243
+ [CRM_ROUND_ROBIN_LAST_ASSIGNED_PATH]: decision.ownerUid
244
+ });
245
+ }
246
+ /*
247
+ * A lead somebody already assigned by hand keeps its owner on a
248
+ * capture — the contact was new, the lead may not have been — and
249
+ * follows the contact on a deliberate reassignment.
250
+ */ const leadOwner = String((_ref = leadSnapshot == null ? void 0 : leadSnapshot.get('ownerUid')) != null ? _ref : '');
251
+ const leadMirrored = Boolean((leadSnapshot == null ? void 0 : leadSnapshot.exists) && (policy.kind === 'reassign' || !leadOwner));
252
+ if (leadMirrored && leadRef) {
253
+ tx.update(leadRef, {
254
+ ownerUid: decision.ownerUid,
255
+ updatedAt: FieldValue.serverTimestamp()
256
+ });
257
+ }
258
+ return _extends({
259
+ outcome: 'assigned',
260
+ ownerUid: decision.ownerUid,
261
+ by: decision.by
262
+ }, decision.ruleId ? {
263
+ ruleId: decision.ruleId
264
+ } : {}, {
265
+ leadMirrored,
266
+ notified: false
267
+ });
268
+ });
269
+ if (verdict.outcome !== 'assigned') return verdict;
270
+ // The owner is what the Contacts list filters by (AGL-3321).
271
+ await restampCrmListFieldsAt(contactRef, 'contacts');
272
+ if (!verdict.leadMirrored && leadRef && policy.kind === 'capture' && LEAD_FILING_SOURCES.has(policy.input.source)) {
273
+ void mirrorOwnerOntoLeadLater(leadRef, verdict.ownerUid);
274
+ }
275
+ const notified = await notifyRecordAssigned({
276
+ hostId: input.hostId,
277
+ orgId,
278
+ ownerUid: verdict.ownerUid,
279
+ actorUid: input.actorUid,
280
+ record: verdict.leadMirrored && leadKey ? {
281
+ kind: 'lead',
282
+ id: leadKey
283
+ } : {
284
+ kind: 'contact',
285
+ id: input.contactId
286
+ },
287
+ who: contactName || input.email
288
+ });
289
+ return _extends({}, verdict, {
290
+ notified
291
+ });
292
+ } catch (error) {
293
+ console.error('assignContactOwner failed', input.hostId, input.contactId, error);
294
+ return {
295
+ outcome: 'none',
296
+ reason: 'failed'
297
+ };
298
+ }
299
+ }
300
+ /**
301
+ * The detached second look for a lead that lands after the contact.
302
+ *
303
+ * Bounded, and only ever ADDS an owner: a lead that arrived with one (a
304
+ * person assigned it in the meantime) is left alone, and a lead that never
305
+ * arrives costs three reads over six seconds and nothing else. Detached
306
+ * because the capture must not hold `contactCreated` back for it — an
307
+ * automation welcoming the contact has nothing to do with the lead's owner
308
+ * column.
309
+ */ async function mirrorOwnerOntoLeadLater(leadRef, ownerUid, delaysMs = LEAD_MIRROR_RETRY_MS) {
310
+ for (const delay of delaysMs){
311
+ await new Promise((resolve)=>setTimeout(resolve, delay));
312
+ try {
313
+ var _lead_get;
314
+ const lead = await leadRef.get();
315
+ if (!lead.exists) continue;
316
+ if (String((_lead_get = lead.get('ownerUid')) != null ? _lead_get : '')) return false;
317
+ await leadRef.update({
318
+ ownerUid,
319
+ updatedAt: FieldValue.serverTimestamp()
320
+ });
321
+ return true;
322
+ } catch (error) {
323
+ console.error('assignContactOwner lead mirror failed', leadRef.path, error);
324
+ return false;
325
+ }
326
+ }
327
+ return false;
328
+ }
329
+ /**
330
+ * The capture door's pass: the org's rules in order, then the capturing
331
+ * site's default owner, on a record that has no owner yet. See the module
332
+ * comment for the whole of it.
333
+ */ export function assignOwnerForCapture(input) {
334
+ return assignOwner({
335
+ kind: 'capture',
336
+ input
337
+ });
338
+ }
339
+ /**
340
+ * The deliberate assignment — the `assignContactOwner` step, and a person
341
+ * handing a record to somebody: a member by uid (verified on the roster) or
342
+ * the next in the round-robin pool, overwriting whoever held it. Naming the
343
+ * owner the record already has changes nothing and tells nobody.
344
+ */ export function reassignContactOwner(input) {
345
+ return assignOwner({
346
+ kind: 'reassign',
347
+ input
348
+ });
349
+ }
350
+ /**
351
+ * {@link reassignContactOwner} for a person who is still a LEAD (AGL-3458).
352
+ *
353
+ * A lead-routed form files a lead and no contact (AGL-3232), so an
354
+ * automation welcoming that person — "assign an owner, then book them a
355
+ * call" — has only the lead to act on. The owner is the lead's own
356
+ * `ownerUid`, the field the Leads list's Owner column and filter read and a
357
+ * conversion hands to the contact. Same transaction shape as a contact's:
358
+ * the org document, the lead and every roster candidate are read inside it,
359
+ * and the round-robin pointer moves in the commit that writes the owner, so
360
+ * a lead and a contact assigned at the same moment take two different
361
+ * members of the one rotation.
362
+ *
363
+ * Never rejects; a failure is logged and answered as `none`, which the
364
+ * automation records as the step's error.
365
+ */ export async function reassignLeadOwner(input) {
366
+ try {
367
+ const resolved = await getOrgForHost(input.hostId);
368
+ if (!resolved) return {
369
+ outcome: 'none',
370
+ reason: 'no-org'
371
+ };
372
+ const { orgId } = resolved;
373
+ const firestore = firebaseAdmin.app().firestore();
374
+ const orgRef = firestore.collection('orgs').doc(orgId);
375
+ const leadRef = orgRef.collection('leads').doc(input.leadId);
376
+ const membersRef = orgRef.collection('members');
377
+ let who = '';
378
+ const verdict = await firestore.runTransaction(async (tx)=>{
379
+ var _leadSnapshot_data, _lead_name, _lead_email, _lead_ownerUid, _orgSnapshot_data;
380
+ const [orgSnapshot, leadSnapshot] = await Promise.all([
381
+ tx.get(orgRef),
382
+ tx.get(leadRef)
383
+ ]);
384
+ if (!leadSnapshot.exists) return {
385
+ outcome: 'none',
386
+ reason: 'no-lead'
387
+ };
388
+ const lead = (_leadSnapshot_data = leadSnapshot.data()) != null ? _leadSnapshot_data : {};
389
+ who = String((_lead_name = lead['name']) != null ? _lead_name : '') || String((_lead_email = lead['email']) != null ? _lead_email : '');
390
+ const current = String((_lead_ownerUid = lead['ownerUid']) != null ? _lead_ownerUid : '');
391
+ const settings = readCrmAssignmentSettings((_orgSnapshot_data = orgSnapshot.data()) != null ? _orgSnapshot_data : {});
392
+ const { resolveTarget } = rosterResolver(tx, membersRef, settings);
393
+ const hit = await resolveTarget(input.assign);
394
+ if (!hit) {
395
+ return {
396
+ outcome: 'none',
397
+ reason: 'roundRobin' in input.assign ? 'empty-pool' : 'not-a-member'
398
+ };
399
+ }
400
+ if (hit.uid === current) return {
401
+ outcome: 'unchanged',
402
+ ownerUid: current
403
+ };
404
+ tx.update(leadRef, {
405
+ ownerUid: hit.uid,
406
+ updatedAt: FieldValue.serverTimestamp()
407
+ });
408
+ if (hit.advancePointer) {
409
+ tx.update(orgRef, {
410
+ [CRM_ROUND_ROBIN_LAST_ASSIGNED_PATH]: hit.uid
411
+ });
412
+ }
413
+ return {
414
+ outcome: 'assigned',
415
+ ownerUid: hit.uid,
416
+ by: 'roundRobin' in input.assign ? 'roundRobin' : 'member',
417
+ leadMirrored: false,
418
+ notified: false
419
+ };
420
+ });
421
+ if (verdict.outcome !== 'assigned') return verdict;
422
+ const notified = await notifyRecordAssigned({
423
+ hostId: input.hostId,
424
+ orgId,
425
+ ownerUid: verdict.ownerUid,
426
+ actorUid: input.actorUid,
427
+ record: {
428
+ kind: 'lead',
429
+ id: input.leadId
430
+ },
431
+ who
432
+ });
433
+ return _extends({}, verdict, {
434
+ notified
435
+ });
436
+ } catch (error) {
437
+ console.error('assignLeadOwner failed', input.hostId, input.leadId, error);
438
+ return {
439
+ outcome: 'none',
440
+ reason: 'failed'
441
+ };
442
+ }
443
+ }
444
+ export default assignOwnerForCapture;
445
+
446
+ //# sourceMappingURL=assign-contact-owner.js.map