@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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/dictionaries/commands/factory.ts"],
4
- "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { Dictionary, DictionaryEntry } from '@open-mercato/core/modules/dictionaries/data/entities'\nimport {\n normalizeDictionaryValue,\n sanitizeDictionaryColor,\n sanitizeDictionaryIcon,\n} from '@open-mercato/core/modules/dictionaries/lib/utils'\nimport {\n registerCommand,\n type CommandHandler,\n type CommandRuntimeContext,\n} from '@open-mercato/shared/lib/commands'\nimport { extractUndoPayload } from '@open-mercato/shared/lib/commands/undo'\nimport { buildChanges, requireId } from '@open-mercato/shared/lib/commands/helpers'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport type { z } from 'zod'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\n\ntype DictionaryScope = {\n tenantId: string\n organizationId: string\n}\n\nexport type DictionaryEntrySnapshot = {\n id: string\n dictionaryId: string\n dictionaryKey: string\n organizationId: string\n tenantId: string\n value: string\n label: string\n color: string | null\n icon: string | null\n createdAt: string\n updatedAt: string\n}\n\nexport type DictionaryEntryUndoPayload = {\n before?: DictionaryEntrySnapshot | null\n after?: DictionaryEntrySnapshot | null\n}\n\nconst ENTRY_CHANGE_KEYS = ['value', 'label', 'color', 'icon'] as const\n\ntype ResolveDictionaryForCreate<TCreate> = (options: {\n em: EntityManager\n ctx: CommandRuntimeContext\n parsed: TCreate\n}) => Promise<{ dictionary: Dictionary; scope: DictionaryScope }>\n\ntype ResolveEntry<TInput> = (options: {\n em: EntityManager\n ctx: CommandRuntimeContext\n id: string\n parsed?: TInput\n}) => Promise<{ entry: DictionaryEntry; dictionary: Dictionary; scope: DictionaryScope }>\n\ntype EnsureDictionaryForUndo = (options: {\n em: EntityManager\n ctx: CommandRuntimeContext\n snapshot: DictionaryEntrySnapshot\n}) => Promise<Dictionary | null>\n\ntype EnsureScopeFn = (ctx: CommandRuntimeContext, scope: DictionaryScope) => void\n\ntype DictionaryEntryCommandLabels = {\n singular?: string\n create?: string\n update?: string\n delete?: string\n}\n\nexport type DictionaryEntryCommandConfig<TCreate, TUpdate> = {\n commandPrefix: string\n resourceKind: string\n translationKeyPrefix?: string\n createSchema: z.ZodType<TCreate>\n updateSchema: z.ZodType<TUpdate>\n resolveDictionaryForCreate: ResolveDictionaryForCreate<TCreate>\n resolveEntry: ResolveEntry<TUpdate>\n ensureScope?: EnsureScopeFn\n ensureDictionaryForUndo?: EnsureDictionaryForUndo\n duplicateError?: string\n labels?: DictionaryEntryCommandLabels\n}\n\nfunction toScopeEnsurer(fn: EnsureScopeFn | undefined): EnsureScopeFn {\n return typeof fn === 'function' ? fn : () => {}\n}\n\nasync function loadSnapshot(em: EntityManager, id: string): Promise<DictionaryEntrySnapshot | null> {\n const entry = await findOneWithDecryption(em, DictionaryEntry, id, { populate: ['dictionary'] })\n if (!entry) return null\n return {\n id: entry.id,\n dictionaryId: entry.dictionary.id,\n dictionaryKey: entry.dictionary.key,\n organizationId: entry.organizationId,\n tenantId: entry.tenantId,\n value: entry.value,\n label: entry.label,\n color: entry.color ?? null,\n icon: entry.icon ?? null,\n createdAt:\n entry.createdAt instanceof Date\n ? entry.createdAt.toISOString()\n : new Date(entry.createdAt).toISOString(),\n updatedAt:\n entry.updatedAt instanceof Date\n ? entry.updatedAt.toISOString()\n : new Date(entry.updatedAt).toISOString(),\n }\n}\n\nfunction applySnapshot(entry: DictionaryEntry, snapshot: DictionaryEntrySnapshot): void {\n entry.value = snapshot.value\n entry.normalizedValue = normalizeDictionaryValue(snapshot.value)\n entry.label = snapshot.label\n entry.color = snapshot.color ?? null\n entry.icon = snapshot.icon ?? null\n entry.organizationId = snapshot.organizationId\n entry.tenantId = snapshot.tenantId\n entry.createdAt = new Date(snapshot.createdAt)\n entry.updatedAt = new Date(snapshot.updatedAt)\n}\n\nfunction ensureDictionaryForUndoFactory(\n fallback?: EnsureDictionaryForUndo\n): EnsureDictionaryForUndo {\n if (fallback) return fallback\n return async ({ em, snapshot }) => {\n const dictionary = await em.findOne(Dictionary, snapshot.dictionaryId)\n return dictionary ?? null\n }\n}\n\nfunction getDuplicateError(config: DictionaryEntryCommandConfig<any, any>): string {\n return config.duplicateError ?? 'Value already exists in this dictionary.'\n}\n\nfunction sanitizeCreatePayload(input: any): {\n value: string\n normalized: string\n label: string\n color: string | null\n icon: string | null\n} {\n const rawValue = typeof input?.value === 'string' ? input.value.trim() : ''\n if (!rawValue) {\n throw new CrudHttpError(400, { error: 'Dictionary entry value is required.' })\n }\n const normalized = normalizeDictionaryValue(rawValue)\n const rawLabel = typeof input?.label === 'string' ? input.label.trim() : ''\n const label = rawLabel || rawValue\n const color = sanitizeDictionaryColor(input?.color ?? null)\n const icon = sanitizeDictionaryIcon(input?.icon ?? null)\n return { value: rawValue, normalized, label, color, icon }\n}\n\nfunction sanitizeUpdatePayload(input: any): {\n value?: string\n normalized?: string\n label?: string\n color?: string | null\n icon?: string | null\n} {\n const payload: {\n value?: string\n normalized?: string\n label?: string\n color?: string | null\n icon?: string | null\n } = {}\n if (Object.prototype.hasOwnProperty.call(input, 'value')) {\n const rawValue = typeof input?.value === 'string' ? input.value.trim() : ''\n if (!rawValue) {\n throw new CrudHttpError(400, { error: 'Dictionary entry value is required.' })\n }\n payload.value = rawValue\n payload.normalized = normalizeDictionaryValue(rawValue)\n }\n if (Object.prototype.hasOwnProperty.call(input, 'label')) {\n const rawLabel = typeof input?.label === 'string' ? input.label.trim() : ''\n payload.label = rawLabel\n }\n if (Object.prototype.hasOwnProperty.call(input, 'color')) {\n payload.color = sanitizeDictionaryColor(input?.color ?? null)\n }\n if (Object.prototype.hasOwnProperty.call(input, 'icon')) {\n payload.icon = sanitizeDictionaryIcon(input?.icon ?? null)\n }\n return payload\n}\n\nexport function registerDictionaryEntryCommands<TCreate, TUpdate>(\n config: DictionaryEntryCommandConfig<TCreate, TUpdate>\n): void {\n const scopeEnsurer = toScopeEnsurer(config.ensureScope)\n const ensureDictionaryForUndo = ensureDictionaryForUndoFactory(config.ensureDictionaryForUndo)\n const translationKeyPrefix = config.translationKeyPrefix ?? config.commandPrefix\n const fallbackSingular = config.labels?.singular ?? 'Dictionary entry'\n const fallbackCreate = config.labels?.create ?? `Create ${fallbackSingular}`\n const fallbackUpdate = config.labels?.update ?? `Update ${fallbackSingular}`\n const fallbackDelete = config.labels?.delete ?? `Delete ${fallbackSingular}`\n const duplicateMessage = getDuplicateError(config)\n\n const createCommand: CommandHandler<\n ReturnType<typeof config.createSchema['parse']>,\n { entryId: string }\n > = {\n id: `${config.commandPrefix}.create`,\n async execute(rawInput, ctx) {\n const parsed = config.createSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const { dictionary, scope } = await config.resolveDictionaryForCreate({ em, ctx, parsed })\n scopeEnsurer(ctx, scope)\n\n const { value, normalized, label, color, icon } = sanitizeCreatePayload(parsed)\n const duplicate = await em.findOne(DictionaryEntry, {\n dictionary,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n normalizedValue: normalized,\n })\n if (duplicate) {\n throw new CrudHttpError(409, { error: duplicateMessage })\n }\n\n const entry = em.create(DictionaryEntry, {\n dictionary,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n value,\n normalizedValue: normalized,\n label,\n color,\n icon,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(entry)\n await em.flush()\n return { entryId: entry.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadSnapshot(em, result.entryId)\n },\n buildLog: async ({ result, snapshots }) => {\n const after = snapshots.after as DictionaryEntrySnapshot | undefined\n if (!after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate(`${translationKeyPrefix}.audit.create`, fallbackCreate),\n resourceKind: config.resourceKind,\n resourceId: result.entryId,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n snapshotAfter: after,\n payload: {\n undo: { after } satisfies DictionaryEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const undo = extractUndoPayload<DictionaryEntryUndoPayload>(logEntry)\n const after =\n undo?.after ??\n (logEntry?.snapshotAfter as DictionaryEntrySnapshot | null | undefined) ??\n null\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n scopeEnsurer(ctx, { tenantId: after.tenantId, organizationId: after.organizationId })\n const entry = await em.findOne(DictionaryEntry, after.id)\n if (entry) {\n await em.removeAndFlush(entry)\n return\n }\n await em.nativeDelete(DictionaryEntry, { id: after.id })\n },\n}\n\n const updateCommand: CommandHandler<\n ReturnType<typeof config.updateSchema['parse']>,\n { entryId: string }\n > = {\n id: `${config.commandPrefix}.update`,\n async prepare(input, ctx) {\n const id = requireId(input, 'Dictionary entry id is required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadSnapshot(em, id)\n if (snapshot) {\n scopeEnsurer(ctx, { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId })\n }\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const parsed = config.updateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const id = requireId(parsed, 'Dictionary entry id is required')\n const { entry, dictionary, scope } = await config.resolveEntry({ em, ctx, id, parsed })\n scopeEnsurer(ctx, scope)\n\n const updates = sanitizeUpdatePayload(parsed)\n if (updates.value !== undefined && updates.normalized !== undefined) {\n if (updates.normalized !== entry.normalizedValue) {\n const duplicate = await em.findOne(DictionaryEntry, {\n dictionary,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n normalizedValue: updates.normalized,\n id: { $ne: entry.id },\n } as any)\n if (duplicate) {\n throw new CrudHttpError(409, { error: duplicateMessage })\n }\n entry.value = updates.value\n entry.normalizedValue = updates.normalized\n if (updates.label === undefined) {\n entry.label = entry.value\n }\n }\n }\n if (updates.label !== undefined) {\n entry.label = updates.label || entry.value\n }\n if (Object.prototype.hasOwnProperty.call(updates, 'color')) {\n entry.color = updates.color ?? null\n }\n if (Object.prototype.hasOwnProperty.call(updates, 'icon')) {\n entry.icon = updates.icon ?? null\n }\n await em.flush()\n return { entryId: entry.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadSnapshot(em, result.entryId)\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as DictionaryEntrySnapshot | undefined\n const after = snapshots.after as DictionaryEntrySnapshot | undefined\n if (!before || !after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate(`${translationKeyPrefix}.audit.update`, fallbackUpdate),\n resourceKind: config.resourceKind,\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes: buildChanges(\n before as Record<string, unknown>,\n after as Record<string, unknown>,\n ENTRY_CHANGE_KEYS,\n ),\n payload: {\n undo: { before, after } satisfies DictionaryEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const undo = extractUndoPayload<DictionaryEntryUndoPayload>(logEntry)\n const before =\n undo?.before ??\n (logEntry?.snapshotBefore as DictionaryEntrySnapshot | null | undefined) ??\n null\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n scopeEnsurer(ctx, { tenantId: before.tenantId, organizationId: before.organizationId })\n const dictionary = await ensureDictionaryForUndo({ em, ctx, snapshot: before })\n if (!dictionary) return\n let entry = await em.findOne(DictionaryEntry, before.id)\n if (!entry) {\n entry = em.create(DictionaryEntry, {\n id: before.id,\n dictionary,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n value: before.value,\n normalizedValue: normalizeDictionaryValue(before.value),\n label: before.label,\n color: before.color,\n icon: before.icon,\n createdAt: new Date(before.createdAt),\n updatedAt: new Date(before.updatedAt),\n })\n em.persist(entry)\n } else {\n entry.dictionary = dictionary\n applySnapshot(entry, before)\n }\n await em.flush()\n },\n }\n\n const deleteCommand: CommandHandler<\n { body?: Record<string, unknown>; query?: Record<string, unknown> },\n { entryId: string }\n > = {\n id: `${config.commandPrefix}.delete`,\n async prepare(input, ctx) {\n const id = requireId(input, 'Dictionary entry id is required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadSnapshot(em, id)\n if (snapshot) {\n scopeEnsurer(ctx, { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId })\n }\n return snapshot ? { before: snapshot } : {}\n },\n async execute(input, ctx) {\n const id = requireId(input, 'Dictionary entry id is required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const { entry, scope } = await config.resolveEntry({ em, ctx, id })\n scopeEnsurer(ctx, scope)\n em.remove(entry)\n await em.flush()\n return { entryId: id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as DictionaryEntrySnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate(`${translationKeyPrefix}.audit.delete`, fallbackDelete),\n resourceKind: config.resourceKind,\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: { before } satisfies DictionaryEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const undo = extractUndoPayload<DictionaryEntryUndoPayload>(logEntry)\n const before =\n undo?.before ??\n (logEntry?.snapshotBefore as DictionaryEntrySnapshot | null | undefined) ??\n null\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n scopeEnsurer(ctx, { tenantId: before.tenantId, organizationId: before.organizationId })\n const dictionary = await ensureDictionaryForUndo({ em, ctx, snapshot: before })\n if (!dictionary) return\n let entry = await em.findOne(DictionaryEntry, before.id)\n if (!entry) {\n entry = em.create(DictionaryEntry, {\n id: before.id,\n dictionary,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n value: before.value,\n normalizedValue: normalizeDictionaryValue(before.value),\n label: before.label,\n color: before.color,\n icon: before.icon,\n createdAt: new Date(before.createdAt),\n updatedAt: new Date(before.updatedAt),\n })\n em.persist(entry)\n } else {\n entry.dictionary = dictionary\n applySnapshot(entry, before)\n }\n await em.flush()\n },\n }\n\n registerCommand(createCommand)\n registerCommand(updateCommand)\n registerCommand(deleteCommand)\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { Dictionary, DictionaryEntry } from '@open-mercato/core/modules/dictionaries/data/entities'\nimport {\n normalizeDictionaryValue,\n sanitizeDictionaryColor,\n sanitizeDictionaryIcon,\n} from '@open-mercato/core/modules/dictionaries/lib/utils'\nimport {\n registerCommand,\n type CommandHandler,\n type CommandRuntimeContext,\n} from '@open-mercato/shared/lib/commands'\nimport { extractUndoPayload } from '@open-mercato/shared/lib/commands/undo'\nimport { buildChanges, requireId } from '@open-mercato/shared/lib/commands/helpers'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport type { z } from 'zod'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\n\ntype DictionaryScope = {\n tenantId: string\n organizationId: string\n}\n\nexport type DictionaryEntrySnapshot = {\n id: string\n dictionaryId: string\n dictionaryKey: string\n organizationId: string\n tenantId: string\n value: string\n label: string\n color: string | null\n icon: string | null\n createdAt: string\n updatedAt: string\n position?: number\n isDefault?: boolean\n}\n\nexport type DictionaryEntryUndoPayload = {\n before?: DictionaryEntrySnapshot | null\n after?: DictionaryEntrySnapshot | null\n}\n\nconst ENTRY_CHANGE_KEYS = ['value', 'label', 'color', 'icon', 'position', 'isDefault'] as const\n\ntype ResolveDictionaryForCreate<TCreate> = (options: {\n em: EntityManager\n ctx: CommandRuntimeContext\n parsed: TCreate\n}) => Promise<{ dictionary: Dictionary; scope: DictionaryScope }>\n\ntype ResolveEntry<TInput> = (options: {\n em: EntityManager\n ctx: CommandRuntimeContext\n id: string\n parsed?: TInput\n}) => Promise<{ entry: DictionaryEntry; dictionary: Dictionary; scope: DictionaryScope }>\n\ntype EnsureDictionaryForUndo = (options: {\n em: EntityManager\n ctx: CommandRuntimeContext\n snapshot: DictionaryEntrySnapshot\n}) => Promise<Dictionary | null>\n\ntype EnsureScopeFn = (ctx: CommandRuntimeContext, scope: DictionaryScope) => void\n\ntype DictionaryEntryCommandLabels = {\n singular?: string\n create?: string\n update?: string\n delete?: string\n}\n\nexport type DictionaryEntryCommandConfig<TCreate, TUpdate> = {\n commandPrefix: string\n resourceKind: string\n translationKeyPrefix?: string\n createSchema: z.ZodType<TCreate>\n updateSchema: z.ZodType<TUpdate>\n resolveDictionaryForCreate: ResolveDictionaryForCreate<TCreate>\n resolveEntry: ResolveEntry<TUpdate>\n ensureScope?: EnsureScopeFn\n ensureDictionaryForUndo?: EnsureDictionaryForUndo\n duplicateError?: string\n labels?: DictionaryEntryCommandLabels\n}\n\nfunction toScopeEnsurer(fn: EnsureScopeFn | undefined): EnsureScopeFn {\n return typeof fn === 'function' ? fn : () => {}\n}\n\nasync function loadSnapshot(em: EntityManager, id: string): Promise<DictionaryEntrySnapshot | null> {\n const entry = await findOneWithDecryption(em, DictionaryEntry, id, { populate: ['dictionary'] })\n if (!entry) return null\n return {\n id: entry.id,\n dictionaryId: entry.dictionary.id,\n dictionaryKey: entry.dictionary.key,\n organizationId: entry.organizationId,\n tenantId: entry.tenantId,\n value: entry.value,\n label: entry.label,\n color: entry.color ?? null,\n icon: entry.icon ?? null,\n position: entry.position ?? 0,\n isDefault: entry.isDefault ?? false,\n createdAt:\n entry.createdAt instanceof Date\n ? entry.createdAt.toISOString()\n : new Date(entry.createdAt).toISOString(),\n updatedAt:\n entry.updatedAt instanceof Date\n ? entry.updatedAt.toISOString()\n : new Date(entry.updatedAt).toISOString(),\n }\n}\n\nfunction applySnapshot(entry: DictionaryEntry, snapshot: DictionaryEntrySnapshot): void {\n entry.value = snapshot.value\n entry.normalizedValue = normalizeDictionaryValue(snapshot.value)\n entry.label = snapshot.label\n entry.color = snapshot.color ?? null\n entry.icon = snapshot.icon ?? null\n if (snapshot.position !== undefined) entry.position = snapshot.position\n if (snapshot.isDefault !== undefined) entry.isDefault = snapshot.isDefault\n entry.organizationId = snapshot.organizationId\n entry.tenantId = snapshot.tenantId\n entry.createdAt = new Date(snapshot.createdAt)\n entry.updatedAt = new Date(snapshot.updatedAt)\n}\n\nfunction ensureDictionaryForUndoFactory(\n fallback?: EnsureDictionaryForUndo\n): EnsureDictionaryForUndo {\n if (fallback) return fallback\n return async ({ em, snapshot }) => {\n const dictionary = await em.findOne(Dictionary, snapshot.dictionaryId)\n return dictionary ?? null\n }\n}\n\nfunction getDuplicateError(config: DictionaryEntryCommandConfig<any, any>): string {\n return config.duplicateError ?? 'Value already exists in this dictionary.'\n}\n\nfunction sanitizeCreatePayload(input: any): {\n value: string\n normalized: string\n label: string\n color: string | null\n icon: string | null\n position: number | undefined\n} {\n const rawValue = typeof input?.value === 'string' ? input.value.trim() : ''\n if (!rawValue) {\n throw new CrudHttpError(400, { error: 'Dictionary entry value is required.' })\n }\n const normalized = normalizeDictionaryValue(rawValue)\n const rawLabel = typeof input?.label === 'string' ? input.label.trim() : ''\n const label = rawLabel || rawValue\n const color = sanitizeDictionaryColor(input?.color ?? null)\n const icon = sanitizeDictionaryIcon(input?.icon ?? null)\n const position = typeof input?.position === 'number' ? input.position : undefined\n return { value: rawValue, normalized, label, color, icon, position }\n}\n\nfunction sanitizeUpdatePayload(input: any): {\n value?: string\n normalized?: string\n label?: string\n color?: string | null\n icon?: string | null\n position?: number\n isDefault?: boolean\n} {\n const payload: {\n value?: string\n normalized?: string\n label?: string\n color?: string | null\n icon?: string | null\n position?: number\n isDefault?: boolean\n } = {}\n if (Object.prototype.hasOwnProperty.call(input, 'value')) {\n const rawValue = typeof input?.value === 'string' ? input.value.trim() : ''\n if (!rawValue) {\n throw new CrudHttpError(400, { error: 'Dictionary entry value is required.' })\n }\n payload.value = rawValue\n payload.normalized = normalizeDictionaryValue(rawValue)\n }\n if (Object.prototype.hasOwnProperty.call(input, 'label')) {\n const rawLabel = typeof input?.label === 'string' ? input.label.trim() : ''\n payload.label = rawLabel\n }\n if (Object.prototype.hasOwnProperty.call(input, 'color')) {\n payload.color = sanitizeDictionaryColor(input?.color ?? null)\n }\n if (Object.prototype.hasOwnProperty.call(input, 'icon')) {\n payload.icon = sanitizeDictionaryIcon(input?.icon ?? null)\n }\n if (Object.prototype.hasOwnProperty.call(input, 'position')) {\n const rawPosition = typeof input?.position === 'number' ? input.position : undefined\n if (rawPosition !== undefined) {\n payload.position = rawPosition\n }\n }\n if (Object.prototype.hasOwnProperty.call(input, 'isDefault')) {\n payload.isDefault = typeof input?.isDefault === 'boolean' ? input.isDefault : undefined\n }\n return payload\n}\n\nexport function registerDictionaryEntryCommands<TCreate, TUpdate>(\n config: DictionaryEntryCommandConfig<TCreate, TUpdate>\n): void {\n const scopeEnsurer = toScopeEnsurer(config.ensureScope)\n const ensureDictionaryForUndo = ensureDictionaryForUndoFactory(config.ensureDictionaryForUndo)\n const translationKeyPrefix = config.translationKeyPrefix ?? config.commandPrefix\n const fallbackSingular = config.labels?.singular ?? 'Dictionary entry'\n const fallbackCreate = config.labels?.create ?? `Create ${fallbackSingular}`\n const fallbackUpdate = config.labels?.update ?? `Update ${fallbackSingular}`\n const fallbackDelete = config.labels?.delete ?? `Delete ${fallbackSingular}`\n const duplicateMessage = getDuplicateError(config)\n\n const createCommand: CommandHandler<\n ReturnType<typeof config.createSchema['parse']>,\n { entryId: string }\n > = {\n id: `${config.commandPrefix}.create`,\n async execute(rawInput, ctx) {\n const parsed = config.createSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const { dictionary, scope } = await config.resolveDictionaryForCreate({ em, ctx, parsed })\n scopeEnsurer(ctx, scope)\n\n const { value, normalized, label, color, icon, position } = sanitizeCreatePayload(parsed)\n const duplicate = await em.findOne(DictionaryEntry, {\n dictionary,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n normalizedValue: normalized,\n })\n if (duplicate) {\n throw new CrudHttpError(409, { error: duplicateMessage })\n }\n\n const entry = em.create(DictionaryEntry, {\n dictionary,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n value,\n normalizedValue: normalized,\n label,\n color,\n icon,\n ...(position !== undefined ? { position } : {}),\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(entry)\n await em.flush()\n return { entryId: entry.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadSnapshot(em, result.entryId)\n },\n buildLog: async ({ result, snapshots }) => {\n const after = snapshots.after as DictionaryEntrySnapshot | undefined\n if (!after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate(`${translationKeyPrefix}.audit.create`, fallbackCreate),\n resourceKind: config.resourceKind,\n resourceId: result.entryId,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n snapshotAfter: after,\n payload: {\n undo: { after } satisfies DictionaryEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const undo = extractUndoPayload<DictionaryEntryUndoPayload>(logEntry)\n const after =\n undo?.after ??\n (logEntry?.snapshotAfter as DictionaryEntrySnapshot | null | undefined) ??\n null\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n scopeEnsurer(ctx, { tenantId: after.tenantId, organizationId: after.organizationId })\n const entry = await em.findOne(DictionaryEntry, after.id)\n if (entry) {\n await em.removeAndFlush(entry)\n return\n }\n await em.nativeDelete(DictionaryEntry, { id: after.id })\n },\n}\n\n const updateCommand: CommandHandler<\n ReturnType<typeof config.updateSchema['parse']>,\n { entryId: string }\n > = {\n id: `${config.commandPrefix}.update`,\n async prepare(input, ctx) {\n const id = requireId(input, 'Dictionary entry id is required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadSnapshot(em, id)\n if (snapshot) {\n scopeEnsurer(ctx, { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId })\n }\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const parsed = config.updateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const id = requireId(parsed, 'Dictionary entry id is required')\n const { entry, dictionary, scope } = await config.resolveEntry({ em, ctx, id, parsed })\n scopeEnsurer(ctx, scope)\n\n const updates = sanitizeUpdatePayload(parsed)\n if (updates.value !== undefined && updates.normalized !== undefined) {\n if (updates.normalized !== entry.normalizedValue) {\n const duplicate = await em.findOne(DictionaryEntry, {\n dictionary,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n normalizedValue: updates.normalized,\n id: { $ne: entry.id },\n } as any)\n if (duplicate) {\n throw new CrudHttpError(409, { error: duplicateMessage })\n }\n entry.value = updates.value\n entry.normalizedValue = updates.normalized\n if (updates.label === undefined) {\n entry.label = entry.value\n }\n }\n }\n if (updates.label !== undefined) {\n entry.label = updates.label || entry.value\n }\n if (Object.prototype.hasOwnProperty.call(updates, 'color')) {\n entry.color = updates.color ?? null\n }\n if (Object.prototype.hasOwnProperty.call(updates, 'icon')) {\n entry.icon = updates.icon ?? null\n }\n if (updates.position !== undefined) {\n entry.position = updates.position\n }\n if (updates.isDefault !== undefined) {\n entry.isDefault = updates.isDefault\n }\n await em.flush()\n return { entryId: entry.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadSnapshot(em, result.entryId)\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as DictionaryEntrySnapshot | undefined\n const after = snapshots.after as DictionaryEntrySnapshot | undefined\n if (!before || !after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate(`${translationKeyPrefix}.audit.update`, fallbackUpdate),\n resourceKind: config.resourceKind,\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes: buildChanges(\n before as Record<string, unknown>,\n after as Record<string, unknown>,\n ENTRY_CHANGE_KEYS,\n ),\n payload: {\n undo: { before, after } satisfies DictionaryEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const undo = extractUndoPayload<DictionaryEntryUndoPayload>(logEntry)\n const before =\n undo?.before ??\n (logEntry?.snapshotBefore as DictionaryEntrySnapshot | null | undefined) ??\n null\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n scopeEnsurer(ctx, { tenantId: before.tenantId, organizationId: before.organizationId })\n const dictionary = await ensureDictionaryForUndo({ em, ctx, snapshot: before })\n if (!dictionary) return\n let entry = await em.findOne(DictionaryEntry, before.id)\n if (!entry) {\n entry = em.create(DictionaryEntry, {\n id: before.id,\n dictionary,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n value: before.value,\n normalizedValue: normalizeDictionaryValue(before.value),\n label: before.label,\n color: before.color,\n icon: before.icon,\n createdAt: new Date(before.createdAt),\n updatedAt: new Date(before.updatedAt),\n })\n em.persist(entry)\n } else {\n entry.dictionary = dictionary\n applySnapshot(entry, before)\n }\n await em.flush()\n },\n }\n\n const deleteCommand: CommandHandler<\n { body?: Record<string, unknown>; query?: Record<string, unknown> },\n { entryId: string }\n > = {\n id: `${config.commandPrefix}.delete`,\n async prepare(input, ctx) {\n const id = requireId(input, 'Dictionary entry id is required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadSnapshot(em, id)\n if (snapshot) {\n scopeEnsurer(ctx, { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId })\n }\n return snapshot ? { before: snapshot } : {}\n },\n async execute(input, ctx) {\n const id = requireId(input, 'Dictionary entry id is required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const { entry, scope } = await config.resolveEntry({ em, ctx, id })\n scopeEnsurer(ctx, scope)\n em.remove(entry)\n await em.flush()\n return { entryId: id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as DictionaryEntrySnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate(`${translationKeyPrefix}.audit.delete`, fallbackDelete),\n resourceKind: config.resourceKind,\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: { before } satisfies DictionaryEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const undo = extractUndoPayload<DictionaryEntryUndoPayload>(logEntry)\n const before =\n undo?.before ??\n (logEntry?.snapshotBefore as DictionaryEntrySnapshot | null | undefined) ??\n null\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n scopeEnsurer(ctx, { tenantId: before.tenantId, organizationId: before.organizationId })\n const dictionary = await ensureDictionaryForUndo({ em, ctx, snapshot: before })\n if (!dictionary) return\n let entry = await em.findOne(DictionaryEntry, before.id)\n if (!entry) {\n entry = em.create(DictionaryEntry, {\n id: before.id,\n dictionary,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n value: before.value,\n normalizedValue: normalizeDictionaryValue(before.value),\n label: before.label,\n color: before.color,\n icon: before.icon,\n createdAt: new Date(before.createdAt),\n updatedAt: new Date(before.updatedAt),\n })\n em.persist(entry)\n } else {\n entry.dictionary = dictionary\n applySnapshot(entry, before)\n }\n await em.flush()\n },\n }\n\n registerCommand(createCommand)\n registerCommand(updateCommand)\n registerCommand(deleteCommand)\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,2 +1,3 @@
1
1
  import "./entries.js";
2
+ import "./entry-operations.js";
2
3
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/dictionaries/commands/index.ts"],
4
- "sourcesContent": ["import './entries'\n"],
5
- "mappings": "AAAA,OAAO;",
4
+ "sourcesContent": ["import './entries'\nimport './entry-operations'\n"],
5
+ "mappings": "AAAA,OAAO;AACP,OAAO;",
6
6
  "names": []
7
7
  }
@@ -35,9 +35,12 @@ function DictionaryTable({
35
35
  accessorKey: "value",
36
36
  header: translations.valueColumn,
37
37
  meta: { priority: 1 },
38
- cell: ({ getValue, row }) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
39
- /* @__PURE__ */ jsx("span", { className: "font-medium", children: String(getValue()) }),
40
- row.original.isInherited ? /* @__PURE__ */ jsx("span", { className: "rounded bg-muted px-2 py-0.5 text-xs text-muted-foreground", title: translations.inheritedTooltip, children: translations.inheritedLabel }) : null
38
+ cell: ({ getValue, row }) => /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
39
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
40
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: String(getValue()) }),
41
+ row.original.isInherited ? /* @__PURE__ */ jsx("span", { className: "rounded bg-muted px-2 py-0.5 text-xs text-muted-foreground", title: translations.inheritedTooltip, children: translations.inheritedLabel }) : null
42
+ ] }),
43
+ typeof row.original.usageCount === "number" && row.original.usageCount > 0 && translations.usageCountLabel ? /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground", children: translations.usageCountLabel.replace("{{count}}", String(row.original.usageCount)) }) : null
41
44
  ] })
42
45
  },
43
46
  {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/dictionaries/components/DictionaryTable.tsx"],
4
- "sourcesContent": ["import * as React from 'react'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { RowActions, type RowActionItem } from '@open-mercato/ui/backend/RowActions'\nimport { renderDictionaryColor, renderDictionaryIcon } from './dictionaryAppearance'\n\nexport type DictionaryTableEntry = {\n id: string\n value: string\n label: string\n color: string | null\n icon: string | null\n organizationId?: string | null\n tenantId?: string | null\n isInherited?: boolean\n createdAt?: string | null\n updatedAt?: string | null\n}\n\nexport type DictionaryTableTranslations = {\n title: string\n valueColumn: string\n labelColumn: string\n appearanceColumn: string\n addLabel: string\n editLabel: string\n deleteLabel: string\n refreshLabel: string\n inheritedLabel: string\n inheritedTooltip: string\n emptyLabel: string\n searchPlaceholder?: string\n}\n\ntype DictionaryTableProps = {\n entries: DictionaryTableEntry[]\n loading?: boolean\n canManage?: boolean\n onCreate?: () => void\n onEdit?: (entry: DictionaryTableEntry) => void\n onDelete?: (entry: DictionaryTableEntry) => void\n onRefresh?: () => void\n translations: DictionaryTableTranslations\n}\n\nexport function DictionaryTable({\n entries,\n loading = false,\n canManage = false,\n onCreate,\n onEdit,\n onDelete,\n onRefresh,\n translations,\n}: DictionaryTableProps) {\n const [search, setSearch] = React.useState('')\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'value', desc: false }])\n const [page, setPage] = React.useState(1)\n const pageSize = 50\n\n const filtered = React.useMemo(() => {\n if (!search.trim()) return entries\n const term = search.trim().toLowerCase()\n return entries.filter((entry) => {\n return (\n entry.value.toLowerCase().includes(term) ||\n (entry.label ?? '').toLowerCase().includes(term)\n )\n })\n }, [entries, search])\n\n const paginated = React.useMemo(() => {\n const start = (page - 1) * pageSize\n return filtered.slice(start, start + pageSize)\n }, [filtered, page])\n\n const totalPages = Math.max(1, Math.ceil(filtered.length / pageSize))\n\n const columns = React.useMemo<ColumnDef<DictionaryTableEntry>[]>(() => [\n {\n accessorKey: 'value',\n header: translations.valueColumn,\n meta: { priority: 1 },\n cell: ({ getValue, row }) => (\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium\">{String(getValue())}</span>\n {row.original.isInherited ? (\n <span className=\"rounded bg-muted px-2 py-0.5 text-xs text-muted-foreground\" title={translations.inheritedTooltip}>\n {translations.inheritedLabel}\n </span>\n ) : null}\n </div>\n ),\n },\n {\n accessorKey: 'label',\n header: translations.labelColumn,\n meta: { priority: 2 },\n cell: ({ getValue }) => <span>{String(getValue() ?? '')}</span>,\n },\n {\n id: 'appearance',\n header: translations.appearanceColumn,\n meta: { priority: 3 },\n cell: ({ row }) => {\n const { color, icon } = row.original\n if (!color && !icon) return <span className=\"text-muted-foreground\">\u2014</span>\n return (\n <div className=\"flex items-center gap-2\">\n {color ? renderDictionaryColor(color, 'h-4 w-4 rounded-full border border-border') : null}\n {icon ? renderDictionaryIcon(icon, 'h-4 w-4') : null}\n </div>\n )\n },\n },\n ], [translations.appearanceColumn, translations.inheritedLabel, translations.inheritedTooltip, translations.labelColumn, translations.valueColumn])\n\n const actions = React.useMemo(() => {\n if (!canManage || !onCreate) return null\n return (\n <Button size=\"sm\" onClick={onCreate}>\n {translations.addLabel}\n </Button>\n )\n }, [canManage, onCreate, translations.addLabel])\n\n const handleRowClick = canManage && onEdit\n ? (entry: DictionaryTableEntry) => {\n if (entry.isInherited) return\n onEdit(entry)\n }\n : undefined\n\n return (\n <DataTable<DictionaryTableEntry>\n title={translations.title}\n actions={actions}\n columns={columns}\n data={paginated}\n embedded\n sortable\n sorting={sorting}\n onSortingChange={setSorting}\n searchValue={search}\n onSearchChange={(value) => {\n setSearch(value)\n setPage(1)\n }}\n searchPlaceholder={translations.searchPlaceholder}\n isLoading={loading}\n emptyState={<p className=\"py-10 text-center text-sm text-muted-foreground\">{translations.emptyLabel}</p>}\n pagination={{\n page,\n pageSize,\n total: filtered.length,\n totalPages,\n onPageChange: setPage,\n }}\n refreshButton={onRefresh ? {\n label: translations.refreshLabel,\n onRefresh,\n isRefreshing: loading,\n } : undefined}\n onRowClick={handleRowClick}\n rowActions={\n canManage\n ? (entry) => {\n if (!entry) return null\n if (entry.isInherited) return null\n const items: RowActionItem[] = []\n if (onEdit) {\n items.push({\n id: 'edit',\n label: translations.editLabel,\n onSelect: () => onEdit(entry),\n })\n }\n if (onDelete) {\n items.push({\n id: 'delete',\n label: translations.deleteLabel,\n onSelect: () => onDelete(entry),\n destructive: true,\n })\n }\n return items.length ? <RowActions items={items} /> : null\n }\n : undefined\n }\n />\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import * as React from 'react'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { RowActions, type RowActionItem } from '@open-mercato/ui/backend/RowActions'\nimport { renderDictionaryColor, renderDictionaryIcon } from './dictionaryAppearance'\n\nexport type DictionaryTableEntry = {\n id: string\n value: string\n label: string\n color: string | null\n icon: string | null\n usageCount?: number\n organizationId?: string | null\n tenantId?: string | null\n isInherited?: boolean\n createdAt?: string | null\n updatedAt?: string | null\n}\n\nexport type DictionaryTableTranslations = {\n title: string\n valueColumn: string\n labelColumn: string\n appearanceColumn: string\n addLabel: string\n editLabel: string\n deleteLabel: string\n refreshLabel: string\n inheritedLabel: string\n inheritedTooltip: string\n emptyLabel: string\n usageCountLabel?: string\n searchPlaceholder?: string\n}\n\ntype DictionaryTableProps = {\n entries: DictionaryTableEntry[]\n loading?: boolean\n canManage?: boolean\n onCreate?: () => void\n onEdit?: (entry: DictionaryTableEntry) => void\n onDelete?: (entry: DictionaryTableEntry) => void\n onRefresh?: () => void\n translations: DictionaryTableTranslations\n}\n\nexport function DictionaryTable({\n entries,\n loading = false,\n canManage = false,\n onCreate,\n onEdit,\n onDelete,\n onRefresh,\n translations,\n}: DictionaryTableProps) {\n const [search, setSearch] = React.useState('')\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'value', desc: false }])\n const [page, setPage] = React.useState(1)\n const pageSize = 50\n\n const filtered = React.useMemo(() => {\n if (!search.trim()) return entries\n const term = search.trim().toLowerCase()\n return entries.filter((entry) => {\n return (\n entry.value.toLowerCase().includes(term) ||\n (entry.label ?? '').toLowerCase().includes(term)\n )\n })\n }, [entries, search])\n\n const paginated = React.useMemo(() => {\n const start = (page - 1) * pageSize\n return filtered.slice(start, start + pageSize)\n }, [filtered, page])\n\n const totalPages = Math.max(1, Math.ceil(filtered.length / pageSize))\n\n const columns = React.useMemo<ColumnDef<DictionaryTableEntry>[]>(() => [\n {\n accessorKey: 'value',\n header: translations.valueColumn,\n meta: { priority: 1 },\n cell: ({ getValue, row }) => (\n <div className=\"space-y-1\">\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium\">{String(getValue())}</span>\n {row.original.isInherited ? (\n <span className=\"rounded bg-muted px-2 py-0.5 text-xs text-muted-foreground\" title={translations.inheritedTooltip}>\n {translations.inheritedLabel}\n </span>\n ) : null}\n </div>\n {typeof row.original.usageCount === 'number' && row.original.usageCount > 0 && translations.usageCountLabel ? (\n <div className=\"text-xs text-muted-foreground\">\n {translations.usageCountLabel.replace('{{count}}', String(row.original.usageCount))}\n </div>\n ) : null}\n </div>\n ),\n },\n {\n accessorKey: 'label',\n header: translations.labelColumn,\n meta: { priority: 2 },\n cell: ({ getValue }) => <span>{String(getValue() ?? '')}</span>,\n },\n {\n id: 'appearance',\n header: translations.appearanceColumn,\n meta: { priority: 3 },\n cell: ({ row }) => {\n const { color, icon } = row.original\n if (!color && !icon) return <span className=\"text-muted-foreground\">\u2014</span>\n return (\n <div className=\"flex items-center gap-2\">\n {color ? renderDictionaryColor(color, 'h-4 w-4 rounded-full border border-border') : null}\n {icon ? renderDictionaryIcon(icon, 'h-4 w-4') : null}\n </div>\n )\n },\n },\n ], [translations.appearanceColumn, translations.inheritedLabel, translations.inheritedTooltip, translations.labelColumn, translations.valueColumn])\n\n const actions = React.useMemo(() => {\n if (!canManage || !onCreate) return null\n return (\n <Button size=\"sm\" onClick={onCreate}>\n {translations.addLabel}\n </Button>\n )\n }, [canManage, onCreate, translations.addLabel])\n\n const handleRowClick = canManage && onEdit\n ? (entry: DictionaryTableEntry) => {\n if (entry.isInherited) return\n onEdit(entry)\n }\n : undefined\n\n return (\n <DataTable<DictionaryTableEntry>\n title={translations.title}\n actions={actions}\n columns={columns}\n data={paginated}\n embedded\n sortable\n sorting={sorting}\n onSortingChange={setSorting}\n searchValue={search}\n onSearchChange={(value) => {\n setSearch(value)\n setPage(1)\n }}\n searchPlaceholder={translations.searchPlaceholder}\n isLoading={loading}\n emptyState={<p className=\"py-10 text-center text-sm text-muted-foreground\">{translations.emptyLabel}</p>}\n pagination={{\n page,\n pageSize,\n total: filtered.length,\n totalPages,\n onPageChange: setPage,\n }}\n refreshButton={onRefresh ? {\n label: translations.refreshLabel,\n onRefresh,\n isRefreshing: loading,\n } : undefined}\n onRowClick={handleRowClick}\n rowActions={\n canManage\n ? (entry) => {\n if (!entry) return null\n if (entry.isInherited) return null\n const items: RowActionItem[] = []\n if (onEdit) {\n items.push({\n id: 'edit',\n label: translations.editLabel,\n onSelect: () => onEdit(entry),\n })\n }\n if (onDelete) {\n items.push({\n id: 'delete',\n label: translations.deleteLabel,\n onSelect: () => onDelete(entry),\n destructive: true,\n })\n }\n return items.length ? <RowActions items={items} /> : null\n }\n : undefined\n }\n />\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -14,7 +14,8 @@ import {
14
14
  Property,
15
15
  Unique,
16
16
  Index,
17
- ManyToOne
17
+ ManyToOne,
18
+ OptionalProps
18
19
  } from "@mikro-orm/core";
19
20
  let Dictionary = class {
20
21
  constructor() {
@@ -65,8 +66,11 @@ Dictionary = __decorateClass([
65
66
  Entity({ tableName: "dictionaries" }),
66
67
  Unique({ name: "dictionaries_scope_key_unique", properties: ["organizationId", "tenantId", "key"] })
67
68
  ], Dictionary);
69
+ OptionalProps;
68
70
  let DictionaryEntry = class {
69
71
  constructor() {
72
+ this.position = 0;
73
+ this.isDefault = false;
70
74
  this.createdAt = /* @__PURE__ */ new Date();
71
75
  this.updatedAt = /* @__PURE__ */ new Date();
72
76
  }
@@ -98,6 +102,12 @@ __decorateClass([
98
102
  __decorateClass([
99
103
  Property({ type: "text", nullable: true })
100
104
  ], DictionaryEntry.prototype, "icon", 2);
105
+ __decorateClass([
106
+ Property({ type: "int", default: 0 })
107
+ ], DictionaryEntry.prototype, "position", 2);
108
+ __decorateClass([
109
+ Property({ name: "is_default", type: "boolean", default: false })
110
+ ], DictionaryEntry.prototype, "isDefault", 2);
101
111
  __decorateClass([
102
112
  Property({ name: "created_at", type: Date, onCreate: () => /* @__PURE__ */ new Date() })
103
113
  ], DictionaryEntry.prototype, "createdAt", 2);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/dictionaries/data/entities.ts"],
4
- "sourcesContent": ["import {\n Entity,\n PrimaryKey,\n Property,\n Unique,\n Index,\n ManyToOne,\n} from '@mikro-orm/core'\n\nexport type DictionaryManagerVisibility = 'default' | 'hidden'\n\n@Entity({ tableName: 'dictionaries' })\n@Unique({ name: 'dictionaries_scope_key_unique', properties: ['organizationId', 'tenantId', 'key'] })\nexport class Dictionary {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ type: 'text' })\n key!: string\n\n @Property({ type: 'text' })\n name!: string\n\n @Property({ type: 'text', nullable: true })\n description?: string | null\n\n @Property({ name: 'is_system', type: 'boolean', default: false })\n isSystem: boolean = false\n\n @Property({ name: 'is_active', type: 'boolean', default: true })\n isActive: boolean = true\n\n @Property({ name: 'manager_visibility', type: 'text', default: 'default' })\n managerVisibility: DictionaryManagerVisibility = 'default'\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'dictionary_entries' })\n@Index({ name: 'dictionary_entries_scope_idx', properties: ['dictionary', 'organizationId', 'tenantId'] })\n@Unique({ name: 'dictionary_entries_unique', properties: ['dictionary', 'organizationId', 'tenantId', 'normalizedValue'] })\nexport class DictionaryEntry {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => Dictionary, { fieldName: 'dictionary_id' })\n dictionary!: Dictionary\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ type: 'text' })\n value!: string\n\n @Property({ name: 'normalized_value', type: 'text' })\n normalizedValue!: string\n\n @Property({ type: 'text' })\n label!: string\n\n @Property({ type: 'text', nullable: true })\n color?: string | null\n\n @Property({ type: 'text', nullable: true })\n icon?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n Entity,\n PrimaryKey,\n Property,\n Unique,\n Index,\n ManyToOne,\n OptionalProps,\n} from '@mikro-orm/core'\n\nexport type DictionaryManagerVisibility = 'default' | 'hidden'\n\n@Entity({ tableName: 'dictionaries' })\n@Unique({ name: 'dictionaries_scope_key_unique', properties: ['organizationId', 'tenantId', 'key'] })\nexport class Dictionary {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ type: 'text' })\n key!: string\n\n @Property({ type: 'text' })\n name!: string\n\n @Property({ type: 'text', nullable: true })\n description?: string | null\n\n @Property({ name: 'is_system', type: 'boolean', default: false })\n isSystem: boolean = false\n\n @Property({ name: 'is_active', type: 'boolean', default: true })\n isActive: boolean = true\n\n @Property({ name: 'manager_visibility', type: 'text', default: 'default' })\n managerVisibility: DictionaryManagerVisibility = 'default'\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'dictionary_entries' })\n@Index({ name: 'dictionary_entries_scope_idx', properties: ['dictionary', 'organizationId', 'tenantId'] })\n@Unique({ name: 'dictionary_entries_unique', properties: ['dictionary', 'organizationId', 'tenantId', 'normalizedValue'] })\nexport class DictionaryEntry {\n [OptionalProps]?: 'position' | 'isDefault' | 'createdAt' | 'updatedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @ManyToOne(() => Dictionary, { fieldName: 'dictionary_id' })\n dictionary!: Dictionary\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ type: 'text' })\n value!: string\n\n @Property({ name: 'normalized_value', type: 'text' })\n normalizedValue!: string\n\n @Property({ type: 'text' })\n label!: string\n\n @Property({ type: 'text', nullable: true })\n color?: string | null\n\n @Property({ type: 'text', nullable: true })\n icon?: string | null\n\n @Property({ type: 'int', default: 0 })\n position: number = 0\n\n @Property({ name: 'is_default', type: 'boolean', default: false })\n isDefault: boolean = false\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -13,13 +13,16 @@ const createDictionaryEntrySchema = z.object({
13
13
  value: z.string().trim().min(1).max(150),
14
14
  label: z.string().trim().min(1).max(150).optional(),
15
15
  color: hexColorSchema.nullable().optional(),
16
- icon: iconSchema.nullable().optional()
16
+ icon: iconSchema.nullable().optional(),
17
+ position: z.number().int().min(0).optional()
17
18
  });
18
19
  const dictionaryEntryUpdateFieldsSchema = z.object({
19
20
  value: z.string().trim().min(1).max(150).optional(),
20
21
  label: z.string().trim().min(1).max(150).optional(),
21
22
  color: hexColorSchema.nullable().optional(),
22
- icon: iconSchema.nullable().optional()
23
+ icon: iconSchema.nullable().optional(),
24
+ position: z.number().int().min(0).optional(),
25
+ isDefault: z.boolean().optional()
23
26
  });
24
27
  const validateDictionaryEntryUpdate = (payload) => Object.keys(payload).length > 0;
25
28
  const updateDictionaryEntrySchema = dictionaryEntryUpdateFieldsSchema.refine(
@@ -36,11 +39,34 @@ const dictionaryEntryCommandUpdateSchema = z.object({
36
39
  }).merge(dictionaryEntryUpdateFieldsSchema).refine(validateDictionaryEntryUpdate, {
37
40
  message: "Provide at least one field to update."
38
41
  });
42
+ const reorderDictionaryEntriesSchema = z.object({
43
+ entries: z.array(z.object({
44
+ id: z.string().uuid(),
45
+ position: z.number().int().min(0)
46
+ })).min(1)
47
+ });
48
+ const reorderDictionaryEntriesCommandSchema = reorderDictionaryEntriesSchema.extend({
49
+ dictionaryId: z.string().uuid(),
50
+ tenantId: z.string().uuid(),
51
+ organizationId: z.string().uuid()
52
+ });
53
+ const setDefaultDictionaryEntrySchema = z.object({
54
+ entryId: z.string().uuid()
55
+ });
56
+ const setDefaultDictionaryEntryCommandSchema = setDefaultDictionaryEntrySchema.extend({
57
+ dictionaryId: z.string().uuid(),
58
+ tenantId: z.string().uuid(),
59
+ organizationId: z.string().uuid()
60
+ });
39
61
  export {
40
62
  createDictionaryEntrySchema,
41
63
  dictionaryEntryCommandCreateSchema,
42
64
  dictionaryEntryCommandUpdateSchema,
43
65
  dictionaryKeySchema,
66
+ reorderDictionaryEntriesCommandSchema,
67
+ reorderDictionaryEntriesSchema,
68
+ setDefaultDictionaryEntryCommandSchema,
69
+ setDefaultDictionaryEntrySchema,
44
70
  updateDictionaryEntrySchema,
45
71
  upsertDictionarySchema
46
72
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/dictionaries/data/validators.ts"],
4
- "sourcesContent": ["import { z } from 'zod'\n\nexport const dictionaryKeySchema = z\n .string()\n .trim()\n .min(1)\n .max(100)\n .regex(/^[a-z0-9][a-z0-9_-]*$/, 'Use lowercase letters, numbers, hyphen, or underscore.')\n\nconst hexColorSchema = z\n .string()\n .trim()\n .regex(/^#([0-9a-fA-F]{6})$/, 'Color must be a valid six-digit hex code like #3366ff')\n\nconst iconSchema = z.string().trim().min(1).max(64)\n\nexport const upsertDictionarySchema = z.object({\n key: dictionaryKeySchema,\n name: z.string().trim().min(1).max(200),\n description: z.string().trim().max(2000).optional(),\n isSystem: z.boolean().optional(),\n isActive: z.boolean().optional(),\n})\n\nexport type UpsertDictionaryInput = z.infer<typeof upsertDictionarySchema>\n\nexport const createDictionaryEntrySchema = z.object({\n value: z.string().trim().min(1).max(150),\n label: z.string().trim().min(1).max(150).optional(),\n color: hexColorSchema.nullable().optional(),\n icon: iconSchema.nullable().optional(),\n})\n\nexport type CreateDictionaryEntryInput = z.infer<typeof createDictionaryEntrySchema>\n\nconst dictionaryEntryUpdateFieldsSchema = z.object({\n value: z.string().trim().min(1).max(150).optional(),\n label: z.string().trim().min(1).max(150).optional(),\n color: hexColorSchema.nullable().optional(),\n icon: iconSchema.nullable().optional(),\n})\n\nconst validateDictionaryEntryUpdate = (payload: z.infer<typeof dictionaryEntryUpdateFieldsSchema>) =>\n Object.keys(payload).length > 0\n\nexport const updateDictionaryEntrySchema = dictionaryEntryUpdateFieldsSchema.refine(\n validateDictionaryEntryUpdate,\n {\n message: 'Provide at least one field to update.',\n },\n)\n\nexport type UpdateDictionaryEntryInput = z.infer<typeof updateDictionaryEntrySchema>\n\nexport const dictionaryEntryCommandCreateSchema = createDictionaryEntrySchema.extend({\n dictionaryId: z.string().uuid(),\n})\n\nexport type DictionaryEntryCommandCreateInput = z.infer<typeof dictionaryEntryCommandCreateSchema>\n\nexport const dictionaryEntryCommandUpdateSchema = z\n .object({\n id: z.string().uuid(),\n })\n .merge(dictionaryEntryUpdateFieldsSchema)\n .refine(validateDictionaryEntryUpdate, {\n message: 'Provide at least one field to update.',\n })\n\nexport type DictionaryEntryCommandUpdateInput = z.infer<typeof dictionaryEntryCommandUpdateSchema>\n"],
5
- "mappings": "AAAA,SAAS,SAAS;AAEX,MAAM,sBAAsB,EAChC,OAAO,EACP,KAAK,EACL,IAAI,CAAC,EACL,IAAI,GAAG,EACP,MAAM,yBAAyB,wDAAwD;AAE1F,MAAM,iBAAiB,EACpB,OAAO,EACP,KAAK,EACL,MAAM,uBAAuB,uDAAuD;AAEvF,MAAM,aAAa,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE;AAE3C,MAAM,yBAAyB,EAAE,OAAO;AAAA,EAC7C,KAAK;AAAA,EACL,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG;AAAA,EACtC,aAAa,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,GAAI,EAAE,SAAS;AAAA,EAClD,UAAU,EAAE,QAAQ,EAAE,SAAS;AAAA,EAC/B,UAAU,EAAE,QAAQ,EAAE,SAAS;AACjC,CAAC;AAIM,MAAM,8BAA8B,EAAE,OAAO;AAAA,EAClD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG;AAAA,EACvC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS;AAAA,EAClD,OAAO,eAAe,SAAS,EAAE,SAAS;AAAA,EAC1C,MAAM,WAAW,SAAS,EAAE,SAAS;AACvC,CAAC;AAID,MAAM,oCAAoC,EAAE,OAAO;AAAA,EACjD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS;AAAA,EAClD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS;AAAA,EAClD,OAAO,eAAe,SAAS,EAAE,SAAS;AAAA,EAC1C,MAAM,WAAW,SAAS,EAAE,SAAS;AACvC,CAAC;AAED,MAAM,gCAAgC,CAAC,YACrC,OAAO,KAAK,OAAO,EAAE,SAAS;AAEzB,MAAM,8BAA8B,kCAAkC;AAAA,EAC3E;AAAA,EACA;AAAA,IACE,SAAS;AAAA,EACX;AACF;AAIO,MAAM,qCAAqC,4BAA4B,OAAO;AAAA,EACnF,cAAc,EAAE,OAAO,EAAE,KAAK;AAChC,CAAC;AAIM,MAAM,qCAAqC,EAC/C,OAAO;AAAA,EACN,IAAI,EAAE,OAAO,EAAE,KAAK;AACtB,CAAC,EACA,MAAM,iCAAiC,EACvC,OAAO,+BAA+B;AAAA,EACrC,SAAS;AACX,CAAC;",
4
+ "sourcesContent": ["import { z } from 'zod'\n\nexport const dictionaryKeySchema = z\n .string()\n .trim()\n .min(1)\n .max(100)\n .regex(/^[a-z0-9][a-z0-9_-]*$/, 'Use lowercase letters, numbers, hyphen, or underscore.')\n\nconst hexColorSchema = z\n .string()\n .trim()\n .regex(/^#([0-9a-fA-F]{6})$/, 'Color must be a valid six-digit hex code like #3366ff')\n\nconst iconSchema = z.string().trim().min(1).max(64)\n\nexport const upsertDictionarySchema = z.object({\n key: dictionaryKeySchema,\n name: z.string().trim().min(1).max(200),\n description: z.string().trim().max(2000).optional(),\n isSystem: z.boolean().optional(),\n isActive: z.boolean().optional(),\n})\n\nexport type UpsertDictionaryInput = z.infer<typeof upsertDictionarySchema>\n\nexport const createDictionaryEntrySchema = z.object({\n value: z.string().trim().min(1).max(150),\n label: z.string().trim().min(1).max(150).optional(),\n color: hexColorSchema.nullable().optional(),\n icon: iconSchema.nullable().optional(),\n position: z.number().int().min(0).optional(),\n})\n\nexport type CreateDictionaryEntryInput = z.infer<typeof createDictionaryEntrySchema>\n\nconst dictionaryEntryUpdateFieldsSchema = z.object({\n value: z.string().trim().min(1).max(150).optional(),\n label: z.string().trim().min(1).max(150).optional(),\n color: hexColorSchema.nullable().optional(),\n icon: iconSchema.nullable().optional(),\n position: z.number().int().min(0).optional(),\n isDefault: z.boolean().optional(),\n})\n\nconst validateDictionaryEntryUpdate = (payload: z.infer<typeof dictionaryEntryUpdateFieldsSchema>) =>\n Object.keys(payload).length > 0\n\nexport const updateDictionaryEntrySchema = dictionaryEntryUpdateFieldsSchema.refine(\n validateDictionaryEntryUpdate,\n {\n message: 'Provide at least one field to update.',\n },\n)\n\nexport type UpdateDictionaryEntryInput = z.infer<typeof updateDictionaryEntrySchema>\n\nexport const dictionaryEntryCommandCreateSchema = createDictionaryEntrySchema.extend({\n dictionaryId: z.string().uuid(),\n})\n\nexport type DictionaryEntryCommandCreateInput = z.infer<typeof dictionaryEntryCommandCreateSchema>\n\nexport const dictionaryEntryCommandUpdateSchema = z\n .object({\n id: z.string().uuid(),\n })\n .merge(dictionaryEntryUpdateFieldsSchema)\n .refine(validateDictionaryEntryUpdate, {\n message: 'Provide at least one field to update.',\n })\n\nexport type DictionaryEntryCommandUpdateInput = z.infer<typeof dictionaryEntryCommandUpdateSchema>\n\nexport const reorderDictionaryEntriesSchema = z.object({\n entries: z.array(z.object({\n id: z.string().uuid(),\n position: z.number().int().min(0),\n })).min(1),\n})\n\nexport type ReorderDictionaryEntriesInput = z.infer<typeof reorderDictionaryEntriesSchema>\n\nexport const reorderDictionaryEntriesCommandSchema = reorderDictionaryEntriesSchema.extend({\n dictionaryId: z.string().uuid(),\n tenantId: z.string().uuid(),\n organizationId: z.string().uuid(),\n})\n\nexport type ReorderDictionaryEntriesCommandInput = z.infer<typeof reorderDictionaryEntriesCommandSchema>\n\nexport const setDefaultDictionaryEntrySchema = z.object({\n entryId: z.string().uuid(),\n})\n\nexport type SetDefaultDictionaryEntryInput = z.infer<typeof setDefaultDictionaryEntrySchema>\n\nexport const setDefaultDictionaryEntryCommandSchema = setDefaultDictionaryEntrySchema.extend({\n dictionaryId: z.string().uuid(),\n tenantId: z.string().uuid(),\n organizationId: z.string().uuid(),\n})\n\nexport type SetDefaultDictionaryEntryCommandInput = z.infer<typeof setDefaultDictionaryEntryCommandSchema>\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,18 @@
1
+ import { createModuleEvents } from "@open-mercato/shared/modules/events";
2
+ const events = [
3
+ { id: "dictionaries.entry.created", label: "Dictionary Entry Created", entity: "entry", category: "crud" },
4
+ { id: "dictionaries.entry.updated", label: "Dictionary Entry Updated", entity: "entry", category: "crud" },
5
+ { id: "dictionaries.entry.deleted", label: "Dictionary Entry Deleted", entity: "entry", category: "crud" }
6
+ ];
7
+ const eventsConfig = createModuleEvents({
8
+ moduleId: "dictionaries",
9
+ events
10
+ });
11
+ const emitDictionariesEvent = eventsConfig.emit;
12
+ var events_default = eventsConfig;
13
+ export {
14
+ events_default as default,
15
+ emitDictionariesEvent,
16
+ eventsConfig
17
+ };
18
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/modules/dictionaries/events.ts"],
4
+ "sourcesContent": ["import { createModuleEvents } from '@open-mercato/shared/modules/events'\n\nconst events = [\n { id: 'dictionaries.entry.created', label: 'Dictionary Entry Created', entity: 'entry', category: 'crud' },\n { id: 'dictionaries.entry.updated', label: 'Dictionary Entry Updated', entity: 'entry', category: 'crud' },\n { id: 'dictionaries.entry.deleted', label: 'Dictionary Entry Deleted', entity: 'entry', category: 'crud' },\n] as const\n\nexport const eventsConfig = createModuleEvents({\n moduleId: 'dictionaries',\n events,\n})\n\n/** Type-safe event emitter for dictionaries module */\nexport const emitDictionariesEvent = eventsConfig.emit\n\n/** Event IDs that can be emitted by the dictionaries module */\nexport type DictionariesEventId = typeof events[number]['id']\n\nexport default eventsConfig\n"],
5
+ "mappings": "AAAA,SAAS,0BAA0B;AAEnC,MAAM,SAAS;AAAA,EACb,EAAE,IAAI,8BAA8B,OAAO,4BAA4B,QAAQ,SAAS,UAAU,OAAO;AAAA,EACzG,EAAE,IAAI,8BAA8B,OAAO,4BAA4B,QAAQ,SAAS,UAAU,OAAO;AAAA,EACzG,EAAE,IAAI,8BAA8B,OAAO,4BAA4B,QAAQ,SAAS,UAAU,OAAO;AAC3G;AAEO,MAAM,eAAe,mBAAmB;AAAA,EAC7C,UAAU;AAAA,EACV;AACF,CAAC;AAGM,MAAM,wBAAwB,aAAa;AAKlD,IAAO,iBAAQ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,43 @@
1
+ "use client";
2
+ import { apiCall } from "@open-mercato/ui/backend/utils/apiCall";
3
+ function normalizeDictionaryList(items) {
4
+ if (!Array.isArray(items)) return [];
5
+ return items.map((item) => {
6
+ if (!item || typeof item !== "object") return null;
7
+ const record = item;
8
+ const id = typeof record.id === "string" ? record.id : null;
9
+ const key = typeof record.key === "string" ? record.key : null;
10
+ if (!id || !key) return null;
11
+ return { id, key };
12
+ }).filter((item) => !!item);
13
+ }
14
+ function normalizeDictionaryEntries(items) {
15
+ if (!Array.isArray(items)) return [];
16
+ return items.map((item) => {
17
+ if (!item || typeof item !== "object") return null;
18
+ const record = item;
19
+ const id = typeof record.id === "string" ? record.id : null;
20
+ const value = typeof record.value === "string" ? record.value : null;
21
+ if (!id || !value) return null;
22
+ return {
23
+ id,
24
+ value,
25
+ label: typeof record.label === "string" && record.label.trim().length > 0 ? record.label : value,
26
+ color: typeof record.color === "string" ? record.color : null,
27
+ icon: typeof record.icon === "string" ? record.icon : null
28
+ };
29
+ }).filter((item) => !!item);
30
+ }
31
+ async function loadDictionaryEntriesByKey(key) {
32
+ const dictionariesCall = await apiCall("/api/dictionaries");
33
+ if (!dictionariesCall.ok) return [];
34
+ const dictionary = normalizeDictionaryList(dictionariesCall.result?.items).find((item) => item.key === key);
35
+ if (!dictionary) return [];
36
+ const entriesCall = await apiCall(`/api/dictionaries/${dictionary.id}/entries`);
37
+ if (!entriesCall.ok) return [];
38
+ return normalizeDictionaryEntries(entriesCall.result?.items);
39
+ }
40
+ export {
41
+ loadDictionaryEntriesByKey
42
+ };
43
+ //# sourceMappingURL=clientEntries.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/dictionaries/lib/clientEntries.ts"],
4
+ "sourcesContent": ["\"use client\"\n\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\n\ntype DictionarySummary = {\n id: string\n key: string\n}\n\nexport type DictionaryEntryOption = {\n id: string\n value: string\n label: string\n color: string | null\n icon: string | null\n}\n\nfunction normalizeDictionaryList(items: unknown): DictionarySummary[] {\n if (!Array.isArray(items)) return []\n return items\n .map((item) => {\n if (!item || typeof item !== 'object') return null\n const record = item as Record<string, unknown>\n const id = typeof record.id === 'string' ? record.id : null\n const key = typeof record.key === 'string' ? record.key : null\n if (!id || !key) return null\n return { id, key }\n })\n .filter((item): item is DictionarySummary => !!item)\n}\n\nfunction normalizeDictionaryEntries(items: unknown): DictionaryEntryOption[] {\n if (!Array.isArray(items)) return []\n return items\n .map((item) => {\n if (!item || typeof item !== 'object') return null\n const record = item as Record<string, unknown>\n const id = typeof record.id === 'string' ? record.id : null\n const value = typeof record.value === 'string' ? record.value : null\n if (!id || !value) return null\n return {\n id,\n value,\n label:\n typeof record.label === 'string' && record.label.trim().length > 0\n ? record.label\n : value,\n color: typeof record.color === 'string' ? record.color : null,\n icon: typeof record.icon === 'string' ? record.icon : null,\n }\n })\n .filter((item): item is DictionaryEntryOption => !!item)\n}\n\nexport async function loadDictionaryEntriesByKey(key: string): Promise<DictionaryEntryOption[]> {\n const dictionariesCall = await apiCall<{ items?: unknown[] }>('/api/dictionaries')\n if (!dictionariesCall.ok) return []\n\n const dictionary = normalizeDictionaryList(dictionariesCall.result?.items).find((item) => item.key === key)\n if (!dictionary) return []\n\n const entriesCall = await apiCall<{ items?: unknown[] }>(`/api/dictionaries/${dictionary.id}/entries`)\n if (!entriesCall.ok) return []\n\n return normalizeDictionaryEntries(entriesCall.result?.items)\n}\n"],
5
+ "mappings": ";AAEA,SAAS,eAAe;AAexB,SAAS,wBAAwB,OAAqC;AACpE,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO,CAAC;AACnC,SAAO,MACJ,IAAI,CAAC,SAAS;AACb,QAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;AAC9C,UAAM,SAAS;AACf,UAAM,KAAK,OAAO,OAAO,OAAO,WAAW,OAAO,KAAK;AACvD,UAAM,MAAM,OAAO,OAAO,QAAQ,WAAW,OAAO,MAAM;AAC1D,QAAI,CAAC,MAAM,CAAC,IAAK,QAAO;AACxB,WAAO,EAAE,IAAI,IAAI;AAAA,EACnB,CAAC,EACA,OAAO,CAAC,SAAoC,CAAC,CAAC,IAAI;AACvD;AAEA,SAAS,2BAA2B,OAAyC;AAC3E,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO,CAAC;AACnC,SAAO,MACJ,IAAI,CAAC,SAAS;AACb,QAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;AAC9C,UAAM,SAAS;AACf,UAAM,KAAK,OAAO,OAAO,OAAO,WAAW,OAAO,KAAK;AACvD,UAAM,QAAQ,OAAO,OAAO,UAAU,WAAW,OAAO,QAAQ;AAChE,QAAI,CAAC,MAAM,CAAC,MAAO,QAAO;AAC1B,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,OACE,OAAO,OAAO,UAAU,YAAY,OAAO,MAAM,KAAK,EAAE,SAAS,IAC7D,OAAO,QACP;AAAA,MACN,OAAO,OAAO,OAAO,UAAU,WAAW,OAAO,QAAQ;AAAA,MACzD,MAAM,OAAO,OAAO,SAAS,WAAW,OAAO,OAAO;AAAA,IACxD;AAAA,EACF,CAAC,EACA,OAAO,CAAC,SAAwC,CAAC,CAAC,IAAI;AAC3D;AAEA,eAAsB,2BAA2B,KAA+C;AAC9F,QAAM,mBAAmB,MAAM,QAA+B,mBAAmB;AACjF,MAAI,CAAC,iBAAiB,GAAI,QAAO,CAAC;AAElC,QAAM,aAAa,wBAAwB,iBAAiB,QAAQ,KAAK,EAAE,KAAK,CAAC,SAAS,KAAK,QAAQ,GAAG;AAC1G,MAAI,CAAC,WAAY,QAAO,CAAC;AAEzB,QAAM,cAAc,MAAM,QAA+B,qBAAqB,WAAW,EAAE,UAAU;AACrG,MAAI,CAAC,YAAY,GAAI,QAAO,CAAC;AAE7B,SAAO,2BAA2B,YAAY,QAAQ,KAAK;AAC7D;",
6
+ "names": []
7
+ }
@@ -0,0 +1,45 @@
1
+ import { Migration } from "@mikro-orm/migrations";
2
+ class Migration20260410171544 extends Migration {
3
+ async up() {
4
+ this.addSql(`alter table "dictionary_entries" add column "position" int not null default 0, add column "is_default" boolean not null default false;`);
5
+ this.addSql(`
6
+ with ranked_entries as (
7
+ select
8
+ "id",
9
+ row_number() over (
10
+ partition by "dictionary_id", "organization_id", "tenant_id"
11
+ order by lower("label"), lower("value"), "id"
12
+ ) - 1 as "rank"
13
+ from "dictionary_entries"
14
+ )
15
+ update "dictionary_entries" as "entries"
16
+ set "position" = ranked_entries."rank"
17
+ from ranked_entries
18
+ where ranked_entries."id" = "entries"."id";
19
+ `);
20
+ this.addSql(`create unique index "dictionary_entries_one_default_per_dict" on "dictionary_entries" ("dictionary_id", "organization_id", "tenant_id") where "is_default" = true;`);
21
+ this.addSql(`
22
+ update "dictionary_entries" as "entries"
23
+ set "is_default" = true
24
+ from "dictionaries" as "dictionaries"
25
+ where "entries"."dictionary_id" = "dictionaries"."id"
26
+ and "dictionaries"."key" = 'customers.status'
27
+ and "entries"."normalized_value" = 'active'
28
+ and not exists (
29
+ select 1 from "dictionary_entries" as "existing"
30
+ where "existing"."dictionary_id" = "entries"."dictionary_id"
31
+ and "existing"."organization_id" = "entries"."organization_id"
32
+ and "existing"."tenant_id" = "entries"."tenant_id"
33
+ and "existing"."is_default" = true
34
+ );
35
+ `);
36
+ }
37
+ async down() {
38
+ this.addSql(`drop index if exists "dictionary_entries_one_default_per_dict";`);
39
+ this.addSql(`alter table "dictionary_entries" drop column "position", drop column "is_default";`);
40
+ }
41
+ }
42
+ export {
43
+ Migration20260410171544
44
+ };
45
+ //# sourceMappingURL=Migration20260410171544.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/dictionaries/migrations/Migration20260410171544.ts"],
4
+ "sourcesContent": ["import { Migration } from '@mikro-orm/migrations';\n\nexport class Migration20260410171544 extends Migration {\n\n override async up(): Promise<void> {\n this.addSql(`alter table \"dictionary_entries\" add column \"position\" int not null default 0, add column \"is_default\" boolean not null default false;`);\n this.addSql(`\n with ranked_entries as (\n select\n \"id\",\n row_number() over (\n partition by \"dictionary_id\", \"organization_id\", \"tenant_id\"\n order by lower(\"label\"), lower(\"value\"), \"id\"\n ) - 1 as \"rank\"\n from \"dictionary_entries\"\n )\n update \"dictionary_entries\" as \"entries\"\n set \"position\" = ranked_entries.\"rank\"\n from ranked_entries\n where ranked_entries.\"id\" = \"entries\".\"id\";\n `);\n this.addSql(`create unique index \"dictionary_entries_one_default_per_dict\" on \"dictionary_entries\" (\"dictionary_id\", \"organization_id\", \"tenant_id\") where \"is_default\" = true;`);\n // Seed an initial default for the out-of-the-box `customers.status` dictionary only.\n // Scoped by the seeded key + normalized 'active' value so tenants that customized\n // their status dictionary (renamed the key, removed 'active', or already set a\n // default through the new UI after deploying this migration) are not overridden.\n this.addSql(`\n update \"dictionary_entries\" as \"entries\"\n set \"is_default\" = true\n from \"dictionaries\" as \"dictionaries\"\n where \"entries\".\"dictionary_id\" = \"dictionaries\".\"id\"\n and \"dictionaries\".\"key\" = 'customers.status'\n and \"entries\".\"normalized_value\" = 'active'\n and not exists (\n select 1 from \"dictionary_entries\" as \"existing\"\n where \"existing\".\"dictionary_id\" = \"entries\".\"dictionary_id\"\n and \"existing\".\"organization_id\" = \"entries\".\"organization_id\"\n and \"existing\".\"tenant_id\" = \"entries\".\"tenant_id\"\n and \"existing\".\"is_default\" = true\n );\n `);\n }\n\n override async down(): Promise<void> {\n this.addSql(`drop index if exists \"dictionary_entries_one_default_per_dict\";`);\n this.addSql(`alter table \"dictionary_entries\" drop column \"position\", drop column \"is_default\";`);\n }\n\n}\n"],
5
+ "mappings": "AAAA,SAAS,iBAAiB;AAEnB,MAAM,gCAAgC,UAAU;AAAA,EAErD,MAAe,KAAoB;AACjC,SAAK,OAAO,wIAAwI;AACpJ,SAAK,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAcX;AACD,SAAK,OAAO,oKAAoK;AAKhL,SAAK,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAcX;AAAA,EACH;AAAA,EAEA,MAAe,OAAsB;AACnC,SAAK,OAAO,iEAAiE;AAC7E,SAAK,OAAO,oFAAoF;AAAA,EAClG;AAEF;",
6
+ "names": []
7
+ }
@@ -44,7 +44,10 @@ async function GET(req) {
44
44
  )
45
45
  ]);
46
46
  return NextResponse.json({
47
- proposal,
47
+ proposal: {
48
+ ...proposal,
49
+ actions
50
+ },
48
51
  actions,
49
52
  discrepancies,
50
53
  email
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/modules/inbox_ops/api/proposals/%5Bid%5D/route.ts"],
4
- "sourcesContent": ["import { NextResponse } from 'next/server'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { InboxProposalAction, InboxDiscrepancy, InboxEmail } from '../../../data/entities'\nimport {\n resolveRequestContext,\n resolveProposal,\n handleRouteError,\n isErrorResponse,\n} from '../../routeHelpers'\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['inbox_ops.proposals.view'] },\n}\n\nexport async function GET(req: Request) {\n try {\n const ctx = await resolveRequestContext(req)\n const proposal = await resolveProposal(new URL(req.url), ctx)\n if (isErrorResponse(proposal)) return proposal\n\n const [actions, discrepancies, email] = await Promise.all([\n findWithDecryption(\n ctx.em,\n InboxProposalAction,\n { proposalId: proposal.id, organizationId: ctx.organizationId, tenantId: ctx.tenantId, deletedAt: null },\n { orderBy: { sortOrder: 'ASC' } },\n ctx.scope,\n ),\n findWithDecryption(\n ctx.em,\n InboxDiscrepancy,\n { proposalId: proposal.id, organizationId: ctx.organizationId, tenantId: ctx.tenantId, deletedAt: null },\n { orderBy: { createdAt: 'ASC' } },\n ctx.scope,\n ),\n findOneWithDecryption(\n ctx.em,\n InboxEmail,\n {\n id: proposal.inboxEmailId,\n organizationId: ctx.organizationId,\n tenantId: ctx.tenantId,\n deletedAt: null,\n },\n undefined,\n ctx.scope,\n ),\n ])\n\n return NextResponse.json({\n proposal,\n actions,\n discrepancies,\n email,\n })\n } catch (err) {\n return handleRouteError(err, 'load proposal')\n }\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'InboxOps',\n summary: 'Proposal detail',\n methods: {\n GET: {\n summary: 'Get proposal detail',\n description: 'Returns proposal with actions, discrepancies, and source email',\n responses: [\n { status: 200, description: 'Full proposal detail' },\n { status: 404, description: 'Proposal not found' },\n ],\n },\n },\n}\n"],
5
- "mappings": "AAAA,SAAS,oBAAoB;AAE7B,SAAS,uBAAuB,0BAA0B;AAC1D,SAAS,qBAAqB,kBAAkB,kBAAkB;AAClE;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEA,MAAM,WAAW;AAAA,EACtB,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,0BAA0B,EAAE;AAC1E;AAEA,eAAsB,IAAI,KAAc;AACtC,MAAI;AACF,UAAM,MAAM,MAAM,sBAAsB,GAAG;AAC3C,UAAM,WAAW,MAAM,gBAAgB,IAAI,IAAI,IAAI,GAAG,GAAG,GAAG;AAC5D,QAAI,gBAAgB,QAAQ,EAAG,QAAO;AAEtC,UAAM,CAAC,SAAS,eAAe,KAAK,IAAI,MAAM,QAAQ,IAAI;AAAA,MACxD;AAAA,QACE,IAAI;AAAA,QACJ;AAAA,QACA,EAAE,YAAY,SAAS,IAAI,gBAAgB,IAAI,gBAAgB,UAAU,IAAI,UAAU,WAAW,KAAK;AAAA,QACvG,EAAE,SAAS,EAAE,WAAW,MAAM,EAAE;AAAA,QAChC,IAAI;AAAA,MACN;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ;AAAA,QACA,EAAE,YAAY,SAAS,IAAI,gBAAgB,IAAI,gBAAgB,UAAU,IAAI,UAAU,WAAW,KAAK;AAAA,QACvG,EAAE,SAAS,EAAE,WAAW,MAAM,EAAE;AAAA,QAChC,IAAI;AAAA,MACN;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ;AAAA,QACA;AAAA,UACE,IAAI,SAAS;AAAA,UACb,gBAAgB,IAAI;AAAA,UACpB,UAAU,IAAI;AAAA,UACd,WAAW;AAAA,QACb;AAAA,QACA;AAAA,QACA,IAAI;AAAA,MACN;AAAA,IACF,CAAC;AAED,WAAO,aAAa,KAAK;AAAA,MACvB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,WAAO,iBAAiB,KAAK,eAAe;AAAA,EAC9C;AACF;AAEO,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,SAAS;AAAA,IACP,KAAK;AAAA,MACH,SAAS;AAAA,MACT,aAAa;AAAA,MACb,WAAW;AAAA,QACT,EAAE,QAAQ,KAAK,aAAa,uBAAuB;AAAA,QACnD,EAAE,QAAQ,KAAK,aAAa,qBAAqB;AAAA,MACnD;AAAA,IACF;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { InboxProposalAction, InboxDiscrepancy, InboxEmail } from '../../../data/entities'\nimport {\n resolveRequestContext,\n resolveProposal,\n handleRouteError,\n isErrorResponse,\n} from '../../routeHelpers'\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['inbox_ops.proposals.view'] },\n}\n\nexport async function GET(req: Request) {\n try {\n const ctx = await resolveRequestContext(req)\n const proposal = await resolveProposal(new URL(req.url), ctx)\n if (isErrorResponse(proposal)) return proposal\n\n const [actions, discrepancies, email] = await Promise.all([\n findWithDecryption(\n ctx.em,\n InboxProposalAction,\n { proposalId: proposal.id, organizationId: ctx.organizationId, tenantId: ctx.tenantId, deletedAt: null },\n { orderBy: { sortOrder: 'ASC' } },\n ctx.scope,\n ),\n findWithDecryption(\n ctx.em,\n InboxDiscrepancy,\n { proposalId: proposal.id, organizationId: ctx.organizationId, tenantId: ctx.tenantId, deletedAt: null },\n { orderBy: { createdAt: 'ASC' } },\n ctx.scope,\n ),\n findOneWithDecryption(\n ctx.em,\n InboxEmail,\n {\n id: proposal.inboxEmailId,\n organizationId: ctx.organizationId,\n tenantId: ctx.tenantId,\n deletedAt: null,\n },\n undefined,\n ctx.scope,\n ),\n ])\n\n return NextResponse.json({\n proposal: {\n ...proposal,\n actions,\n },\n actions,\n discrepancies,\n email,\n })\n } catch (err) {\n return handleRouteError(err, 'load proposal')\n }\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'InboxOps',\n summary: 'Proposal detail',\n methods: {\n GET: {\n summary: 'Get proposal detail',\n description: 'Returns proposal with actions, discrepancies, and source email',\n responses: [\n { status: 200, description: 'Full proposal detail' },\n { status: 404, description: 'Proposal not found' },\n ],\n },\n },\n}\n"],
5
+ "mappings": "AAAA,SAAS,oBAAoB;AAE7B,SAAS,uBAAuB,0BAA0B;AAC1D,SAAS,qBAAqB,kBAAkB,kBAAkB;AAClE;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEA,MAAM,WAAW;AAAA,EACtB,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,0BAA0B,EAAE;AAC1E;AAEA,eAAsB,IAAI,KAAc;AACtC,MAAI;AACF,UAAM,MAAM,MAAM,sBAAsB,GAAG;AAC3C,UAAM,WAAW,MAAM,gBAAgB,IAAI,IAAI,IAAI,GAAG,GAAG,GAAG;AAC5D,QAAI,gBAAgB,QAAQ,EAAG,QAAO;AAEtC,UAAM,CAAC,SAAS,eAAe,KAAK,IAAI,MAAM,QAAQ,IAAI;AAAA,MACxD;AAAA,QACE,IAAI;AAAA,QACJ;AAAA,QACA,EAAE,YAAY,SAAS,IAAI,gBAAgB,IAAI,gBAAgB,UAAU,IAAI,UAAU,WAAW,KAAK;AAAA,QACvG,EAAE,SAAS,EAAE,WAAW,MAAM,EAAE;AAAA,QAChC,IAAI;AAAA,MACN;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ;AAAA,QACA,EAAE,YAAY,SAAS,IAAI,gBAAgB,IAAI,gBAAgB,UAAU,IAAI,UAAU,WAAW,KAAK;AAAA,QACvG,EAAE,SAAS,EAAE,WAAW,MAAM,EAAE;AAAA,QAChC,IAAI;AAAA,MACN;AAAA,MACA;AAAA,QACE,IAAI;AAAA,QACJ;AAAA,QACA;AAAA,UACE,IAAI,SAAS;AAAA,UACb,gBAAgB,IAAI;AAAA,UACpB,UAAU,IAAI;AAAA,UACd,WAAW;AAAA,QACb;AAAA,QACA;AAAA,QACA,IAAI;AAAA,MACN;AAAA,IACF,CAAC;AAED,WAAO,aAAa,KAAK;AAAA,MACvB,UAAU;AAAA,QACR,GAAG;AAAA,QACH;AAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,WAAO,iBAAiB,KAAK,eAAe;AAAA,EAC9C;AACF;AAEO,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,SAAS;AAAA,IACP,KAAK;AAAA,MACH,SAAS;AAAA,MACT,aAAa;AAAA,MACb,WAAW;AAAA,QACT,EAAE,QAAQ,KAAK,aAAa,uBAAuB;AAAA,QACnD,EAAE,QAAQ,KAAK,aAAa,qBAAqB;AAAA,MACnD;AAAA,IACF;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -637,7 +637,7 @@ class HybridQueryEngine {
637
637
  };
638
638
  const applyJoinSearchFilterOp = async (target, filter, _qualified, join) => {
639
639
  if (!searchEnabled || !join.entityId) return false;
640
- if (!["like", "ilike"].includes(filter.op)) return false;
640
+ if (!["eq", "like", "ilike"].includes(filter.op)) return false;
641
641
  if (typeof filter.value !== "string" || filter.value.trim().length === 0) return false;
642
642
  let searchAvailable = joinSearchAvailability.get(join.entityId);
643
643
  if (searchAvailable === void 0) {