@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
@@ -12,6 +12,8 @@ import {
12
12
  CustomerActivity,
13
13
  CustomerTagAssignment,
14
14
  CustomerTag,
15
+ CustomerLabelAssignment,
16
+ CustomerLabel,
15
17
  CustomerDealPersonLink,
16
18
  CustomerDeal,
17
19
  CustomerTodoLink,
@@ -33,8 +35,9 @@ import { hydrateCanonicalInteractions } from '../../../lib/interactionReadModel'
33
35
  import type { QueryEngine } from '@open-mercato/shared/lib/query/types'
34
36
  import type { EntityId } from '@open-mercato/shared/modules/entities'
35
37
  import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
36
- import { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'
38
+ import { findWithDecryption, findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
37
39
  import { parseBooleanFromUnknown, parseBooleanToken } from '@open-mercato/shared/lib/boolean'
40
+ import { loadPersonCompanyLinks, summarizePersonCompanies } from '../../../lib/personCompanies'
38
41
 
39
42
  export const metadata = {
40
43
  GET: { requireAuth: true, requireFeatures: ['customers.people.view'] },
@@ -396,6 +399,7 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
396
399
  const includeDeals = includeTokens.has('deals')
397
400
  const includeInteractions = includeTokens.has('interactions')
398
401
  const includeTodos = includeTokens.has('todos') || includeTokens.has('tasks')
402
+ const plannedPreviewLimit = 5
399
403
 
400
404
  let statusCode = 500
401
405
  let profileMeta: Record<string, unknown> | undefined
@@ -410,6 +414,7 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
410
414
  let customFields: Record<string, unknown> = {}
411
415
  let viewerUserId: string | null = null
412
416
  let profile: CustomerPersonProfile | null = null
417
+ let companies: Array<{ linkId: string | null; companyId: string; displayName: string; isPrimary: boolean; synthetic?: boolean }> = []
413
418
 
414
419
  try {
415
420
  const parse = paramsSchema.safeParse({ id: ctx.params?.id })
@@ -446,7 +451,7 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
446
451
  })
447
452
  const em = (container.resolve('em') as EntityManager)
448
453
 
449
- const person = await em.findOne(CustomerEntity, { id: parse.data.id, kind: 'person', deletedAt: null })
454
+ const person = await findOneWithDecryption(em, CustomerEntity, { id: parse.data.id, kind: 'person', deletedAt: null }, {}, { tenantId: auth.tenantId ?? null, organizationId: auth.orgId ?? null })
450
455
  profiler.mark('person_loaded', { found: !!person })
451
456
  if (!person) {
452
457
  statusCode = 404
@@ -469,11 +474,12 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
469
474
  return forbidden('Access denied')
470
475
  }
471
476
 
472
- profile = await em.findOne(CustomerPersonProfile, { entity: person }, { populate: ['company'] })
477
+ profile = await findOneWithDecryption(em, CustomerPersonProfile, { entity: person }, { populate: ['company'] }, { tenantId: person.tenantId ?? auth.tenantId ?? null, organizationId: person.organizationId ?? auth.orgId ?? null })
473
478
  profiler.mark('profile_loaded', { found: !!profile })
479
+ companies = summarizePersonCompanies(profile, await loadPersonCompanyLinks(em, person))
474
480
 
475
481
  if (includeAddresses) {
476
- addresses = await em.find(CustomerAddress, { entity: person.id }, { orderBy: { isPrimary: 'desc', createdAt: 'desc' } })
482
+ addresses = await findWithDecryption(em, CustomerAddress, { entity: person.id }, { orderBy: { isPrimary: 'desc', createdAt: 'desc' } }, { tenantId: person.tenantId ?? auth.tenantId ?? null, organizationId: person.organizationId ?? auth.orgId ?? null })
477
483
  profiler.mark('addresses_loaded', { count: addresses.length })
478
484
  }
479
485
 
@@ -486,19 +492,30 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
486
492
  )
487
493
  profiler.mark('tags_loaded', { count: tagAssignments.length })
488
494
 
495
+ const labelAssignments = await findWithDecryption(
496
+ em,
497
+ CustomerLabelAssignment,
498
+ { entity: person.id },
499
+ { populate: ['label'] },
500
+ { tenantId: person.tenantId ?? auth.tenantId ?? null, organizationId: person.organizationId ?? auth.orgId ?? null },
501
+ )
502
+ profiler.mark('labels_loaded', { count: labelAssignments.length })
503
+
489
504
  if (includeComments) {
490
- comments = await em.find(CustomerComment, { entity: person.id }, { orderBy: { createdAt: 'desc' }, limit: 50 })
505
+ comments = await findWithDecryption(em, CustomerComment, { entity: person.id }, { orderBy: { createdAt: 'desc' }, limit: 50 }, { tenantId: person.tenantId ?? auth.tenantId ?? null, organizationId: person.organizationId ?? auth.orgId ?? null })
491
506
  profiler.mark('comments_loaded', { count: comments.length })
492
507
  }
493
508
 
494
509
  const shouldLoadCanonicalInteractions = includeInteractions || includeActivities || includeTodos
495
510
  const canonicalInteractionRows = shouldLoadCanonicalInteractions
496
- ? await em.find(
511
+ ? await findWithDecryption(
512
+ em,
497
513
  CustomerInteraction,
498
514
  interactionFlags.unified
499
515
  ? { entity: person.id, deletedAt: null }
500
516
  : { entity: person.id },
501
517
  { orderBy: { scheduledAt: 'asc', createdAt: 'desc' }, limit: 100 },
518
+ { tenantId: person.tenantId ?? auth.tenantId ?? null, organizationId: person.organizationId ?? auth.orgId ?? null },
502
519
  )
503
520
  : []
504
521
  profiler.mark('canonical_interactions_loaded', { count: canonicalInteractionRows.length })
@@ -515,8 +532,42 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
515
532
  : []
516
533
  profiler.mark('canonical_interactions_hydrated', { count: canonicalInteractions.length })
517
534
 
535
+ const plannedPreviewInteractions = shouldLoadCanonicalInteractions
536
+ ? (() => {
537
+ const sorted = [...canonicalInteractions]
538
+ .filter((interaction) => interaction.status === 'planned' && interaction.interactionType !== 'task')
539
+ .sort((left, right) => {
540
+ const leftTime = new Date(left.scheduledAt ?? left.createdAt).getTime()
541
+ const rightTime = new Date(right.scheduledAt ?? right.createdAt).getTime()
542
+ if (leftTime === rightTime) return left.id.localeCompare(right.id)
543
+ return leftTime - rightTime
544
+ })
545
+ return sorted.slice(0, plannedPreviewLimit)
546
+ })()
547
+ : await hydrateCanonicalInteractions({
548
+ em,
549
+ container,
550
+ auth,
551
+ selectedOrganizationId: scope?.selectedId ?? auth.orgId ?? null,
552
+ interactions: await findWithDecryption(
553
+ em,
554
+ CustomerInteraction,
555
+ {
556
+ entity: person.id,
557
+ organizationId: person.organizationId,
558
+ tenantId: person.tenantId,
559
+ deletedAt: null,
560
+ status: 'planned',
561
+ interactionType: { $ne: 'task' },
562
+ },
563
+ { orderBy: { scheduledAt: 'ASC', createdAt: 'ASC' }, limit: plannedPreviewLimit },
564
+ { tenantId: person.tenantId ?? auth.tenantId ?? null, organizationId: person.organizationId ?? auth.orgId ?? null },
565
+ ),
566
+ enrich: true,
567
+ })
568
+
518
569
  if (includeActivities && !interactionFlags.unified) {
519
- activities = await em.find(CustomerActivity, { entity: person.id }, { orderBy: { occurredAt: 'desc', createdAt: 'desc' }, limit: 50 })
570
+ activities = await findWithDecryption(em, CustomerActivity, { entity: person.id }, { orderBy: { occurredAt: 'desc', createdAt: 'desc' }, limit: 50 }, { tenantId: person.tenantId ?? auth.tenantId ?? null, organizationId: person.organizationId ?? auth.orgId ?? null })
520
571
  profiler.mark('activities_loaded', { count: activities.length })
521
572
  }
522
573
 
@@ -525,7 +576,7 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
525
576
  }
526
577
 
527
578
  if (includeTodos && !interactionFlags.unified) {
528
- todoLinks = await em.find(CustomerTodoLink, { entity: person.id }, { orderBy: { createdAt: 'desc' }, limit: 50 })
579
+ todoLinks = await findWithDecryption(em, CustomerTodoLink, { entity: person.id }, { orderBy: { createdAt: 'desc' }, limit: 50 }, { tenantId: person.tenantId ?? auth.tenantId ?? null, organizationId: person.organizationId ?? auth.orgId ?? null })
529
580
  profiler.mark('todo_links_loaded', { count: todoLinks.length })
530
581
  if (todoLinks.length) {
531
582
  const queryEngine = (container.resolve('queryEngine') as QueryEngine)
@@ -575,7 +626,7 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
575
626
  if (viewerUserId) authorIds.add(viewerUserId)
576
627
 
577
628
  if (authorIds.size) {
578
- const users = await em.find(User, { id: { $in: Array.from(authorIds) } })
629
+ const users = await findWithDecryption(em, User, { id: { $in: Array.from(authorIds) } }, {}, { tenantId: person.tenantId ?? auth.tenantId ?? null, organizationId: person.organizationId ?? auth.orgId ?? null })
579
630
  userMap = new Map(
580
631
  users.map((user) => [
581
632
  user.id,
@@ -640,6 +691,56 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
640
691
  profiler.mark('custom_fields_merged', { keys: Object.keys(customFields).length })
641
692
 
642
693
  const viewerUserIdFinal = viewerUserId
694
+ const counts = {
695
+ tags: tagAssignments.length + labelAssignments.length,
696
+ comments: includeComments
697
+ ? comments.length
698
+ : await em.count(CustomerComment, {
699
+ entity: person.id,
700
+ organizationId: person.organizationId,
701
+ tenantId: person.tenantId,
702
+ }),
703
+ activities: await em.count(CustomerInteraction, {
704
+ entity: person.id,
705
+ organizationId: person.organizationId,
706
+ tenantId: person.tenantId,
707
+ deletedAt: null,
708
+ interactionType: { $ne: 'task' },
709
+ }),
710
+ interactions: await em.count(CustomerInteraction, {
711
+ entity: person.id,
712
+ organizationId: person.organizationId,
713
+ tenantId: person.tenantId,
714
+ deletedAt: null,
715
+ }),
716
+ todos: interactionFlags.unified
717
+ ? await em.count(CustomerInteraction, {
718
+ entity: person.id,
719
+ organizationId: person.organizationId,
720
+ tenantId: person.tenantId,
721
+ deletedAt: null,
722
+ interactionType: 'task',
723
+ })
724
+ : await em.count(CustomerTodoLink, {
725
+ entity: person.id,
726
+ organizationId: person.organizationId,
727
+ tenantId: person.tenantId,
728
+ }),
729
+ addresses: includeAddresses
730
+ ? addresses.length
731
+ : await em.count(CustomerAddress, {
732
+ entity: person.id,
733
+ organizationId: person.organizationId,
734
+ tenantId: person.tenantId,
735
+ }),
736
+ deals: includeDeals
737
+ ? deals.length
738
+ : await em.count(CustomerDealPersonLink, {
739
+ person: person.id,
740
+ }),
741
+ companies: companies.length,
742
+ }
743
+
643
744
  const response = NextResponse.json({
644
745
  interactionMode,
645
746
  person: {
@@ -652,6 +753,8 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
652
753
  status: person.status,
653
754
  lifecycleStage: person.lifecycleStage,
654
755
  source: person.source,
756
+ temperature: person.temperature,
757
+ renewalQuarter: person.renewalQuarter,
655
758
  nextInteractionAt: person.nextInteractionAt ? person.nextInteractionAt.toISOString() : null,
656
759
  nextInteractionName: person.nextInteractionName,
657
760
  nextInteractionRefId: person.nextInteractionRefId,
@@ -680,7 +783,16 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
680
783
  }
681
784
  : null,
682
785
  customFields,
683
- tags: serializeTags(tagAssignments),
786
+ tags: [
787
+ ...serializeTags(tagAssignments),
788
+ ...labelAssignments
789
+ .map((a) => {
790
+ const label = a.label as CustomerLabel | string | null
791
+ if (!label || typeof label === 'string') return null
792
+ return { id: label.id, label: label.label, color: null }
793
+ })
794
+ .filter((t): t is { id: string; label: string; color: null } => t !== null),
795
+ ],
684
796
  addresses: includeAddresses
685
797
  ? addresses.map((address) => ({
686
798
  id: address.id,
@@ -762,12 +874,17 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
762
874
  title: deal.title,
763
875
  status: deal.status,
764
876
  pipelineStage: deal.pipelineStage,
877
+ pipelineId: deal.pipelineId ?? null,
878
+ pipelineStageId: deal.pipelineStageId ?? null,
765
879
  valueAmount: deal.valueAmount,
766
880
  valueCurrency: deal.valueCurrency,
767
881
  probability: deal.probability,
768
882
  expectedCloseAt: deal.expectedCloseAt ? deal.expectedCloseAt.toISOString() : null,
769
883
  ownerUserId: deal.ownerUserId,
770
884
  source: deal.source,
885
+ closureOutcome: deal.closureOutcome ?? null,
886
+ lossReasonId: deal.lossReasonId ?? null,
887
+ lossNotes: deal.lossNotes ?? null,
771
888
  createdAt: deal.createdAt.toISOString(),
772
889
  updatedAt: deal.updatedAt.toISOString(),
773
890
  }))
@@ -815,9 +932,20 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
815
932
  }).slice(0, 50)
816
933
  )
817
934
  : [],
818
- company: profile?.company && typeof profile.company !== 'string'
819
- ? { id: profile.company.id, displayName: profile.company.displayName }
820
- : null,
935
+ isPrimary: companies.some((entry) => entry.isPrimary),
936
+ companies: companies.map((entry) => ({
937
+ id: entry.companyId,
938
+ displayName: entry.displayName,
939
+ isPrimary: entry.isPrimary,
940
+ })),
941
+ company: (() => {
942
+ const primaryCompany = companies.find((entry) => entry.isPrimary) ?? companies[0] ?? null
943
+ return primaryCompany
944
+ ? { id: primaryCompany.companyId, displayName: primaryCompany.displayName }
945
+ : null
946
+ })(),
947
+ plannedActivitiesPreview: plannedPreviewInteractions,
948
+ counts,
821
949
  viewer: {
822
950
  userId: viewerUserIdFinal,
823
951
  name: viewerUserIdFinal ? userMap.get(viewerUserIdFinal)?.name ?? null : null,
@@ -828,19 +956,7 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
828
956
  profileMeta = {
829
957
  include: Array.from(includeTokens),
830
958
  interactionMode,
831
- counts: {
832
- tags: tagAssignments.length,
833
- comments: comments.length,
834
- activities: includeActivities
835
- ? (interactionFlags.unified ? canonicalActivityItems.length : activities.length + canonicalActivityItems.length)
836
- : 0,
837
- interactions: canonicalInteractions.length,
838
- todos: includeTodos
839
- ? (interactionFlags.unified ? canonicalTodoItems.length : todoLinks.length + canonicalTodoItems.length)
840
- : 0,
841
- addresses: addresses.length,
842
- deals: deals.length,
843
- },
959
+ counts,
844
960
  }
845
961
  profiler.mark('response_ready', { status: statusCode })
846
962
  return response
@@ -995,6 +1111,9 @@ const personDetailResponseSchema = z.object({
995
1111
  expectedCloseAt: z.string().nullable().optional(),
996
1112
  ownerUserId: z.string().uuid().nullable().optional(),
997
1113
  source: z.string().nullable().optional(),
1114
+ closureOutcome: z.string().nullable().optional(),
1115
+ lossReasonId: z.string().uuid().nullable().optional(),
1116
+ lossNotes: z.string().nullable().optional(),
998
1117
  createdAt: z.string(),
999
1118
  updatedAt: z.string(),
1000
1119
  }),
@@ -1016,6 +1135,14 @@ const personDetailResponseSchema = z.object({
1016
1135
  customValues: z.record(z.string(), z.unknown()).nullable().optional(),
1017
1136
  }),
1018
1137
  ),
1138
+ isPrimary: z.boolean(),
1139
+ companies: z.array(
1140
+ z.object({
1141
+ id: z.string().uuid(),
1142
+ displayName: z.string(),
1143
+ isPrimary: z.boolean(),
1144
+ }),
1145
+ ),
1019
1146
  viewer: z.object({
1020
1147
  userId: z.string().uuid().nullable(),
1021
1148
  name: z.string().nullable(),
@@ -1,12 +1,18 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
1
+ import type { EntityManager, FilterQuery } from '@mikro-orm/postgresql'
2
2
  import { z } from 'zod'
3
3
  import { makeCrudRoute } from '@open-mercato/shared/lib/crud/factory'
4
4
  import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
5
- import { CustomerEntity, CustomerPersonProfile } from '../../data/entities'
5
+ import {
6
+ CustomerDealPersonLink,
7
+ CustomerEntity,
8
+ CustomerPersonCompanyLink,
9
+ CustomerPersonProfile,
10
+ } from '../../data/entities'
6
11
  import { E } from '#generated/entities.ids.generated'
7
12
  import { personCreateSchema, personUpdateSchema } from '../../data/validators'
8
13
  import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
9
14
  import {
15
+ applyEntityIdExclusion,
10
16
  applyEntityIdRestriction,
11
17
  consumeAdvancedFilterState,
12
18
  findMatchingEntityIdsWithQueryEngine,
@@ -23,6 +29,7 @@ import {
23
29
  createPagedListResponseSchema,
24
30
  defaultOkResponseSchema,
25
31
  } from '../openapi'
32
+ import { withActiveCustomerPersonCompanyLinkFilter } from '../../lib/personCompanyLinkTable'
26
33
  import { normalizeProfilePayload } from './payload'
27
34
 
28
35
  const rawBodySchema = z.object({}).passthrough()
@@ -48,6 +55,9 @@ const listSchema = z
48
55
  id: z.string().uuid().optional(),
49
56
  tagIds: z.string().optional(),
50
57
  tagIdsEmpty: z.string().optional(),
58
+ excludeIds: z.string().optional(),
59
+ excludeLinkedCompanyId: z.string().uuid().optional(),
60
+ excludeLinkedDealId: z.string().uuid().optional(),
51
61
  })
52
62
  .passthrough()
53
63
 
@@ -98,10 +108,10 @@ const crud = makeCrudRoute({
98
108
  createdAt: 'created_at',
99
109
  updatedAt: 'updated_at',
100
110
  },
101
- buildFilters: async (query: any, ctx) => {
111
+ buildFilters: async (query, ctx) => {
102
112
  const advancedQuery = { ...query }
103
113
  const advancedFilterState = consumeAdvancedFilterState(query)
104
- const filters: Record<string, any> = { kind: { $eq: 'person' } }
114
+ const filters: Record<string, unknown> = { kind: { $eq: 'person' } }
105
115
  if (query.id) filters.id = { $eq: query.id }
106
116
  if (query.search) {
107
117
  const matchingIds = ctx
@@ -192,6 +202,65 @@ const crud = makeCrudRoute({
192
202
  } else if (tagIds.length > 0) {
193
203
  filters['tag_assignments.tag_id'] = { $in: tagIds }
194
204
  }
205
+ const excludedIds = new Set<string>()
206
+ const excludeIdsRaw = typeof query.excludeIds === 'string' ? query.excludeIds : ''
207
+ excludeIdsRaw
208
+ .split(',')
209
+ .map((value: string) => value.trim())
210
+ .filter((value: string) => value.length > 0)
211
+ .forEach((value: string) => excludedIds.add(value))
212
+ if (ctx && query.excludeLinkedCompanyId) {
213
+ try {
214
+ const em = ctx.container.resolve('em') as EntityManager
215
+ const decryptionScope = {
216
+ tenantId: ctx.auth?.tenantId ?? null,
217
+ organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,
218
+ }
219
+ const linkWhere = await withActiveCustomerPersonCompanyLinkFilter(
220
+ em,
221
+ { company: query.excludeLinkedCompanyId },
222
+ 'customers.people.GET',
223
+ )
224
+ const links = await findWithDecryption(
225
+ em,
226
+ CustomerPersonCompanyLink,
227
+ linkWhere,
228
+ { populate: ['person'] },
229
+ decryptionScope,
230
+ )
231
+ links.forEach((link) => {
232
+ const personId = link.person?.id
233
+ if (typeof personId === 'string' && personId.length > 0) excludedIds.add(personId)
234
+ })
235
+ } catch (err) {
236
+ console.warn('[customers.people.list] exclusion lookup failed; falling back to base result set', err)
237
+ }
238
+ }
239
+ if (ctx && query.excludeLinkedDealId) {
240
+ try {
241
+ const em = ctx.container.resolve('em') as EntityManager
242
+ const decryptionScope = {
243
+ tenantId: ctx.auth?.tenantId ?? null,
244
+ organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,
245
+ }
246
+ const links = await findWithDecryption(
247
+ em,
248
+ CustomerDealPersonLink,
249
+ {
250
+ deal: query.excludeLinkedDealId,
251
+ },
252
+ { populate: ['person'] },
253
+ decryptionScope,
254
+ )
255
+ links.forEach((link) => {
256
+ const personId = link.person?.id
257
+ if (typeof personId === 'string' && personId.length > 0) excludedIds.add(personId)
258
+ })
259
+ } catch (err) {
260
+ console.warn('[customers.people.list] exclusion lookup failed; falling back to base result set', err)
261
+ }
262
+ }
263
+ applyEntityIdExclusion(filters, Array.from(excludedIds))
195
264
  const hasEmail = parseBooleanToken(query.hasEmail)
196
265
  if (!email && !emailStartsWith && !emailContains && hasEmail !== null) {
197
266
  filters.primary_email = { $exists: hasEmail }
@@ -218,7 +287,7 @@ const crud = makeCrudRoute({
218
287
  }
219
288
  if (ctx) {
220
289
  try {
221
- const em = ctx.container.resolve('em') as any
290
+ const em = ctx.container.resolve('em') as EntityManager
222
291
  const cfFilters = await buildCustomFieldFiltersFromQuery({
223
292
  entityIds: [E.customers.customer_entity, E.customers.customer_person_profile],
224
293
  query,
@@ -226,8 +295,8 @@ const crud = makeCrudRoute({
226
295
  tenantId: ctx.auth?.tenantId ?? null,
227
296
  })
228
297
  Object.assign(filters, cfFilters)
229
- } catch {
230
- // ignore custom field filter errors; fall back to base filters
298
+ } catch (err) {
299
+ console.warn('[customers.people.list] custom field filter resolution failed; falling back to base filters', err)
231
300
  }
232
301
  }
233
302
  if (ctx && advancedFilterState) {
@@ -280,11 +349,12 @@ const crud = makeCrudRoute({
280
349
  type: 'left',
281
350
  },
282
351
  ],
283
- transformItem: (item: any) => {
284
- if (!item) return item
285
- const normalized = { ...item }
352
+ transformItem: (item) => {
353
+ if (!item || typeof item !== 'object') return item
354
+ const record = item as Record<string, unknown>
355
+ const normalized: Record<string, unknown> = { ...record }
286
356
  delete normalized.kind
287
- const cfEntries = extractAllCustomFieldEntries(item)
357
+ const cfEntries = extractAllCustomFieldEntries(record)
288
358
  for (const key of Object.keys(normalized)) {
289
359
  if (key.startsWith('cf:')) {
290
360
  delete normalized[key]
@@ -351,6 +421,27 @@ const crud = makeCrudRoute({
351
421
  .filter((id: string | null): id is string => typeof id === 'string' && id.length > 0)
352
422
  if (!ids.length) return
353
423
 
424
+ const em = ctx.container.resolve('em') as EntityManager
425
+ const decryptionScope = {
426
+ tenantId: ctx.auth?.tenantId ?? null,
427
+ organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,
428
+ }
429
+ const entities = await findWithDecryption(
430
+ em,
431
+ CustomerEntity,
432
+ {
433
+ id: { $in: ids },
434
+ deletedAt: null,
435
+ kind: 'person',
436
+ } as FilterQuery<CustomerEntity>,
437
+ undefined,
438
+ decryptionScope,
439
+ )
440
+ const entitiesById = new Map<string, CustomerEntity>()
441
+ for (const entity of entities) {
442
+ entitiesById.set(entity.id, entity)
443
+ }
444
+
354
445
  const where: Record<string, unknown> = {
355
446
  entity: { $in: ids },
356
447
  tenantId: ctx.auth?.tenantId ?? null,
@@ -360,42 +451,54 @@ const crud = makeCrudRoute({
360
451
  }
361
452
 
362
453
  const profiles = await findWithDecryption(
363
- ctx.container.resolve('em') as any,
454
+ em,
364
455
  CustomerPersonProfile,
365
- where as any,
366
- { populate: ['entity', 'company'] } as any,
367
- {
368
- tenantId: ctx.auth?.tenantId ?? null,
369
- organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,
370
- },
456
+ where as FilterQuery<CustomerPersonProfile>,
457
+ { populate: ['entity', 'company'] },
458
+ decryptionScope,
371
459
  )
372
460
 
373
461
  const profilesByEntityId = new Map<string, CustomerPersonProfile>()
374
462
  for (const profile of profiles) {
375
- const entityId = typeof (profile as any)?.entity?.id === 'string' ? (profile as any).entity.id : null
463
+ const profileEntity = (profile as { entity?: { id?: unknown } }).entity
464
+ const entityId = typeof profileEntity?.id === 'string' ? profileEntity.id : null
376
465
  if (entityId) profilesByEntityId.set(entityId, profile)
377
466
  }
378
467
 
379
468
  payload.items = items.map((item: unknown) => {
380
469
  if (!item || typeof item !== 'object') return item
381
470
  const record = item as Record<string, unknown>
471
+ const entity = typeof record.id === 'string' ? entitiesById.get(record.id) : undefined
382
472
  const profile = typeof record.id === 'string' ? profilesByEntityId.get(record.id) : undefined
383
- if (!profile) return item
473
+ if (!entity && !profile) return item
384
474
  return {
385
475
  ...record,
386
- first_name: profile.firstName ?? null,
387
- last_name: profile.lastName ?? null,
388
- preferred_name: profile.preferredName ?? null,
389
- job_title: profile.jobTitle ?? null,
390
- department: profile.department ?? null,
391
- seniority: profile.seniority ?? null,
392
- timezone: profile.timezone ?? null,
393
- linked_in_url: profile.linkedInUrl ?? null,
394
- twitter_url: profile.twitterUrl ?? null,
476
+ display_name: entity?.displayName ?? record.display_name ?? null,
477
+ description: entity?.description ?? record.description ?? null,
478
+ owner_user_id: entity?.ownerUserId ?? record.owner_user_id ?? null,
479
+ primary_email: entity?.primaryEmail ?? record.primary_email ?? null,
480
+ primary_phone: entity?.primaryPhone ?? record.primary_phone ?? null,
481
+ status: entity?.status ?? record.status ?? null,
482
+ lifecycle_stage: entity?.lifecycleStage ?? record.lifecycle_stage ?? null,
483
+ source: entity?.source ?? record.source ?? null,
484
+ next_interaction_at: entity?.nextInteractionAt ? entity.nextInteractionAt.toISOString() : record.next_interaction_at ?? null,
485
+ next_interaction_name: entity?.nextInteractionName ?? record.next_interaction_name ?? null,
486
+ next_interaction_ref_id: entity?.nextInteractionRefId ?? record.next_interaction_ref_id ?? null,
487
+ next_interaction_icon: entity?.nextInteractionIcon ?? record.next_interaction_icon ?? null,
488
+ next_interaction_color: entity?.nextInteractionColor ?? record.next_interaction_color ?? null,
489
+ first_name: profile?.firstName ?? null,
490
+ last_name: profile?.lastName ?? null,
491
+ preferred_name: profile?.preferredName ?? null,
492
+ job_title: profile?.jobTitle ?? null,
493
+ department: profile?.department ?? null,
494
+ seniority: profile?.seniority ?? null,
495
+ timezone: profile?.timezone ?? null,
496
+ linked_in_url: profile?.linkedInUrl ?? null,
497
+ twitter_url: profile?.twitterUrl ?? null,
395
498
  company_entity_id:
396
- profile.company && typeof profile.company === 'object'
499
+ profile?.company && typeof profile.company === 'object'
397
500
  ? profile.company.id
398
- : profile.company ?? null,
501
+ : profile?.company ?? null,
399
502
  }
400
503
  })
401
504
  },
@@ -181,6 +181,8 @@ async function ensureCanonicalTodoBridge(
181
181
  await commandBus.execute('customers.interactions.create', {
182
182
  input: {
183
183
  id: link.todoId,
184
+ tenantId: link.tenantId,
185
+ organizationId: link.organizationId,
184
186
  entityId,
185
187
  interactionType: 'task',
186
188
  title: detail?.title ?? null,
@@ -344,6 +346,8 @@ export async function POST(request: Request): Promise<Response> {
344
346
 
345
347
  const { result } = await commandBus.execute('customers.interactions.create', {
346
348
  input: {
349
+ tenantId: auth.tenantId,
350
+ organizationId: selectedOrganizationId ?? auth.orgId,
347
351
  entityId: body.entityId,
348
352
  interactionType: 'task',
349
353
  title: body.title,
@@ -234,6 +234,42 @@ export function applyEntityIdRestriction(
234
234
  filters.id = ids.length > 0 ? { $in: ids } : { $eq: NO_MATCH_ID }
235
235
  }
236
236
 
237
+ export function applyEntityIdExclusion(
238
+ filters: Record<string, unknown>,
239
+ ids: string[],
240
+ ): void {
241
+ const uniqueIds = Array.from(new Set(ids.filter((id) => typeof id === 'string' && id.length > 0)))
242
+ if (!uniqueIds.length) return
243
+
244
+ const currentIdFilter =
245
+ filters.id && typeof filters.id === 'object' && !Array.isArray(filters.id)
246
+ ? (filters.id as { $eq?: unknown; $in?: unknown; $nin?: unknown })
247
+ : null
248
+ const currentEq = typeof currentIdFilter?.$eq === 'string' ? currentIdFilter.$eq : null
249
+ const currentIn = Array.isArray(currentIdFilter?.$in)
250
+ ? currentIdFilter.$in.filter((value): value is string => typeof value === 'string' && value.length > 0)
251
+ : null
252
+ const currentNotIn = Array.isArray(currentIdFilter?.$nin)
253
+ ? currentIdFilter.$nin.filter((value): value is string => typeof value === 'string' && value.length > 0)
254
+ : []
255
+
256
+ if (currentEq) {
257
+ filters.id = uniqueIds.includes(currentEq) ? { $eq: NO_MATCH_ID } : { $eq: currentEq }
258
+ return
259
+ }
260
+
261
+ if (currentIn) {
262
+ const nextIds = currentIn.filter((id) => !uniqueIds.includes(id))
263
+ filters.id = nextIds.length > 0 ? { $in: nextIds } : { $eq: NO_MATCH_ID }
264
+ return
265
+ }
266
+
267
+ filters.id = {
268
+ ...(currentIdFilter ?? {}),
269
+ $nin: Array.from(new Set([...currentNotIn, ...uniqueIds])),
270
+ }
271
+ }
272
+
237
273
  export function consumeAdvancedFilterState(query: Record<string, unknown>) {
238
274
  const state = deserializeAdvancedFilter(query)
239
275
  if (!state) return null
@@ -2,9 +2,7 @@ import Link from 'next/link'
2
2
  import { Page, PageBody } from '@open-mercato/ui/backend/Page'
3
3
  import { Button } from '@open-mercato/ui/primitives/button'
4
4
  import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
5
- import DictionarySettings from '../../../components/DictionarySettings'
6
- import AddressFormatSettings from '../../../components/AddressFormatSettings'
7
- import PipelineSettings from '../../../components/PipelineSettings'
5
+ import CustomersConfigurationSections from '../../../components/CustomersConfigurationSections'
8
6
 
9
7
  export default async function CustomersConfigurationPage({
10
8
  searchParams,
@@ -27,9 +25,7 @@ export default async function CustomersConfigurationPage({
27
25
  </Link>
28
26
  </Button>
29
27
  ) : null}
30
- <AddressFormatSettings />
31
- <PipelineSettings />
32
- <DictionarySettings />
28
+ <CustomersConfigurationSections />
33
29
  </div>
34
30
  </PageBody>
35
31
  </Page>