@endora-commerce/mod-organizations 0.100.0

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 (288) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +62 -0
  3. package/dist/admin/components/OrganizationSalesRepsTab.d.ts +27 -0
  4. package/dist/admin/components/OrganizationSalesRepsTab.d.ts.map +1 -0
  5. package/dist/admin/components/OrganizationSalesRepsTab.js +170 -0
  6. package/dist/admin/components/OrganizationSalesRepsTab.js.map +1 -0
  7. package/dist/admin/index.d.ts +30 -0
  8. package/dist/admin/index.d.ts.map +1 -0
  9. package/dist/admin/index.js +59 -0
  10. package/dist/admin/index.js.map +1 -0
  11. package/dist/admin/pages/OrganizationDetail.d.ts +9 -0
  12. package/dist/admin/pages/OrganizationDetail.d.ts.map +1 -0
  13. package/dist/admin/pages/OrganizationDetail.js +247 -0
  14. package/dist/admin/pages/OrganizationDetail.js.map +1 -0
  15. package/dist/admin/pages/OrganizationsList.d.ts +9 -0
  16. package/dist/admin/pages/OrganizationsList.d.ts.map +1 -0
  17. package/dist/admin/pages/OrganizationsList.js +73 -0
  18. package/dist/admin/pages/OrganizationsList.js.map +1 -0
  19. package/dist/admin/panels/ApplicablePriceListsPanel.d.ts +12 -0
  20. package/dist/admin/panels/ApplicablePriceListsPanel.d.ts.map +1 -0
  21. package/dist/admin/panels/ApplicablePriceListsPanel.js +49 -0
  22. package/dist/admin/panels/ApplicablePriceListsPanel.js.map +1 -0
  23. package/dist/admin/panels/FulfilmentStrategyPanel.d.ts +16 -0
  24. package/dist/admin/panels/FulfilmentStrategyPanel.d.ts.map +1 -0
  25. package/dist/admin/panels/FulfilmentStrategyPanel.js +29 -0
  26. package/dist/admin/panels/FulfilmentStrategyPanel.js.map +1 -0
  27. package/dist/admin/panels/HierarchyPanel.d.ts +15 -0
  28. package/dist/admin/panels/HierarchyPanel.d.ts.map +1 -0
  29. package/dist/admin/panels/HierarchyPanel.js +65 -0
  30. package/dist/admin/panels/HierarchyPanel.js.map +1 -0
  31. package/dist/admin/panels/ModerationActionsPanel.d.ts +28 -0
  32. package/dist/admin/panels/ModerationActionsPanel.d.ts.map +1 -0
  33. package/dist/admin/panels/ModerationActionsPanel.js +111 -0
  34. package/dist/admin/panels/ModerationActionsPanel.js.map +1 -0
  35. package/dist/admin/panels/RestrictionsPanel.d.ts +24 -0
  36. package/dist/admin/panels/RestrictionsPanel.d.ts.map +1 -0
  37. package/dist/admin/panels/RestrictionsPanel.js +121 -0
  38. package/dist/admin/panels/RestrictionsPanel.js.map +1 -0
  39. package/dist/admin/panels/VatValidationPanel.d.ts +28 -0
  40. package/dist/admin/panels/VatValidationPanel.d.ts.map +1 -0
  41. package/dist/admin/panels/VatValidationPanel.js +79 -0
  42. package/dist/admin/panels/VatValidationPanel.js.map +1 -0
  43. package/dist/backend/commands/move.command.d.ts +11 -0
  44. package/dist/backend/commands/move.command.d.ts.map +1 -0
  45. package/dist/backend/commands/move.command.js +11 -0
  46. package/dist/backend/commands/move.command.js.map +1 -0
  47. package/dist/backend/commands/set-cart-approval-policy.command.d.ts +31 -0
  48. package/dist/backend/commands/set-cart-approval-policy.command.d.ts.map +1 -0
  49. package/dist/backend/commands/set-cart-approval-policy.command.js +56 -0
  50. package/dist/backend/commands/set-cart-approval-policy.command.js.map +1 -0
  51. package/dist/backend/commands/set-credit-mode.command.d.ts +16 -0
  52. package/dist/backend/commands/set-credit-mode.command.d.ts.map +1 -0
  53. package/dist/backend/commands/set-credit-mode.command.js +25 -0
  54. package/dist/backend/commands/set-credit-mode.command.js.map +1 -0
  55. package/dist/backend/commands/set-parent.command.d.ts +26 -0
  56. package/dist/backend/commands/set-parent.command.d.ts.map +1 -0
  57. package/dist/backend/commands/set-parent.command.js +51 -0
  58. package/dist/backend/commands/set-parent.command.js.map +1 -0
  59. package/dist/backend/demo/reset.d.ts +20 -0
  60. package/dist/backend/demo/reset.d.ts.map +1 -0
  61. package/dist/backend/demo/reset.js +11 -0
  62. package/dist/backend/demo/reset.js.map +1 -0
  63. package/dist/backend/demo/rows.d.ts +44 -0
  64. package/dist/backend/demo/rows.d.ts.map +1 -0
  65. package/dist/backend/demo/rows.js +44 -0
  66. package/dist/backend/demo/rows.js.map +1 -0
  67. package/dist/backend/demo/seed.d.ts +20 -0
  68. package/dist/backend/demo/seed.d.ts.map +1 -0
  69. package/dist/backend/demo/seed.js +28 -0
  70. package/dist/backend/demo/seed.js.map +1 -0
  71. package/dist/backend/email-templates/invitation.d.ts +23 -0
  72. package/dist/backend/email-templates/invitation.d.ts.map +1 -0
  73. package/dist/backend/email-templates/invitation.js +35 -0
  74. package/dist/backend/email-templates/invitation.js.map +1 -0
  75. package/dist/backend/email-templates/transactional-defaults.d.ts +54 -0
  76. package/dist/backend/email-templates/transactional-defaults.d.ts.map +1 -0
  77. package/dist/backend/email-templates/transactional-defaults.js +242 -0
  78. package/dist/backend/email-templates/transactional-defaults.js.map +1 -0
  79. package/dist/backend/email-templates/verification.d.ts +14 -0
  80. package/dist/backend/email-templates/verification.d.ts.map +1 -0
  81. package/dist/backend/email-templates/verification.js +34 -0
  82. package/dist/backend/email-templates/verification.js.map +1 -0
  83. package/dist/backend/entities/email-verification-token.entity.d.ts +17 -0
  84. package/dist/backend/entities/email-verification-token.entity.d.ts.map +1 -0
  85. package/dist/backend/entities/email-verification-token.entity.js +60 -0
  86. package/dist/backend/entities/email-verification-token.entity.js.map +1 -0
  87. package/dist/backend/entities/organization-delivery-method-link.entity.d.ts +14 -0
  88. package/dist/backend/entities/organization-delivery-method-link.entity.d.ts.map +1 -0
  89. package/dist/backend/entities/organization-delivery-method-link.entity.js +41 -0
  90. package/dist/backend/entities/organization-delivery-method-link.entity.js.map +1 -0
  91. package/dist/backend/entities/organization-invitation.entity.d.ts +21 -0
  92. package/dist/backend/entities/organization-invitation.entity.d.ts.map +1 -0
  93. package/dist/backend/entities/organization-invitation.entity.js +85 -0
  94. package/dist/backend/entities/organization-invitation.entity.js.map +1 -0
  95. package/dist/backend/entities/organization-payment-method-link.entity.d.ts +14 -0
  96. package/dist/backend/entities/organization-payment-method-link.entity.d.ts.map +1 -0
  97. package/dist/backend/entities/organization-payment-method-link.entity.js +41 -0
  98. package/dist/backend/entities/organization-payment-method-link.entity.js.map +1 -0
  99. package/dist/backend/entities/organization-sales-rep-assignment.entity.d.ts +17 -0
  100. package/dist/backend/entities/organization-sales-rep-assignment.entity.d.ts.map +1 -0
  101. package/dist/backend/entities/organization-sales-rep-assignment.entity.js +56 -0
  102. package/dist/backend/entities/organization-sales-rep-assignment.entity.js.map +1 -0
  103. package/dist/backend/entities/organization-tax-id-validation.entity.d.ts +29 -0
  104. package/dist/backend/entities/organization-tax-id-validation.entity.d.ts.map +1 -0
  105. package/dist/backend/entities/organization-tax-id-validation.entity.js +78 -0
  106. package/dist/backend/entities/organization-tax-id-validation.entity.js.map +1 -0
  107. package/dist/backend/entities/organization-warehouse-link.entity.d.ts +15 -0
  108. package/dist/backend/entities/organization-warehouse-link.entity.d.ts.map +1 -0
  109. package/dist/backend/entities/organization-warehouse-link.entity.js +42 -0
  110. package/dist/backend/entities/organization-warehouse-link.entity.js.map +1 -0
  111. package/dist/backend/entities/organization.entity.d.ts +125 -0
  112. package/dist/backend/entities/organization.entity.d.ts.map +1 -0
  113. package/dist/backend/entities/organization.entity.js +282 -0
  114. package/dist/backend/entities/organization.entity.js.map +1 -0
  115. package/dist/backend/index.d.ts +250 -0
  116. package/dist/backend/index.d.ts.map +1 -0
  117. package/dist/backend/index.js +506 -0
  118. package/dist/backend/index.js.map +1 -0
  119. package/dist/backend/integrations/ministerstwo-finansow-client.d.ts +22 -0
  120. package/dist/backend/integrations/ministerstwo-finansow-client.d.ts.map +1 -0
  121. package/dist/backend/integrations/ministerstwo-finansow-client.js +172 -0
  122. package/dist/backend/integrations/ministerstwo-finansow-client.js.map +1 -0
  123. package/dist/backend/integrations/vies-client.d.ts +18 -0
  124. package/dist/backend/integrations/vies-client.d.ts.map +1 -0
  125. package/dist/backend/integrations/vies-client.js +133 -0
  126. package/dist/backend/integrations/vies-client.js.map +1 -0
  127. package/dist/backend/plugin.d.ts +126 -0
  128. package/dist/backend/plugin.d.ts.map +1 -0
  129. package/dist/backend/plugin.js +139 -0
  130. package/dist/backend/plugin.js.map +1 -0
  131. package/dist/backend/routes.admin.d.ts +66 -0
  132. package/dist/backend/routes.admin.d.ts.map +1 -0
  133. package/dist/backend/routes.admin.js +711 -0
  134. package/dist/backend/routes.admin.js.map +1 -0
  135. package/dist/backend/routes.customer.d.ts +33 -0
  136. package/dist/backend/routes.customer.d.ts.map +1 -0
  137. package/dist/backend/routes.customer.js +139 -0
  138. package/dist/backend/routes.customer.js.map +1 -0
  139. package/dist/backend/routes.members.d.ts +31 -0
  140. package/dist/backend/routes.members.d.ts.map +1 -0
  141. package/dist/backend/routes.members.js +109 -0
  142. package/dist/backend/routes.members.js.map +1 -0
  143. package/dist/backend/routes.public.d.ts +49 -0
  144. package/dist/backend/routes.public.d.ts.map +1 -0
  145. package/dist/backend/routes.public.js +220 -0
  146. package/dist/backend/routes.public.js.map +1 -0
  147. package/dist/backend/routes.sales-reps.d.ts +46 -0
  148. package/dist/backend/routes.sales-reps.d.ts.map +1 -0
  149. package/dist/backend/routes.sales-reps.js +114 -0
  150. package/dist/backend/routes.sales-reps.js.map +1 -0
  151. package/dist/backend/routes.storefront.d.ts +25 -0
  152. package/dist/backend/routes.storefront.d.ts.map +1 -0
  153. package/dist/backend/routes.storefront.js +65 -0
  154. package/dist/backend/routes.storefront.js.map +1 -0
  155. package/dist/backend/schemas/organization.d.ts +59 -0
  156. package/dist/backend/schemas/organization.d.ts.map +1 -0
  157. package/dist/backend/schemas/organization.js +55 -0
  158. package/dist/backend/schemas/organization.js.map +1 -0
  159. package/dist/backend/schemas/settings.d.ts +30 -0
  160. package/dist/backend/schemas/settings.d.ts.map +1 -0
  161. package/dist/backend/schemas/settings.js +35 -0
  162. package/dist/backend/schemas/settings.js.map +1 -0
  163. package/dist/backend/services/email-verification-service.d.ts +45 -0
  164. package/dist/backend/services/email-verification-service.d.ts.map +1 -0
  165. package/dist/backend/services/email-verification-service.js +95 -0
  166. package/dist/backend/services/email-verification-service.js.map +1 -0
  167. package/dist/backend/services/invitation-service.d.ts +85 -0
  168. package/dist/backend/services/invitation-service.d.ts.map +1 -0
  169. package/dist/backend/services/invitation-service.js +266 -0
  170. package/dist/backend/services/invitation-service.js.map +1 -0
  171. package/dist/backend/services/normalize-name.d.ts +14 -0
  172. package/dist/backend/services/normalize-name.d.ts.map +1 -0
  173. package/dist/backend/services/normalize-name.js +14 -0
  174. package/dist/backend/services/normalize-name.js.map +1 -0
  175. package/dist/backend/services/org-registration-notifier.d.ts +36 -0
  176. package/dist/backend/services/org-registration-notifier.d.ts.map +1 -0
  177. package/dist/backend/services/org-registration-notifier.js +109 -0
  178. package/dist/backend/services/org-registration-notifier.js.map +1 -0
  179. package/dist/backend/services/org-template-email.d.ts +18 -0
  180. package/dist/backend/services/org-template-email.d.ts.map +1 -0
  181. package/dist/backend/services/org-template-email.js +16 -0
  182. package/dist/backend/services/org-template-email.js.map +1 -0
  183. package/dist/backend/services/organization-context-service.d.ts +52 -0
  184. package/dist/backend/services/organization-context-service.d.ts.map +1 -0
  185. package/dist/backend/services/organization-context-service.js +70 -0
  186. package/dist/backend/services/organization-context-service.js.map +1 -0
  187. package/dist/backend/services/organization-country-reference.d.ts +11 -0
  188. package/dist/backend/services/organization-country-reference.d.ts.map +1 -0
  189. package/dist/backend/services/organization-country-reference.js +24 -0
  190. package/dist/backend/services/organization-country-reference.js.map +1 -0
  191. package/dist/backend/services/organization-details-port.d.ts +33 -0
  192. package/dist/backend/services/organization-details-port.d.ts.map +1 -0
  193. package/dist/backend/services/organization-details-port.js +95 -0
  194. package/dist/backend/services/organization-details-port.js.map +1 -0
  195. package/dist/backend/services/organization-effective-pricelists-service.d.ts +50 -0
  196. package/dist/backend/services/organization-effective-pricelists-service.d.ts.map +1 -0
  197. package/dist/backend/services/organization-effective-pricelists-service.js +68 -0
  198. package/dist/backend/services/organization-effective-pricelists-service.js.map +1 -0
  199. package/dist/backend/services/organization-inheritance-service.d.ts +73 -0
  200. package/dist/backend/services/organization-inheritance-service.d.ts.map +1 -0
  201. package/dist/backend/services/organization-inheritance-service.js +63 -0
  202. package/dist/backend/services/organization-inheritance-service.js.map +1 -0
  203. package/dist/backend/services/organization-moderation-service.d.ts +124 -0
  204. package/dist/backend/services/organization-moderation-service.d.ts.map +1 -0
  205. package/dist/backend/services/organization-moderation-service.js +337 -0
  206. package/dist/backend/services/organization-moderation-service.js.map +1 -0
  207. package/dist/backend/services/organization-restriction-service.d.ts +70 -0
  208. package/dist/backend/services/organization-restriction-service.d.ts.map +1 -0
  209. package/dist/backend/services/organization-restriction-service.js +210 -0
  210. package/dist/backend/services/organization-restriction-service.js.map +1 -0
  211. package/dist/backend/services/organization-tax-id-validation-service.d.ts +59 -0
  212. package/dist/backend/services/organization-tax-id-validation-service.d.ts.map +1 -0
  213. package/dist/backend/services/organization-tax-id-validation-service.js +115 -0
  214. package/dist/backend/services/organization-tax-id-validation-service.js.map +1 -0
  215. package/dist/backend/services/organization-tree-service.d.ts +102 -0
  216. package/dist/backend/services/organization-tree-service.d.ts.map +1 -0
  217. package/dist/backend/services/organization-tree-service.js +184 -0
  218. package/dist/backend/services/organization-tree-service.js.map +1 -0
  219. package/dist/backend/services/personal-organization-service.d.ts +130 -0
  220. package/dist/backend/services/personal-organization-service.d.ts.map +1 -0
  221. package/dist/backend/services/personal-organization-service.js +207 -0
  222. package/dist/backend/services/personal-organization-service.js.map +1 -0
  223. package/dist/backend/services/registration-service.d.ts +80 -0
  224. package/dist/backend/services/registration-service.d.ts.map +1 -0
  225. package/dist/backend/services/registration-service.js +126 -0
  226. package/dist/backend/services/registration-service.js.map +1 -0
  227. package/dist/backend/services/sales-rep-assignment-service.d.ts +89 -0
  228. package/dist/backend/services/sales-rep-assignment-service.d.ts.map +1 -0
  229. package/dist/backend/services/sales-rep-assignment-service.js +176 -0
  230. package/dist/backend/services/sales-rep-assignment-service.js.map +1 -0
  231. package/dist/backend/services/vat-validator-port.d.ts +20 -0
  232. package/dist/backend/services/vat-validator-port.d.ts.map +1 -0
  233. package/dist/backend/services/vat-validator-port.js +2 -0
  234. package/dist/backend/services/vat-validator-port.js.map +1 -0
  235. package/dist/manifest.d.ts +176 -0
  236. package/dist/manifest.d.ts.map +1 -0
  237. package/dist/manifest.js +503 -0
  238. package/dist/manifest.js.map +1 -0
  239. package/dist/migrations/20260424T205317_organizations_init.d.ts +13 -0
  240. package/dist/migrations/20260424T205317_organizations_init.d.ts.map +1 -0
  241. package/dist/migrations/20260424T205317_organizations_init.js +100 -0
  242. package/dist/migrations/20260424T205317_organizations_init.js.map +1 -0
  243. package/dist/migrations/20260425T051700_organizations_invitations_init.d.ts +13 -0
  244. package/dist/migrations/20260425T051700_organizations_invitations_init.d.ts.map +1 -0
  245. package/dist/migrations/20260425T051700_organizations_invitations_init.js +39 -0
  246. package/dist/migrations/20260425T051700_organizations_invitations_init.js.map +1 -0
  247. package/dist/migrations/20260611T140349_organizations_consolidation.d.ts +35 -0
  248. package/dist/migrations/20260611T140349_organizations_consolidation.d.ts.map +1 -0
  249. package/dist/migrations/20260611T140349_organizations_consolidation.js +180 -0
  250. package/dist/migrations/20260611T140349_organizations_consolidation.js.map +1 -0
  251. package/dist/migrations/20260611T140358_organizations_org_order_confirmation_emails.d.ts +10 -0
  252. package/dist/migrations/20260611T140358_organizations_org_order_confirmation_emails.d.ts.map +1 -0
  253. package/dist/migrations/20260611T140358_organizations_org_order_confirmation_emails.js +14 -0
  254. package/dist/migrations/20260611T140358_organizations_org_order_confirmation_emails.js.map +1 -0
  255. package/dist/migrations/20260611T140402_organizations_org_fulfilment_strategy.d.ts +14 -0
  256. package/dist/migrations/20260611T140402_organizations_org_fulfilment_strategy.d.ts.map +1 -0
  257. package/dist/migrations/20260611T140402_organizations_org_fulfilment_strategy.js +20 -0
  258. package/dist/migrations/20260611T140402_organizations_org_fulfilment_strategy.js.map +1 -0
  259. package/dist/migrations/20260717T151403_organizations_personal_organizations.d.ts +24 -0
  260. package/dist/migrations/20260717T151403_organizations_personal_organizations.d.ts.map +1 -0
  261. package/dist/migrations/20260717T151403_organizations_personal_organizations.js +63 -0
  262. package/dist/migrations/20260717T151403_organizations_personal_organizations.js.map +1 -0
  263. package/dist/migrations/20260718T200340_organizations_organization_custom_field_values.d.ts +12 -0
  264. package/dist/migrations/20260718T200340_organizations_organization_custom_field_values.d.ts.map +1 -0
  265. package/dist/migrations/20260718T200340_organizations_organization_custom_field_values.js +16 -0
  266. package/dist/migrations/20260718T200340_organizations_organization_custom_field_values.js.map +1 -0
  267. package/dist/migrations/20260720T044254_organizations_org_hierarchy.d.ts +23 -0
  268. package/dist/migrations/20260720T044254_organizations_org_hierarchy.d.ts.map +1 -0
  269. package/dist/migrations/20260720T044254_organizations_org_hierarchy.js +37 -0
  270. package/dist/migrations/20260720T044254_organizations_org_hierarchy.js.map +1 -0
  271. package/dist/migrations/20260912T094646_organizations_sales_channel_organizations.d.ts +27 -0
  272. package/dist/migrations/20260912T094646_organizations_sales_channel_organizations.d.ts.map +1 -0
  273. package/dist/migrations/20260912T094646_organizations_sales_channel_organizations.js +44 -0
  274. package/dist/migrations/20260912T094646_organizations_sales_channel_organizations.js.map +1 -0
  275. package/dist/migrations/index.d.ts +35 -0
  276. package/dist/migrations/index.d.ts.map +1 -0
  277. package/dist/migrations/index.js +45 -0
  278. package/dist/migrations/index.js.map +1 -0
  279. package/dist/ports/index.d.ts +53 -0
  280. package/dist/ports/index.d.ts.map +1 -0
  281. package/dist/ports/index.js +2 -0
  282. package/dist/ports/index.js.map +1 -0
  283. package/docs/organization-hierarchy.md +117 -0
  284. package/docs/organizations.md +312 -0
  285. package/i18n/en.json +17 -0
  286. package/i18n/pl.json +17 -0
  287. package/package.json +107 -0
  288. package/tailwind.css +14 -0
@@ -0,0 +1,36 @@
1
+ import type { EntityManager } from '@mikro-orm/postgresql';
2
+ import type { AdminNotificationRecordPort, EmailMailerPort } from '@endora-commerce/contracts';
3
+ import { type OrgTemplateEmail } from './org-template-email.js';
4
+ /**
5
+ * OrgRegistrationNotifier — subscribes to `organization.registered.v1` and
6
+ * dispatches two side effects:
7
+ *
8
+ * 1. Writes one `admin_notifications` row (audience='all_admins',
9
+ * kind='organization.registered') so the admin bell + feed pick it up.
10
+ * 2. Reads the `organizations.notifications.new_registration_recipients`
11
+ * setting (a list of e-mail addresses) and sends one notification e-mail
12
+ * per recipient. Empty / unset list ⇒ no e-mails (the admin bell still
13
+ * fires).
14
+ *
15
+ * The notifier is best-effort by design — a downstream failure never
16
+ * poisons the registration itself, which has already committed before the
17
+ * event was emitted.
18
+ */
19
+ export interface OrgRegistrationNotifierDeps {
20
+ emFactory: () => EntityManager;
21
+ adminNotificationService: AdminNotificationRecordPort;
22
+ mailer: EmailMailerPort;
23
+ resolveRecipients: () => Promise<string[]>;
24
+ onError?: (err: unknown) => void;
25
+ /** Feature 047 — optional admin-editable template path. */
26
+ templateEmail?: OrgTemplateEmail;
27
+ }
28
+ export declare class OrgRegistrationNotifier {
29
+ private readonly deps;
30
+ constructor(deps: OrgRegistrationNotifierDeps);
31
+ handleRegistered(organizationId: string): Promise<void>;
32
+ private writeAdminNotification;
33
+ private dispatchRecipientEmails;
34
+ private composeBody;
35
+ }
36
+ //# sourceMappingURL=org-registration-notifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"org-registration-notifier.d.ts","sourceRoot":"","sources":["../../../src/backend/services/org-registration-notifier.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAG3D,OAAO,KAAK,EAAE,2BAA2B,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC/F,OAAO,EAAwB,KAAK,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEtF;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,MAAM,aAAa,CAAC;IAC/B,wBAAwB,EAAE,2BAA2B,CAAC;IACtD,MAAM,EAAE,eAAe,CAAC;IACxB,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC3C,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IACjC,2DAA2D;IAC3D,aAAa,CAAC,EAAE,gBAAgB,CAAC;CAClC;AAED,qBAAa,uBAAuB;IACtB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,2BAA2B;IAExD,gBAAgB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAuB/C,sBAAsB;YAetB,uBAAuB;IAmDrC,OAAO,CAAC,WAAW;CAWpB"}
@@ -0,0 +1,109 @@
1
+ import { rethrowIfModuleDisabled } from '@endora-commerce/platform/kernel';
2
+ import { Organization } from '../entities/organization.entity.js';
3
+ import { noopOrgTemplateEmail } from './org-template-email.js';
4
+ export class OrgRegistrationNotifier {
5
+ deps;
6
+ constructor(deps) {
7
+ this.deps = deps;
8
+ }
9
+ async handleRegistered(organizationId) {
10
+ try {
11
+ const em = this.deps.emFactory();
12
+ const org = await em.findOne(Organization, { id: organizationId, deletedAt: null });
13
+ if (!org)
14
+ return;
15
+ await this.writeAdminNotification(org);
16
+ await this.dispatchRecipientEmails(org);
17
+ }
18
+ catch (err) {
19
+ // `writeAdminNotification` reaches `admin_notifications` through a gated
20
+ // port, and that module declares no `activation.nonDeactivatable`: switch
21
+ // it off and every organization registration went silently un-notified,
22
+ // with `onError` absorbing the 503 (D-88). A registration nobody was told
23
+ // about is not a degrade `organizations` may choose on
24
+ // `admin_notifications`' behalf — if that module is off, the answer
25
+ // belongs in its own port's return type, decided by its owner. The rest
26
+ // of the tolerance stays: the registration itself has already committed,
27
+ // so an ordinary downstream failure must not poison it.
28
+ rethrowIfModuleDisabled(err);
29
+ this.deps.onError?.(err);
30
+ }
31
+ }
32
+ async writeAdminNotification(org) {
33
+ await this.deps.adminNotificationService.record({
34
+ audience: 'all_admins',
35
+ kind: 'organization.registered',
36
+ subjectType: 'organization',
37
+ subjectId: org.id,
38
+ title: `Nowa Organizacja: ${org.name}`,
39
+ body: org.status === 'pending_verification'
40
+ ? 'Oczekuje na weryfikację.'
41
+ : 'Zarejestrowana automatycznie.',
42
+ linkPath: `/organizations/${org.id}`,
43
+ });
44
+ }
45
+ async dispatchRecipientEmails(org) {
46
+ let recipients = [];
47
+ try {
48
+ recipients = await this.deps.resolveRecipients();
49
+ }
50
+ catch {
51
+ // Setting unreachable — degrade to "no email recipients".
52
+ }
53
+ if (recipients.length === 0)
54
+ return;
55
+ const template = this.deps.templateEmail ?? noopOrgTemplateEmail;
56
+ const statusLabel = org.status === 'pending_verification' ? 'Oczekuje na weryfikację' : 'Aktywna';
57
+ for (const to of recipients) {
58
+ const messageId = `organization.registered.${org.id}.${to.toLowerCase()}`;
59
+ try {
60
+ const sentViaTemplate = await template.trySend({
61
+ code: 'new_org_registration',
62
+ to,
63
+ messageId,
64
+ variables: {
65
+ organizationName: org.name,
66
+ taxId: org.taxId,
67
+ statusLabel,
68
+ linkPath: `/organizations/${org.id}`,
69
+ },
70
+ meta: { organizationId: org.id, kind: 'organization.registered' },
71
+ });
72
+ if (!sentViaTemplate) {
73
+ const outcome = await this.deps.mailer.send({
74
+ messageId,
75
+ to,
76
+ subject: `Nowa Organizacja: ${org.name}`,
77
+ text: this.composeBody(org),
78
+ meta: { organizationId: org.id, kind: 'organization.registered' },
79
+ });
80
+ if (outcome.status !== 'sent') {
81
+ // `onError` is for a throw; a suppression is not one. Each
82
+ // recipient is independent, so it is named on its own — and D-59's
83
+ // record holds the same fact per recipient.
84
+ console.warn('[organizations] the new-organization e-mail was not sent', {
85
+ organizationId: org.id,
86
+ to,
87
+ reason: outcome.reason,
88
+ });
89
+ }
90
+ }
91
+ }
92
+ catch (err) {
93
+ this.deps.onError?.(err);
94
+ }
95
+ }
96
+ }
97
+ composeBody(org) {
98
+ return [
99
+ `Zarejestrowała się nowa Organizacja na platformie B2B.`,
100
+ ``,
101
+ ` Nazwa: ${org.name}`,
102
+ ` NIP/VAT: ${org.taxId}`,
103
+ ` Status: ${org.status === 'pending_verification' ? 'Oczekuje na weryfikację' : 'Aktywna'}`,
104
+ ``,
105
+ `Otwórz w Panelu Administracyjnym: /organizations/${org.id}`,
106
+ ].join('\n');
107
+ }
108
+ }
109
+ //# sourceMappingURL=org-registration-notifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"org-registration-notifier.js","sourceRoot":"","sources":["../../../src/backend/services/org-registration-notifier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ export interface OrgTemplateEmail {
2
+ /**
3
+ * `true` means "handled — do not use the legacy in-code builder", which
4
+ * includes an email the operator deactivated: off must stay off rather than
5
+ * silently degrade to the in-code version. Only a code with no definition at
6
+ * all answers `false`.
7
+ */
8
+ trySend(input: {
9
+ code: string;
10
+ to: string;
11
+ messageId: string;
12
+ variables: Record<string, unknown>;
13
+ meta?: Record<string, unknown> | undefined;
14
+ }): Promise<boolean>;
15
+ }
16
+ /** No-op helper (sender not wired) — always falls back to the legacy builder. */
17
+ export declare const noopOrgTemplateEmail: OrgTemplateEmail;
18
+ //# sourceMappingURL=org-template-email.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"org-template-email.d.ts","sourceRoot":"","sources":["../../../src/backend/services/org-template-email.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,gBAAgB;IAC/B;;;;;OAKG;IACH,OAAO,CAAC,KAAK,EAAE;QACb,IAAI,EAAE,MAAM,CAAC;QACb,EAAE,EAAE,MAAM,CAAC;QACX,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACnC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;KAC5C,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACtB;AAED,iFAAiF;AACjF,eAAO,MAAM,oBAAoB,EAAE,gBAIlC,CAAC"}
@@ -0,0 +1,16 @@
1
+ // Feature 047 — the shape an organizations email takes when it routes through
2
+ // the admin-editable transactional template, and the no-op that makes the
3
+ // caller fall back to its legacy in-code builder.
4
+ //
5
+ // The implementation left in T120: it was pure sender-plus-channel logic, so it
6
+ // belongs to `transactional_emails`, which offers it as `templateEmailPort`.
7
+ // What stays here is the *shape this module needs*, declared locally so
8
+ // resolving the port crosses no boundary — the port pattern, rather than an
9
+ // import of another module's helper.
10
+ /** No-op helper (sender not wired) — always falls back to the legacy builder. */
11
+ export const noopOrgTemplateEmail = {
12
+ async trySend() {
13
+ return false;
14
+ },
15
+ };
16
+ //# sourceMappingURL=org-template-email.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"org-template-email.js","sourceRoot":"","sources":["../../../src/backend/services/org-template-email.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,0EAA0E;AAC1E,kDAAkD;AAClD,EAAE;AACF,gFAAgF;AAChF,6EAA6E;AAC7E,wEAAwE;AACxE,4EAA4E;AAC5E,qCAAqC;AAkBrC,iFAAiF;AACjF,MAAM,CAAC,MAAM,oBAAoB,GAAqB;IACpD,KAAK,CAAC,OAAO;QACX,OAAO,KAAK,CAAC;IACf,CAAC;CACF,CAAC"}
@@ -0,0 +1,52 @@
1
+ import type { EntityManager } from '@mikro-orm/postgresql';
2
+ import { OrganizationCannotTransactError, OrganizationNotFoundError } from '@endora-commerce/contracts';
3
+ import { Organization } from '../entities/organization.entity.js';
4
+ /**
5
+ * Lightweight read-side service that exposes "what's the effective state of
6
+ * this Customer's Organization?" without forcing every caller to write the
7
+ * `findOne` boilerplate.
8
+ *
9
+ * Two responsibilities only:
10
+ *
11
+ * 1. `loadEffectiveOrganization(organizationId)` — returns the Organization
12
+ * or `null` if it doesn't exist / is soft-deleted. Cheap (single PK
13
+ * lookup; MikroORM caches per request).
14
+ *
15
+ * 2. `assertCanTransact(orgId | org)` — throws `OrganizationCannotTransactError`
16
+ * when the status is anything other than `active`. The error carries a
17
+ * localized-message key and the current status so route handlers can map
18
+ * it to HTTP 423 with a Customer-friendly body.
19
+ *
20
+ * The service is consumed by cart-line-add, checkout-submit, and
21
+ * quote-request-submit route handlers. Read-only flows (browse, view-cart,
22
+ * order-history) do NOT call `assertCanTransact` — pending / blocked /
23
+ * rejected Organizations may still see the storefront.
24
+ */
25
+ export declare class OrganizationContextService {
26
+ private readonly emFactory;
27
+ constructor(emFactory: () => EntityManager);
28
+ loadEffectiveOrganization(organizationId: string): Promise<Organization | null>;
29
+ /**
30
+ * @throws {OrganizationNotFoundError} when the org doesn't exist.
31
+ * @throws {OrganizationCannotTransactError} when status ≠ `active`.
32
+ */
33
+ assertCanTransact(organizationId: string): Promise<Organization>;
34
+ /**
35
+ * Feature 027 §R2 — single-boolean lookup driving the per-Organization
36
+ * cart-approval policy. Returns `false` when the Organization is
37
+ * missing or soft-deleted (the gate is off by definition in that case
38
+ * — a Customer with no Organization uses platform defaults).
39
+ */
40
+ loadCartApprovalPolicy(organizationId: string | null): Promise<boolean>;
41
+ }
42
+ /**
43
+ * Both error classes moved to `@endora-commerce/contracts` in feature 075's Phase P. An
44
+ * error is a shape, not behaviour — four modules catch `instanceof` on the
45
+ * second one to turn it into a 409 envelope, and the kernel's
46
+ * `OrganizationReadPort` has documented both as `assertCanTransact`'s failure
47
+ * modes since D-32 while the classes themselves lived in this file.
48
+ *
49
+ * Re-exported here for the length of Phase P, which cuts no consumer.
50
+ */
51
+ export { OrganizationNotFoundError, OrganizationCannotTransactError };
52
+ //# sourceMappingURL=organization-context-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"organization-context-service.d.ts","sourceRoot":"","sources":["../../../src/backend/services/organization-context-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EACL,+BAA+B,EAC/B,yBAAyB,EAC1B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,0BAA0B;IACzB,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAAT,SAAS,EAAE,MAAM,aAAa;IAErD,yBAAyB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAKrF;;;OAGG;IACG,iBAAiB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAWtE;;;;;OAKG;IACG,sBAAsB,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;CAK9E;AAED;;;;;;;;GAQG;AACH,OAAO,EAAE,yBAAyB,EAAE,+BAA+B,EAAE,CAAC"}
@@ -0,0 +1,70 @@
1
+ import { OrganizationCannotTransactError, OrganizationNotFoundError, } from '@endora-commerce/contracts';
2
+ import { Organization } from '../entities/organization.entity.js';
3
+ /**
4
+ * Lightweight read-side service that exposes "what's the effective state of
5
+ * this Customer's Organization?" without forcing every caller to write the
6
+ * `findOne` boilerplate.
7
+ *
8
+ * Two responsibilities only:
9
+ *
10
+ * 1. `loadEffectiveOrganization(organizationId)` — returns the Organization
11
+ * or `null` if it doesn't exist / is soft-deleted. Cheap (single PK
12
+ * lookup; MikroORM caches per request).
13
+ *
14
+ * 2. `assertCanTransact(orgId | org)` — throws `OrganizationCannotTransactError`
15
+ * when the status is anything other than `active`. The error carries a
16
+ * localized-message key and the current status so route handlers can map
17
+ * it to HTTP 423 with a Customer-friendly body.
18
+ *
19
+ * The service is consumed by cart-line-add, checkout-submit, and
20
+ * quote-request-submit route handlers. Read-only flows (browse, view-cart,
21
+ * order-history) do NOT call `assertCanTransact` — pending / blocked /
22
+ * rejected Organizations may still see the storefront.
23
+ */
24
+ export class OrganizationContextService {
25
+ emFactory;
26
+ constructor(emFactory) {
27
+ this.emFactory = emFactory;
28
+ }
29
+ async loadEffectiveOrganization(organizationId) {
30
+ const em = this.emFactory();
31
+ return em.findOne(Organization, { id: organizationId, deletedAt: null });
32
+ }
33
+ /**
34
+ * @throws {OrganizationNotFoundError} when the org doesn't exist.
35
+ * @throws {OrganizationCannotTransactError} when status ≠ `active`.
36
+ */
37
+ async assertCanTransact(organizationId) {
38
+ const org = await this.loadEffectiveOrganization(organizationId);
39
+ if (!org) {
40
+ throw new OrganizationNotFoundError(organizationId);
41
+ }
42
+ if (org.status !== 'active') {
43
+ throw new OrganizationCannotTransactError(org.id, org.status);
44
+ }
45
+ return org;
46
+ }
47
+ /**
48
+ * Feature 027 §R2 — single-boolean lookup driving the per-Organization
49
+ * cart-approval policy. Returns `false` when the Organization is
50
+ * missing or soft-deleted (the gate is off by definition in that case
51
+ * — a Customer with no Organization uses platform defaults).
52
+ */
53
+ async loadCartApprovalPolicy(organizationId) {
54
+ if (!organizationId)
55
+ return false;
56
+ const org = await this.loadEffectiveOrganization(organizationId);
57
+ return org?.requiresCartApproval ?? false;
58
+ }
59
+ }
60
+ /**
61
+ * Both error classes moved to `@endora-commerce/contracts` in feature 075's Phase P. An
62
+ * error is a shape, not behaviour — four modules catch `instanceof` on the
63
+ * second one to turn it into a 409 envelope, and the kernel's
64
+ * `OrganizationReadPort` has documented both as `assertCanTransact`'s failure
65
+ * modes since D-32 while the classes themselves lived in this file.
66
+ *
67
+ * Re-exported here for the length of Phase P, which cuts no consumer.
68
+ */
69
+ export { OrganizationNotFoundError, OrganizationCannotTransactError };
70
+ //# sourceMappingURL=organization-context-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"organization-context-service.js","sourceRoot":"","sources":["../../../src/backend/services/organization-context-service.ts"],"names":[],"mappings":"AACA,OAAO,EACL,+BAA+B,EAC/B,yBAAyB,GAC1B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,OAAO,0BAA0B;IACR;IAA7B,YAA6B,SAA8B;QAA9B,cAAS,GAAT,SAAS,CAAqB;IAAG,CAAC;IAE/D,KAAK,CAAC,yBAAyB,CAAC,cAAsB;QACpD,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAC5B,OAAO,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,EAAE,EAAE,cAAc,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3E,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,iBAAiB,CAAC,cAAsB;QAC5C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,yBAAyB,CAAC,cAAc,CAAC,CAAC;QACjE,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,yBAAyB,CAAC,cAAc,CAAC,CAAC;QACtD,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC5B,MAAM,IAAI,+BAA+B,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;QAChE,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,sBAAsB,CAAC,cAA6B;QACxD,IAAI,CAAC,cAAc;YAAE,OAAO,KAAK,CAAC;QAClC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,yBAAyB,CAAC,cAAc,CAAC,CAAC;QACjE,OAAO,GAAG,EAAE,oBAAoB,IAAI,KAAK,CAAC;IAC5C,CAAC;CACF;AAED;;;;;;;;GAQG;AACH,OAAO,EAAE,yBAAyB,EAAE,+BAA+B,EAAE,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { DictionaryReferenceRegistryPort } from '@endora-commerce/contracts';
2
+ import type { EntityManager } from '@mikro-orm/postgresql';
3
+ /**
4
+ * Who in `organizations` still points at a country (feature 077, D-87).
5
+ *
6
+ * The country sits inside the `registered_address` JSONB column, which is
7
+ * why `dictionaries` used to reach for `->>'country'` against this module's
8
+ * table directly. The path lives here now, next to the column it is about.
9
+ */
10
+ export declare function registerOrganizationCountryReferences(registry: DictionaryReferenceRegistryPort, emFactory: () => EntityManager): void;
11
+ //# sourceMappingURL=organization-country-reference.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"organization-country-reference.d.ts","sourceRoot":"","sources":["../../../src/backend/services/organization-country-reference.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,4BAA4B,CAAC;AAClF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D;;;;;;GAMG;AACH,wBAAgB,qCAAqC,CACnD,QAAQ,EAAE,+BAA+B,EACzC,SAAS,EAAE,MAAM,aAAa,GAC7B,IAAI,CAqBN"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Who in `organizations` still points at a country (feature 077, D-87).
3
+ *
4
+ * The country sits inside the `registered_address` JSONB column, which is
5
+ * why `dictionaries` used to reach for `->>'country'` against this module's
6
+ * table directly. The path lives here now, next to the column it is about.
7
+ */
8
+ export function registerOrganizationCountryReferences(registry, emFactory) {
9
+ registry.register({
10
+ ownerModuleId: 'organizations',
11
+ consumer: 'organizations',
12
+ tableName: 'organizations',
13
+ columnName: 'registered_address.country',
14
+ blocking: true,
15
+ countReferences: async (code) => {
16
+ const rows = (await emFactory().execute(`select count(*)::int as n from "organizations" where "registered_address"->>'country' = ?`, [code]));
17
+ return rows[0]?.n ?? 0;
18
+ },
19
+ usedCodes: async () => (await emFactory().execute(`select "registered_address"->>'country' as code, count(*)::int as count
20
+ from "organizations" where "registered_address"->>'country' is not null
21
+ group by "registered_address"->>'country'`)),
22
+ });
23
+ }
24
+ //# sourceMappingURL=organization-country-reference.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"organization-country-reference.js","sourceRoot":"","sources":["../../../src/backend/services/organization-country-reference.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,MAAM,UAAU,qCAAqC,CACnD,QAAyC,EACzC,SAA8B;IAE9B,QAAQ,CAAC,QAAQ,CAAC;QAChB,aAAa,EAAE,eAAe;QAC9B,QAAQ,EAAE,eAAe;QACzB,SAAS,EAAE,eAAe;QAC1B,UAAU,EAAE,4BAA4B;QACxC,QAAQ,EAAE,IAAI;QACd,eAAe,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YAC9B,MAAM,IAAI,GAAG,CAAC,MAAM,SAAS,EAAE,CAAC,OAAO,CACrC,2FAA2F,EAC3F,CAAC,IAAI,CAAC,CACP,CAAyB,CAAC;YAC3B,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;QACzB,CAAC;QACD,SAAS,EAAE,KAAK,IAAI,EAAE,CACpB,CAAC,MAAM,SAAS,EAAE,CAAC,OAAO,CACxB;;oDAE4C,CAC7C,CAA2C;KAC/C,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,33 @@
1
+ import type { EntityManager } from '@mikro-orm/postgresql';
2
+ import type { OrganizationDetailsPort, OrganizationRecord } from '@endora-commerce/contracts';
3
+ import { Organization } from '../entities/organization.entity.js';
4
+ /**
5
+ * The row-level read model `organizations` publishes (feature 075, Phase P).
6
+ *
7
+ * Eleven modules read this table; 24 of the 47 inbound import sites are a
8
+ * direct `em.findOne` / `em.find` on the entity class, spread across carts,
9
+ * orders, pricing, quotes, push messages and two admin pickers. This service
10
+ * is the union of what they ask for, and the mapping into
11
+ * `OrganizationRecord` is what keeps the entity on this side of the boundary.
12
+ *
13
+ * It is a **second** port beside the kernel's `organizationReadPort`, not a
14
+ * replacement: that one is the tenancy projection (`{ id, status }` plus
15
+ * `assertCanTransact`), and D-55 settled it at that. See the contract's note.
16
+ *
17
+ * One behaviour deliberately changes as callers move onto it. Two of the three
18
+ * name pickers query `name` with `$ilike`, so a search for "lodz" misses
19
+ * "Łódź"; `searchByName` queries the diacritic-folded `nameSearch` column that
20
+ * exists for precisely this, as `orders`' list filter already does.
21
+ */
22
+ export declare class OrganizationDetailsService implements OrganizationDetailsPort {
23
+ #private;
24
+ private readonly emFactory;
25
+ constructor(emFactory: () => EntityManager);
26
+ findById(id: string): Promise<OrganizationRecord | null>;
27
+ findByIds(ids: readonly string[]): Promise<OrganizationRecord[]>;
28
+ countByIds(ids: readonly string[]): Promise<number>;
29
+ searchByName(query: string, limit: number): Promise<OrganizationRecord[]>;
30
+ searchIdsByName(query: string): Promise<string[]>;
31
+ }
32
+ export declare function toOrganizationRecord(organization: Organization): OrganizationRecord;
33
+ //# sourceMappingURL=organization-details-port.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"organization-details-port.d.ts","sourceRoot":"","sources":["../../../src/backend/services/organization-details-port.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAE9F,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAElE;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,0BAA2B,YAAW,uBAAuB;;IAC5D,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAAT,SAAS,EAAE,MAAM,aAAa;IAErD,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAKxD,SAAS,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAMhE,UAAU,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAKnD,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAQzE,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;CAYxD;AAED,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,YAAY,GAAG,kBAAkB,CAiCnF"}
@@ -0,0 +1,95 @@
1
+ import { normalizeOrganizationName } from '@endora-commerce/contracts';
2
+ import { Organization } from '../entities/organization.entity.js';
3
+ /**
4
+ * The row-level read model `organizations` publishes (feature 075, Phase P).
5
+ *
6
+ * Eleven modules read this table; 24 of the 47 inbound import sites are a
7
+ * direct `em.findOne` / `em.find` on the entity class, spread across carts,
8
+ * orders, pricing, quotes, push messages and two admin pickers. This service
9
+ * is the union of what they ask for, and the mapping into
10
+ * `OrganizationRecord` is what keeps the entity on this side of the boundary.
11
+ *
12
+ * It is a **second** port beside the kernel's `organizationReadPort`, not a
13
+ * replacement: that one is the tenancy projection (`{ id, status }` plus
14
+ * `assertCanTransact`), and D-55 settled it at that. See the contract's note.
15
+ *
16
+ * One behaviour deliberately changes as callers move onto it. Two of the three
17
+ * name pickers query `name` with `$ilike`, so a search for "lodz" misses
18
+ * "Łódź"; `searchByName` queries the diacritic-folded `nameSearch` column that
19
+ * exists for precisely this, as `orders`' list filter already does.
20
+ */
21
+ export class OrganizationDetailsService {
22
+ emFactory;
23
+ constructor(emFactory) {
24
+ this.emFactory = emFactory;
25
+ }
26
+ async findById(id) {
27
+ const organization = await this.emFactory().findOne(Organization, { id });
28
+ return organization ? toOrganizationRecord(organization) : null;
29
+ }
30
+ async findByIds(ids) {
31
+ if (ids.length === 0)
32
+ return [];
33
+ const organizations = await this.emFactory().find(Organization, { id: { $in: [...ids] } });
34
+ return organizations.map(toOrganizationRecord);
35
+ }
36
+ async countByIds(ids) {
37
+ if (ids.length === 0)
38
+ return 0;
39
+ return this.emFactory().count(Organization, { id: { $in: [...ids] } });
40
+ }
41
+ async searchByName(query, limit) {
42
+ const organizations = await this.emFactory().find(Organization, this.#where(query), {
43
+ orderBy: { name: 'asc' },
44
+ limit,
45
+ });
46
+ return organizations.map(toOrganizationRecord);
47
+ }
48
+ async searchIdsByName(query) {
49
+ const rows = await this.emFactory().find(Organization, this.#where(query), {
50
+ fields: ['id'],
51
+ });
52
+ return rows.map((row) => row.id);
53
+ }
54
+ #where(query) {
55
+ const trimmed = query.trim();
56
+ if (!trimmed)
57
+ return {};
58
+ return { nameSearch: { $like: `%${normalizeOrganizationName(trimmed)}%` } };
59
+ }
60
+ }
61
+ export function toOrganizationRecord(organization) {
62
+ return {
63
+ id: organization.id,
64
+ name: organization.name,
65
+ legalName: organization.legalName ?? null,
66
+ taxId: organization.taxId,
67
+ status: organization.status,
68
+ vatStatus: organization.vatStatus,
69
+ isPersonal: organization.isPersonal,
70
+ customerGroupId: organization.customerGroupId ?? null,
71
+ registeredAddress: organization.registeredAddress,
72
+ orderConfirmationEmails: organization.orderConfirmationEmails ?? [],
73
+ vatValidatedAt: organization.vatValidatedAt ?? null,
74
+ vatValidationProvider: organization.vatValidationProvider ?? null,
75
+ vatValidationOutcome: organization.vatValidationOutcome ?? null,
76
+ blockedReason: organization.blockedReason ?? null,
77
+ blockedAt: organization.blockedAt ?? null,
78
+ rejectedReason: organization.rejectedReason ?? null,
79
+ rejectedAt: organization.rejectedAt ?? null,
80
+ approvedAt: organization.approvedAt ?? null,
81
+ approvedByAdminUserId: organization.approvedByAdminUserId ?? null,
82
+ requiresCartApproval: organization.requiresCartApproval,
83
+ fulfilmentStrategy: organization.fulfilmentStrategy ?? null,
84
+ fulfilmentStrategyWarehouseOrder: organization.fulfilmentStrategyWarehouseOrder ?? null,
85
+ parentId: organization.parentId ?? null,
86
+ path: organization.path,
87
+ creditInheritanceMode: organization.creditInheritanceMode ?? null,
88
+ customFieldValues: organization.customFieldValues ?? {},
89
+ version: organization.version,
90
+ createdAt: organization.createdAt,
91
+ updatedAt: organization.updatedAt,
92
+ deletedAt: organization.deletedAt ?? null,
93
+ };
94
+ }
95
+ //# sourceMappingURL=organization-details-port.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"organization-details-port.js","sourceRoot":"","sources":["../../../src/backend/services/organization-details-port.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import type { EntityManager } from '@mikro-orm/postgresql';
2
+ import { type PriceListReadPort } from '@endora-commerce/contracts';
3
+ /**
4
+ * Maps the application-rule-evaluator's `RuleCriterionType` tags to the
5
+ * customer-facing "reason" labels surfaced by the Organization detail
6
+ * panel (feature 026 US5). The Organization detail page reads
7
+ * `reasons[]` and renders one chip per entry.
8
+ *
9
+ * The category criterion is mapped to `segment_rule_match` because in
10
+ * practice a category-scoped price list functions as a segment rule
11
+ * from the operator's perspective.
12
+ */
13
+ export type ApplicablePriceListReason = 'direct_organization_match' | 'customer_group_match' | 'sales_channel_inheritance' | 'segment_rule_match';
14
+ export interface ApplicablePriceListEntry {
15
+ priceListId: string;
16
+ name: string;
17
+ priority: number;
18
+ reasons: ApplicablePriceListReason[];
19
+ }
20
+ export interface OrganizationEffectivePriceListsDeps {
21
+ emFactory: () => EntityManager;
22
+ /**
23
+ * Sales-channel id used to evaluate channel-bound rules. The org-detail
24
+ * panel is read-only; passing the platform's system-default channel is
25
+ * sufficient because the panel surfaces what applies "to this
26
+ * Organization broadly" — channel-specific overrides are visible when
27
+ * an admin opens the relevant Sales Channel.
28
+ */
29
+ resolveDefaultSalesChannelId: () => Promise<string>;
30
+ /**
31
+ * `price_lists`' own answer to "which lists are active", rather than this
32
+ * module's copy of the status filter (feature 075, Phase C). With
33
+ * `price_lists` off the call fails closed and the panel refuses: an empty
34
+ * list here reads as "no price list applies to this organisation", which is
35
+ * a plausible answer and the wrong one.
36
+ */
37
+ priceListRead: PriceListReadPort;
38
+ }
39
+ /**
40
+ * Returns the set of Price Lists currently applicable to a given
41
+ * Organization, each tagged with the reasons it applies. Implementation
42
+ * reuses the existing application-rule evaluator (no new persistence
43
+ * surface) — see research.md R6.
44
+ */
45
+ export declare class OrganizationEffectivePriceListsService {
46
+ private readonly deps;
47
+ constructor(deps: OrganizationEffectivePriceListsDeps);
48
+ listApplicable(organizationId: string): Promise<ApplicablePriceListEntry[]>;
49
+ }
50
+ //# sourceMappingURL=organization-effective-pricelists-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"organization-effective-pricelists-service.d.ts","sourceRoot":"","sources":["../../../src/backend/services/organization-effective-pricelists-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAEL,KAAK,iBAAiB,EAEvB,MAAM,4BAA4B,CAAC;AAGpC;;;;;;;;;GASG;AACH,MAAM,MAAM,yBAAyB,GACjC,2BAA2B,GAC3B,sBAAsB,GACtB,2BAA2B,GAC3B,oBAAoB,CAAC;AAEzB,MAAM,WAAW,wBAAwB;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,yBAAyB,EAAE,CAAC;CACtC;AAED,MAAM,WAAW,mCAAmC;IAClD,SAAS,EAAE,MAAM,aAAa,CAAC;IAC/B;;;;;;OAMG;IACH,4BAA4B,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACpD;;;;;;OAMG;IACH,aAAa,EAAE,iBAAiB,CAAC;CAClC;AAED;;;;;GAKG;AACH,qBAAa,sCAAsC;IACrC,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,mCAAmC;IAEhE,cAAc,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,EAAE,CAAC;CAoDlF"}