@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
@@ -2,11 +2,14 @@
2
2
 
3
3
  import * as React from 'react'
4
4
  import Link from 'next/link'
5
- import { ArrowUpRightSquare, Loader2, Pencil, Trash2 } from 'lucide-react'
5
+ import { Link2, Pencil, Plus } from 'lucide-react'
6
6
  import { Button } from '@open-mercato/ui/primitives/button'
7
+ import { IconButton } from '@open-mercato/ui/primitives/icon-button'
7
8
  import { flash } from '@open-mercato/ui/backend/FlashMessages'
8
9
  import { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
9
10
  import { createCrud, updateCrud } from '@open-mercato/ui/backend/utils/crud'
11
+ import { LinkEntityDialog } from '../linking/LinkEntityDialog'
12
+ import { createDealLinkAdapter } from '../linking/adapters/dealAdapter'
10
13
  import { LoadingMessage, TabEmptyState } from '@open-mercato/ui/backend/detail'
11
14
  import { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'
12
15
  import { useT } from '@open-mercato/shared/lib/i18n/context'
@@ -30,7 +33,7 @@ type DealsScope =
30
33
  | { kind: 'person'; entityId: string }
31
34
  | { kind: 'company'; entityId: string }
32
35
 
33
- type GuardedMutationRunner = <T>(
36
+ type GuardedMutationRunner = <T,>(
34
37
  operation: () => Promise<T>,
35
38
  mutationPayload?: Record<string, unknown>,
36
39
  ) => Promise<T>
@@ -120,10 +123,15 @@ function sanitizeCustomFieldEntries(
120
123
  return Array.from(map.values())
121
124
  }
122
125
 
123
- type NormalizedDeal = Omit<DealSummary, 'valueAmount' | 'probability' | 'expectedCloseAt' | 'customValues' | 'customFields'> & {
126
+ type NormalizedDeal = Omit<
127
+ DealSummary,
128
+ 'valueAmount' | 'probability' | 'expectedCloseAt' | 'customValues' | 'customFields' | 'personIds' | 'companyIds'
129
+ > & {
124
130
  valueAmount: number | null
125
131
  probability: number | null
126
132
  expectedCloseAt: string | null
133
+ personIds: string[]
134
+ companyIds: string[]
127
135
  customValues: Record<string, unknown> | null
128
136
  customFields: DealCustomFieldEntry[]
129
137
  }
@@ -235,6 +243,18 @@ function normalizeDeal(deal: Partial<DealSummary> & { id: string; title?: string
235
243
  : deal.ownerUserId ?? null,
236
244
  source:
237
245
  typeof deal.source === 'string' && deal.source.trim().length ? deal.source : deal.source ?? null,
246
+ closureOutcome:
247
+ typeof deal.closureOutcome === 'string' && deal.closureOutcome.trim().length
248
+ ? deal.closureOutcome
249
+ : deal.closureOutcome ?? null,
250
+ lossReasonId:
251
+ typeof deal.lossReasonId === 'string' && deal.lossReasonId.trim().length
252
+ ? deal.lossReasonId
253
+ : deal.lossReasonId ?? null,
254
+ lossNotes:
255
+ typeof deal.lossNotes === 'string' && deal.lossNotes.trim().length
256
+ ? deal.lossNotes
257
+ : deal.lossNotes ?? null,
238
258
  createdAt: toIso(deal.createdAt ?? null),
239
259
  updatedAt: toIso(deal.updatedAt ?? null),
240
260
  personIds,
@@ -246,46 +266,6 @@ function normalizeDeal(deal: Partial<DealSummary> & { id: string; title?: string
246
266
  }
247
267
  }
248
268
 
249
- function buildInitialValues(deal: NormalizedDeal): Partial<DealFormBaseValues & Record<string, unknown>> {
250
- const base: Partial<DealFormBaseValues & Record<string, unknown>> = {
251
- title: deal.title,
252
- status: deal.status ?? '',
253
- pipelineStage: deal.pipelineStage ?? '',
254
- valueAmount: (() => {
255
- if (typeof deal.valueAmount === 'number') return deal.valueAmount
256
- if (deal.valueAmount == null) return null
257
- const parsed = Number(deal.valueAmount)
258
- return Number.isFinite(parsed) ? parsed : null
259
- })(),
260
- valueCurrency: deal.valueCurrency ?? '',
261
- probability: (() => {
262
- if (typeof deal.probability === 'number') return deal.probability
263
- if (deal.probability == null) return null
264
- const parsed = Number(deal.probability)
265
- return Number.isFinite(parsed) ? parsed : null
266
- })(),
267
- expectedCloseAt: deal.expectedCloseAt ?? null,
268
- description: deal.description ?? '',
269
- personIds: Array.isArray(deal.personIds) ? deal.personIds : [],
270
- companyIds: Array.isArray(deal.companyIds) ? deal.companyIds : [],
271
- }
272
- if (deal.customValues) {
273
- for (const [key, value] of Object.entries(deal.customValues)) {
274
- base[`cf_${key}`] = value
275
- }
276
- }
277
- if (Array.isArray(deal.customFields)) {
278
- deal.customFields.forEach((entry) => {
279
- if (!entry || typeof entry.key !== 'string') return
280
- const fieldKey = `cf_${entry.key}`
281
- if (base[fieldKey] === undefined) {
282
- base[fieldKey] = entry.value ?? null
283
- }
284
- })
285
- }
286
- return base
287
- }
288
-
289
269
  function formatValueLabel(amount: number | null, currency: string | null, emptyLabel: string): string {
290
270
  if (typeof amount === 'number') {
291
271
  const formatter = new Intl.NumberFormat(undefined, {
@@ -307,6 +287,7 @@ export type DealsSectionProps = {
307
287
  addActionLabel: string
308
288
  emptyLabel: string
309
289
  emptyState: TabEmptyStateConfig
290
+ onCountDelta?: (delta: number) => void
310
291
  onActionChange?: (action: SectionAction | null) => void
311
292
  onLoadingChange?: (isLoading: boolean) => void
312
293
  onDataRefresh?: () => Promise<void> | void
@@ -319,6 +300,7 @@ export function DealsSection({
319
300
  addActionLabel,
320
301
  emptyLabel,
321
302
  emptyState,
303
+ onCountDelta,
322
304
  onActionChange,
323
305
  onLoadingChange,
324
306
  onDataRefresh,
@@ -343,8 +325,6 @@ export function DealsSection({
343
325
  const pageRef = React.useRef(0)
344
326
  const hasMoreRef = React.useRef(true)
345
327
  const [dialogOpen, setDialogOpen] = React.useState(false)
346
- const [dialogMode, setDialogMode] = React.useState<'create' | 'edit'>('create')
347
- const [editingDealId, setEditingDealId] = React.useState<string | null>(null)
348
328
  const [initialValues, setInitialValues] = React.useState<
349
329
  Partial<DealFormBaseValues & Record<string, unknown>> | undefined
350
330
  >(undefined)
@@ -460,6 +440,24 @@ export function DealsSection({
460
440
  typeof record.source === 'string' && record.source.trim().length
461
441
  ? record.source
462
442
  : null
443
+ const closureOutcome =
444
+ typeof record.closureOutcome === 'string' && record.closureOutcome.trim().length
445
+ ? record.closureOutcome
446
+ : typeof record.closure_outcome === 'string' && record.closure_outcome.trim().length
447
+ ? record.closure_outcome
448
+ : null
449
+ const lossReasonId =
450
+ typeof record.lossReasonId === 'string' && record.lossReasonId.trim().length
451
+ ? record.lossReasonId
452
+ : typeof record.loss_reason_id === 'string' && record.loss_reason_id.trim().length
453
+ ? record.loss_reason_id
454
+ : null
455
+ const lossNotes =
456
+ typeof record.lossNotes === 'string' && record.lossNotes.trim().length
457
+ ? record.lossNotes
458
+ : typeof record.loss_notes === 'string' && record.loss_notes.trim().length
459
+ ? record.loss_notes
460
+ : null
463
461
  const createdAt =
464
462
  typeof record.createdAt === 'string' && record.createdAt.trim().length
465
463
  ? record.createdAt
@@ -503,6 +501,9 @@ export function DealsSection({
503
501
  description,
504
502
  ownerUserId,
505
503
  source,
504
+ closureOutcome,
505
+ lossReasonId,
506
+ lossNotes,
506
507
  createdAt,
507
508
  updatedAt,
508
509
  personIds: personIds as string[] | undefined,
@@ -558,8 +559,6 @@ export function DealsSection({
558
559
 
559
560
  const openCreateDialog = React.useCallback(() => {
560
561
  if (!scope) return
561
- setDialogMode('create')
562
- setEditingDealId(null)
563
562
  setInitialValues({
564
563
  personIds: scope.kind === 'person' ? [scope.entityId] : [],
565
564
  companyIds: scope.kind === 'company' ? [scope.entityId] : [],
@@ -567,20 +566,141 @@ export function DealsSection({
567
566
  setDialogOpen(true)
568
567
  }, [scope])
569
568
 
570
- const openEditDialog = React.useCallback(
571
- (deal: NormalizedDeal) => {
572
- setDialogMode('edit')
573
- setEditingDealId(deal.id)
574
- setInitialValues(buildInitialValues(deal))
575
- setDialogOpen(true)
569
+ const [linkDialogOpen, setLinkDialogOpen] = React.useState(false)
570
+ const openLinkDialog = React.useCallback(() => {
571
+ if (!scope) return
572
+ setLinkDialogOpen(true)
573
+ }, [scope])
574
+
575
+ const existingDealIds = React.useMemo(() => deals.map((deal) => deal.id), [deals])
576
+
577
+ const dealLinkAdapter = React.useMemo(
578
+ () =>
579
+ createDealLinkAdapter({
580
+ dialogTitle: t('customers.linking.deal.dialogTitle', 'Link deal'),
581
+ dialogSubtitle: t(
582
+ 'customers.linking.deal.dialogSubtitle',
583
+ 'Link an existing deal to this record',
584
+ ),
585
+ sectionLabel: t('customers.linking.deal.sectionLabel', 'MATCHING DEALS'),
586
+ searchPlaceholder: t('customers.linking.deal.searchPlaceholder', 'Search all deals…'),
587
+ searchEmptyHint: t('customers.linking.deal.searchEmpty', 'No matching deals found.'),
588
+ selectedEmptyHint: t('customers.linking.deal.selectedEmpty', 'No deals selected.'),
589
+ confirmButtonLabel: t('customers.linking.deal.confirmButton', 'Link deal'),
590
+ orphanWarningTitle: t('customers.linking.deal.orphanWarningTitle', 'Deal without company'),
591
+ orphanWarningMessage: t(
592
+ 'customers.linking.deal.orphanWarning',
593
+ 'This deal has no other linked entities. If you unlink it later, it will become unreachable.',
594
+ ),
595
+ contextEntityId: scope?.entityId,
596
+ }),
597
+ [scope?.entityId, t],
598
+ )
599
+
600
+ const handleLinkConfirm = React.useCallback(
601
+ async ({
602
+ addedIds,
603
+ removedIds,
604
+ }: {
605
+ addedIds: string[]
606
+ removedIds: string[]
607
+ }) => {
608
+ if (!scope) return
609
+ if (!addedIds.length && !removedIds.length) return
610
+ pushLoading()
611
+ try {
612
+ for (const dealId of addedIds) {
613
+ const payload = await readApiResultOrThrow<Record<string, unknown>>(
614
+ `/api/customers/deals/${encodeURIComponent(dealId)}`,
615
+ )
616
+ const currentPersonIds = Array.isArray(payload.personIds)
617
+ ? (payload.personIds as string[]).filter((id) => typeof id === 'string')
618
+ : []
619
+ const currentCompanyIds = Array.isArray(payload.companyIds)
620
+ ? (payload.companyIds as string[]).filter((id) => typeof id === 'string')
621
+ : []
622
+ const nextPersonIds =
623
+ scope.kind === 'person' && !currentPersonIds.includes(scope.entityId)
624
+ ? [...currentPersonIds, scope.entityId]
625
+ : currentPersonIds
626
+ const nextCompanyIds =
627
+ scope.kind === 'company' && !currentCompanyIds.includes(scope.entityId)
628
+ ? [...currentCompanyIds, scope.entityId]
629
+ : currentCompanyIds
630
+ await runWriteMutation(
631
+ () =>
632
+ updateCrud(
633
+ 'customers/deals',
634
+ { id: dealId, personIds: nextPersonIds, companyIds: nextCompanyIds },
635
+ {
636
+ errorMessage: t(
637
+ 'customers.people.detail.deals.linkError',
638
+ 'Failed to link deal.',
639
+ ),
640
+ },
641
+ ),
642
+ { dealId, scopeKind: scope.kind, scopeEntityId: scope.entityId, operation: 'linkDeal' },
643
+ )
644
+ }
645
+ for (const dealId of removedIds) {
646
+ const payload = await readApiResultOrThrow<Record<string, unknown>>(
647
+ `/api/customers/deals/${encodeURIComponent(dealId)}`,
648
+ )
649
+ const currentPersonIds = Array.isArray(payload.personIds)
650
+ ? (payload.personIds as string[]).filter((id) => typeof id === 'string')
651
+ : []
652
+ const currentCompanyIds = Array.isArray(payload.companyIds)
653
+ ? (payload.companyIds as string[]).filter((id) => typeof id === 'string')
654
+ : []
655
+ const nextPersonIds =
656
+ scope.kind === 'person'
657
+ ? currentPersonIds.filter((id) => id !== scope.entityId)
658
+ : currentPersonIds
659
+ const nextCompanyIds =
660
+ scope.kind === 'company'
661
+ ? currentCompanyIds.filter((id) => id !== scope.entityId)
662
+ : currentCompanyIds
663
+ await runWriteMutation(
664
+ () =>
665
+ updateCrud(
666
+ 'customers/deals',
667
+ { id: dealId, personIds: nextPersonIds, companyIds: nextCompanyIds },
668
+ {
669
+ errorMessage: t(
670
+ 'customers.people.detail.deals.unlinkError',
671
+ 'Failed to unlink deal.',
672
+ ),
673
+ },
674
+ ),
675
+ { dealId, scopeKind: scope.kind, scopeEntityId: scope.entityId, operation: 'unlinkDeal' },
676
+ )
677
+ }
678
+ await loadDeals({ append: false })
679
+ await refreshParentData()
680
+ if (addedIds.length + removedIds.length > 0) {
681
+ onCountDelta?.(addedIds.length - removedIds.length)
682
+ }
683
+ flash(
684
+ addedIds.length > 0
685
+ ? t('customers.people.detail.deals.linkSuccess', 'Deal linked.')
686
+ : t('customers.people.detail.deals.unlinkSuccess', 'Deal unlinked.'),
687
+ 'success',
688
+ )
689
+ } catch (error) {
690
+ const message =
691
+ error instanceof Error
692
+ ? error.message
693
+ : t('customers.people.detail.deals.linkError', 'Failed to link deal.')
694
+ flash(message, 'error')
695
+ } finally {
696
+ popLoading()
697
+ }
576
698
  },
577
- [],
699
+ [loadDeals, onCountDelta, popLoading, pushLoading, refreshParentData, runWriteMutation, scope, t],
578
700
  )
579
701
 
580
702
  const closeDialog = React.useCallback(() => {
581
703
  setDialogOpen(false)
582
- setDialogMode('create')
583
- setEditingDealId(null)
584
704
  setInitialValues(undefined)
585
705
  }, [])
586
706
 
@@ -621,7 +741,10 @@ export function DealsSection({
621
741
  createCrud<{ id?: string }>('customers/deals', payload, {
622
742
  errorMessage: translate('customers.people.detail.deals.error', 'Failed to save deal.'),
623
743
  }),
624
- payload,
744
+ {
745
+ ...payload,
746
+ operation: 'createDeal',
747
+ },
625
748
  )
626
749
  const dealId =
627
750
  typeof result?.id === 'string' && result.id.trim().length ? result.id : generateTempId()
@@ -650,6 +773,7 @@ export function DealsSection({
650
773
  updatedAt: timestamp,
651
774
  })
652
775
  setDeals((prev) => [normalized, ...prev])
776
+ onCountDelta?.(1)
653
777
  }
654
778
  await refreshParentData()
655
779
  flash(translate('customers.people.detail.deals.success', 'Deal created.'), 'success')
@@ -658,156 +782,76 @@ export function DealsSection({
658
782
  popLoading()
659
783
  }
660
784
  },
661
- [popLoading, pushLoading, refreshParentData, runWriteMutation, scope, translate],
662
- )
663
-
664
- const handleUpdate = React.useCallback(
665
- async (dealId: string, { base, custom }: DealFormSubmitPayload) => {
666
- if (!scope) {
667
- throw new Error(translate('customers.people.detail.deals.error', 'Failed to save deal.'))
668
- }
669
- setPendingAction({ kind: 'update', id: dealId })
670
- pushLoading()
671
- try {
672
- const personIds = mergeIds(base.personIds)
673
- const companyIds = mergeIds(base.companyIds)
674
-
675
- const payload: Record<string, unknown> = {
676
- id: dealId,
677
- title: base.title,
678
- status: base.status ?? undefined,
679
- pipelineStage: base.pipelineStage ?? undefined,
680
- valueAmount: typeof base.valueAmount === 'number' ? base.valueAmount : undefined,
681
- valueCurrency: base.valueCurrency ?? undefined,
682
- probability: typeof base.probability === 'number' ? base.probability : undefined,
683
- expectedCloseAt: base.expectedCloseAt ?? undefined,
684
- description: base.description ?? undefined,
685
- personIds,
686
- companyIds,
687
- }
688
- if (Object.keys(custom).length) payload.customFields = custom
689
- await runWriteMutation(
690
- () =>
691
- updateCrud('customers/deals', payload, {
692
- errorMessage: translate('customers.people.detail.deals.error', 'Failed to save deal.'),
693
- }),
694
- payload,
695
- )
696
- const hasCustomChanges = Object.keys(custom).length > 0
697
- const customValuesForState = hasCustomChanges ? sanitizeCustomValues(custom) : null
698
- const remainsInScope =
699
- (scope.kind !== 'person' || personIds.includes(scope.entityId)) &&
700
- (scope.kind !== 'company' || companyIds.includes(scope.entityId))
701
- if (!remainsInScope) {
702
- setDeals((prev) => prev.filter((deal) => deal.id !== dealId))
703
- } else {
704
- setDeals((prev) =>
705
- prev.map((deal) =>
706
- deal.id === dealId
707
- ? normalizeDeal({
708
- ...deal,
709
- title: base.title,
710
- status: base.status ?? null,
711
- pipelineStage: base.pipelineStage ?? null,
712
- valueAmount: base.valueAmount ?? null,
713
- valueCurrency: base.valueCurrency ?? null,
714
- probability: base.probability ?? null,
715
- expectedCloseAt: base.expectedCloseAt ?? null,
716
- description: base.description ?? null,
717
- personIds,
718
- people: personIds.map((id) => deal.people?.find((entry) => entry.id === id) ?? { id, label: '' }),
719
- companyIds,
720
- companies: companyIds.map((id) => deal.companies?.find((entry) => entry.id === id) ?? { id, label: '' }),
721
- customValues: hasCustomChanges ? customValuesForState : deal.customValues,
722
- customFields: hasCustomChanges
723
- ? customValuesForState
724
- ? deal.customFields
725
- : []
726
- : deal.customFields,
727
- updatedAt: new Date().toISOString(),
728
- })
729
- : deal,
730
- ),
731
- )
732
- }
733
- await refreshParentData()
734
- flash(translate('customers.people.detail.deals.updateSuccess', 'Deal updated.'), 'success')
735
- } finally {
736
- setPendingAction(null)
737
- popLoading()
738
- }
739
- },
740
- [popLoading, pushLoading, refreshParentData, runWriteMutation, scope, translate],
785
+ [onCountDelta, popLoading, pushLoading, refreshParentData, runWriteMutation, scope, translate],
741
786
  )
742
787
 
743
- const handleRemove = React.useCallback(
788
+ const handleUnlink = React.useCallback(
744
789
  async (deal: NormalizedDeal) => {
745
790
  if (!scope) return
791
+
792
+ const nextPersonIds =
793
+ scope.kind === 'person'
794
+ ? deal.personIds.filter((id) => id !== scope.entityId)
795
+ : deal.personIds
796
+ const nextCompanyIds =
797
+ scope.kind === 'company'
798
+ ? deal.companyIds.filter((id) => id !== scope.entityId)
799
+ : deal.companyIds
800
+
746
801
  const confirmed = await confirm({
747
- title: translate(
748
- 'customers.people.detail.deals.removeConfirm',
749
- 'Remove this deal from this record? The deal itself will not be deleted.',
802
+ title:
803
+ scope.kind === 'person'
804
+ ? translate('customers.people.detail.deals.unlinkConfirmPerson', 'Unlink this deal from this person?')
805
+ : translate('customers.people.detail.deals.unlinkConfirmCompany', 'Unlink this deal from this company?'),
806
+ description: translate(
807
+ 'customers.people.detail.deals.unlinkDescription',
808
+ 'The deal will remain available from its own detail page.',
750
809
  ),
751
- variant: 'destructive',
810
+ confirmText: translate('customers.people.card.unlink', 'Unlink'),
811
+ cancelText: translate('customers.people.detail.deals.cancel', 'Cancel'),
752
812
  })
753
813
  if (!confirmed) return
754
- const mutationPayload =
755
- scope.kind === 'person'
756
- ? {
757
- id: deal.id,
758
- personIds: (deal.personIds ?? []).filter((personId) => personId !== scope.entityId),
759
- }
760
- : {
761
- id: deal.id,
762
- companyIds: (deal.companyIds ?? []).filter((companyId) => companyId !== scope.entityId),
763
- }
814
+
764
815
  setPendingAction({ kind: 'remove', id: deal.id })
765
816
  pushLoading()
766
817
  try {
818
+ const payload: Record<string, unknown> = {
819
+ id: deal.id,
820
+ personIds: nextPersonIds,
821
+ companyIds: nextCompanyIds,
822
+ }
767
823
  await runWriteMutation(
768
824
  () =>
769
- updateCrud('customers/deals', mutationPayload, {
770
- errorMessage: translate(
771
- 'customers.people.detail.deals.removeError',
772
- 'Failed to remove deal from this record.',
773
- ),
825
+ updateCrud('customers/deals', payload, {
826
+ errorMessage: translate('customers.people.detail.deals.unlinkError', 'Failed to unlink deal.'),
774
827
  }),
775
- mutationPayload,
828
+ {
829
+ ...payload,
830
+ operation: 'unlinkDeal',
831
+ },
776
832
  )
777
833
  setDeals((prev) => prev.filter((item) => item.id !== deal.id))
834
+ onCountDelta?.(-1)
778
835
  await refreshParentData()
779
- flash(
780
- translate(
781
- 'customers.people.detail.deals.removeSuccess',
782
- 'Deal removed from this record.',
783
- ),
784
- 'success',
785
- )
786
- } catch (err) {
836
+ flash(translate('customers.people.detail.deals.unlinkSuccess', 'Deal unlinked.'), 'success')
837
+ } catch (error) {
787
838
  const message =
788
- err instanceof Error
789
- ? err.message
790
- : translate(
791
- 'customers.people.detail.deals.removeError',
792
- 'Failed to remove deal from this record.',
793
- )
839
+ error instanceof Error
840
+ ? error.message
841
+ : translate('customers.people.detail.deals.unlinkError', 'Failed to unlink deal.')
794
842
  flash(message, 'error')
795
843
  } finally {
796
844
  setPendingAction(null)
797
845
  popLoading()
798
846
  }
799
847
  },
800
- [confirm, popLoading, pushLoading, refreshParentData, runWriteMutation, scope, translate],
848
+ [confirm, onCountDelta, popLoading, pushLoading, refreshParentData, runWriteMutation, scope, translate],
801
849
  )
802
850
 
803
851
  const handleDialogSubmit = React.useCallback(
804
852
  async (payload: DealFormSubmitPayload) => {
805
853
  try {
806
- if (dialogMode === 'edit' && editingDealId) {
807
- await handleUpdate(editingDealId, payload)
808
- } else {
809
- await handleCreate(payload)
810
- }
854
+ await handleCreate(payload)
811
855
  closeDialog()
812
856
  } catch (err) {
813
857
  const message =
@@ -817,7 +861,7 @@ export function DealsSection({
817
861
  flash(message, 'error')
818
862
  }
819
863
  },
820
- [closeDialog, dialogMode, editingDealId, handleCreate, handleUpdate, translate],
864
+ [closeDialog, handleCreate, translate],
821
865
  )
822
866
 
823
867
  React.useEffect(() => {
@@ -836,9 +880,7 @@ export function DealsSection({
836
880
  }
837
881
  }, [addActionLabel, isLoading, onActionChange, openCreateDialog, pendingAction, scope])
838
882
 
839
- const isFormPending =
840
- pendingAction?.kind === 'create' ||
841
- (pendingAction?.kind === 'update' && pendingAction.id === editingDealId)
883
+ const isFormPending = pendingAction?.kind === 'create'
842
884
 
843
885
  const sortedDeals = React.useMemo(() => {
844
886
  return [...deals].sort((a, b) => {
@@ -855,6 +897,28 @@ export function DealsSection({
855
897
  {loadError}
856
898
  </div>
857
899
  ) : null}
900
+ <div className="flex flex-wrap items-center justify-end gap-2">
901
+ <Button
902
+ type="button"
903
+ variant="outline"
904
+ size="sm"
905
+ onClick={openLinkDialog}
906
+ disabled={!scope || pendingAction !== null}
907
+ >
908
+ <Link2 className="mr-1.5 size-3.5" />
909
+ {t('customers.people.detail.deals.linkExisting', 'Link existing deal')}
910
+ </Button>
911
+ <Button
912
+ type="button"
913
+ variant="default"
914
+ size="sm"
915
+ onClick={openCreateDialog}
916
+ disabled={!scope || pendingAction !== null}
917
+ >
918
+ <Plus className="mr-1.5 size-3.5" />
919
+ {addActionLabel}
920
+ </Button>
921
+ </div>
858
922
  {isLoading && sortedDeals.length === 0 ? (
859
923
  <LoadingMessage
860
924
  label={t('customers.people.detail.deals.loading', 'Loading deals…')}
@@ -878,8 +942,7 @@ export function DealsSection({
878
942
  const expectedLabel = deal.expectedCloseAt ? formatDate(deal.expectedCloseAt) ?? emptyLabel : emptyLabel
879
943
  const probabilityLabel =
880
944
  typeof deal.probability === 'number' ? `${deal.probability}%` : emptyLabel
881
- const isUpdatePending = pendingAction?.kind === 'update' && pendingAction.id === deal.id
882
- const isRemovePending = pendingAction?.kind === 'remove' && pendingAction.id === deal.id
945
+ const isUnlinkPending = pendingAction?.kind === 'remove' && pendingAction.id === deal.id
883
946
  const statusLabel =
884
947
  deal.status && statusDictionaryMap
885
948
  ? statusDictionaryMap[deal.status]?.label ?? deal.status
@@ -888,7 +951,12 @@ export function DealsSection({
888
951
  <article key={deal.id} className="group rounded-lg border bg-card p-4 shadow-xs transition hover:border-border/80">
889
952
  <header className="flex flex-wrap items-center justify-between gap-2">
890
953
  <div>
891
- <h3 className="text-base font-semibold">{deal.title || emptyLabel}</h3>
954
+ <Link
955
+ href={`/backend/customers/deals/${encodeURIComponent(deal.id)}`}
956
+ className="text-base font-semibold text-foreground transition hover:text-primary hover:underline"
957
+ >
958
+ {deal.title || emptyLabel}
959
+ </Link>
892
960
  {deal.description ? (
893
961
  <p className="mt-1 text-sm text-muted-foreground whitespace-pre-wrap">{deal.description}</p>
894
962
  ) : null}
@@ -898,39 +966,28 @@ export function DealsSection({
898
966
  {statusLabel}
899
967
  </span>
900
968
  <div className="flex items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100 focus-within:opacity-100">
969
+ <IconButton asChild variant="ghost" size="sm" className="h-8 w-8">
970
+ <Link
971
+ href={`/backend/customers/deals/${encodeURIComponent(deal.id)}`}
972
+ aria-label={t('customers.people.detail.deals.edit', 'Open deal details')}
973
+ >
974
+ <Pencil className="size-4" />
975
+ </Link>
976
+ </IconButton>
901
977
  <Button
902
978
  type="button"
903
- variant="ghost"
904
- size="icon"
979
+ variant="outline"
980
+ size="sm"
981
+ className="h-8 rounded-lg px-3 text-xs"
905
982
  onClick={(event) => {
906
983
  event.preventDefault()
907
- openEditDialog(deal)
984
+ void handleUnlink(deal)
908
985
  }}
909
986
  disabled={pendingAction !== null}
910
987
  >
911
- {isUpdatePending ? (
912
- <Loader2 className="h-4 w-4 animate-spin" />
913
- ) : (
914
- <Pencil className="h-4 w-4" />
915
- )}
916
- </Button>
917
- <Button
918
- type="button"
919
- variant="ghost"
920
- size="icon"
921
- onClick={(event) => {
922
- event.preventDefault()
923
- handleRemove(deal)
924
- }}
925
- disabled={pendingAction !== null}
926
- >
927
- {isRemovePending ? (
928
- <span className="relative flex h-4 w-4 items-center justify-center text-destructive">
929
- <span className="absolute h-4 w-4 animate-spin rounded-full border border-destructive border-t-transparent" />
930
- </span>
931
- ) : (
932
- <Trash2 className="h-4 w-4" />
933
- )}
988
+ {isUnlinkPending
989
+ ? t('customers.people.detail.deals.unlinking', 'Unlinking…')
990
+ : t('customers.people.card.unlink', 'Unlink')}
934
991
  </Button>
935
992
  </div>
936
993
  </div>
@@ -973,15 +1030,6 @@ export function DealsSection({
973
1030
  itemKeyPrefix={`deal-${deal.id}-field`}
974
1031
  className="mt-3"
975
1032
  />
976
- <div className="mt-3 text-xs">
977
- <Link
978
- href={`/backend/customers/deals/${encodeURIComponent(deal.id)}`}
979
- className="inline-flex items-center gap-1 text-primary hover:underline"
980
- >
981
- <ArrowUpRightSquare className="h-3.5 w-3.5" aria-hidden />
982
- {t('customers.people.detail.deals.openDeal', 'Open deal')}
983
- </Link>
984
- </div>
985
1033
  </article>
986
1034
  )
987
1035
  })}
@@ -1013,7 +1061,7 @@ export function DealsSection({
1013
1061
 
1014
1062
  <DealDialog
1015
1063
  open={dialogOpen}
1016
- mode={dialogMode}
1064
+ mode="create"
1017
1065
  onOpenChange={handleDialogOpenChange}
1018
1066
  initialValues={initialValues}
1019
1067
  onSubmit={async (payload) => {
@@ -1021,6 +1069,13 @@ export function DealsSection({
1021
1069
  }}
1022
1070
  isSubmitting={Boolean(isFormPending)}
1023
1071
  />
1072
+ <LinkEntityDialog
1073
+ open={linkDialogOpen}
1074
+ onOpenChange={setLinkDialogOpen}
1075
+ adapter={dealLinkAdapter}
1076
+ initialSelectedIds={existingDealIds}
1077
+ onConfirm={handleLinkConfirm}
1078
+ />
1024
1079
  {ConfirmDialogElement}
1025
1080
  </div>
1026
1081
  )