@open-mercato/core 0.5.1-develop.2663.2c29774b5b → 0.5.1-develop.2681.c559bb2bc3

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 (687) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/generated/entities/action_log/index.js +8 -0
  3. package/dist/generated/entities/action_log/index.js.map +2 -2
  4. package/dist/generated/entities/customer_company_billing/index.js +23 -0
  5. package/dist/generated/entities/customer_company_billing/index.js.map +7 -0
  6. package/dist/generated/entities/customer_deal/index.js +8 -0
  7. package/dist/generated/entities/customer_deal/index.js.map +2 -2
  8. package/dist/generated/entities/customer_deal_stage_transition/index.js +31 -0
  9. package/dist/generated/entities/customer_deal_stage_transition/index.js.map +7 -0
  10. package/dist/generated/entities/customer_dictionary_kind_setting/index.js +21 -0
  11. package/dist/generated/entities/customer_dictionary_kind_setting/index.js.map +7 -0
  12. package/dist/generated/entities/customer_entity/index.js +8 -0
  13. package/dist/generated/entities/customer_entity/index.js.map +2 -2
  14. package/dist/generated/entities/customer_entity_role/index.js +23 -0
  15. package/dist/generated/entities/customer_entity_role/index.js.map +7 -0
  16. package/dist/generated/entities/customer_interaction/index.js +23 -1
  17. package/dist/generated/entities/customer_interaction/index.js.map +2 -2
  18. package/dist/generated/entities/customer_label/index.js +19 -0
  19. package/dist/generated/entities/customer_label/index.js.map +7 -0
  20. package/dist/generated/entities/customer_label_assignment/index.js +17 -0
  21. package/dist/generated/entities/customer_label_assignment/index.js.map +7 -0
  22. package/dist/generated/entities/customer_person_company_link/index.js +21 -0
  23. package/dist/generated/entities/customer_person_company_link/index.js.map +7 -0
  24. package/dist/generated/entities/customer_person_company_role/index.js +17 -0
  25. package/dist/generated/entities/customer_person_company_role/index.js.map +7 -0
  26. package/dist/generated/entities/dictionary_entry/index.js +4 -0
  27. package/dist/generated/entities/dictionary_entry/index.js.map +2 -2
  28. package/dist/generated/entities.ids.generated.js +9 -1
  29. package/dist/generated/entities.ids.generated.js.map +2 -2
  30. package/dist/generated/entity-fields-registry.js +116 -1
  31. package/dist/generated/entity-fields-registry.js.map +2 -2
  32. package/dist/modules/attachments/api/route.js +46 -8
  33. package/dist/modules/attachments/api/route.js.map +2 -2
  34. package/dist/modules/audit_logs/api/audit-logs/actions/export/route.js +208 -0
  35. package/dist/modules/audit_logs/api/audit-logs/actions/export/route.js.map +7 -0
  36. package/dist/modules/audit_logs/api/audit-logs/actions/route.js +52 -6
  37. package/dist/modules/audit_logs/api/audit-logs/actions/route.js.map +2 -2
  38. package/dist/modules/audit_logs/cli.js +62 -0
  39. package/dist/modules/audit_logs/cli.js.map +7 -0
  40. package/dist/modules/audit_logs/data/entities.js +21 -1
  41. package/dist/modules/audit_logs/data/entities.js.map +2 -2
  42. package/dist/modules/audit_logs/data/validators.js +9 -1
  43. package/dist/modules/audit_logs/data/validators.js.map +2 -2
  44. package/dist/modules/audit_logs/lib/changeRows.js +34 -0
  45. package/dist/modules/audit_logs/lib/changeRows.js.map +7 -0
  46. package/dist/modules/audit_logs/lib/display-helpers.js +2 -20
  47. package/dist/modules/audit_logs/lib/display-helpers.js.map +3 -3
  48. package/dist/modules/audit_logs/lib/projections.js +58 -0
  49. package/dist/modules/audit_logs/lib/projections.js.map +7 -0
  50. package/dist/modules/audit_logs/migrations/Migration20260412160533.js +21 -0
  51. package/dist/modules/audit_logs/migrations/Migration20260412160533.js.map +7 -0
  52. package/dist/modules/audit_logs/services/actionLogService.js +313 -79
  53. package/dist/modules/audit_logs/services/actionLogService.js.map +2 -2
  54. package/dist/modules/customers/acl.js +3 -1
  55. package/dist/modules/customers/acl.js.map +2 -2
  56. package/dist/modules/customers/api/activities/route.js +4 -0
  57. package/dist/modules/customers/api/activities/route.js.map +2 -2
  58. package/dist/modules/customers/api/assignable-staff/route.js +208 -0
  59. package/dist/modules/customers/api/assignable-staff/route.js.map +7 -0
  60. package/dist/modules/customers/api/companies/[id]/people/route.js +205 -0
  61. package/dist/modules/customers/api/companies/[id]/people/route.js.map +7 -0
  62. package/dist/modules/customers/api/companies/[id]/roles/route.js +22 -0
  63. package/dist/modules/customers/api/companies/[id]/roles/route.js.map +7 -0
  64. package/dist/modules/customers/api/companies/[id]/route.js +374 -32
  65. package/dist/modules/customers/api/companies/[id]/route.js.map +2 -2
  66. package/dist/modules/customers/api/companies/route.js +82 -7
  67. package/dist/modules/customers/api/companies/route.js.map +2 -2
  68. package/dist/modules/customers/api/deals/[id]/companies/route.js +172 -0
  69. package/dist/modules/customers/api/deals/[id]/companies/route.js.map +7 -0
  70. package/dist/modules/customers/api/deals/[id]/people/route.js +156 -0
  71. package/dist/modules/customers/api/deals/[id]/people/route.js.map +7 -0
  72. package/dist/modules/customers/api/deals/[id]/route.js +459 -53
  73. package/dist/modules/customers/api/deals/[id]/route.js.map +2 -2
  74. package/dist/modules/customers/api/deals/[id]/stats/route.js +195 -0
  75. package/dist/modules/customers/api/deals/[id]/stats/route.js.map +7 -0
  76. package/dist/modules/customers/api/deals/route.js +20 -10
  77. package/dist/modules/customers/api/deals/route.js.map +3 -3
  78. package/dist/modules/customers/api/dictionaries/[kind]/[id]/route.js +105 -4
  79. package/dist/modules/customers/api/dictionaries/[kind]/[id]/route.js.map +2 -2
  80. package/dist/modules/customers/api/dictionaries/[kind]/route.js +118 -42
  81. package/dist/modules/customers/api/dictionaries/[kind]/route.js.map +2 -2
  82. package/dist/modules/customers/api/dictionaries/context.js +30 -6
  83. package/dist/modules/customers/api/dictionaries/context.js.map +2 -2
  84. package/dist/modules/customers/api/dictionaries/kind-settings/route.js +207 -0
  85. package/dist/modules/customers/api/dictionaries/kind-settings/route.js.map +7 -0
  86. package/dist/modules/customers/api/entity-roles-factory.js +471 -0
  87. package/dist/modules/customers/api/entity-roles-factory.js.map +7 -0
  88. package/dist/modules/customers/api/interactions/conflicts/route.js +158 -0
  89. package/dist/modules/customers/api/interactions/conflicts/route.js.map +7 -0
  90. package/dist/modules/customers/api/interactions/counts/route.js +92 -0
  91. package/dist/modules/customers/api/interactions/counts/route.js.map +7 -0
  92. package/dist/modules/customers/api/interactions/route.js +83 -4
  93. package/dist/modules/customers/api/interactions/route.js.map +2 -2
  94. package/dist/modules/customers/api/labels/assign/route.js +189 -0
  95. package/dist/modules/customers/api/labels/assign/route.js.map +7 -0
  96. package/dist/modules/customers/api/labels/auth.js +17 -0
  97. package/dist/modules/customers/api/labels/auth.js.map +7 -0
  98. package/dist/modules/customers/api/labels/route.js +281 -0
  99. package/dist/modules/customers/api/labels/route.js.map +7 -0
  100. package/dist/modules/customers/api/labels/table-errors.js +38 -0
  101. package/dist/modules/customers/api/labels/table-errors.js.map +7 -0
  102. package/dist/modules/customers/api/labels/unassign/route.js +184 -0
  103. package/dist/modules/customers/api/labels/unassign/route.js.map +7 -0
  104. package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js +292 -0
  105. package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js.map +7 -0
  106. package/dist/modules/customers/api/people/[id]/companies/context.js +66 -0
  107. package/dist/modules/customers/api/people/[id]/companies/context.js.map +7 -0
  108. package/dist/modules/customers/api/people/[id]/companies/enriched/route.js +334 -0
  109. package/dist/modules/customers/api/people/[id]/companies/enriched/route.js.map +7 -0
  110. package/dist/modules/customers/api/people/[id]/companies/route.js +205 -0
  111. package/dist/modules/customers/api/people/[id]/companies/route.js.map +7 -0
  112. package/dist/modules/customers/api/people/[id]/roles/route.js +22 -0
  113. package/dist/modules/customers/api/people/[id]/roles/route.js.map +7 -0
  114. package/dist/modules/customers/api/people/[id]/route.js +134 -21
  115. package/dist/modules/customers/api/people/[id]/route.js.map +2 -2
  116. package/dist/modules/customers/api/people/route.js +122 -23
  117. package/dist/modules/customers/api/people/route.js.map +2 -2
  118. package/dist/modules/customers/api/todos/route.js +4 -0
  119. package/dist/modules/customers/api/todos/route.js.map +2 -2
  120. package/dist/modules/customers/api/utils.js +22 -0
  121. package/dist/modules/customers/api/utils.js.map +2 -2
  122. package/dist/modules/customers/backend/config/customers/page.js +2 -6
  123. package/dist/modules/customers/backend/config/customers/page.js.map +2 -2
  124. package/dist/modules/customers/backend/customers/companies/page.js +37 -26
  125. package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
  126. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +265 -262
  127. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +3 -3
  128. package/dist/modules/customers/backend/customers/deals/[id]/hooks/formatters.js +23 -0
  129. package/dist/modules/customers/backend/customers/deals/[id]/hooks/formatters.js.map +7 -0
  130. package/dist/modules/customers/backend/customers/deals/[id]/hooks/types.js +1 -0
  131. package/dist/modules/customers/backend/customers/deals/[id]/hooks/types.js.map +7 -0
  132. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.js +43 -0
  133. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.js.map +7 -0
  134. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealAssociations.js +264 -0
  135. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealAssociations.js.map +7 -0
  136. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealClosure.js +88 -0
  137. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealClosure.js.map +7 -0
  138. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealData.js +41 -0
  139. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealData.js.map +7 -0
  140. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.js +66 -0
  141. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.js.map +7 -0
  142. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealInjectedTabs.js +39 -0
  143. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealInjectedTabs.js.map +7 -0
  144. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealMutationContext.js +49 -0
  145. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealMutationContext.js.map +7 -0
  146. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealPipeline.js +43 -0
  147. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealPipeline.js.map +7 -0
  148. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useScheduleDialog.js +28 -0
  149. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useScheduleDialog.js.map +7 -0
  150. package/dist/modules/customers/backend/customers/deals/[id]/page.js +556 -503
  151. package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +3 -3
  152. package/dist/modules/customers/backend/customers/deals/page.js +66 -21
  153. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  154. package/dist/modules/customers/backend/customers/people/page.js +36 -28
  155. package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
  156. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +318 -203
  157. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +3 -3
  158. package/dist/modules/customers/cli.js +105 -13
  159. package/dist/modules/customers/cli.js.map +2 -2
  160. package/dist/modules/customers/commands/activities.js +6 -0
  161. package/dist/modules/customers/commands/activities.js.map +2 -2
  162. package/dist/modules/customers/commands/deals.js +315 -107
  163. package/dist/modules/customers/commands/deals.js.map +2 -2
  164. package/dist/modules/customers/commands/dictionaries.js +166 -32
  165. package/dist/modules/customers/commands/dictionaries.js.map +2 -2
  166. package/dist/modules/customers/commands/dictionaryKindSettings.js +208 -0
  167. package/dist/modules/customers/commands/dictionaryKindSettings.js.map +7 -0
  168. package/dist/modules/customers/commands/entity-roles.js +415 -0
  169. package/dist/modules/customers/commands/entity-roles.js.map +7 -0
  170. package/dist/modules/customers/commands/index.js +4 -0
  171. package/dist/modules/customers/commands/index.js.map +2 -2
  172. package/dist/modules/customers/commands/interactions.js +108 -21
  173. package/dist/modules/customers/commands/interactions.js.map +2 -2
  174. package/dist/modules/customers/commands/labels.js +539 -0
  175. package/dist/modules/customers/commands/labels.js.map +7 -0
  176. package/dist/modules/customers/commands/people.js +560 -463
  177. package/dist/modules/customers/commands/people.js.map +3 -3
  178. package/dist/modules/customers/commands/personCompanyLinks.js +568 -0
  179. package/dist/modules/customers/commands/personCompanyLinks.js.map +7 -0
  180. package/dist/modules/customers/commands/shared.js +12 -4
  181. package/dist/modules/customers/commands/shared.js.map +2 -2
  182. package/dist/modules/customers/commands/todos.js +10 -1
  183. package/dist/modules/customers/commands/todos.js.map +2 -2
  184. package/dist/modules/customers/components/AddressEditor.js +1 -1
  185. package/dist/modules/customers/components/AddressEditor.js.map +2 -2
  186. package/dist/modules/customers/components/CustomersConfigurationSections.js +31 -0
  187. package/dist/modules/customers/components/CustomersConfigurationSections.js.map +7 -0
  188. package/dist/modules/customers/components/DictionarySettings.js +37 -2
  189. package/dist/modules/customers/components/DictionarySettings.js.map +2 -2
  190. package/dist/modules/customers/components/detail/ActiveDealCard.js +121 -0
  191. package/dist/modules/customers/components/detail/ActiveDealCard.js.map +7 -0
  192. package/dist/modules/customers/components/detail/ActivitiesSection.js +222 -331
  193. package/dist/modules/customers/components/detail/ActivitiesSection.js.map +3 -3
  194. package/dist/modules/customers/components/detail/ActivityAiActions.js +36 -0
  195. package/dist/modules/customers/components/detail/ActivityAiActions.js.map +7 -0
  196. package/dist/modules/customers/components/detail/ActivityCard.js +126 -0
  197. package/dist/modules/customers/components/detail/ActivityCard.js.map +7 -0
  198. package/dist/modules/customers/components/detail/ActivityHistorySection.js +340 -0
  199. package/dist/modules/customers/components/detail/ActivityHistorySection.js.map +7 -0
  200. package/dist/modules/customers/components/detail/ActivityLogTab.js +56 -0
  201. package/dist/modules/customers/components/detail/ActivityLogTab.js.map +7 -0
  202. package/dist/modules/customers/components/detail/ActivityTimeline.js +108 -0
  203. package/dist/modules/customers/components/detail/ActivityTimeline.js.map +7 -0
  204. package/dist/modules/customers/components/detail/ActivityTimelineFilters.js +139 -0
  205. package/dist/modules/customers/components/detail/ActivityTimelineFilters.js.map +7 -0
  206. package/dist/modules/customers/components/detail/ActivityTypeSelector.js +42 -0
  207. package/dist/modules/customers/components/detail/ActivityTypeSelector.js.map +7 -0
  208. package/dist/modules/customers/components/detail/AiActionChips.js +38 -0
  209. package/dist/modules/customers/components/detail/AiActionChips.js.map +7 -0
  210. package/dist/modules/customers/components/detail/AssignRoleDialog.js +534 -0
  211. package/dist/modules/customers/components/detail/AssignRoleDialog.js.map +7 -0
  212. package/dist/modules/customers/components/detail/ChangelogEntryRow.js +79 -0
  213. package/dist/modules/customers/components/detail/ChangelogEntryRow.js.map +7 -0
  214. package/dist/modules/customers/components/detail/ChangelogFilters.js +176 -0
  215. package/dist/modules/customers/components/detail/ChangelogFilters.js.map +7 -0
  216. package/dist/modules/customers/components/detail/ChangelogKpiCards.js +88 -0
  217. package/dist/modules/customers/components/detail/ChangelogKpiCards.js.map +7 -0
  218. package/dist/modules/customers/components/detail/ChangelogTab.js +470 -0
  219. package/dist/modules/customers/components/detail/ChangelogTab.js.map +7 -0
  220. package/dist/modules/customers/components/detail/ComingSoonPlaceholder.js +16 -0
  221. package/dist/modules/customers/components/detail/ComingSoonPlaceholder.js.map +7 -0
  222. package/dist/modules/customers/components/detail/CompanyCard.js +283 -0
  223. package/dist/modules/customers/components/detail/CompanyCard.js.map +7 -0
  224. package/dist/modules/customers/components/detail/CompanyDashboardTab.js +133 -0
  225. package/dist/modules/customers/components/detail/CompanyDashboardTab.js.map +7 -0
  226. package/dist/modules/customers/components/detail/CompanyDetailHeader.js +191 -0
  227. package/dist/modules/customers/components/detail/CompanyDetailHeader.js.map +7 -0
  228. package/dist/modules/customers/components/detail/CompanyDetailTabs.js +123 -0
  229. package/dist/modules/customers/components/detail/CompanyDetailTabs.js.map +7 -0
  230. package/dist/modules/customers/components/detail/CompanyKpiBar.js +174 -0
  231. package/dist/modules/customers/components/detail/CompanyKpiBar.js.map +7 -0
  232. package/dist/modules/customers/components/detail/CompanyPeopleSection.js +514 -230
  233. package/dist/modules/customers/components/detail/CompanyPeopleSection.js.map +2 -2
  234. package/dist/modules/customers/components/detail/CompanyTagsDialog.js +22 -0
  235. package/dist/modules/customers/components/detail/CompanyTagsDialog.js.map +7 -0
  236. package/dist/modules/customers/components/detail/ConfirmDealLostDialog.js +159 -0
  237. package/dist/modules/customers/components/detail/ConfirmDealLostDialog.js.map +7 -0
  238. package/dist/modules/customers/components/detail/CreatePersonDialog.js +135 -0
  239. package/dist/modules/customers/components/detail/CreatePersonDialog.js.map +7 -0
  240. package/dist/modules/customers/components/detail/DealClosureActionBar.js +59 -0
  241. package/dist/modules/customers/components/detail/DealClosureActionBar.js.map +7 -0
  242. package/dist/modules/customers/components/detail/DealDetailHeader.js +237 -0
  243. package/dist/modules/customers/components/detail/DealDetailHeader.js.map +7 -0
  244. package/dist/modules/customers/components/detail/DealDetailTabs.js +109 -0
  245. package/dist/modules/customers/components/detail/DealDetailTabs.js.map +7 -0
  246. package/dist/modules/customers/components/detail/DealForm.js +219 -92
  247. package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
  248. package/dist/modules/customers/components/detail/DealLinkedEntitiesTab.js +295 -0
  249. package/dist/modules/customers/components/detail/DealLinkedEntitiesTab.js.map +7 -0
  250. package/dist/modules/customers/components/detail/DealLostSummaryDialog.js +107 -0
  251. package/dist/modules/customers/components/detail/DealLostSummaryDialog.js.map +7 -0
  252. package/dist/modules/customers/components/detail/DealWonPopup.js +113 -0
  253. package/dist/modules/customers/components/detail/DealWonPopup.js.map +7 -0
  254. package/dist/modules/customers/components/detail/DealsSection.js +206 -193
  255. package/dist/modules/customers/components/detail/DealsSection.js.map +2 -2
  256. package/dist/modules/customers/components/detail/DecisionMakersFooter.js +39 -0
  257. package/dist/modules/customers/components/detail/DecisionMakersFooter.js.map +7 -0
  258. package/dist/modules/customers/components/detail/EntityTagsDialog.js +1096 -0
  259. package/dist/modules/customers/components/detail/EntityTagsDialog.js.map +7 -0
  260. package/dist/modules/customers/components/detail/InlineActivityComposer.js +197 -0
  261. package/dist/modules/customers/components/detail/InlineActivityComposer.js.map +7 -0
  262. package/dist/modules/customers/components/detail/ManageTagsDialog.js +1091 -0
  263. package/dist/modules/customers/components/detail/ManageTagsDialog.js.map +7 -0
  264. package/dist/modules/customers/components/detail/MiniWeekCalendar.js +272 -0
  265. package/dist/modules/customers/components/detail/MiniWeekCalendar.js.map +7 -0
  266. package/dist/modules/customers/components/detail/MobilePersonDetail.js +106 -0
  267. package/dist/modules/customers/components/detail/MobilePersonDetail.js.map +7 -0
  268. package/dist/modules/customers/components/detail/NextStepCard.js +72 -0
  269. package/dist/modules/customers/components/detail/NextStepCard.js.map +7 -0
  270. package/dist/modules/customers/components/detail/PersonCard.js +192 -0
  271. package/dist/modules/customers/components/detail/PersonCard.js.map +7 -0
  272. package/dist/modules/customers/components/detail/PersonCompaniesSection.js +345 -0
  273. package/dist/modules/customers/components/detail/PersonCompaniesSection.js.map +7 -0
  274. package/dist/modules/customers/components/detail/PersonDetailHeader.js +220 -0
  275. package/dist/modules/customers/components/detail/PersonDetailHeader.js.map +7 -0
  276. package/dist/modules/customers/components/detail/PersonDetailTabs.js +122 -0
  277. package/dist/modules/customers/components/detail/PersonDetailTabs.js.map +7 -0
  278. package/dist/modules/customers/components/detail/PersonTagsDialog.js +24 -0
  279. package/dist/modules/customers/components/detail/PersonTagsDialog.js.map +7 -0
  280. package/dist/modules/customers/components/detail/PipelineStepper.js +191 -0
  281. package/dist/modules/customers/components/detail/PipelineStepper.js.map +7 -0
  282. package/dist/modules/customers/components/detail/PlannedActivitiesSection.js +222 -0
  283. package/dist/modules/customers/components/detail/PlannedActivitiesSection.js.map +7 -0
  284. package/dist/modules/customers/components/detail/RelationshipHealthCard.js +49 -0
  285. package/dist/modules/customers/components/detail/RelationshipHealthCard.js.map +7 -0
  286. package/dist/modules/customers/components/detail/RoleAssignmentRow.js +189 -0
  287. package/dist/modules/customers/components/detail/RoleAssignmentRow.js.map +7 -0
  288. package/dist/modules/customers/components/detail/RolesSection.js +234 -0
  289. package/dist/modules/customers/components/detail/RolesSection.js.map +7 -0
  290. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +410 -0
  291. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +7 -0
  292. package/dist/modules/customers/components/detail/aiActionCatalog.js +41 -0
  293. package/dist/modules/customers/components/detail/aiActionCatalog.js.map +7 -0
  294. package/dist/modules/customers/components/detail/assignableStaff.js +48 -0
  295. package/dist/modules/customers/components/detail/assignableStaff.js.map +7 -0
  296. package/dist/modules/customers/components/detail/dashboard/ActiveDealWidget.js +48 -0
  297. package/dist/modules/customers/components/detail/dashboard/ActiveDealWidget.js.map +7 -0
  298. package/dist/modules/customers/components/detail/dashboard/OpenTasksWidget.js +86 -0
  299. package/dist/modules/customers/components/detail/dashboard/OpenTasksWidget.js.map +7 -0
  300. package/dist/modules/customers/components/detail/dashboard/RecentActivityWidget.js +53 -0
  301. package/dist/modules/customers/components/detail/dashboard/RecentActivityWidget.js.map +7 -0
  302. package/dist/modules/customers/components/detail/dashboard/RelationshipHealthWidget.js +30 -0
  303. package/dist/modules/customers/components/detail/dashboard/RelationshipHealthWidget.js.map +7 -0
  304. package/dist/modules/customers/components/detail/dashboard/UpcomingMeetingsWidget.js +43 -0
  305. package/dist/modules/customers/components/detail/dashboard/UpcomingMeetingsWidget.js.map +7 -0
  306. package/dist/modules/customers/components/detail/dashboard/helpers.js +71 -0
  307. package/dist/modules/customers/components/detail/dashboard/helpers.js.map +7 -0
  308. package/dist/modules/customers/components/detail/healthScoreUtils.js +69 -0
  309. package/dist/modules/customers/components/detail/healthScoreUtils.js.map +7 -0
  310. package/dist/modules/customers/components/detail/hooks/useCurrencyDictionary.js +5 -5
  311. package/dist/modules/customers/components/detail/hooks/useCurrencyDictionary.js.map +2 -2
  312. package/dist/modules/customers/components/detail/hooks/useCustomerDictionary.js +9 -8
  313. package/dist/modules/customers/components/detail/hooks/useCustomerDictionary.js.map +3 -3
  314. package/dist/modules/customers/components/detail/hooks/useInteractionMutations.js +65 -0
  315. package/dist/modules/customers/components/detail/hooks/useInteractionMutations.js.map +7 -0
  316. package/dist/modules/customers/components/detail/notesAdapter.js +70 -30
  317. package/dist/modules/customers/components/detail/notesAdapter.js.map +2 -2
  318. package/dist/modules/customers/components/detail/pipelineStageUtils.js +26 -0
  319. package/dist/modules/customers/components/detail/pipelineStageUtils.js.map +7 -0
  320. package/dist/modules/customers/components/detail/schedule/DateTimeFields.js +144 -0
  321. package/dist/modules/customers/components/detail/schedule/DateTimeFields.js.map +7 -0
  322. package/dist/modules/customers/components/detail/schedule/FooterFields.js +60 -0
  323. package/dist/modules/customers/components/detail/schedule/FooterFields.js.map +7 -0
  324. package/dist/modules/customers/components/detail/schedule/LinkedEntitiesField.js +216 -0
  325. package/dist/modules/customers/components/detail/schedule/LinkedEntitiesField.js.map +7 -0
  326. package/dist/modules/customers/components/detail/schedule/LocationField.js +34 -0
  327. package/dist/modules/customers/components/detail/schedule/LocationField.js.map +7 -0
  328. package/dist/modules/customers/components/detail/schedule/ParticipantsField.js +226 -0
  329. package/dist/modules/customers/components/detail/schedule/ParticipantsField.js.map +7 -0
  330. package/dist/modules/customers/components/detail/schedule/fieldConfig.js +69 -0
  331. package/dist/modules/customers/components/detail/schedule/fieldConfig.js.map +7 -0
  332. package/dist/modules/customers/components/detail/schedule/index.js +21 -0
  333. package/dist/modules/customers/components/detail/schedule/index.js.map +7 -0
  334. package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js +172 -0
  335. package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js.map +7 -0
  336. package/dist/modules/customers/components/detail/utils.js +23 -0
  337. package/dist/modules/customers/components/detail/utils.js.map +2 -2
  338. package/dist/modules/customers/components/formConfig.js +144 -22
  339. package/dist/modules/customers/components/formConfig.js.map +2 -2
  340. package/dist/modules/customers/components/linking/LinkEntityDialog.js +661 -0
  341. package/dist/modules/customers/components/linking/LinkEntityDialog.js.map +7 -0
  342. package/dist/modules/customers/components/linking/adapters/companyAdapter.js +252 -0
  343. package/dist/modules/customers/components/linking/adapters/companyAdapter.js.map +7 -0
  344. package/dist/modules/customers/components/linking/adapters/dealAdapter.js +384 -0
  345. package/dist/modules/customers/components/linking/adapters/dealAdapter.js.map +7 -0
  346. package/dist/modules/customers/components/linking/adapters/personAdapter.js +324 -0
  347. package/dist/modules/customers/components/linking/adapters/personAdapter.js.map +7 -0
  348. package/dist/modules/customers/components/list/CollectionPreviewCell.js +53 -0
  349. package/dist/modules/customers/components/list/CollectionPreviewCell.js.map +7 -0
  350. package/dist/modules/customers/data/entities.js +407 -1
  351. package/dist/modules/customers/data/entities.js.map +2 -2
  352. package/dist/modules/customers/data/validators.js +139 -21
  353. package/dist/modules/customers/data/validators.js.map +2 -2
  354. package/dist/modules/customers/events.js +19 -1
  355. package/dist/modules/customers/events.js.map +2 -2
  356. package/dist/modules/customers/lib/customerRoleTypes.js +19 -0
  357. package/dist/modules/customers/lib/customerRoleTypes.js.map +7 -0
  358. package/dist/modules/customers/lib/dealClosureNotification.js +39 -0
  359. package/dist/modules/customers/lib/dealClosureNotification.js.map +7 -0
  360. package/dist/modules/customers/lib/dealStageTransitionTable.js +29 -0
  361. package/dist/modules/customers/lib/dealStageTransitionTable.js.map +7 -0
  362. package/dist/modules/customers/lib/dictionaries.js +25 -0
  363. package/dist/modules/customers/lib/dictionaries.js.map +2 -2
  364. package/dist/modules/customers/lib/interactionReadModel.js +10 -0
  365. package/dist/modules/customers/lib/interactionReadModel.js.map +2 -2
  366. package/dist/modules/customers/lib/personCompanies.js +235 -0
  367. package/dist/modules/customers/lib/personCompanies.js.map +7 -0
  368. package/dist/modules/customers/lib/personCompanyLinkTable.js +42 -0
  369. package/dist/modules/customers/lib/personCompanyLinkTable.js.map +7 -0
  370. package/dist/modules/customers/lib/roleTypeUsage.js +104 -0
  371. package/dist/modules/customers/lib/roleTypeUsage.js.map +7 -0
  372. package/dist/modules/customers/migrations/Migration20260406214502.js +18 -0
  373. package/dist/modules/customers/migrations/Migration20260406214502.js.map +7 -0
  374. package/dist/modules/customers/migrations/Migration20260408135736.js +17 -0
  375. package/dist/modules/customers/migrations/Migration20260408135736.js.map +7 -0
  376. package/dist/modules/customers/migrations/Migration20260408225345.js +21 -0
  377. package/dist/modules/customers/migrations/Migration20260408225345.js.map +7 -0
  378. package/dist/modules/customers/migrations/Migration20260411075533.js +27 -0
  379. package/dist/modules/customers/migrations/Migration20260411075533.js.map +7 -0
  380. package/dist/modules/customers/migrations/Migration20260411103551.js +13 -0
  381. package/dist/modules/customers/migrations/Migration20260411103551.js.map +7 -0
  382. package/dist/modules/customers/migrations/Migration20260411130944.js +26 -0
  383. package/dist/modules/customers/migrations/Migration20260411130944.js.map +7 -0
  384. package/dist/modules/customers/migrations/Migration20260415095203.js +13 -0
  385. package/dist/modules/customers/migrations/Migration20260415095203.js.map +7 -0
  386. package/dist/modules/customers/migrations/Migration20260415135056.js +20 -0
  387. package/dist/modules/customers/migrations/Migration20260415135056.js.map +7 -0
  388. package/dist/modules/customers/migrations/Migration20260417140000.js +15 -0
  389. package/dist/modules/customers/migrations/Migration20260417140000.js.map +7 -0
  390. package/dist/modules/customers/migrations/Migration20260417160000.js +17 -0
  391. package/dist/modules/customers/migrations/Migration20260417160000.js.map +7 -0
  392. package/dist/modules/customers/migrations/Migration20260417235407.js +13 -0
  393. package/dist/modules/customers/migrations/Migration20260417235407.js.map +7 -0
  394. package/dist/modules/customers/setup.js +16 -1
  395. package/dist/modules/customers/setup.js.map +2 -2
  396. package/dist/modules/customers/subscribers/deal-closure-notification.js +16 -0
  397. package/dist/modules/customers/subscribers/deal-closure-notification.js.map +7 -0
  398. package/dist/modules/customers/subscribers/deal-lost-notification.js +16 -0
  399. package/dist/modules/customers/subscribers/deal-lost-notification.js.map +7 -0
  400. package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js +2 -0
  401. package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js.map +2 -2
  402. package/dist/modules/dictionaries/api/[dictionaryId]/entries/reorder/route.js +154 -0
  403. package/dist/modules/dictionaries/api/[dictionaryId]/entries/reorder/route.js.map +7 -0
  404. package/dist/modules/dictionaries/api/[dictionaryId]/entries/route.js +6 -2
  405. package/dist/modules/dictionaries/api/[dictionaryId]/entries/route.js.map +2 -2
  406. package/dist/modules/dictionaries/api/[dictionaryId]/entries/set-default/route.js +154 -0
  407. package/dist/modules/dictionaries/api/[dictionaryId]/entries/set-default/route.js.map +7 -0
  408. package/dist/modules/dictionaries/api/context.js +8 -1
  409. package/dist/modules/dictionaries/api/context.js.map +2 -2
  410. package/dist/modules/dictionaries/api/openapi.js +18 -1
  411. package/dist/modules/dictionaries/api/openapi.js.map +2 -2
  412. package/dist/modules/dictionaries/commands/entry-operations.js +388 -0
  413. package/dist/modules/dictionaries/commands/entry-operations.js.map +7 -0
  414. package/dist/modules/dictionaries/commands/factory.js +24 -3
  415. package/dist/modules/dictionaries/commands/factory.js.map +2 -2
  416. package/dist/modules/dictionaries/commands/index.js +1 -0
  417. package/dist/modules/dictionaries/commands/index.js.map +2 -2
  418. package/dist/modules/dictionaries/components/DictionaryTable.js +6 -3
  419. package/dist/modules/dictionaries/components/DictionaryTable.js.map +2 -2
  420. package/dist/modules/dictionaries/data/entities.js +11 -1
  421. package/dist/modules/dictionaries/data/entities.js.map +2 -2
  422. package/dist/modules/dictionaries/data/validators.js +28 -2
  423. package/dist/modules/dictionaries/data/validators.js.map +2 -2
  424. package/dist/modules/dictionaries/events.js +18 -0
  425. package/dist/modules/dictionaries/events.js.map +7 -0
  426. package/dist/modules/dictionaries/lib/clientEntries.js +43 -0
  427. package/dist/modules/dictionaries/lib/clientEntries.js.map +7 -0
  428. package/dist/modules/dictionaries/migrations/Migration20260410171544.js +45 -0
  429. package/dist/modules/dictionaries/migrations/Migration20260410171544.js.map +7 -0
  430. package/dist/modules/inbox_ops/api/proposals/[id]/route.js +4 -1
  431. package/dist/modules/inbox_ops/api/proposals/[id]/route.js.map +2 -2
  432. package/dist/modules/query_index/lib/engine.js +1 -1
  433. package/dist/modules/query_index/lib/engine.js.map +2 -2
  434. package/dist/modules/sales/components/documents/AddressesSection.js +82 -42
  435. package/dist/modules/sales/components/documents/AddressesSection.js.map +2 -2
  436. package/dist/modules/sales/lib/dictionaries.js +16 -0
  437. package/dist/modules/sales/lib/dictionaries.js.map +2 -2
  438. package/dist/modules/sales/widgets/injection-table.js +5 -1
  439. package/dist/modules/sales/widgets/injection-table.js.map +2 -2
  440. package/generated/entities/action_log/index.ts +4 -0
  441. package/generated/entities/customer_company_billing/index.ts +10 -0
  442. package/generated/entities/customer_deal/index.ts +4 -0
  443. package/generated/entities/customer_deal_stage_transition/index.ts +14 -0
  444. package/generated/entities/customer_dictionary_kind_setting/index.ts +9 -0
  445. package/generated/entities/customer_entity/index.ts +4 -0
  446. package/generated/entities/customer_entity_role/index.ts +10 -0
  447. package/generated/entities/customer_interaction/index.ts +11 -0
  448. package/generated/entities/customer_label/index.ts +8 -0
  449. package/generated/entities/customer_label_assignment/index.ts +7 -0
  450. package/generated/entities/customer_person_company_link/index.ts +9 -0
  451. package/generated/entities/customer_person_company_role/index.ts +7 -0
  452. package/generated/entities/dictionary_entry/index.ts +2 -0
  453. package/generated/entities.ids.generated.ts +9 -1
  454. package/generated/entity-fields-registry.ts +116 -1
  455. package/package.json +3 -3
  456. package/src/modules/attachments/api/route.ts +48 -6
  457. package/src/modules/attachments/i18n/de.json +4 -0
  458. package/src/modules/attachments/i18n/en.json +4 -0
  459. package/src/modules/attachments/i18n/es.json +4 -0
  460. package/src/modules/attachments/i18n/pl.json +4 -0
  461. package/src/modules/audit_logs/api/audit-logs/actions/export/route.ts +260 -0
  462. package/src/modules/audit_logs/api/audit-logs/actions/route.ts +81 -6
  463. package/src/modules/audit_logs/cli.ts +79 -0
  464. package/src/modules/audit_logs/data/entities.ts +17 -0
  465. package/src/modules/audit_logs/data/validators.ts +9 -1
  466. package/src/modules/audit_logs/lib/changeRows.ts +47 -0
  467. package/src/modules/audit_logs/lib/display-helpers.tsx +4 -30
  468. package/src/modules/audit_logs/lib/projections.ts +110 -0
  469. package/src/modules/audit_logs/migrations/.snapshot-open-mercato.json +325 -2
  470. package/src/modules/audit_logs/migrations/Migration20260412160533.ts +21 -0
  471. package/src/modules/audit_logs/services/actionLogService.ts +455 -85
  472. package/src/modules/catalog/i18n/de.json +1 -0
  473. package/src/modules/catalog/i18n/en.json +1 -0
  474. package/src/modules/catalog/i18n/es.json +1 -0
  475. package/src/modules/catalog/i18n/pl.json +1 -0
  476. package/src/modules/customer_accounts/i18n/de.json +2 -0
  477. package/src/modules/customer_accounts/i18n/en.json +2 -0
  478. package/src/modules/customer_accounts/i18n/es.json +2 -0
  479. package/src/modules/customer_accounts/i18n/pl.json +2 -0
  480. package/src/modules/customers/acl.ts +2 -0
  481. package/src/modules/customers/api/activities/route.ts +4 -0
  482. package/src/modules/customers/api/assignable-staff/route.ts +250 -0
  483. package/src/modules/customers/api/companies/[id]/people/route.ts +244 -0
  484. package/src/modules/customers/api/companies/[id]/roles/route.ts +15 -0
  485. package/src/modules/customers/api/companies/[id]/route.ts +458 -40
  486. package/src/modules/customers/api/companies/route.ts +93 -15
  487. package/src/modules/customers/api/deals/[id]/companies/route.ts +203 -0
  488. package/src/modules/customers/api/deals/[id]/people/route.ts +182 -0
  489. package/src/modules/customers/api/deals/[id]/route.ts +554 -57
  490. package/src/modules/customers/api/deals/[id]/stats/route.ts +221 -0
  491. package/src/modules/customers/api/deals/route.ts +35 -46
  492. package/src/modules/customers/api/dictionaries/[kind]/[id]/route.ts +105 -3
  493. package/src/modules/customers/api/dictionaries/[kind]/route.ts +143 -44
  494. package/src/modules/customers/api/dictionaries/context.ts +45 -16
  495. package/src/modules/customers/api/dictionaries/kind-settings/route.ts +232 -0
  496. package/src/modules/customers/api/entity-roles-factory.ts +520 -0
  497. package/src/modules/customers/api/interactions/conflicts/route.ts +196 -0
  498. package/src/modules/customers/api/interactions/counts/route.ts +112 -0
  499. package/src/modules/customers/api/interactions/route.ts +95 -2
  500. package/src/modules/customers/api/labels/assign/route.ts +202 -0
  501. package/src/modules/customers/api/labels/auth.ts +19 -0
  502. package/src/modules/customers/api/labels/route.ts +310 -0
  503. package/src/modules/customers/api/labels/table-errors.ts +36 -0
  504. package/src/modules/customers/api/labels/unassign/route.ts +197 -0
  505. package/src/modules/customers/api/people/[id]/companies/[linkId]/route.ts +331 -0
  506. package/src/modules/customers/api/people/[id]/companies/context.ts +70 -0
  507. package/src/modules/customers/api/people/[id]/companies/enriched/route.ts +384 -0
  508. package/src/modules/customers/api/people/[id]/companies/route.ts +215 -0
  509. package/src/modules/customers/api/people/[id]/roles/route.ts +15 -0
  510. package/src/modules/customers/api/people/[id]/route.ts +153 -26
  511. package/src/modules/customers/api/people/route.ts +134 -31
  512. package/src/modules/customers/api/todos/route.ts +4 -0
  513. package/src/modules/customers/api/utils.ts +36 -0
  514. package/src/modules/customers/backend/config/customers/page.tsx +2 -6
  515. package/src/modules/customers/backend/customers/companies/page.tsx +36 -26
  516. package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +277 -262
  517. package/src/modules/customers/backend/customers/deals/[id]/hooks/formatters.ts +19 -0
  518. package/src/modules/customers/backend/customers/deals/[id]/hooks/types.ts +104 -0
  519. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.ts +60 -0
  520. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealAssociations.ts +362 -0
  521. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealClosure.ts +113 -0
  522. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealData.ts +52 -0
  523. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.ts +86 -0
  524. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealInjectedTabs.tsx +60 -0
  525. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealMutationContext.ts +76 -0
  526. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealPipeline.ts +56 -0
  527. package/src/modules/customers/backend/customers/deals/[id]/hooks/useScheduleDialog.ts +38 -0
  528. package/src/modules/customers/backend/customers/deals/[id]/page.tsx +587 -624
  529. package/src/modules/customers/backend/customers/deals/page.tsx +71 -28
  530. package/src/modules/customers/backend/customers/people/page.tsx +35 -29
  531. package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +343 -209
  532. package/src/modules/customers/cli.ts +107 -12
  533. package/src/modules/customers/commands/activities.ts +13 -0
  534. package/src/modules/customers/commands/deals.ts +386 -114
  535. package/src/modules/customers/commands/dictionaries.ts +175 -32
  536. package/src/modules/customers/commands/dictionaryKindSettings.ts +268 -0
  537. package/src/modules/customers/commands/entity-roles.ts +494 -0
  538. package/src/modules/customers/commands/index.ts +4 -0
  539. package/src/modules/customers/commands/interactions.ts +125 -21
  540. package/src/modules/customers/commands/labels.ts +626 -0
  541. package/src/modules/customers/commands/people.ts +373 -259
  542. package/src/modules/customers/commands/personCompanyLinks.ts +654 -0
  543. package/src/modules/customers/commands/shared.ts +16 -15
  544. package/src/modules/customers/commands/todos.ts +17 -1
  545. package/src/modules/customers/components/AddressEditor.tsx +1 -1
  546. package/src/modules/customers/components/CustomersConfigurationSections.tsx +36 -0
  547. package/src/modules/customers/components/DictionarySettings.tsx +43 -2
  548. package/src/modules/customers/components/detail/ActiveDealCard.tsx +175 -0
  549. package/src/modules/customers/components/detail/ActivitiesSection.tsx +267 -361
  550. package/src/modules/customers/components/detail/ActivityAiActions.tsx +49 -0
  551. package/src/modules/customers/components/detail/ActivityCard.tsx +154 -0
  552. package/src/modules/customers/components/detail/ActivityHistorySection.tsx +412 -0
  553. package/src/modules/customers/components/detail/ActivityLogTab.tsx +67 -0
  554. package/src/modules/customers/components/detail/ActivityTimeline.tsx +158 -0
  555. package/src/modules/customers/components/detail/ActivityTimelineFilters.tsx +163 -0
  556. package/src/modules/customers/components/detail/ActivityTypeSelector.tsx +53 -0
  557. package/src/modules/customers/components/detail/AiActionChips.tsx +48 -0
  558. package/src/modules/customers/components/detail/AssignRoleDialog.tsx +672 -0
  559. package/src/modules/customers/components/detail/ChangelogEntryRow.tsx +132 -0
  560. package/src/modules/customers/components/detail/ChangelogFilters.tsx +193 -0
  561. package/src/modules/customers/components/detail/ChangelogKpiCards.tsx +107 -0
  562. package/src/modules/customers/components/detail/ChangelogTab.tsx +629 -0
  563. package/src/modules/customers/components/detail/ComingSoonPlaceholder.tsx +21 -0
  564. package/src/modules/customers/components/detail/CompanyCard.tsx +419 -0
  565. package/src/modules/customers/components/detail/CompanyDashboardTab.tsx +161 -0
  566. package/src/modules/customers/components/detail/CompanyDetailHeader.tsx +243 -0
  567. package/src/modules/customers/components/detail/CompanyDetailTabs.tsx +172 -0
  568. package/src/modules/customers/components/detail/CompanyKpiBar.tsx +206 -0
  569. package/src/modules/customers/components/detail/CompanyPeopleSection.tsx +582 -288
  570. package/src/modules/customers/components/detail/CompanyTagsDialog.tsx +23 -0
  571. package/src/modules/customers/components/detail/ConfirmDealLostDialog.tsx +210 -0
  572. package/src/modules/customers/components/detail/CreatePersonDialog.tsx +178 -0
  573. package/src/modules/customers/components/detail/DealClosureActionBar.tsx +63 -0
  574. package/src/modules/customers/components/detail/DealDetailHeader.tsx +335 -0
  575. package/src/modules/customers/components/detail/DealDetailTabs.tsx +154 -0
  576. package/src/modules/customers/components/detail/DealForm.tsx +253 -101
  577. package/src/modules/customers/components/detail/DealLinkedEntitiesTab.tsx +349 -0
  578. package/src/modules/customers/components/detail/DealLostSummaryDialog.tsx +156 -0
  579. package/src/modules/customers/components/detail/DealWonPopup.tsx +164 -0
  580. package/src/modules/customers/components/detail/DealsSection.tsx +276 -221
  581. package/src/modules/customers/components/detail/DecisionMakersFooter.tsx +56 -0
  582. package/src/modules/customers/components/detail/EntityTagsDialog.tsx +1372 -0
  583. package/src/modules/customers/components/detail/InlineActivityComposer.tsx +239 -0
  584. package/src/modules/customers/components/detail/ManageTagsDialog.tsx +1331 -0
  585. package/src/modules/customers/components/detail/MiniWeekCalendar.tsx +338 -0
  586. package/src/modules/customers/components/detail/MobilePersonDetail.tsx +124 -0
  587. package/src/modules/customers/components/detail/NextStepCard.tsx +104 -0
  588. package/src/modules/customers/components/detail/PersonCard.tsx +238 -0
  589. package/src/modules/customers/components/detail/PersonCompaniesSection.tsx +426 -0
  590. package/src/modules/customers/components/detail/PersonDetailHeader.tsx +294 -0
  591. package/src/modules/customers/components/detail/PersonDetailTabs.tsx +172 -0
  592. package/src/modules/customers/components/detail/PersonTagsDialog.tsx +26 -0
  593. package/src/modules/customers/components/detail/PipelineStepper.tsx +245 -0
  594. package/src/modules/customers/components/detail/PlannedActivitiesSection.tsx +255 -0
  595. package/src/modules/customers/components/detail/RelationshipHealthCard.tsx +63 -0
  596. package/src/modules/customers/components/detail/RoleAssignmentRow.tsx +248 -0
  597. package/src/modules/customers/components/detail/RolesSection.tsx +311 -0
  598. package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +481 -0
  599. package/src/modules/customers/components/detail/aiActionCatalog.ts +77 -0
  600. package/src/modules/customers/components/detail/assignableStaff.ts +124 -0
  601. package/src/modules/customers/components/detail/dashboard/ActiveDealWidget.tsx +63 -0
  602. package/src/modules/customers/components/detail/dashboard/OpenTasksWidget.tsx +114 -0
  603. package/src/modules/customers/components/detail/dashboard/RecentActivityWidget.tsx +69 -0
  604. package/src/modules/customers/components/detail/dashboard/RelationshipHealthWidget.tsx +40 -0
  605. package/src/modules/customers/components/detail/dashboard/UpcomingMeetingsWidget.tsx +64 -0
  606. package/src/modules/customers/components/detail/dashboard/helpers.ts +78 -0
  607. package/src/modules/customers/components/detail/healthScoreUtils.ts +91 -0
  608. package/src/modules/customers/components/detail/hooks/useCurrencyDictionary.ts +8 -8
  609. package/src/modules/customers/components/detail/hooks/useCustomerDictionary.ts +10 -6
  610. package/src/modules/customers/components/detail/hooks/useInteractionMutations.ts +91 -0
  611. package/src/modules/customers/components/detail/notesAdapter.ts +91 -30
  612. package/src/modules/customers/components/detail/pipelineStageUtils.ts +29 -0
  613. package/src/modules/customers/components/detail/schedule/DateTimeFields.tsx +187 -0
  614. package/src/modules/customers/components/detail/schedule/FooterFields.tsx +79 -0
  615. package/src/modules/customers/components/detail/schedule/LinkedEntitiesField.tsx +277 -0
  616. package/src/modules/customers/components/detail/schedule/LocationField.tsx +42 -0
  617. package/src/modules/customers/components/detail/schedule/ParticipantsField.tsx +255 -0
  618. package/src/modules/customers/components/detail/schedule/fieldConfig.ts +70 -0
  619. package/src/modules/customers/components/detail/schedule/index.ts +9 -0
  620. package/src/modules/customers/components/detail/schedule/useScheduleFormState.ts +221 -0
  621. package/src/modules/customers/components/detail/types.ts +16 -0
  622. package/src/modules/customers/components/detail/utils.ts +25 -0
  623. package/src/modules/customers/components/formConfig.tsx +223 -28
  624. package/src/modules/customers/components/linking/LinkEntityDialog.tsx +920 -0
  625. package/src/modules/customers/components/linking/adapters/companyAdapter.tsx +398 -0
  626. package/src/modules/customers/components/linking/adapters/dealAdapter.tsx +578 -0
  627. package/src/modules/customers/components/linking/adapters/personAdapter.tsx +512 -0
  628. package/src/modules/customers/components/list/CollectionPreviewCell.tsx +66 -0
  629. package/src/modules/customers/data/entities.ts +353 -1
  630. package/src/modules/customers/data/validators.ts +170 -19
  631. package/src/modules/customers/events.ts +22 -0
  632. package/src/modules/customers/i18n/de.json +841 -2
  633. package/src/modules/customers/i18n/en.json +841 -2
  634. package/src/modules/customers/i18n/es.json +840 -1
  635. package/src/modules/customers/i18n/pl.json +841 -2
  636. package/src/modules/customers/lib/customerRoleTypes.ts +24 -0
  637. package/src/modules/customers/lib/dealClosureNotification.ts +64 -0
  638. package/src/modules/customers/lib/dealStageTransitionTable.ts +32 -0
  639. package/src/modules/customers/lib/dictionaries.ts +26 -10
  640. package/src/modules/customers/lib/interactionReadModel.ts +10 -0
  641. package/src/modules/customers/lib/personCompanies.ts +317 -0
  642. package/src/modules/customers/lib/personCompanyLinkTable.ts +58 -0
  643. package/src/modules/customers/lib/roleTypeUsage.ts +146 -0
  644. package/src/modules/customers/migrations/.snapshot-open-mercato.json +2747 -798
  645. package/src/modules/customers/migrations/Migration20260406214502.ts +19 -0
  646. package/src/modules/customers/migrations/Migration20260408135736.ts +15 -0
  647. package/src/modules/customers/migrations/Migration20260408225345.ts +23 -0
  648. package/src/modules/customers/migrations/Migration20260411075533.ts +30 -0
  649. package/src/modules/customers/migrations/Migration20260411103551.ts +13 -0
  650. package/src/modules/customers/migrations/Migration20260411130944.ts +30 -0
  651. package/src/modules/customers/migrations/Migration20260415095203.ts +13 -0
  652. package/src/modules/customers/migrations/Migration20260415135056.ts +22 -0
  653. package/src/modules/customers/migrations/Migration20260417140000.ts +15 -0
  654. package/src/modules/customers/migrations/Migration20260417160000.ts +17 -0
  655. package/src/modules/customers/migrations/Migration20260417235407.ts +13 -0
  656. package/src/modules/customers/setup.ts +15 -0
  657. package/src/modules/customers/subscribers/deal-closure-notification.ts +22 -0
  658. package/src/modules/customers/subscribers/deal-lost-notification.ts +22 -0
  659. package/src/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.ts +2 -0
  660. package/src/modules/dictionaries/api/[dictionaryId]/entries/reorder/route.ts +162 -0
  661. package/src/modules/dictionaries/api/[dictionaryId]/entries/route.ts +6 -2
  662. package/src/modules/dictionaries/api/[dictionaryId]/entries/set-default/route.ts +162 -0
  663. package/src/modules/dictionaries/api/context.ts +9 -0
  664. package/src/modules/dictionaries/api/openapi.ts +17 -0
  665. package/src/modules/dictionaries/commands/entry-operations.ts +457 -0
  666. package/src/modules/dictionaries/commands/factory.ts +31 -3
  667. package/src/modules/dictionaries/commands/index.ts +1 -0
  668. package/src/modules/dictionaries/components/DictionaryTable.tsx +15 -6
  669. package/src/modules/dictionaries/data/entities.ts +9 -0
  670. package/src/modules/dictionaries/data/validators.ts +34 -0
  671. package/src/modules/dictionaries/events.ts +20 -0
  672. package/src/modules/dictionaries/i18n/de.json +2 -0
  673. package/src/modules/dictionaries/i18n/en.json +2 -0
  674. package/src/modules/dictionaries/i18n/es.json +2 -0
  675. package/src/modules/dictionaries/i18n/pl.json +2 -0
  676. package/src/modules/dictionaries/lib/clientEntries.ts +66 -0
  677. package/src/modules/dictionaries/migrations/.snapshot-open-mercato.json +185 -3
  678. package/src/modules/dictionaries/migrations/Migration20260410171544.ts +49 -0
  679. package/src/modules/inbox_ops/api/proposals/[id]/route.ts +4 -1
  680. package/src/modules/query_index/lib/engine.ts +9 -1
  681. package/src/modules/sales/components/documents/AddressesSection.tsx +92 -42
  682. package/src/modules/sales/i18n/de.json +28 -0
  683. package/src/modules/sales/i18n/en.json +28 -0
  684. package/src/modules/sales/i18n/es.json +28 -0
  685. package/src/modules/sales/i18n/pl.json +28 -0
  686. package/src/modules/sales/lib/dictionaries.ts +18 -0
  687. package/src/modules/sales/widgets/injection-table.ts +4 -0
@@ -6,10 +6,18 @@ import {
6
6
  emitCrudSideEffects,
7
7
  emitCrudUndoSideEffects,
8
8
  requireId,
9
+ normalizeAuthorUserId,
9
10
  } from '@open-mercato/shared/lib/commands/helpers'
11
+ import { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'
10
12
  import type { DataEngine } from '@open-mercato/shared/lib/data/engine'
11
13
  import type { EntityManager } from '@mikro-orm/postgresql'
12
- import { CustomerDeal, CustomerDealPersonLink, CustomerDealCompanyLink, CustomerPipelineStage } from '../data/entities'
14
+ import {
15
+ CustomerDeal,
16
+ CustomerDealPersonLink,
17
+ CustomerDealCompanyLink,
18
+ CustomerDealStageTransition,
19
+ CustomerPipelineStage,
20
+ } from '../data/entities'
13
21
  import {
14
22
  dealCreateSchema,
15
23
  dealUpdateSchema,
@@ -33,10 +41,8 @@ import {
33
41
  import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
34
42
  import type { CrudIndexerConfig, CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'
35
43
  import { E } from '#generated/entities.ids.generated'
36
- import { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'
37
- import { resolveNotificationService } from '../../notifications/lib/notificationService'
38
- import { buildNotificationFromType } from '../../notifications/lib/notificationBuilder'
39
- import { notificationTypes } from '../notifications'
44
+ import { findWithDecryption, findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
45
+ import { isMissingDealStageTransitionTable, warnMissingDealStageTransitionTable } from '../lib/dealStageTransitionTable'
40
46
 
41
47
  const DEAL_ENTITY_ID = 'customers:customer_deal'
42
48
  const dealCrudIndexer: CrudIndexerConfig<CustomerDeal> = {
@@ -54,13 +60,46 @@ const dealCrudEvents: CrudEventsConfig = {
54
60
  }),
55
61
  }
56
62
 
63
+ type PipelineStageSnapshot = {
64
+ id: string
65
+ pipelineId: string
66
+ label: string
67
+ order: number
68
+ }
69
+
70
+ type DealStageTransitionSnapshot = {
71
+ id: string
72
+ pipelineId: string
73
+ stageId: string
74
+ stageLabel: string
75
+ stageOrder: number
76
+ transitionedAt: Date
77
+ transitionedByUserId: string | null
78
+ }
79
+
80
+ async function loadPipelineStageSnapshot(
81
+ em: EntityManager,
82
+ pipelineStageId: string,
83
+ tenantId: string,
84
+ organizationId: string,
85
+ ): Promise<PipelineStageSnapshot | null> {
86
+ const stage = await findOneWithDecryption(em, CustomerPipelineStage, { id: pipelineStageId }, {}, { tenantId, organizationId })
87
+ if (!stage) return null
88
+ return {
89
+ id: stage.id,
90
+ pipelineId: stage.pipelineId,
91
+ label: stage.label,
92
+ order: stage.order,
93
+ }
94
+ }
95
+
57
96
  async function resolvePipelineStageValue(
58
97
  em: EntityManager,
59
98
  pipelineStageId: string,
60
99
  tenantId: string,
61
100
  organizationId: string,
62
101
  ): Promise<string | null> {
63
- const stage = await em.findOne(CustomerPipelineStage, { id: pipelineStageId })
102
+ const stage = await loadPipelineStageSnapshot(em, pipelineStageId, tenantId, organizationId)
64
103
  if (!stage) return null
65
104
  const entry = await ensureDictionaryEntry(em, {
66
105
  tenantId,
@@ -71,6 +110,96 @@ async function resolvePipelineStageValue(
71
110
  return entry?.value ?? stage.label
72
111
  }
73
112
 
113
+ async function upsertDealStageTransition(
114
+ em: EntityManager,
115
+ input: {
116
+ deal: CustomerDeal
117
+ pipelineId: string
118
+ stageId: string
119
+ stageLabel: string
120
+ stageOrder: number
121
+ transitionedByUserId: string | null
122
+ transitionedAt?: Date
123
+ },
124
+ ): Promise<void> {
125
+ let existing: CustomerDealStageTransition | null = null
126
+ try {
127
+ existing = await findOneWithDecryption(
128
+ em,
129
+ CustomerDealStageTransition,
130
+ { deal: input.deal.id, stageId: input.stageId, deletedAt: null },
131
+ {},
132
+ { tenantId: input.deal.tenantId, organizationId: input.deal.organizationId },
133
+ )
134
+ } catch (error) {
135
+ if (!isMissingDealStageTransitionTable(error)) {
136
+ throw error
137
+ }
138
+ warnMissingDealStageTransitionTable('customers.commands.deals.upsertTransition')
139
+ return
140
+ }
141
+ const transitionedAt = input.transitionedAt ?? new Date()
142
+ if (existing) {
143
+ existing.pipelineId = input.pipelineId
144
+ existing.stageLabel = input.stageLabel
145
+ existing.stageOrder = input.stageOrder
146
+ existing.transitionedAt = transitionedAt
147
+ existing.transitionedByUserId = input.transitionedByUserId
148
+ existing.deletedAt = null
149
+ existing.isActive = true
150
+ return
151
+ }
152
+
153
+ const transition = em.create(CustomerDealStageTransition, {
154
+ organizationId: input.deal.organizationId,
155
+ tenantId: input.deal.tenantId,
156
+ deal: input.deal,
157
+ pipelineId: input.pipelineId,
158
+ stageId: input.stageId,
159
+ stageLabel: input.stageLabel,
160
+ stageOrder: input.stageOrder,
161
+ transitionedAt,
162
+ transitionedByUserId: input.transitionedByUserId,
163
+ isActive: true,
164
+ })
165
+ em.persist(transition)
166
+ }
167
+
168
+ async function deleteDealStageTransitions(em: EntityManager, deal: CustomerDeal): Promise<void> {
169
+ try {
170
+ await em.nativeDelete(CustomerDealStageTransition, { deal: deal.id })
171
+ } catch (error) {
172
+ if (!isMissingDealStageTransitionTable(error)) {
173
+ throw error
174
+ }
175
+ warnMissingDealStageTransitionTable('customers.commands.deals.deleteTransitions')
176
+ }
177
+ }
178
+
179
+ async function restoreDealStageTransitions(
180
+ em: EntityManager,
181
+ deal: CustomerDeal,
182
+ transitions: DealStageTransitionSnapshot[],
183
+ ): Promise<void> {
184
+ if (!transitions.length) return
185
+ for (const transitionSnapshot of transitions) {
186
+ const transition = em.create(CustomerDealStageTransition, {
187
+ id: transitionSnapshot.id,
188
+ organizationId: deal.organizationId,
189
+ tenantId: deal.tenantId,
190
+ deal,
191
+ pipelineId: transitionSnapshot.pipelineId,
192
+ stageId: transitionSnapshot.stageId,
193
+ stageLabel: transitionSnapshot.stageLabel,
194
+ stageOrder: transitionSnapshot.stageOrder,
195
+ transitionedAt: transitionSnapshot.transitionedAt,
196
+ transitionedByUserId: transitionSnapshot.transitionedByUserId,
197
+ isActive: true,
198
+ })
199
+ em.persist(transition)
200
+ }
201
+ }
202
+
74
203
  type DealSnapshot = {
75
204
  deal: {
76
205
  id: string
@@ -88,9 +217,13 @@ type DealSnapshot = {
88
217
  expectedCloseAt: Date | null
89
218
  ownerUserId: string | null
90
219
  source: string | null
220
+ closureOutcome: string | null
221
+ lossReasonId: string | null
222
+ lossNotes: string | null
91
223
  }
92
224
  people: string[]
93
225
  companies: string[]
226
+ transitions: DealStageTransitionSnapshot[]
94
227
  custom?: Record<string, unknown>
95
228
  }
96
229
 
@@ -104,7 +237,7 @@ type DealChangeMap = Record<string, { from: unknown; to: unknown }> & {
104
237
  }
105
238
 
106
239
  async function loadDealSnapshot(em: EntityManager, id: string): Promise<DealSnapshot | null> {
107
- const deal = await em.findOne(CustomerDeal, { id, deletedAt: null })
240
+ const deal = await findOneWithDecryption(em, CustomerDeal, { id, deletedAt: null })
108
241
  if (!deal) return null
109
242
  const decryptionScope = { tenantId: deal.tenantId ?? null, organizationId: deal.organizationId ?? null }
110
243
  const peopleLinks = await findWithDecryption(
@@ -121,6 +254,19 @@ async function loadDealSnapshot(em: EntityManager, id: string): Promise<DealSnap
121
254
  { populate: ['company'] },
122
255
  decryptionScope,
123
256
  )
257
+ const transitions = await findWithDecryption(
258
+ em,
259
+ CustomerDealStageTransition,
260
+ { deal: deal.id, deletedAt: null },
261
+ { orderBy: { stageOrder: 'ASC', transitionedAt: 'ASC' } },
262
+ decryptionScope,
263
+ ).catch((error: unknown) => {
264
+ if (!isMissingDealStageTransitionTable(error)) {
265
+ throw error
266
+ }
267
+ warnMissingDealStageTransitionTable('customers.commands.deals.loadSnapshot')
268
+ return [] as CustomerDealStageTransition[]
269
+ })
124
270
  const custom = await loadCustomFieldSnapshot(em, {
125
271
  entityId: DEAL_ENTITY_ID,
126
272
  recordId: deal.id,
@@ -144,6 +290,9 @@ async function loadDealSnapshot(em: EntityManager, id: string): Promise<DealSnap
144
290
  expectedCloseAt: deal.expectedCloseAt ?? null,
145
291
  ownerUserId: deal.ownerUserId ?? null,
146
292
  source: deal.source ?? null,
293
+ closureOutcome: deal.closureOutcome ?? null,
294
+ lossReasonId: deal.lossReasonId ?? null,
295
+ lossNotes: deal.lossNotes ?? null,
147
296
  },
148
297
  people: peopleLinks.map((link) =>
149
298
  typeof link.person === 'string' ? link.person : link.person.id
@@ -151,6 +300,15 @@ async function loadDealSnapshot(em: EntityManager, id: string): Promise<DealSnap
151
300
  companies: companyLinks.map((link) =>
152
301
  typeof link.company === 'string' ? link.company : link.company.id
153
302
  ),
303
+ transitions: transitions.map((transition) => ({
304
+ id: transition.id,
305
+ pipelineId: transition.pipelineId,
306
+ stageId: transition.stageId,
307
+ stageLabel: transition.stageLabel,
308
+ stageOrder: transition.stageOrder,
309
+ transitionedAt: transition.transitionedAt,
310
+ transitionedByUserId: transition.transitionedByUserId ?? null,
311
+ })),
154
312
  custom,
155
313
  }
156
314
  }
@@ -208,34 +366,64 @@ const createDealCommand: CommandHandler<DealCreateInput, { dealId: string }> = {
208
366
  ensureOrganizationScope(ctx, parsed.organizationId)
209
367
 
210
368
  const em = (ctx.container.resolve('em') as EntityManager).fork()
211
- const deal = em.create(CustomerDeal, {
212
- organizationId: parsed.organizationId,
213
- tenantId: parsed.tenantId,
214
- title: parsed.title,
215
- description: parsed.description ?? null,
216
- status: parsed.status ?? 'open',
217
- pipelineStage: parsed.pipelineStage ?? null,
218
- pipelineId: parsed.pipelineId ?? null,
219
- pipelineStageId: parsed.pipelineStageId ?? null,
220
- valueAmount: toNumericString(parsed.valueAmount),
221
- valueCurrency: parsed.valueCurrency ?? null,
222
- probability: parsed.probability ?? null,
223
- expectedCloseAt: parsed.expectedCloseAt ?? null,
224
- ownerUserId: parsed.ownerUserId ?? null,
225
- source: parsed.source ?? null,
226
- })
227
- em.persist(deal)
228
-
229
- if (deal.pipelineStageId && !deal.pipelineStage) {
230
- const resolved = await resolvePipelineStageValue(em, deal.pipelineStageId, parsed.tenantId, parsed.organizationId)
231
- if (resolved) deal.pipelineStage = resolved
232
- }
233
-
234
- await em.flush()
235
-
236
- await syncDealPeople(em, deal, parsed.personIds ?? [])
237
- await syncDealCompanies(em, deal, parsed.companyIds ?? [])
238
- await em.flush()
369
+ const normalizedTransitionAuthorUserId = normalizeAuthorUserId(null, ctx.auth)
370
+ let deal!: CustomerDeal
371
+ let stageSnapshot: PipelineStageSnapshot | null = null
372
+ let resolvedPipelineStageLabel: string | null = null
373
+ await withAtomicFlush(em, [
374
+ async () => {
375
+ stageSnapshot = parsed.pipelineStageId
376
+ ? await loadPipelineStageSnapshot(em, parsed.pipelineStageId, parsed.tenantId, parsed.organizationId)
377
+ : null
378
+ resolvedPipelineStageLabel = stageSnapshot
379
+ ? (await ensureDictionaryEntry(em, {
380
+ tenantId: parsed.tenantId,
381
+ organizationId: parsed.organizationId,
382
+ kind: 'pipeline_stage',
383
+ value: stageSnapshot.label,
384
+ }))?.value ?? stageSnapshot.label
385
+ : parsed.pipelineStage ?? null
386
+ },
387
+ () => {
388
+ deal = em.create(CustomerDeal, {
389
+ organizationId: parsed.organizationId,
390
+ tenantId: parsed.tenantId,
391
+ title: parsed.title,
392
+ description: parsed.description ?? null,
393
+ status: parsed.status ?? 'open',
394
+ pipelineStage: resolvedPipelineStageLabel,
395
+ pipelineId: parsed.pipelineId ?? null,
396
+ pipelineStageId: parsed.pipelineStageId ?? null,
397
+ valueAmount: toNumericString(parsed.valueAmount),
398
+ valueCurrency: parsed.valueCurrency ?? null,
399
+ probability: parsed.probability ?? null,
400
+ expectedCloseAt: parsed.expectedCloseAt ?? null,
401
+ ownerUserId: parsed.ownerUserId ?? null,
402
+ source: parsed.source ?? null,
403
+ closureOutcome: parsed.closureOutcome ?? null,
404
+ lossReasonId: parsed.lossReasonId ?? null,
405
+ lossNotes: parsed.lossNotes ?? null,
406
+ })
407
+ em.persist(deal)
408
+ },
409
+ ], { transaction: true })
410
+
411
+ await withAtomicFlush(em, [
412
+ async () => {
413
+ const snapshot = stageSnapshot
414
+ if (!snapshot) return
415
+ await upsertDealStageTransition(em, {
416
+ deal,
417
+ pipelineId: snapshot.pipelineId,
418
+ stageId: snapshot.id,
419
+ stageLabel: snapshot.label,
420
+ stageOrder: snapshot.order,
421
+ transitionedByUserId: normalizedTransitionAuthorUserId,
422
+ })
423
+ },
424
+ () => syncDealPeople(em, deal, parsed.personIds ?? []),
425
+ () => syncDealCompanies(em, deal, parsed.companyIds ?? []),
426
+ ], { transaction: true })
239
427
 
240
428
  const de = (ctx.container.resolve('dataEngine') as DataEngine)
241
429
  await setCustomFieldsIfAny({
@@ -267,9 +455,10 @@ const createDealCommand: CommandHandler<DealCreateInput, { dealId: string }> = {
267
455
  const em = (ctx.container.resolve('em') as EntityManager).fork()
268
456
  return await loadDealSnapshot(em, result.dealId)
269
457
  },
270
- buildLog: async ({ result, snapshots }) => {
458
+ buildLog: async ({ result, ctx }) => {
271
459
  const { translate } = await resolveTranslations()
272
- const snapshot = snapshots.after as DealSnapshot | undefined
460
+ const em = (ctx.container.resolve('em') as EntityManager).fork()
461
+ const snapshot = await loadDealSnapshot(em, result.dealId)
273
462
  return {
274
463
  actionLabel: translate('customers.audit.deals.create', 'Create deal'),
275
464
  resourceKind: 'customers.deal',
@@ -288,8 +477,9 @@ const createDealCommand: CommandHandler<DealCreateInput, { dealId: string }> = {
288
477
  const dealId = logEntry?.resourceId
289
478
  if (!dealId) return
290
479
  const em = (ctx.container.resolve('em') as EntityManager).fork()
291
- const deal = await em.findOne(CustomerDeal, { id: dealId })
480
+ const deal = await findOneWithDecryption(em, CustomerDeal, { id: dealId })
292
481
  if (!deal) return
482
+ await deleteDealStageTransitions(em, deal)
293
483
  await em.nativeDelete(CustomerDealPersonLink, { deal })
294
484
  await em.nativeDelete(CustomerDealCompanyLink, { deal })
295
485
  em.remove(deal)
@@ -301,42 +491,89 @@ const updateDealCommand: CommandHandler<DealUpdateInput, { dealId: string }> = {
301
491
  id: 'customers.deals.update',
302
492
  async prepare(rawInput, ctx) {
303
493
  const { parsed } = parseWithCustomFields(dealUpdateSchema, rawInput)
304
- const em = (ctx.container.resolve('em') as EntityManager)
494
+ const em = (ctx.container.resolve('em') as EntityManager).fork()
305
495
  const snapshot = await loadDealSnapshot(em, parsed.id)
306
496
  return snapshot ? { before: snapshot } : {}
307
497
  },
308
498
  async execute(rawInput, ctx) {
309
499
  const { parsed, custom } = parseWithCustomFields(dealUpdateSchema, rawInput)
310
500
  const em = (ctx.container.resolve('em') as EntityManager).fork()
311
- const deal = await em.findOne(CustomerDeal, { id: parsed.id, deletedAt: null })
501
+ const deal = await findOneWithDecryption(em, CustomerDeal, { id: parsed.id, deletedAt: null })
312
502
  const record = deal ?? null
313
503
  if (!record) throw new CrudHttpError(404, { error: 'Deal not found' })
314
504
  ensureTenantScope(ctx, record.tenantId)
315
505
  ensureOrganizationScope(ctx, record.organizationId)
316
506
 
317
507
  const previousStatus = record.status
508
+ const previousPipelineStageId = record.pipelineStageId ?? null
509
+ const normalizedTransitionAuthorUserId = normalizeAuthorUserId(null, ctx.auth)
510
+
511
+ let nextStageSnapshot: PipelineStageSnapshot | null = null
512
+ let nextPipelineStageLabel: string | null = null
513
+ let resolvedCurrentPipelineStageLabel: string | null = null
514
+
515
+ await withAtomicFlush(em, [
516
+ async () => {
517
+ nextStageSnapshot = parsed.pipelineStageId
518
+ ? await loadPipelineStageSnapshot(em, parsed.pipelineStageId, record.tenantId, record.organizationId)
519
+ : null
520
+ nextPipelineStageLabel = nextStageSnapshot
521
+ ? (await ensureDictionaryEntry(em, {
522
+ tenantId: record.tenantId,
523
+ organizationId: record.organizationId,
524
+ kind: 'pipeline_stage',
525
+ value: nextStageSnapshot.label,
526
+ }))?.value ?? nextStageSnapshot.label
527
+ : null
528
+ resolvedCurrentPipelineStageLabel =
529
+ !nextStageSnapshot && record.pipelineStageId && (parsed.pipelineStageId !== undefined || !record.pipelineStage)
530
+ ? await resolvePipelineStageValue(em, record.pipelineStageId, record.tenantId, record.organizationId)
531
+ : null
532
+ },
533
+ () => {
534
+ if (parsed.title !== undefined) record.title = parsed.title
535
+ if (parsed.description !== undefined) record.description = parsed.description ?? null
536
+ if (parsed.status !== undefined) record.status = parsed.status ?? record.status
537
+ if (parsed.pipelineStage !== undefined) record.pipelineStage = parsed.pipelineStage ?? null
538
+ if (parsed.pipelineId !== undefined) record.pipelineId = parsed.pipelineId ?? null
539
+ if (parsed.pipelineStageId !== undefined) record.pipelineStageId = parsed.pipelineStageId ?? null
540
+
541
+ if (nextPipelineStageLabel && (parsed.pipelineStageId !== undefined || !record.pipelineStage)) {
542
+ record.pipelineStage = nextPipelineStageLabel
543
+ } else if (resolvedCurrentPipelineStageLabel && (parsed.pipelineStageId !== undefined || !record.pipelineStage)) {
544
+ record.pipelineStage = resolvedCurrentPipelineStageLabel
545
+ }
318
546
 
319
- if (parsed.title !== undefined) record.title = parsed.title
320
- if (parsed.description !== undefined) record.description = parsed.description ?? null
321
- if (parsed.status !== undefined) record.status = parsed.status ?? record.status
322
- if (parsed.pipelineStage !== undefined) record.pipelineStage = parsed.pipelineStage ?? null
323
- if (parsed.pipelineId !== undefined) record.pipelineId = parsed.pipelineId ?? null
324
- if (parsed.pipelineStageId !== undefined) record.pipelineStageId = parsed.pipelineStageId ?? null
325
-
326
- if (record.pipelineStageId && (parsed.pipelineStageId !== undefined || !record.pipelineStage)) {
327
- const resolved = await resolvePipelineStageValue(em, record.pipelineStageId, record.tenantId, record.organizationId)
328
- if (resolved) record.pipelineStage = resolved
329
- }
330
- if (parsed.valueAmount !== undefined) record.valueAmount = toNumericString(parsed.valueAmount)
331
- if (parsed.valueCurrency !== undefined) record.valueCurrency = parsed.valueCurrency ?? null
332
- if (parsed.probability !== undefined) record.probability = parsed.probability ?? null
333
- if (parsed.expectedCloseAt !== undefined) record.expectedCloseAt = parsed.expectedCloseAt ?? null
334
- if (parsed.ownerUserId !== undefined) record.ownerUserId = parsed.ownerUserId ?? null
335
- if (parsed.source !== undefined) record.source = parsed.source ?? null
336
-
337
- await syncDealPeople(em, record, parsed.personIds)
338
- await syncDealCompanies(em, record, parsed.companyIds)
339
- await em.flush()
547
+ if (parsed.valueAmount !== undefined) record.valueAmount = toNumericString(parsed.valueAmount)
548
+ if (parsed.valueCurrency !== undefined) record.valueCurrency = parsed.valueCurrency ?? null
549
+ if (parsed.probability !== undefined) record.probability = parsed.probability ?? null
550
+ if (parsed.expectedCloseAt !== undefined) record.expectedCloseAt = parsed.expectedCloseAt ?? null
551
+ if (parsed.ownerUserId !== undefined) record.ownerUserId = parsed.ownerUserId ?? null
552
+ if (parsed.source !== undefined) record.source = parsed.source ?? null
553
+ if (parsed.closureOutcome !== undefined) record.closureOutcome = parsed.closureOutcome ?? null
554
+ if (parsed.lossReasonId !== undefined) record.lossReasonId = parsed.lossReasonId ?? null
555
+ if (parsed.lossNotes !== undefined) record.lossNotes = parsed.lossNotes ?? null
556
+ },
557
+ async () => {
558
+ const snapshot = nextStageSnapshot
559
+ if (!snapshot) return
560
+ const shouldRecord =
561
+ parsed.pipelineStageId !== undefined &&
562
+ parsed.pipelineStageId !== null &&
563
+ parsed.pipelineStageId !== previousPipelineStageId
564
+ if (!shouldRecord) return
565
+ await upsertDealStageTransition(em, {
566
+ deal: record,
567
+ pipelineId: snapshot.pipelineId,
568
+ stageId: snapshot.id,
569
+ stageLabel: nextPipelineStageLabel ?? snapshot.label,
570
+ stageOrder: snapshot.order,
571
+ transitionedByUserId: normalizedTransitionAuthorUserId,
572
+ })
573
+ },
574
+ () => syncDealPeople(em, record, parsed.personIds),
575
+ () => syncDealCompanies(em, record, parsed.companyIds),
576
+ ], { transaction: true })
340
577
 
341
578
  const de = (ctx.container.resolve('dataEngine') as DataEngine)
342
579
  await setCustomFieldsIfAny({
@@ -362,37 +599,31 @@ const updateDealCommand: CommandHandler<DealUpdateInput, { dealId: string }> = {
362
599
  events: dealCrudEvents,
363
600
  })
364
601
 
365
- // Send notifications for deal won/lost status changes
602
+ // Emit a lifecycle event for deal won/lost status changes; the notifications
603
+ // subscriber translates these into recipient notifications.
366
604
  const newStatus = record.status
367
605
  const normalizedStatus = newStatus === 'win' ? 'won' : newStatus === 'loose' ? 'lost' : newStatus
368
- if (previousStatus !== newStatus && (normalizedStatus === 'won' || normalizedStatus === 'lost') && record.ownerUserId) {
606
+ if (previousStatus !== newStatus && (normalizedStatus === 'won' || normalizedStatus === 'lost')) {
607
+ const closureEvent = normalizedStatus === 'won' ? 'customers.deal.won' : 'customers.deal.lost'
369
608
  try {
370
- const notificationService = resolveNotificationService(ctx.container)
371
- const notificationType = normalizedStatus === 'won' ? 'customers.deal.won' : 'customers.deal.lost'
372
- const typeDef = notificationTypes.find((type) => type.type === notificationType)
373
- if (typeDef) {
374
- const valueDisplay = record.valueAmount && record.valueCurrency
375
- ? `${record.valueCurrency} ${record.valueAmount}`
376
- : ''
377
-
378
- const notificationInput = buildNotificationFromType(typeDef, {
379
- recipientUserId: record.ownerUserId,
380
- bodyVariables: {
381
- dealTitle: record.title,
382
- dealValue: valueDisplay,
609
+ const eventBus = ctx.container.resolve('eventBus') as { emitEvent(event: string, payload: unknown, options?: unknown): Promise<void> } | undefined
610
+ if (eventBus) {
611
+ await eventBus.emitEvent(
612
+ closureEvent,
613
+ {
614
+ id: record.id,
615
+ tenantId: record.tenantId,
616
+ organizationId: record.organizationId,
617
+ ownerUserId: record.ownerUserId ?? null,
618
+ title: record.title,
619
+ valueAmount: record.valueAmount ?? null,
620
+ valueCurrency: record.valueCurrency ?? null,
383
621
  },
384
- sourceEntityType: 'customers:customer_deal',
385
- sourceEntityId: record.id,
386
- linkHref: `/backend/customers/deals/${record.id}`,
387
- })
388
-
389
- await notificationService.create(notificationInput, {
390
- tenantId: record.tenantId,
391
- organizationId: record.organizationId,
392
- })
622
+ { persistent: true },
623
+ )
393
624
  }
394
- } catch {
395
- // Notification creation is non-critical, don't fail the command
625
+ } catch (err) {
626
+ console.warn('[customers.deals.update] deal closure event emit failed', closureEvent, err)
396
627
  }
397
628
  }
398
629
 
@@ -402,11 +633,12 @@ const updateDealCommand: CommandHandler<DealUpdateInput, { dealId: string }> = {
402
633
  const em = (ctx.container.resolve('em') as EntityManager).fork()
403
634
  return await loadDealSnapshot(em, result.dealId)
404
635
  },
405
- buildLog: async ({ snapshots }) => {
636
+ buildLog: async ({ result, snapshots, ctx }) => {
406
637
  const { translate } = await resolveTranslations()
407
638
  const before = snapshots.before as DealSnapshot | undefined
408
639
  if (!before) return null
409
- const afterSnapshot = snapshots.after as DealSnapshot | undefined
640
+ const em = (ctx.container.resolve('em') as EntityManager).fork()
641
+ const afterSnapshot = await loadDealSnapshot(em, result.dealId)
410
642
  return {
411
643
  actionLabel: translate('customers.audit.deals.update', 'Update deal'),
412
644
  resourceKind: 'customers.deal',
@@ -428,7 +660,8 @@ const updateDealCommand: CommandHandler<DealUpdateInput, { dealId: string }> = {
428
660
  const before = payload?.before
429
661
  if (!before) return
430
662
  const em = (ctx.container.resolve('em') as EntityManager).fork()
431
- let deal = await em.findOne(CustomerDeal, { id: before.deal.id })
663
+ const normalizedTransitionAuthorUserId = normalizeAuthorUserId(null, ctx.auth)
664
+ let deal = await findOneWithDecryption(em, CustomerDeal, { id: before.deal.id })
432
665
  if (!deal) {
433
666
  deal = em.create(CustomerDeal, {
434
667
  id: before.deal.id,
@@ -446,26 +679,59 @@ const updateDealCommand: CommandHandler<DealUpdateInput, { dealId: string }> = {
446
679
  expectedCloseAt: before.deal.expectedCloseAt,
447
680
  ownerUserId: before.deal.ownerUserId,
448
681
  source: before.deal.source,
682
+ closureOutcome: before.deal.closureOutcome,
683
+ lossReasonId: before.deal.lossReasonId,
684
+ lossNotes: before.deal.lossNotes,
449
685
  })
450
686
  em.persist(deal)
451
- } else {
452
- deal.title = before.deal.title
453
- deal.description = before.deal.description
454
- deal.status = before.deal.status
455
- deal.pipelineStage = before.deal.pipelineStage
456
- deal.pipelineId = before.deal.pipelineId
457
- deal.pipelineStageId = before.deal.pipelineStageId
458
- deal.valueAmount = before.deal.valueAmount
459
- deal.valueCurrency = before.deal.valueCurrency
460
- deal.probability = before.deal.probability
461
- deal.expectedCloseAt = before.deal.expectedCloseAt
462
- deal.ownerUserId = before.deal.ownerUserId
463
- deal.source = before.deal.source
464
687
  }
465
- await em.flush()
466
- await syncDealPeople(em, deal, before.people)
467
- await syncDealCompanies(em, deal, before.companies)
468
- await em.flush()
688
+ const revertedStageSnapshot = before.deal.pipelineStageId
689
+ ? await loadPipelineStageSnapshot(em, before.deal.pipelineStageId, before.deal.tenantId, before.deal.organizationId)
690
+ : null
691
+ const existingTransition = before.deal.pipelineStageId
692
+ ? before.transitions.find((transition) => transition.stageId === before.deal.pipelineStageId) ?? null
693
+ : null
694
+ const shouldRecordRevertTransition =
695
+ before.deal.pipelineStageId !== (payload?.after?.deal.pipelineStageId ?? null) &&
696
+ !!before.deal.pipelineStageId &&
697
+ !!(revertedStageSnapshot?.pipelineId ?? before.deal.pipelineId ?? existingTransition?.pipelineId) &&
698
+ !!(revertedStageSnapshot?.label ?? before.deal.pipelineStage ?? existingTransition?.stageLabel)
699
+
700
+ await withAtomicFlush(em, [
701
+ () => {
702
+ deal.title = before.deal.title
703
+ deal.description = before.deal.description
704
+ deal.status = before.deal.status
705
+ deal.pipelineStage = before.deal.pipelineStage
706
+ deal.pipelineId = before.deal.pipelineId
707
+ deal.pipelineStageId = before.deal.pipelineStageId
708
+ deal.valueAmount = before.deal.valueAmount
709
+ deal.valueCurrency = before.deal.valueCurrency
710
+ deal.probability = before.deal.probability
711
+ deal.expectedCloseAt = before.deal.expectedCloseAt
712
+ deal.ownerUserId = before.deal.ownerUserId
713
+ deal.source = before.deal.source
714
+ deal.closureOutcome = before.deal.closureOutcome
715
+ deal.lossReasonId = before.deal.lossReasonId
716
+ deal.lossNotes = before.deal.lossNotes
717
+ },
718
+ async () => {
719
+ if (!shouldRecordRevertTransition || !before.deal.pipelineStageId) return
720
+ const pipelineId = revertedStageSnapshot?.pipelineId ?? before.deal.pipelineId ?? existingTransition?.pipelineId
721
+ const stageLabel = revertedStageSnapshot?.label ?? before.deal.pipelineStage ?? existingTransition?.stageLabel
722
+ if (!pipelineId || !stageLabel) return
723
+ await upsertDealStageTransition(em, {
724
+ deal,
725
+ pipelineId,
726
+ stageId: before.deal.pipelineStageId,
727
+ stageLabel,
728
+ stageOrder: revertedStageSnapshot?.order ?? existingTransition?.stageOrder ?? 0,
729
+ transitionedByUserId: normalizedTransitionAuthorUserId,
730
+ })
731
+ },
732
+ () => syncDealPeople(em, deal, before.people),
733
+ () => syncDealCompanies(em, deal, before.companies),
734
+ ], { transaction: true })
469
735
 
470
736
  const de = (ctx.container.resolve('dataEngine') as DataEngine)
471
737
  await emitCrudUndoSideEffects({
@@ -501,18 +767,19 @@ const deleteDealCommand: CommandHandler<{ body?: Record<string, unknown>; query?
501
767
  id: 'customers.deals.delete',
502
768
  async prepare(input, ctx) {
503
769
  const id = requireId(input, 'Deal id required')
504
- const em = (ctx.container.resolve('em') as EntityManager)
770
+ const em = (ctx.container.resolve('em') as EntityManager).fork()
505
771
  const snapshot = await loadDealSnapshot(em, id)
506
772
  return snapshot ? { before: snapshot } : {}
507
773
  },
508
774
  async execute(input, ctx) {
509
775
  const id = requireId(input, 'Deal id required')
510
776
  const em = (ctx.container.resolve('em') as EntityManager).fork()
511
- const deal = await em.findOne(CustomerDeal, { id, deletedAt: null })
777
+ const deal = await findOneWithDecryption(em, CustomerDeal, { id, deletedAt: null })
512
778
  const record = deal ?? null
513
779
  if (!record) throw new CrudHttpError(404, { error: 'Deal not found' })
514
780
  ensureTenantScope(ctx, record.tenantId)
515
781
  ensureOrganizationScope(ctx, record.organizationId)
782
+ await deleteDealStageTransitions(em, record)
516
783
  await em.nativeDelete(CustomerDealPersonLink, { deal: record })
517
784
  await em.nativeDelete(CustomerDealCompanyLink, { deal: record })
518
785
  em.remove(record)
@@ -556,7 +823,7 @@ const deleteDealCommand: CommandHandler<{ body?: Record<string, unknown>; query?
556
823
  const before = payload?.before
557
824
  if (!before) return
558
825
  const em = (ctx.container.resolve('em') as EntityManager).fork()
559
- let deal = await em.findOne(CustomerDeal, { id: before.deal.id })
826
+ let deal = await findOneWithDecryption(em, CustomerDeal, { id: before.deal.id })
560
827
  if (!deal) {
561
828
  deal = em.create(CustomerDeal, {
562
829
  id: before.deal.id,
@@ -574,13 +841,18 @@ const deleteDealCommand: CommandHandler<{ body?: Record<string, unknown>; query?
574
841
  expectedCloseAt: before.deal.expectedCloseAt,
575
842
  ownerUserId: before.deal.ownerUserId,
576
843
  source: before.deal.source,
844
+ closureOutcome: before.deal.closureOutcome,
845
+ lossReasonId: before.deal.lossReasonId,
846
+ lossNotes: before.deal.lossNotes,
577
847
  })
578
848
  em.persist(deal)
579
849
  }
580
- await em.flush()
581
- await syncDealPeople(em, deal, before.people)
582
- await syncDealCompanies(em, deal, before.companies)
583
- await em.flush()
850
+ await withAtomicFlush(em, [
851
+ () => syncDealPeople(em, deal, before.people),
852
+ () => syncDealCompanies(em, deal, before.companies),
853
+ () => deleteDealStageTransitions(em, deal),
854
+ () => restoreDealStageTransitions(em, deal, before.transitions),
855
+ ], { transaction: true })
584
856
 
585
857
  const de = (ctx.container.resolve('dataEngine') as DataEngine)
586
858
  await emitCrudUndoSideEffects({