@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.
- package/LICENSE +21 -0
- package/README.md +62 -0
- package/dist/admin/components/OrganizationSalesRepsTab.d.ts +27 -0
- package/dist/admin/components/OrganizationSalesRepsTab.d.ts.map +1 -0
- package/dist/admin/components/OrganizationSalesRepsTab.js +170 -0
- package/dist/admin/components/OrganizationSalesRepsTab.js.map +1 -0
- package/dist/admin/index.d.ts +30 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +59 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/pages/OrganizationDetail.d.ts +9 -0
- package/dist/admin/pages/OrganizationDetail.d.ts.map +1 -0
- package/dist/admin/pages/OrganizationDetail.js +247 -0
- package/dist/admin/pages/OrganizationDetail.js.map +1 -0
- package/dist/admin/pages/OrganizationsList.d.ts +9 -0
- package/dist/admin/pages/OrganizationsList.d.ts.map +1 -0
- package/dist/admin/pages/OrganizationsList.js +73 -0
- package/dist/admin/pages/OrganizationsList.js.map +1 -0
- package/dist/admin/panels/ApplicablePriceListsPanel.d.ts +12 -0
- package/dist/admin/panels/ApplicablePriceListsPanel.d.ts.map +1 -0
- package/dist/admin/panels/ApplicablePriceListsPanel.js +49 -0
- package/dist/admin/panels/ApplicablePriceListsPanel.js.map +1 -0
- package/dist/admin/panels/FulfilmentStrategyPanel.d.ts +16 -0
- package/dist/admin/panels/FulfilmentStrategyPanel.d.ts.map +1 -0
- package/dist/admin/panels/FulfilmentStrategyPanel.js +29 -0
- package/dist/admin/panels/FulfilmentStrategyPanel.js.map +1 -0
- package/dist/admin/panels/HierarchyPanel.d.ts +15 -0
- package/dist/admin/panels/HierarchyPanel.d.ts.map +1 -0
- package/dist/admin/panels/HierarchyPanel.js +65 -0
- package/dist/admin/panels/HierarchyPanel.js.map +1 -0
- package/dist/admin/panels/ModerationActionsPanel.d.ts +28 -0
- package/dist/admin/panels/ModerationActionsPanel.d.ts.map +1 -0
- package/dist/admin/panels/ModerationActionsPanel.js +111 -0
- package/dist/admin/panels/ModerationActionsPanel.js.map +1 -0
- package/dist/admin/panels/RestrictionsPanel.d.ts +24 -0
- package/dist/admin/panels/RestrictionsPanel.d.ts.map +1 -0
- package/dist/admin/panels/RestrictionsPanel.js +121 -0
- package/dist/admin/panels/RestrictionsPanel.js.map +1 -0
- package/dist/admin/panels/VatValidationPanel.d.ts +28 -0
- package/dist/admin/panels/VatValidationPanel.d.ts.map +1 -0
- package/dist/admin/panels/VatValidationPanel.js +79 -0
- package/dist/admin/panels/VatValidationPanel.js.map +1 -0
- package/dist/backend/commands/move.command.d.ts +11 -0
- package/dist/backend/commands/move.command.d.ts.map +1 -0
- package/dist/backend/commands/move.command.js +11 -0
- package/dist/backend/commands/move.command.js.map +1 -0
- package/dist/backend/commands/set-cart-approval-policy.command.d.ts +31 -0
- package/dist/backend/commands/set-cart-approval-policy.command.d.ts.map +1 -0
- package/dist/backend/commands/set-cart-approval-policy.command.js +56 -0
- package/dist/backend/commands/set-cart-approval-policy.command.js.map +1 -0
- package/dist/backend/commands/set-credit-mode.command.d.ts +16 -0
- package/dist/backend/commands/set-credit-mode.command.d.ts.map +1 -0
- package/dist/backend/commands/set-credit-mode.command.js +25 -0
- package/dist/backend/commands/set-credit-mode.command.js.map +1 -0
- package/dist/backend/commands/set-parent.command.d.ts +26 -0
- package/dist/backend/commands/set-parent.command.d.ts.map +1 -0
- package/dist/backend/commands/set-parent.command.js +51 -0
- package/dist/backend/commands/set-parent.command.js.map +1 -0
- package/dist/backend/demo/reset.d.ts +20 -0
- package/dist/backend/demo/reset.d.ts.map +1 -0
- package/dist/backend/demo/reset.js +11 -0
- package/dist/backend/demo/reset.js.map +1 -0
- package/dist/backend/demo/rows.d.ts +44 -0
- package/dist/backend/demo/rows.d.ts.map +1 -0
- package/dist/backend/demo/rows.js +44 -0
- package/dist/backend/demo/rows.js.map +1 -0
- package/dist/backend/demo/seed.d.ts +20 -0
- package/dist/backend/demo/seed.d.ts.map +1 -0
- package/dist/backend/demo/seed.js +28 -0
- package/dist/backend/demo/seed.js.map +1 -0
- package/dist/backend/email-templates/invitation.d.ts +23 -0
- package/dist/backend/email-templates/invitation.d.ts.map +1 -0
- package/dist/backend/email-templates/invitation.js +35 -0
- package/dist/backend/email-templates/invitation.js.map +1 -0
- package/dist/backend/email-templates/transactional-defaults.d.ts +54 -0
- package/dist/backend/email-templates/transactional-defaults.d.ts.map +1 -0
- package/dist/backend/email-templates/transactional-defaults.js +242 -0
- package/dist/backend/email-templates/transactional-defaults.js.map +1 -0
- package/dist/backend/email-templates/verification.d.ts +14 -0
- package/dist/backend/email-templates/verification.d.ts.map +1 -0
- package/dist/backend/email-templates/verification.js +34 -0
- package/dist/backend/email-templates/verification.js.map +1 -0
- package/dist/backend/entities/email-verification-token.entity.d.ts +17 -0
- package/dist/backend/entities/email-verification-token.entity.d.ts.map +1 -0
- package/dist/backend/entities/email-verification-token.entity.js +60 -0
- package/dist/backend/entities/email-verification-token.entity.js.map +1 -0
- package/dist/backend/entities/organization-delivery-method-link.entity.d.ts +14 -0
- package/dist/backend/entities/organization-delivery-method-link.entity.d.ts.map +1 -0
- package/dist/backend/entities/organization-delivery-method-link.entity.js +41 -0
- package/dist/backend/entities/organization-delivery-method-link.entity.js.map +1 -0
- package/dist/backend/entities/organization-invitation.entity.d.ts +21 -0
- package/dist/backend/entities/organization-invitation.entity.d.ts.map +1 -0
- package/dist/backend/entities/organization-invitation.entity.js +85 -0
- package/dist/backend/entities/organization-invitation.entity.js.map +1 -0
- package/dist/backend/entities/organization-payment-method-link.entity.d.ts +14 -0
- package/dist/backend/entities/organization-payment-method-link.entity.d.ts.map +1 -0
- package/dist/backend/entities/organization-payment-method-link.entity.js +41 -0
- package/dist/backend/entities/organization-payment-method-link.entity.js.map +1 -0
- package/dist/backend/entities/organization-sales-rep-assignment.entity.d.ts +17 -0
- package/dist/backend/entities/organization-sales-rep-assignment.entity.d.ts.map +1 -0
- package/dist/backend/entities/organization-sales-rep-assignment.entity.js +56 -0
- package/dist/backend/entities/organization-sales-rep-assignment.entity.js.map +1 -0
- package/dist/backend/entities/organization-tax-id-validation.entity.d.ts +29 -0
- package/dist/backend/entities/organization-tax-id-validation.entity.d.ts.map +1 -0
- package/dist/backend/entities/organization-tax-id-validation.entity.js +78 -0
- package/dist/backend/entities/organization-tax-id-validation.entity.js.map +1 -0
- package/dist/backend/entities/organization-warehouse-link.entity.d.ts +15 -0
- package/dist/backend/entities/organization-warehouse-link.entity.d.ts.map +1 -0
- package/dist/backend/entities/organization-warehouse-link.entity.js +42 -0
- package/dist/backend/entities/organization-warehouse-link.entity.js.map +1 -0
- package/dist/backend/entities/organization.entity.d.ts +125 -0
- package/dist/backend/entities/organization.entity.d.ts.map +1 -0
- package/dist/backend/entities/organization.entity.js +282 -0
- package/dist/backend/entities/organization.entity.js.map +1 -0
- package/dist/backend/index.d.ts +250 -0
- package/dist/backend/index.d.ts.map +1 -0
- package/dist/backend/index.js +506 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/integrations/ministerstwo-finansow-client.d.ts +22 -0
- package/dist/backend/integrations/ministerstwo-finansow-client.d.ts.map +1 -0
- package/dist/backend/integrations/ministerstwo-finansow-client.js +172 -0
- package/dist/backend/integrations/ministerstwo-finansow-client.js.map +1 -0
- package/dist/backend/integrations/vies-client.d.ts +18 -0
- package/dist/backend/integrations/vies-client.d.ts.map +1 -0
- package/dist/backend/integrations/vies-client.js +133 -0
- package/dist/backend/integrations/vies-client.js.map +1 -0
- package/dist/backend/plugin.d.ts +126 -0
- package/dist/backend/plugin.d.ts.map +1 -0
- package/dist/backend/plugin.js +139 -0
- package/dist/backend/plugin.js.map +1 -0
- package/dist/backend/routes.admin.d.ts +66 -0
- package/dist/backend/routes.admin.d.ts.map +1 -0
- package/dist/backend/routes.admin.js +711 -0
- package/dist/backend/routes.admin.js.map +1 -0
- package/dist/backend/routes.customer.d.ts +33 -0
- package/dist/backend/routes.customer.d.ts.map +1 -0
- package/dist/backend/routes.customer.js +139 -0
- package/dist/backend/routes.customer.js.map +1 -0
- package/dist/backend/routes.members.d.ts +31 -0
- package/dist/backend/routes.members.d.ts.map +1 -0
- package/dist/backend/routes.members.js +109 -0
- package/dist/backend/routes.members.js.map +1 -0
- package/dist/backend/routes.public.d.ts +49 -0
- package/dist/backend/routes.public.d.ts.map +1 -0
- package/dist/backend/routes.public.js +220 -0
- package/dist/backend/routes.public.js.map +1 -0
- package/dist/backend/routes.sales-reps.d.ts +46 -0
- package/dist/backend/routes.sales-reps.d.ts.map +1 -0
- package/dist/backend/routes.sales-reps.js +114 -0
- package/dist/backend/routes.sales-reps.js.map +1 -0
- package/dist/backend/routes.storefront.d.ts +25 -0
- package/dist/backend/routes.storefront.d.ts.map +1 -0
- package/dist/backend/routes.storefront.js +65 -0
- package/dist/backend/routes.storefront.js.map +1 -0
- package/dist/backend/schemas/organization.d.ts +59 -0
- package/dist/backend/schemas/organization.d.ts.map +1 -0
- package/dist/backend/schemas/organization.js +55 -0
- package/dist/backend/schemas/organization.js.map +1 -0
- package/dist/backend/schemas/settings.d.ts +30 -0
- package/dist/backend/schemas/settings.d.ts.map +1 -0
- package/dist/backend/schemas/settings.js +35 -0
- package/dist/backend/schemas/settings.js.map +1 -0
- package/dist/backend/services/email-verification-service.d.ts +45 -0
- package/dist/backend/services/email-verification-service.d.ts.map +1 -0
- package/dist/backend/services/email-verification-service.js +95 -0
- package/dist/backend/services/email-verification-service.js.map +1 -0
- package/dist/backend/services/invitation-service.d.ts +85 -0
- package/dist/backend/services/invitation-service.d.ts.map +1 -0
- package/dist/backend/services/invitation-service.js +266 -0
- package/dist/backend/services/invitation-service.js.map +1 -0
- package/dist/backend/services/normalize-name.d.ts +14 -0
- package/dist/backend/services/normalize-name.d.ts.map +1 -0
- package/dist/backend/services/normalize-name.js +14 -0
- package/dist/backend/services/normalize-name.js.map +1 -0
- package/dist/backend/services/org-registration-notifier.d.ts +36 -0
- package/dist/backend/services/org-registration-notifier.d.ts.map +1 -0
- package/dist/backend/services/org-registration-notifier.js +109 -0
- package/dist/backend/services/org-registration-notifier.js.map +1 -0
- package/dist/backend/services/org-template-email.d.ts +18 -0
- package/dist/backend/services/org-template-email.d.ts.map +1 -0
- package/dist/backend/services/org-template-email.js +16 -0
- package/dist/backend/services/org-template-email.js.map +1 -0
- package/dist/backend/services/organization-context-service.d.ts +52 -0
- package/dist/backend/services/organization-context-service.d.ts.map +1 -0
- package/dist/backend/services/organization-context-service.js +70 -0
- package/dist/backend/services/organization-context-service.js.map +1 -0
- package/dist/backend/services/organization-country-reference.d.ts +11 -0
- package/dist/backend/services/organization-country-reference.d.ts.map +1 -0
- package/dist/backend/services/organization-country-reference.js +24 -0
- package/dist/backend/services/organization-country-reference.js.map +1 -0
- package/dist/backend/services/organization-details-port.d.ts +33 -0
- package/dist/backend/services/organization-details-port.d.ts.map +1 -0
- package/dist/backend/services/organization-details-port.js +95 -0
- package/dist/backend/services/organization-details-port.js.map +1 -0
- package/dist/backend/services/organization-effective-pricelists-service.d.ts +50 -0
- package/dist/backend/services/organization-effective-pricelists-service.d.ts.map +1 -0
- package/dist/backend/services/organization-effective-pricelists-service.js +68 -0
- package/dist/backend/services/organization-effective-pricelists-service.js.map +1 -0
- package/dist/backend/services/organization-inheritance-service.d.ts +73 -0
- package/dist/backend/services/organization-inheritance-service.d.ts.map +1 -0
- package/dist/backend/services/organization-inheritance-service.js +63 -0
- package/dist/backend/services/organization-inheritance-service.js.map +1 -0
- package/dist/backend/services/organization-moderation-service.d.ts +124 -0
- package/dist/backend/services/organization-moderation-service.d.ts.map +1 -0
- package/dist/backend/services/organization-moderation-service.js +337 -0
- package/dist/backend/services/organization-moderation-service.js.map +1 -0
- package/dist/backend/services/organization-restriction-service.d.ts +70 -0
- package/dist/backend/services/organization-restriction-service.d.ts.map +1 -0
- package/dist/backend/services/organization-restriction-service.js +210 -0
- package/dist/backend/services/organization-restriction-service.js.map +1 -0
- package/dist/backend/services/organization-tax-id-validation-service.d.ts +59 -0
- package/dist/backend/services/organization-tax-id-validation-service.d.ts.map +1 -0
- package/dist/backend/services/organization-tax-id-validation-service.js +115 -0
- package/dist/backend/services/organization-tax-id-validation-service.js.map +1 -0
- package/dist/backend/services/organization-tree-service.d.ts +102 -0
- package/dist/backend/services/organization-tree-service.d.ts.map +1 -0
- package/dist/backend/services/organization-tree-service.js +184 -0
- package/dist/backend/services/organization-tree-service.js.map +1 -0
- package/dist/backend/services/personal-organization-service.d.ts +130 -0
- package/dist/backend/services/personal-organization-service.d.ts.map +1 -0
- package/dist/backend/services/personal-organization-service.js +207 -0
- package/dist/backend/services/personal-organization-service.js.map +1 -0
- package/dist/backend/services/registration-service.d.ts +80 -0
- package/dist/backend/services/registration-service.d.ts.map +1 -0
- package/dist/backend/services/registration-service.js +126 -0
- package/dist/backend/services/registration-service.js.map +1 -0
- package/dist/backend/services/sales-rep-assignment-service.d.ts +89 -0
- package/dist/backend/services/sales-rep-assignment-service.d.ts.map +1 -0
- package/dist/backend/services/sales-rep-assignment-service.js +176 -0
- package/dist/backend/services/sales-rep-assignment-service.js.map +1 -0
- package/dist/backend/services/vat-validator-port.d.ts +20 -0
- package/dist/backend/services/vat-validator-port.d.ts.map +1 -0
- package/dist/backend/services/vat-validator-port.js +2 -0
- package/dist/backend/services/vat-validator-port.js.map +1 -0
- package/dist/manifest.d.ts +176 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +503 -0
- package/dist/manifest.js.map +1 -0
- package/dist/migrations/20260424T205317_organizations_init.d.ts +13 -0
- package/dist/migrations/20260424T205317_organizations_init.d.ts.map +1 -0
- package/dist/migrations/20260424T205317_organizations_init.js +100 -0
- package/dist/migrations/20260424T205317_organizations_init.js.map +1 -0
- package/dist/migrations/20260425T051700_organizations_invitations_init.d.ts +13 -0
- package/dist/migrations/20260425T051700_organizations_invitations_init.d.ts.map +1 -0
- package/dist/migrations/20260425T051700_organizations_invitations_init.js +39 -0
- package/dist/migrations/20260425T051700_organizations_invitations_init.js.map +1 -0
- package/dist/migrations/20260611T140349_organizations_consolidation.d.ts +35 -0
- package/dist/migrations/20260611T140349_organizations_consolidation.d.ts.map +1 -0
- package/dist/migrations/20260611T140349_organizations_consolidation.js +180 -0
- package/dist/migrations/20260611T140349_organizations_consolidation.js.map +1 -0
- package/dist/migrations/20260611T140358_organizations_org_order_confirmation_emails.d.ts +10 -0
- package/dist/migrations/20260611T140358_organizations_org_order_confirmation_emails.d.ts.map +1 -0
- package/dist/migrations/20260611T140358_organizations_org_order_confirmation_emails.js +14 -0
- package/dist/migrations/20260611T140358_organizations_org_order_confirmation_emails.js.map +1 -0
- package/dist/migrations/20260611T140402_organizations_org_fulfilment_strategy.d.ts +14 -0
- package/dist/migrations/20260611T140402_organizations_org_fulfilment_strategy.d.ts.map +1 -0
- package/dist/migrations/20260611T140402_organizations_org_fulfilment_strategy.js +20 -0
- package/dist/migrations/20260611T140402_organizations_org_fulfilment_strategy.js.map +1 -0
- package/dist/migrations/20260717T151403_organizations_personal_organizations.d.ts +24 -0
- package/dist/migrations/20260717T151403_organizations_personal_organizations.d.ts.map +1 -0
- package/dist/migrations/20260717T151403_organizations_personal_organizations.js +63 -0
- package/dist/migrations/20260717T151403_organizations_personal_organizations.js.map +1 -0
- package/dist/migrations/20260718T200340_organizations_organization_custom_field_values.d.ts +12 -0
- package/dist/migrations/20260718T200340_organizations_organization_custom_field_values.d.ts.map +1 -0
- package/dist/migrations/20260718T200340_organizations_organization_custom_field_values.js +16 -0
- package/dist/migrations/20260718T200340_organizations_organization_custom_field_values.js.map +1 -0
- package/dist/migrations/20260720T044254_organizations_org_hierarchy.d.ts +23 -0
- package/dist/migrations/20260720T044254_organizations_org_hierarchy.d.ts.map +1 -0
- package/dist/migrations/20260720T044254_organizations_org_hierarchy.js +37 -0
- package/dist/migrations/20260720T044254_organizations_org_hierarchy.js.map +1 -0
- package/dist/migrations/20260912T094646_organizations_sales_channel_organizations.d.ts +27 -0
- package/dist/migrations/20260912T094646_organizations_sales_channel_organizations.d.ts.map +1 -0
- package/dist/migrations/20260912T094646_organizations_sales_channel_organizations.js +44 -0
- package/dist/migrations/20260912T094646_organizations_sales_channel_organizations.js.map +1 -0
- package/dist/migrations/index.d.ts +35 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +45 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/ports/index.d.ts +53 -0
- package/dist/ports/index.d.ts.map +1 -0
- package/dist/ports/index.js +2 -0
- package/dist/ports/index.js.map +1 -0
- package/docs/organization-hierarchy.md +117 -0
- package/docs/organizations.md +312 -0
- package/i18n/en.json +17 -0
- package/i18n/pl.json +17 -0
- package/package.json +107 -0
- package/tailwind.css +14 -0
package/dist/manifest.js
ADDED
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
import { defineModuleManifest, defineModuleSettingsManifest, } from '@endora-commerce/contracts';
|
|
2
|
+
/**
|
|
3
|
+
* The demo data this module owns (feature 113, T222 — contract §1.3).
|
|
4
|
+
*
|
|
5
|
+
* A typed `const` rather than an inline object literal: declared inline the
|
|
6
|
+
* parameter infers from the schema and is `never`, so the author loses
|
|
7
|
+
* `context.ctx: ModuleContext`.
|
|
8
|
+
*
|
|
9
|
+
* Both bodies are reached by a **relative `await import()`** (§1.4), in
|
|
10
|
+
* `cliCommands.run`'s shape and for `cliCommands`' reason: a manifest is loaded
|
|
11
|
+
* by every process that composes the platform and by the check scripts that
|
|
12
|
+
* import the generated index, so a demo body imported at the top of this file
|
|
13
|
+
* would be a service graph pulled into all of them. It needs no `exports`
|
|
14
|
+
* subpath and no `files` entry (§1.5).
|
|
15
|
+
*
|
|
16
|
+
* **The buyer who belongs to this organisation and the credit limit granted to
|
|
17
|
+
* it are not here.** Each is another module's row against this one's, so each is
|
|
18
|
+
* a composition step (§5.1) and belongs to whoever owns the instance.
|
|
19
|
+
*/
|
|
20
|
+
const demo = {
|
|
21
|
+
summary: 'The buying organisation the demo shop trades with.',
|
|
22
|
+
seed: async (context) => (await import('./backend/demo/seed.js')).seedDemo(context),
|
|
23
|
+
reset: async (context) => (await import('./backend/demo/reset.js')).resetDemo(context),
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Organization-owned setting codes (feature 026 consolidation).
|
|
27
|
+
*
|
|
28
|
+
* Both keys are platform-wide policies (no per-channel override).
|
|
29
|
+
*/
|
|
30
|
+
export const ORGANIZATIONS_SETTING_CODES = {
|
|
31
|
+
MODERATION_MODE: 'organizations.moderation.mode',
|
|
32
|
+
NEW_REGISTRATION_RECIPIENTS: 'organizations.notifications.new_registration_recipients',
|
|
33
|
+
// Feature 056 — platform-wide factory default for credit inheritance across the
|
|
34
|
+
// organization tree; a per-org `credit_inheritance_mode` column overrides it.
|
|
35
|
+
CREDIT_INHERITANCE_MODE: 'organizations.hierarchy.credit_inheritance_mode',
|
|
36
|
+
};
|
|
37
|
+
const settings = defineModuleSettingsManifest({
|
|
38
|
+
moduleCode: 'organizations',
|
|
39
|
+
groups: [{ code: 'organizations', name: 'Organizations' }],
|
|
40
|
+
settings: [
|
|
41
|
+
{
|
|
42
|
+
code: ORGANIZATIONS_SETTING_CODES.MODERATION_MODE,
|
|
43
|
+
name: 'Moderation mode for new Organizations',
|
|
44
|
+
description: 'Whether newly registered Organizations enter pending_verification (manual moderation) or active (auto-activation). One of: manual | auto.',
|
|
45
|
+
groupCode: 'organizations',
|
|
46
|
+
valueType: 'string',
|
|
47
|
+
defaultValue: 'manual',
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
code: ORGANIZATIONS_SETTING_CODES.NEW_REGISTRATION_RECIPIENTS,
|
|
51
|
+
name: 'New Organization registration — email recipients',
|
|
52
|
+
description: 'List of email addresses receiving a notification on every new Organization registration. Validated syntactically; max 50 entries; case-insensitive dedup. Empty list ⇒ no emails sent (in-app admin notification still fires).',
|
|
53
|
+
groupCode: 'organizations',
|
|
54
|
+
valueType: 'json',
|
|
55
|
+
defaultValue: [],
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
code: ORGANIZATIONS_SETTING_CODES.CREDIT_INHERITANCE_MODE,
|
|
59
|
+
name: 'Credit inheritance mode (organization hierarchy)',
|
|
60
|
+
description: 'Factory default for how a parent organization\'s credit limit is consumed by sub-organizations that have no own limit. One of: shared_pool (branches draw against one shared pool; concurrent draws never exceed it) | independent_default (each branch draws its own full copy of the inherited amount). A per-organization override may be set by a platform administrator.',
|
|
61
|
+
groupCode: 'organizations',
|
|
62
|
+
valueType: 'string',
|
|
63
|
+
defaultValue: 'shared_pool',
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
});
|
|
67
|
+
/**
|
|
68
|
+
* Organizations module — manifest backfill (Module Lifecycle, feature 018)
|
|
69
|
+
* extended by feature 026 with two settings keys (moderation mode + new
|
|
70
|
+
* registration email recipients).
|
|
71
|
+
*/
|
|
72
|
+
export const manifest = defineModuleManifest({
|
|
73
|
+
id: 'organizations',
|
|
74
|
+
name: 'Organizations',
|
|
75
|
+
description: 'B2B organization records, members, addresses, sales-rep assignment, moderation lifecycle, and per-org commercial scoping.',
|
|
76
|
+
version: '1.1.0',
|
|
77
|
+
// Rule 3 (tenancy root) — specs/065-manifest-aware-migrations/research.md §R9.
|
|
78
|
+
// `organizations` is the single unit of tenancy (Principle XI) and must stay
|
|
79
|
+
// installable first, so it declares no tenant-owned domain module. Five
|
|
80
|
+
// cross-module foreign keys are therefore deliberately NOT declared here —
|
|
81
|
+
// each is a late additive column, not an install-time necessity:
|
|
82
|
+
// → customer_accounts (email_verification_tokens.customer_account_id)
|
|
83
|
+
// would cycle: organizations → customer_accounts →
|
|
84
|
+
// organizations
|
|
85
|
+
// → inventory (organization_warehouses.warehouse_id)
|
|
86
|
+
// cycles as soon as the sales_channels bridge edge is
|
|
87
|
+
// also declared: organizations → inventory →
|
|
88
|
+
// sales_channels → organizations
|
|
89
|
+
// → delivery_methods (organization_delivery_methods.delivery_method_id)
|
|
90
|
+
// → payment_methods (organization_payment_methods.payment_method_id)
|
|
91
|
+
// The last two close no cycle on their own; they are dropped because a
|
|
92
|
+
// tenancy root that cannot install before an optional module is
|
|
93
|
+
// not a root. All four are recorded in
|
|
94
|
+
// test/unit/db/acknowledged-fk-edges.ts, which asserts each is still real and
|
|
95
|
+
// still an exception.
|
|
96
|
+
// `dictionaries` since feature 072 (T138): registration validates the
|
|
97
|
+
// Organization's country code against the dictionary. `RegistrationService`
|
|
98
|
+
// has always taken the validator and neither root ever passed one, so the
|
|
99
|
+
// check was dead and the edge undeclared.
|
|
100
|
+
// `email` since feature 072 (T138): the invitation, verification and
|
|
101
|
+
// new-registration mails. The in-app admin notification that accompanies the
|
|
102
|
+
// last of them was declared in the same task and has moved to
|
|
103
|
+
// `nonBindingDependencies` below (D-179.3). `admin_users` comes back with it:
|
|
104
|
+
// the sales-rep endpoints resolve `adminUserReadPort`, and the edge was
|
|
105
|
+
// satisfied transitively through `admin_notifications` until now. It closes no
|
|
106
|
+
// cycle — `admin_users` depends on `admin_roles` and `auth`, neither of which
|
|
107
|
+
// declares this module. `addresses` is deliberately absent for
|
|
108
|
+
// the same reason the five FK edges above are — it declares this module, so
|
|
109
|
+
// the edge is mutual and declaring it back closes the cycle; it is recorded
|
|
110
|
+
// in `acknowledgedDependencies` below instead.
|
|
111
|
+
// `transactional_emails` since T120: verification, invitation and
|
|
112
|
+
// new-registration mail routes through that module's `templateEmailPort`.
|
|
113
|
+
// `admin_roles` since T143a: the sales-rep visibility scope asks
|
|
114
|
+
// `permissionService` whether the rep holds `organizations:rollup` before it
|
|
115
|
+
// expands an assignment to its subtree. Declarable rather than acknowledged —
|
|
116
|
+
// `admin_roles` depends on nothing, so the edge closes no cycle.
|
|
117
|
+
dependencies: [
|
|
118
|
+
'admin_roles',
|
|
119
|
+
'admin_users',
|
|
120
|
+
'custom_fields',
|
|
121
|
+
'dictionaries',
|
|
122
|
+
'email',
|
|
123
|
+
'settings',
|
|
124
|
+
'transactional_emails',
|
|
125
|
+
],
|
|
126
|
+
// Feature 073, Amendment A1 — the five port edges this module genuinely has
|
|
127
|
+
// and cannot declare above, moved here from `ACKNOWLEDGED_PORT_EDGES` in
|
|
128
|
+
// `backend/scripts/check-port-dependencies.ts` so that one declaration feeds
|
|
129
|
+
// both the CI check and the flip-time refusal. They are ignored by the
|
|
130
|
+
// install and migration order, which is the only reason they were withheld.
|
|
131
|
+
acknowledgedDependencies: [
|
|
132
|
+
{
|
|
133
|
+
moduleId: 'addresses',
|
|
134
|
+
port: 'addressServicePort',
|
|
135
|
+
reason: 'Mutual by nature. `addresses` declares this module because every stored ' +
|
|
136
|
+
'address is organization-scoped, and it must install after the tenancy root. ' +
|
|
137
|
+
'This module resolves the published `AddressServicePort` because its customer ' +
|
|
138
|
+
'routes expose address CRUD — it named the `addressService` class registration ' +
|
|
139
|
+
'until issue #195, which is how the entity crossed the boundary behind a ' +
|
|
140
|
+
'record-shaped type. Declaring the second direction closes the cycle and makes ' +
|
|
141
|
+
'the tenancy root uninstallable first, which Rule 3 forbids — the same trade the ' +
|
|
142
|
+
"manifest's five acknowledged FK edges record. It goes when the address routes " +
|
|
143
|
+
'move to the module that owns the table.',
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
moduleId: 'customer_accounts',
|
|
147
|
+
port: 'customerAuthPort',
|
|
148
|
+
reason: 'The same mutual pair, five names over. `customer_accounts` declares this ' +
|
|
149
|
+
'module — every account belongs to one, and feature 051 made that the tenancy ' +
|
|
150
|
+
"direction — while this module's public registration, login and password-reset " +
|
|
151
|
+
'routes are served by those services. The manifest already ' +
|
|
152
|
+
'records the mirror of this as an acknowledged FK edge ' +
|
|
153
|
+
'(`email_verification_tokens.customer_account_id`). Feature 075 Phase C ' +
|
|
154
|
+
'renamed two of the five: `customerAuthService` and `customerRoleService` hand ' +
|
|
155
|
+
"back that module's entity, and this module resolves the record-returning " +
|
|
156
|
+
'`customerAuthPort` / `customerRolePort` beside them instead.',
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
moduleId: 'customer_accounts',
|
|
160
|
+
port: 'passwordResetService',
|
|
161
|
+
reason: 'See the `customerAuthPort` edge above — same mutual pair.',
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
moduleId: 'customer_accounts',
|
|
165
|
+
port: 'customerRolePort',
|
|
166
|
+
reason: 'See the `customerAuthPort` edge above — same mutual pair.',
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
moduleId: 'customer_accounts',
|
|
170
|
+
port: 'customerAccountReadPort',
|
|
171
|
+
reason: 'Feature 075 Phase C. Every route file and three services in this module read ' +
|
|
172
|
+
"that module's `CustomerAccount` entity directly — the member panel, the " +
|
|
173
|
+
'Org-Admin gate, `GET /me`, registration, invitation and the personal-organization ' +
|
|
174
|
+
'provisioner. D-87 adds a fourth service: the moderation notifier resolved its ' +
|
|
175
|
+
'recipient in raw SQL against that table, which named no specifier and so was ' +
|
|
176
|
+
'invisible to the import predicate. Same mutual pair as `customerAuthPort` above, ' +
|
|
177
|
+
'so the same trade.',
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
moduleId: 'customer_accounts',
|
|
181
|
+
port: 'customerAccountMemberWritePort',
|
|
182
|
+
reason: 'Feature 075 Phase C, the write half of the edge above: this module created and ' +
|
|
183
|
+
"mutated that module's entity in seven places. The writes moved to the owner and " +
|
|
184
|
+
'the audit rows stayed here. Same mutual pair, same trade.',
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
moduleId: 'price_lists',
|
|
188
|
+
port: 'priceListReadPort',
|
|
189
|
+
reason: 'Feature 075 Phase C. The applicable-price-lists panel ran ' +
|
|
190
|
+
"`em.find(PriceList, { status: 'active' })` against that module's table and spelled " +
|
|
191
|
+
"the status filter itself; it asks `price_lists` now. `price_lists` declares this " +
|
|
192
|
+
'module (every price rule is organization-scoped), so declaring the second direction ' +
|
|
193
|
+
'closes the cycle and makes the tenancy root uninstallable first, which Rule 3 ' +
|
|
194
|
+
'forbids — the same trade the four FK edges above record. It goes when the panel ' +
|
|
195
|
+
'moves to the module that owns the table.',
|
|
196
|
+
},
|
|
197
|
+
],
|
|
198
|
+
/**
|
|
199
|
+
* D-44 — real to the container, binding on no operator.
|
|
200
|
+
*
|
|
201
|
+
* D-179.1 moves the `credit_limits` edge here. It described its own refusal
|
|
202
|
+
* in prose before the spelling for it existed, and the spelling is what makes
|
|
203
|
+
* the owner's control work.
|
|
204
|
+
*
|
|
205
|
+
* D-179.3 moves `admin_notifications` here for the same reason and with the
|
|
206
|
+
* same kind. `catalog` reaches that owner too and takes `degrades-without`,
|
|
207
|
+
* because its recorder decides absence in front of the gate; the kind belongs
|
|
208
|
+
* to the **edge**, not to the owner, and the two consumers answer differently.
|
|
209
|
+
*/
|
|
210
|
+
nonBindingDependencies: [
|
|
211
|
+
{
|
|
212
|
+
moduleId: 'admin_notifications',
|
|
213
|
+
name: 'adminNotificationRecordPort',
|
|
214
|
+
kind: 'refuses-without',
|
|
215
|
+
whenAbsent: 'nobody is told a new organisation has registered: the bell entry refuses, and that ' +
|
|
216
|
+
'refusal stops the new-registration e-mails too — the registration itself still ' +
|
|
217
|
+
'completes',
|
|
218
|
+
reason: 'D-179.3. The registration notifier writes one bell entry and then mails the ' +
|
|
219
|
+
'recipient list, and its `catch` calls `rethrowIfModuleDisabled` first under D-88: a ' +
|
|
220
|
+
'registration nobody was told about is not a degrade this module may choose on the ' +
|
|
221
|
+
'owner’s behalf, so the refusal surfaces instead of being absorbed by the ' +
|
|
222
|
+
'best-effort tolerance around it. That is what `refuses-without` spells, and ' +
|
|
223
|
+
'declaring `degrades-without` here would reverse D-88 in a manifest field. It was ' +
|
|
224
|
+
'`dependencies`, which bought no schema order — nothing this module owns references ' +
|
|
225
|
+
'either `admin_notification` table — and only the flip-time refusal that made ' +
|
|
226
|
+
'`admin_notifications.enabled` a control an operator could move with nothing ' +
|
|
227
|
+
'happening.',
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
moduleId: 'credit_limits',
|
|
231
|
+
name: 'creditLimitReadPort',
|
|
232
|
+
kind: 'refuses-without',
|
|
233
|
+
whenAbsent: 'the ancestor-chain lookup for who holds a credit limit refuses — no screen reaches ' +
|
|
234
|
+
"it, because its only caller is that module's own service",
|
|
235
|
+
reason: 'Feature 077, D-87. `creditOwner` walks an ancestor chain and has to know which of ' +
|
|
236
|
+
"those organisations hold a credit limit. It selected from that module's table — a " +
|
|
237
|
+
'statement naming no import specifier, so the boundary compiled and returned rows ' +
|
|
238
|
+
'whatever state the owner was in. It asks `creditLimitReadPort` now, through a ' +
|
|
239
|
+
'`lazyPort` call on a `di.providePort` name, with no fallback and no `catch`: an ' +
|
|
240
|
+
'empty set would read as "nobody here holds a limit", which on a credit check is the ' +
|
|
241
|
+
'difference between refusing an order and quoting unlimited credit. D-179.1 spells ' +
|
|
242
|
+
'that `refuses-without`. It was `acknowledgedDependencies`, which described the same ' +
|
|
243
|
+
'behaviour and carried a bind as well, and the bind is what made the owner\'s ' +
|
|
244
|
+
'activation control answer 409 forever.',
|
|
245
|
+
},
|
|
246
|
+
],
|
|
247
|
+
// Feature 072/073 (Constitution XVII). The Organization is the single unit of
|
|
248
|
+
// tenancy (Principle XI): every transacting customer has one, every
|
|
249
|
+
// tenant-scoped entity carries its id, and the global-filter guard in
|
|
250
|
+
// `src/tenancy/` resolves against this module's table. Principle XI states
|
|
251
|
+
// outright that a design with a "no-organization" path is invalid, so there is
|
|
252
|
+
// no coherent deployment with this switched off — it is not a smaller platform
|
|
253
|
+
// but one with no tenant.
|
|
254
|
+
//
|
|
255
|
+
// The declaration is also forced from above: `customer_accounts` is itself
|
|
256
|
+
// non-deactivatable and depends on this module, and dependencies fail closed.
|
|
257
|
+
// Without it, switching `organizations` off would break a module the operator
|
|
258
|
+
// was promised could not be broken.
|
|
259
|
+
demo,
|
|
260
|
+
activation: {
|
|
261
|
+
nonDeactivatable: true,
|
|
262
|
+
reason: 'The single unit of tenancy — every organization-scoped entity, membership and ' +
|
|
263
|
+
'transacting customer resolves through it; switched off, the platform has no tenant.',
|
|
264
|
+
},
|
|
265
|
+
// D-166 — the code gating the three `/organizations/:id/sales-reps`
|
|
266
|
+
// endpoints, which this module registers from its own `backend.ts`.
|
|
267
|
+
//
|
|
268
|
+
// It is the name this module's own route file proposed in feature 008: those
|
|
269
|
+
// endpoints were gated `rfqs:handle` "for now, because that's the existing
|
|
270
|
+
// admin permission slot for RFQ-adjacent work", with a comment saying a
|
|
271
|
+
// dedicated `organizations:assign-sales-rep` should follow. It has to, and
|
|
272
|
+
// for a reason sharper than tidiness — `rfqs:handle` is declared
|
|
273
|
+
// `module: 'quote_requests'`, so an operator switching quote requests off
|
|
274
|
+
// removes that code from `/admin-roles` while these endpoints, owned by a
|
|
275
|
+
// module that cannot be switched off, keep answering. The screen would sit
|
|
276
|
+
// there behind a permission nobody could be granted.
|
|
277
|
+
//
|
|
278
|
+
// `organizations:rollup` stays in the core `PERMISSION_CATALOGUE`: it is read
|
|
279
|
+
// by `admin_roles`' capability check on behalf of three modules, and moving it
|
|
280
|
+
// is a data migration on every admin role that holds it.
|
|
281
|
+
//
|
|
282
|
+
// D-173 — the two `customers:*` codes are the same finding, one route file
|
|
283
|
+
// over. Every admin organization endpoint here is gated on `customers:manage`
|
|
284
|
+
// (or on `customers:read` OR `customers:manage`), and both codes' core
|
|
285
|
+
// `PERMISSION_CATALOGUE` rows name `customers`, which an operator can switch
|
|
286
|
+
// off while this module cannot be. Declaring them here makes this module a
|
|
287
|
+
// second *owner*, in the shape issue #213 gave `integrations:manage`, so the
|
|
288
|
+
// presence filter keeps them grantable while these screens are on. The
|
|
289
|
+
// labels are why they are shared rather than replaced by codes of this
|
|
290
|
+
// module's own: *"Manage customer organizations"* and *"View customers"*
|
|
291
|
+
// read as sentences about this module's screens, which is what the
|
|
292
|
+
// paragraph above had to invent a new code for and these do not.
|
|
293
|
+
permissions: [
|
|
294
|
+
{
|
|
295
|
+
code: 'organizations:assign-sales-rep',
|
|
296
|
+
label: 'Assign sales representatives to organizations',
|
|
297
|
+
},
|
|
298
|
+
{ code: 'customers:read', label: 'View customers' },
|
|
299
|
+
{ code: 'customers:manage', label: 'Manage customer organizations' },
|
|
300
|
+
],
|
|
301
|
+
settings,
|
|
302
|
+
/**
|
|
303
|
+
* The module's landing surface in the command palette (Principle XVI) — its
|
|
304
|
+
* first action, declared by feature 091's Phase 4 batch 14.
|
|
305
|
+
*
|
|
306
|
+
* `AppShell.tsx` carried a hand-written *Navigate* row for `/organizations`
|
|
307
|
+
* until that batch. A hand-written palette row is a copy the server was never
|
|
308
|
+
* asked about, so it went on advertising the screen whatever the effective
|
|
309
|
+
* enabled-set said; a manifest action is the one surface that set filters.
|
|
310
|
+
* The destination and the keywords are the row's, and the label and
|
|
311
|
+
* description are the two strings it rendered
|
|
312
|
+
* (`appShell.nav.organizations`, `appShell.palette.sub.customerAccounts`),
|
|
313
|
+
* moved into this module's own bundle.
|
|
314
|
+
*
|
|
315
|
+
* **`customers:read` and not the row's any-of pair.**
|
|
316
|
+
* `ModuleActionSchema.requiredPermission` is a single string, and either code
|
|
317
|
+
* alone opens `/organizations` — the gate is
|
|
318
|
+
* `requireAdminAny(['customers:read', 'customers:manage'])`, which is the
|
|
319
|
+
* sufficiency `check:action-route-permissions` reads. The narrowing is real
|
|
320
|
+
* for a role holding only `customers:manage` and is recorded where the row
|
|
321
|
+
* used to stand; the sidebar entry keeps the pair, because
|
|
322
|
+
* `AdminNavDeclaration.requiredPermission` takes the whole
|
|
323
|
+
* `PermissionRequirement`.
|
|
324
|
+
*/
|
|
325
|
+
actions: [
|
|
326
|
+
{
|
|
327
|
+
id: 'open-organizations',
|
|
328
|
+
labelKey: 'actions.openOrganizations.label',
|
|
329
|
+
descriptionKey: 'actions.openOrganizations.description',
|
|
330
|
+
icon: 'Building2',
|
|
331
|
+
targetRoute: '/organizations',
|
|
332
|
+
requiredPermission: 'customers:read',
|
|
333
|
+
keywords: ['org', 'orgs', 'customer', 'organization', 'organizacja', 'klient'],
|
|
334
|
+
weight: 220,
|
|
335
|
+
},
|
|
336
|
+
],
|
|
337
|
+
// Feature 047 — admin-editable transactional emails owned by this module.
|
|
338
|
+
transactionalEmails: [
|
|
339
|
+
{
|
|
340
|
+
code: 'email_verification',
|
|
341
|
+
name: 'Email verification',
|
|
342
|
+
group: 'organizations',
|
|
343
|
+
variables: [
|
|
344
|
+
{ key: 'organizationName', label: 'Organization name', sampleValue: 'Acme Sp. z o.o.' },
|
|
345
|
+
{ key: 'verifyUrl', label: 'Verification link', sampleValue: 'https://shop.example/verify?token=…' },
|
|
346
|
+
],
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
code: 'organization_invitation',
|
|
350
|
+
name: 'Organization invitation',
|
|
351
|
+
group: 'organizations',
|
|
352
|
+
variables: [
|
|
353
|
+
{ key: 'organizationName', label: 'Organization name', sampleValue: 'Acme Sp. z o.o.' },
|
|
354
|
+
{ key: 'inviterName', label: 'Inviter name', sampleValue: 'Anna Nowak' },
|
|
355
|
+
{ key: 'roleLabel', label: 'Role', sampleValue: 'Member' },
|
|
356
|
+
{ key: 'acceptUrl', label: 'Accept link', sampleValue: 'https://shop.example/invitations/…/accept' },
|
|
357
|
+
{ key: 'expiresOn', label: 'Expiry date', sampleValue: '2026-07-15' },
|
|
358
|
+
],
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
code: 'new_org_registration',
|
|
362
|
+
name: 'New organization registration (admin)',
|
|
363
|
+
group: 'organizations',
|
|
364
|
+
variables: [
|
|
365
|
+
{ key: 'organizationName', label: 'Organization name', sampleValue: 'Acme Sp. z o.o.' },
|
|
366
|
+
{ key: 'taxId', label: 'Tax ID', sampleValue: 'PL1234567890' },
|
|
367
|
+
{ key: 'statusLabel', label: 'Status', sampleValue: 'Oczekuje na weryfikację' },
|
|
368
|
+
{ key: 'linkPath', label: 'Admin link', sampleValue: '/organizations/…' },
|
|
369
|
+
],
|
|
370
|
+
},
|
|
371
|
+
// The two moderation outcomes a buyer is told about. Both reached the
|
|
372
|
+
// transport as hard-coded Polish prose with no code and no language until
|
|
373
|
+
// the seam-B carve-out in `specs/093-backend-delivered-prose/`; declaring
|
|
374
|
+
// them here is what gives them a language at all, and an operator a place
|
|
375
|
+
// to edit them.
|
|
376
|
+
{
|
|
377
|
+
code: 'organization_approved',
|
|
378
|
+
name: 'Organization verified (customer)',
|
|
379
|
+
group: 'organizations',
|
|
380
|
+
variables: [
|
|
381
|
+
{ key: 'organizationName', label: 'Organization name', sampleValue: 'Acme Sp. z o.o.' },
|
|
382
|
+
],
|
|
383
|
+
},
|
|
384
|
+
{
|
|
385
|
+
code: 'organization_rejected',
|
|
386
|
+
name: 'Organization registration rejected (customer)',
|
|
387
|
+
group: 'organizations',
|
|
388
|
+
variables: [
|
|
389
|
+
{ key: 'organizationName', label: 'Organization name', sampleValue: 'Acme Sp. z o.o.' },
|
|
390
|
+
{ key: 'reason', label: 'Rejection reason', sampleValue: 'Tax ID could not be verified.' },
|
|
391
|
+
],
|
|
392
|
+
},
|
|
393
|
+
],
|
|
394
|
+
/**
|
|
395
|
+
* This module's first i18n bundle — D-129's remaining sweep, MR 7.
|
|
396
|
+
*
|
|
397
|
+
* It exists because a **declaring** module that contributes no bundle file is
|
|
398
|
+
* `check:error-translations` exit 2 for the whole tree rather than a finding
|
|
399
|
+
* (`specs/090-module-owned-error-codes/contracts/error-translation-population.md`
|
|
400
|
+
* §2.1, §2.3; `d129-sweep.md` §3.4). The bundle lives at the **package
|
|
401
|
+
* root**, not under `dist`: `manifest-locations.ts` resolves a packaged
|
|
402
|
+
* module's `manifestPath` to its `package.json`, so `dirname` is the package
|
|
403
|
+
* directory. The file is a **flat** `{"a.b.c": "text"}` map, because a nested
|
|
404
|
+
* object fails `TranslationBundleEntriesSchema` and the boot reconciler logs
|
|
405
|
+
* and skips it — silently.
|
|
406
|
+
*/
|
|
407
|
+
i18n: { bundlesDir: 'i18n' },
|
|
408
|
+
docs: { dir: 'docs' },
|
|
409
|
+
/**
|
|
410
|
+
* The eight codes whose noun is an organization — D-129's remaining sweep,
|
|
411
|
+
* **Tier C** (`specs/090-module-owned-error-codes/d129-sweep.md` §5.2,
|
|
412
|
+
* Appendix A; MR 7, the largest batch in the sweep).
|
|
413
|
+
*
|
|
414
|
+
* They were declared by `_i18n` until this merge request, not because anybody
|
|
415
|
+
* judged them the platform's but because the deleted prefix chain had no rule
|
|
416
|
+
* for them and its last line was `return 'core'`. **D-121 T1 puts all eight
|
|
417
|
+
* here**: the noun in each is this module's `organizations` row, its
|
|
418
|
+
* invitation, its administrator or its tree.
|
|
419
|
+
*
|
|
420
|
+
* **Two of the eight are raised by a module that does not own them**, which is
|
|
421
|
+
* the shape D-95.2 already ruled for `INVOICE_NOT_READY` and D-186 §1 re-took
|
|
422
|
+
* for `CUSTOMER_*`: the owner of a noun is not required to be the module that
|
|
423
|
+
* throws about it. `ORG_OWNER_DEPLETION` is raised three times in `customers`
|
|
424
|
+
* — deleting, blocking and unassigning the last organization administrator —
|
|
425
|
+
* and the invariant it protects is this module's, not that module's: an
|
|
426
|
+
* organization is the unit of tenancy and may not be left with nobody able to
|
|
427
|
+
* manage it. `ORGANIZATION_SUSPENDED` is raised once in `orders`, at
|
|
428
|
+
* placement, and is a statement about the organization's `status` column,
|
|
429
|
+
* which this module owns and moderates. Homing either with its thrower would
|
|
430
|
+
* split the sentence from the rule it describes and put it in a bundle that
|
|
431
|
+
* says nothing else about organizations.
|
|
432
|
+
*
|
|
433
|
+
* **Two are always tokened, and their token sets were measured rather than
|
|
434
|
+
* read off the bundle** (runbook §5): the arguments of every `HttpError` call
|
|
435
|
+
* naming them were extracted by balancing the call's own parentheses,
|
|
436
|
+
* resolving `ERROR_CODES.<CODE>` and the bare literal alike, and `details`
|
|
437
|
+
* read as the **positional fourth argument** it is — the correction MR 6
|
|
438
|
+
* recorded, because looking for a named `details:` property reports `(none)`
|
|
439
|
+
* for a raise that plainly carries a token. `ORGANIZATION_HAS_CHILDREN` has
|
|
440
|
+
* one raise and it passes `has_children`; `ORGANIZATION_TREE_INVALID` has two
|
|
441
|
+
* and they pass `cycle` and `max_depth_exceeded`. The other six carry no
|
|
442
|
+
* `details` at all, at any raise site, which is why they declare no tokens.
|
|
443
|
+
*
|
|
444
|
+
* **So all four sentences these two codes had were unreachable, and this
|
|
445
|
+
* change is the first time either renders anything.**
|
|
446
|
+
* `localizeErrorEnvelope` composes `` `${target.key}.${token}` `` whenever
|
|
447
|
+
* `details.code` is present and has **no** fall-back to the base key
|
|
448
|
+
* (`packages/platform/src/http/error-envelope.ts`), so `_i18n`'s two prose
|
|
449
|
+
* pairs were read by nobody. The three sub-keys are written here for the
|
|
450
|
+
* first time and are the ones an operator meets.
|
|
451
|
+
*
|
|
452
|
+
* **The base pairs move anyway, and D-190 is why.** They are unreachable for
|
|
453
|
+
* the operator and load-bearing for the instrument at the same time:
|
|
454
|
+
* `findUntranslatedErrorCodes` asks its question at
|
|
455
|
+
* `read(target.moduleId, language)[target.key]` and at **no other key**, so a
|
|
456
|
+
* bundle without them reports both codes as untranslated and exits 1 — MR 6
|
|
457
|
+
* measured exactly that when it tried. `UNTRANSLATED_ERROR_CODES` would be a
|
|
458
|
+
* false entry for a code with five written sentences, and widening P1 to
|
|
459
|
+
* accept "every declared token answered" is a tree-wide instrument changed by
|
|
460
|
+
* the merge request that benefits from it, which D-190 refuses in terms. So
|
|
461
|
+
* the base sentence is carried, and the sub-key beside it is the one to edit
|
|
462
|
+
* when the wording changes.
|
|
463
|
+
*
|
|
464
|
+
* **The other six arrive with prose.** Five carried a placeholder in `_i18n`'s
|
|
465
|
+
* bundle — `"Organization Suspended."` / `"Błąd: organization suspended."`
|
|
466
|
+
* and four like it — which D-186 §2 deletes rather than carries,
|
|
467
|
+
* because in this module's own bundle it would read as this module's answer
|
|
468
|
+
* and every instrument would then count the code as translated.
|
|
469
|
+
* `d129-sweep.md` §5.4 keeps writing the prose available and is not a
|
|
470
|
+
* re-opening of that ruling; every one of the six has a live raise site whose
|
|
471
|
+
* English states the refusal and a reader who meets it — an organization
|
|
472
|
+
* administrator inviting a member, a buyer whose organization was suspended,
|
|
473
|
+
* a company registering with a tax ID somebody already used, an operator on
|
|
474
|
+
* `/customers` removing the last administrator. The sixth,
|
|
475
|
+
* `ORG_OWNER_DEPLETION`, had no sentence at all and sat on
|
|
476
|
+
* `UNTRANSLATED_ERROR_CODES`; writing it is what makes that ledger **shrink**
|
|
477
|
+
* for the first time in the sweep.
|
|
478
|
+
*
|
|
479
|
+
* `ORGANIZATION_TREE_INVALID.max_depth_exceeded` needed one repair before its
|
|
480
|
+
* sentence could be written: the raise interpolates the depth bound into its
|
|
481
|
+
* English message and passed only the token, so a translated sentence with no
|
|
482
|
+
* placeholder would have rendered cleanly and lost the number — the shape
|
|
483
|
+
* !1181 measured at 85 codes tree-wide. The raise now carries
|
|
484
|
+
* `{ code: 'max_depth_exceeded', maxDepth: MAX_TREE_DEPTH_SEGMENTS }` and both
|
|
485
|
+
* sentences name it as `{maxDepth}`. The member is `maxDepth` and not `code`
|
|
486
|
+
* deliberately: `details.code` is the refusal **token**, and a second value
|
|
487
|
+
* written there would re-key the lookup rather than fill the sentence.
|
|
488
|
+
* `test/unit/organizations/error-code-sentences.test.ts` renders a real
|
|
489
|
+
* refusal against these keys, which is the three-way agreement issue #168
|
|
490
|
+
* found nothing was checking and which `check:error-translations` cannot see.
|
|
491
|
+
*/
|
|
492
|
+
errorCodes: [
|
|
493
|
+
{ code: 'CANNOT_REVOKE_LAST_ADMIN_INVITE' },
|
|
494
|
+
{ code: 'EMAIL_ALREADY_IN_ORGANIZATION' },
|
|
495
|
+
{ code: 'EMAIL_BELONGS_TO_ANOTHER_ORGANIZATION' },
|
|
496
|
+
{ code: 'ORGANIZATION_HAS_CHILDREN', tokens: ['has_children'] },
|
|
497
|
+
{ code: 'ORGANIZATION_SUSPENDED' },
|
|
498
|
+
{ code: 'ORGANIZATION_TAX_ID_EXISTS' },
|
|
499
|
+
{ code: 'ORGANIZATION_TREE_INVALID', tokens: ['cycle', 'max_depth_exceeded'] },
|
|
500
|
+
{ code: 'ORG_OWNER_DEPLETION' },
|
|
501
|
+
],
|
|
502
|
+
});
|
|
503
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,4BAA4B,GAE7B,MAAM,4BAA4B,CAAC;AAGpC;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,IAAI,GAAsC;IAC9C,OAAO,EAAE,oDAAoD;IAC7D,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;IACnF,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC;CACvF,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG;IACzC,eAAe,EAAE,+BAA+B;IAChD,2BAA2B,EAAE,yDAAyD;IACtF,gFAAgF;IAChF,8EAA8E;IAC9E,uBAAuB,EAAE,iDAAiD;CAClE,CAAC;AAEX,MAAM,QAAQ,GAAG,4BAA4B,CAAC;IAC5C,UAAU,EAAE,eAAe;IAC3B,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC;IAC1D,QAAQ,EAAE;QACR;YACE,IAAI,EAAE,2BAA2B,CAAC,eAAe;YACjD,IAAI,EAAE,uCAAuC;YAC7C,WAAW,EACT,2IAA2I;YAC7I,SAAS,EAAE,eAAe;YAC1B,SAAS,EAAE,QAAQ;YACnB,YAAY,EAAE,QAAQ;SACvB;QACD;YACE,IAAI,EAAE,2BAA2B,CAAC,2BAA2B;YAC7D,IAAI,EAAE,kDAAkD;YACxD,WAAW,EACT,gOAAgO;YAClO,SAAS,EAAE,eAAe;YAC1B,SAAS,EAAE,MAAM;YACjB,YAAY,EAAE,EAAE;SACjB;QACD;YACE,IAAI,EAAE,2BAA2B,CAAC,uBAAuB;YACzD,IAAI,EAAE,kDAAkD;YACxD,WAAW,EACT,+WAA+W;YACjX,SAAS,EAAE,eAAe;YAC1B,SAAS,EAAE,QAAQ;YACnB,YAAY,EAAE,aAAa;SAC5B;KACF;CACF,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,oBAAoB,CAAC;IAC3C,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,eAAe;IACrB,WAAW,EACT,2HAA2H;IAC7H,OAAO,EAAE,OAAO;IAChB,+EAA+E;IAC/E,6EAA6E;IAC7E,wEAAwE;IACxE,2EAA2E;IAC3E,iEAAiE;IACjE,yEAAyE;IACzE,0EAA0E;IAC1E,uCAAuC;IACvC,gEAAgE;IAChE,6EAA6E;IAC7E,oEAAoE;IACpE,wDAAwD;IACxD,4EAA4E;IAC5E,0EAA0E;IAC1E,uEAAuE;IACvE,gEAAgE;IAChE,uCAAuC;IACvC,8EAA8E;IAC9E,sBAAsB;IACtB,sEAAsE;IACtE,4EAA4E;IAC5E,0EAA0E;IAC1E,0CAA0C;IAC1C,qEAAqE;IACrE,6EAA6E;IAC7E,8DAA8D;IAC9D,8EAA8E;IAC9E,wEAAwE;IACxE,+EAA+E;IAC/E,8EAA8E;IAC9E,+DAA+D;IAC/D,4EAA4E;IAC5E,4EAA4E;IAC5E,+CAA+C;IAC/C,kEAAkE;IAClE,0EAA0E;IAC1E,iEAAiE;IACjE,6EAA6E;IAC7E,8EAA8E;IAC9E,iEAAiE;IACjE,YAAY,EAAE;QACZ,aAAa;QACb,aAAa;QACb,eAAe;QACf,cAAc;QACd,OAAO;QACP,UAAU;QACV,sBAAsB;KACvB;IACD,4EAA4E;IAC5E,yEAAyE;IACzE,6EAA6E;IAC7E,uEAAuE;IACvE,4EAA4E;IAC5E,wBAAwB,EAAE;QACxB;YACE,QAAQ,EAAE,WAAW;YACrB,IAAI,EAAE,oBAAoB;YAC1B,MAAM,EACJ,0EAA0E;gBAC1E,8EAA8E;gBAC9E,+EAA+E;gBAC/E,gFAAgF;gBAChF,0EAA0E;gBAC1E,gFAAgF;gBAChF,kFAAkF;gBAClF,gFAAgF;gBAChF,yCAAyC;SAC5C;QACD;YACE,QAAQ,EAAE,mBAAmB;YAC7B,IAAI,EAAE,kBAAkB;YACxB,MAAM,EACJ,2EAA2E;gBAC3E,+EAA+E;gBAC/E,gFAAgF;gBAChF,4DAA4D;gBAC5D,wDAAwD;gBACxD,yEAAyE;gBACzE,gFAAgF;gBAChF,2EAA2E;gBAC3E,8DAA8D;SACjE;QACD;YACE,QAAQ,EAAE,mBAAmB;YAC7B,IAAI,EAAE,sBAAsB;YAC5B,MAAM,EAAE,2DAA2D;SACpE;QACD;YACE,QAAQ,EAAE,mBAAmB;YAC7B,IAAI,EAAE,kBAAkB;YACxB,MAAM,EAAE,2DAA2D;SACpE;QACD;YACE,QAAQ,EAAE,mBAAmB;YAC7B,IAAI,EAAE,yBAAyB;YAC/B,MAAM,EACJ,+EAA+E;gBAC/E,0EAA0E;gBAC1E,oFAAoF;gBACpF,gFAAgF;gBAChF,+EAA+E;gBAC/E,mFAAmF;gBACnF,oBAAoB;SACvB;QACD;YACE,QAAQ,EAAE,mBAAmB;YAC7B,IAAI,EAAE,gCAAgC;YACtC,MAAM,EACJ,iFAAiF;gBACjF,kFAAkF;gBAClF,2DAA2D;SAC9D;QACD;YACE,QAAQ,EAAE,aAAa;YACvB,IAAI,EAAE,mBAAmB;YACzB,MAAM,EACJ,4DAA4D;gBAC5D,qFAAqF;gBACrF,mFAAmF;gBACnF,sFAAsF;gBACtF,gFAAgF;gBAChF,kFAAkF;gBAClF,0CAA0C;SAC7C;KACF;IACD;;;;;;;;;;;OAWG;IACH,sBAAsB,EAAE;QACtB;YACE,QAAQ,EAAE,qBAAqB;YAC/B,IAAI,EAAE,6BAA6B;YACnC,IAAI,EAAE,iBAAiB;YACvB,UAAU,EACR,qFAAqF;gBACrF,iFAAiF;gBACjF,WAAW;YACb,MAAM,EACJ,8EAA8E;gBAC9E,sFAAsF;gBACtF,oFAAoF;gBACpF,2EAA2E;gBAC3E,8EAA8E;gBAC9E,mFAAmF;gBACnF,qFAAqF;gBACrF,+EAA+E;gBAC/E,8EAA8E;gBAC9E,YAAY;SACf;QACD;YACE,QAAQ,EAAE,eAAe;YACzB,IAAI,EAAE,qBAAqB;YAC3B,IAAI,EAAE,iBAAiB;YACvB,UAAU,EACR,qFAAqF;gBACrF,0DAA0D;YAC5D,MAAM,EACJ,oFAAoF;gBACpF,oFAAoF;gBACpF,mFAAmF;gBACnF,gFAAgF;gBAChF,kFAAkF;gBAClF,sFAAsF;gBACtF,oFAAoF;gBACpF,sFAAsF;gBACtF,+EAA+E;gBAC/E,wCAAwC;SAC3C;KACF;IACD,8EAA8E;IAC9E,oEAAoE;IACpE,sEAAsE;IACtE,2EAA2E;IAC3E,+EAA+E;IAC/E,+EAA+E;IAC/E,0BAA0B;IAC1B,EAAE;IACF,2EAA2E;IAC3E,8EAA8E;IAC9E,8EAA8E;IAC9E,oCAAoC;IACpC,IAAI;IACJ,UAAU,EAAE;QACV,gBAAgB,EAAE,IAAI;QACtB,MAAM,EACJ,gFAAgF;YAChF,qFAAqF;KACxF;IACD,oEAAoE;IACpE,oEAAoE;IACpE,EAAE;IACF,6EAA6E;IAC7E,2EAA2E;IAC3E,wEAAwE;IACxE,2EAA2E;IAC3E,iEAAiE;IACjE,0EAA0E;IAC1E,0EAA0E;IAC1E,2EAA2E;IAC3E,qDAAqD;IACrD,EAAE;IACF,8EAA8E;IAC9E,+EAA+E;IAC/E,yDAAyD;IACzD,EAAE;IACF,2EAA2E;IAC3E,8EAA8E;IAC9E,uEAAuE;IACvE,6EAA6E;IAC7E,2EAA2E;IAC3E,6EAA6E;IAC7E,uEAAuE;IACvE,uEAAuE;IACvE,yEAAyE;IACzE,mEAAmE;IACnE,iEAAiE;IACjE,WAAW,EAAE;QACX;YACE,IAAI,EAAE,gCAAgC;YACtC,KAAK,EAAE,+CAA+C;SACvD;QACD,EAAE,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,gBAAgB,EAAE;QACnD,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,+BAA+B,EAAE;KACrE;IACD,QAAQ;IACR;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,OAAO,EAAE;QACP;YACE,EAAE,EAAE,oBAAoB;YACxB,QAAQ,EAAE,iCAAiC;YAC3C,cAAc,EAAE,uCAAuC;YACvD,IAAI,EAAE,WAAW;YACjB,WAAW,EAAE,gBAAgB;YAC7B,kBAAkB,EAAE,gBAAgB;YACpC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,aAAa,EAAE,QAAQ,CAAC;YAC9E,MAAM,EAAE,GAAG;SACZ;KACF;IACD,0EAA0E;IAC1E,mBAAmB,EAAE;QACnB;YACE,IAAI,EAAE,oBAAoB;YAC1B,IAAI,EAAE,oBAAoB;YAC1B,KAAK,EAAE,eAAe;YACtB,SAAS,EAAE;gBACT,EAAE,GAAG,EAAE,kBAAkB,EAAE,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,iBAAiB,EAAE;gBACvF,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,qCAAqC,EAAE;aACrG;SACF;QACD;YACE,IAAI,EAAE,yBAAyB;YAC/B,IAAI,EAAE,yBAAyB;YAC/B,KAAK,EAAE,eAAe;YACtB,SAAS,EAAE;gBACT,EAAE,GAAG,EAAE,kBAAkB,EAAE,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,iBAAiB,EAAE;gBACvF,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,YAAY,EAAE;gBACxE,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE;gBAC1D,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,2CAA2C,EAAE;gBACpG,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE;aACtE;SACF;QACD;YACE,IAAI,EAAE,sBAAsB;YAC5B,IAAI,EAAE,uCAAuC;YAC7C,KAAK,EAAE,eAAe;YACtB,SAAS,EAAE;gBACT,EAAE,GAAG,EAAE,kBAAkB,EAAE,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,iBAAiB,EAAE;gBACvF,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE;gBAC9D,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,yBAAyB,EAAE;gBAC/E,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE;aAC1E;SACF;QACD,sEAAsE;QACtE,0EAA0E;QAC1E,0EAA0E;QAC1E,0EAA0E;QAC1E,gBAAgB;QAChB;YACE,IAAI,EAAE,uBAAuB;YAC7B,IAAI,EAAE,kCAAkC;YACxC,KAAK,EAAE,eAAe;YACtB,SAAS,EAAE;gBACT,EAAE,GAAG,EAAE,kBAAkB,EAAE,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,iBAAiB,EAAE;aACxF;SACF;QACD;YACE,IAAI,EAAE,uBAAuB;YAC7B,IAAI,EAAE,+CAA+C;YACrD,KAAK,EAAE,eAAe;YACtB,SAAS,EAAE;gBACT,EAAE,GAAG,EAAE,kBAAkB,EAAE,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,iBAAiB,EAAE;gBACvF,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,+BAA+B,EAAE;aAC3F;SACF;KACF;IACD;;;;;;;;;;;;OAYG;IACH,IAAI,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE;IAC5B,IAAI,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE;IACrB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAkFG;IACH,UAAU,EAAE;QACV,EAAE,IAAI,EAAE,iCAAiC,EAAE;QAC3C,EAAE,IAAI,EAAE,+BAA+B,EAAE;QACzC,EAAE,IAAI,EAAE,uCAAuC,EAAE;QACjD,EAAE,IAAI,EAAE,2BAA2B,EAAE,MAAM,EAAE,CAAC,cAAc,CAAC,EAAE;QAC/D,EAAE,IAAI,EAAE,wBAAwB,EAAE;QAClC,EAAE,IAAI,EAAE,4BAA4B,EAAE;QACtC,EAAE,IAAI,EAAE,2BAA2B,EAAE,MAAM,EAAE,CAAC,OAAO,EAAE,oBAAoB,CAAC,EAAE;QAC9E,EAAE,IAAI,EAAE,qBAAqB,EAAE;KAChC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Migration } from '@mikro-orm/migrations';
|
|
2
|
+
/**
|
|
3
|
+
* Organizations module (+ customer_accounts + addresses) — Phase 4b (T116).
|
|
4
|
+
*
|
|
5
|
+
* Also lands email_verification_tokens used by registration + email change flows.
|
|
6
|
+
* The partial unique index on `addresses (organization_id, kind) WHERE is_default`
|
|
7
|
+
* enforces "at most one default per kind" atomically (T097 contract).
|
|
8
|
+
*/
|
|
9
|
+
export declare class Migration20260424T205317OrganizationsInit extends Migration {
|
|
10
|
+
up(): Promise<void>;
|
|
11
|
+
down(): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=20260424T205317_organizations_init.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"20260424T205317_organizations_init.d.ts","sourceRoot":"","sources":["../../src/migrations/20260424T205317_organizations_init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD;;;;;;GAMG;AACH,qBAAa,yCAA0C,SAAQ,SAAS;IACvD,EAAE,IAAI,OAAO,CAAC,IAAI,CAAC;IAyFnB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAMrC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { Migration } from '@mikro-orm/migrations';
|
|
2
|
+
/**
|
|
3
|
+
* Organizations module (+ customer_accounts + addresses) — Phase 4b (T116).
|
|
4
|
+
*
|
|
5
|
+
* Also lands email_verification_tokens used by registration + email change flows.
|
|
6
|
+
* The partial unique index on `addresses (organization_id, kind) WHERE is_default`
|
|
7
|
+
* enforces "at most one default per kind" atomically (T097 contract).
|
|
8
|
+
*/
|
|
9
|
+
export class Migration20260424T205317OrganizationsInit extends Migration {
|
|
10
|
+
async up() {
|
|
11
|
+
this.addSql(`
|
|
12
|
+
create table "organizations" (
|
|
13
|
+
"id" uuid not null,
|
|
14
|
+
"name" varchar(255) not null,
|
|
15
|
+
"tax_id" varchar(32) not null,
|
|
16
|
+
"status" varchar(32) not null default 'pending_verification',
|
|
17
|
+
"vat_status" varchar(16) not null default 'vat_payer',
|
|
18
|
+
"registered_address" jsonb not null,
|
|
19
|
+
"created_at" timestamptz not null,
|
|
20
|
+
"updated_at" timestamptz not null,
|
|
21
|
+
"deleted_at" timestamptz null,
|
|
22
|
+
constraint "organizations_pkey" primary key ("id"),
|
|
23
|
+
constraint "organizations_tax_id_unique" unique ("tax_id")
|
|
24
|
+
);
|
|
25
|
+
`);
|
|
26
|
+
this.addSql('create index "organizations_name_index" on "organizations" ("name");');
|
|
27
|
+
this.addSql('create index "organizations_status_index" on "organizations" ("status");');
|
|
28
|
+
this.addSql(`
|
|
29
|
+
create table "customer_accounts" (
|
|
30
|
+
"id" uuid not null,
|
|
31
|
+
"organization_id" uuid not null,
|
|
32
|
+
"email" varchar(320) not null,
|
|
33
|
+
"password_hash" varchar(512) not null,
|
|
34
|
+
"first_name" varchar(120) not null,
|
|
35
|
+
"last_name" varchar(120) not null,
|
|
36
|
+
"role" varchar(32) not null default 'regular_user',
|
|
37
|
+
"email_verified_at" timestamptz null,
|
|
38
|
+
"two_factor_secret" varchar(64) null,
|
|
39
|
+
"two_factor_confirmed_at" timestamptz null,
|
|
40
|
+
"last_login_at" timestamptz null,
|
|
41
|
+
"created_at" timestamptz not null,
|
|
42
|
+
"updated_at" timestamptz not null,
|
|
43
|
+
"deleted_at" timestamptz null,
|
|
44
|
+
constraint "customer_accounts_pkey" primary key ("id"),
|
|
45
|
+
constraint "customer_accounts_email_unique" unique ("email"),
|
|
46
|
+
constraint "customer_accounts_organization_fk" foreign key ("organization_id")
|
|
47
|
+
references "organizations" ("id") on delete restrict
|
|
48
|
+
);
|
|
49
|
+
`);
|
|
50
|
+
this.addSql('create index "customer_accounts_organization_id_index" on "customer_accounts" ("organization_id");');
|
|
51
|
+
this.addSql('create index "customer_accounts_role_index" on "customer_accounts" ("role");');
|
|
52
|
+
this.addSql(`
|
|
53
|
+
create table "addresses" (
|
|
54
|
+
"id" uuid not null,
|
|
55
|
+
"organization_id" uuid not null,
|
|
56
|
+
"kind" varchar(16) not null,
|
|
57
|
+
"recipient_name" varchar(160) not null,
|
|
58
|
+
"street" varchar(255) not null,
|
|
59
|
+
"city" varchar(120) not null,
|
|
60
|
+
"postal_code" varchar(20) not null,
|
|
61
|
+
"country" varchar(2) not null,
|
|
62
|
+
"phone" varchar(32) null,
|
|
63
|
+
"is_default" boolean not null default false,
|
|
64
|
+
"created_at" timestamptz not null,
|
|
65
|
+
"updated_at" timestamptz not null,
|
|
66
|
+
"deleted_at" timestamptz null,
|
|
67
|
+
constraint "addresses_pkey" primary key ("id"),
|
|
68
|
+
constraint "addresses_organization_fk" foreign key ("organization_id")
|
|
69
|
+
references "organizations" ("id") on delete restrict
|
|
70
|
+
);
|
|
71
|
+
`);
|
|
72
|
+
this.addSql('create index "addresses_organization_id_index" on "addresses" ("organization_id");');
|
|
73
|
+
this.addSql('create index "addresses_kind_index" on "addresses" ("kind");');
|
|
74
|
+
// At most one default per (organization, kind) — partial unique index.
|
|
75
|
+
this.addSql(`create unique index "addresses_one_default_per_kind" on "addresses" ("organization_id", "kind") where "is_default" = true and "deleted_at" is null;`);
|
|
76
|
+
this.addSql(`
|
|
77
|
+
create table "email_verification_tokens" (
|
|
78
|
+
"id" uuid not null,
|
|
79
|
+
"customer_account_id" uuid not null,
|
|
80
|
+
"token_hash" varchar(128) not null,
|
|
81
|
+
"expires_at" timestamptz not null,
|
|
82
|
+
"consumed_at" timestamptz null,
|
|
83
|
+
"created_at" timestamptz not null,
|
|
84
|
+
constraint "email_verification_tokens_pkey" primary key ("id"),
|
|
85
|
+
constraint "email_verification_tokens_token_hash_unique" unique ("token_hash"),
|
|
86
|
+
constraint "email_verification_tokens_customer_fk" foreign key ("customer_account_id")
|
|
87
|
+
references "customer_accounts" ("id") on delete cascade
|
|
88
|
+
);
|
|
89
|
+
`);
|
|
90
|
+
this.addSql('create index "email_verification_tokens_customer_account_id_index" on "email_verification_tokens" ("customer_account_id");');
|
|
91
|
+
this.addSql('create index "email_verification_tokens_expires_at_index" on "email_verification_tokens" ("expires_at");');
|
|
92
|
+
}
|
|
93
|
+
async down() {
|
|
94
|
+
this.addSql('drop table if exists "email_verification_tokens" cascade;');
|
|
95
|
+
this.addSql('drop table if exists "addresses" cascade;');
|
|
96
|
+
this.addSql('drop table if exists "customer_accounts" cascade;');
|
|
97
|
+
this.addSql('drop table if exists "organizations" cascade;');
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=20260424T205317_organizations_init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"20260424T205317_organizations_init.js","sourceRoot":"","sources":["../../src/migrations/20260424T205317_organizations_init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD;;;;;;GAMG;AACH,MAAM,OAAO,yCAA0C,SAAQ,SAAS;IAC7D,KAAK,CAAC,EAAE;QACf,IAAI,CAAC,MAAM,CAAC;;;;;;;;;;;;;;KAcX,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,sEAAsE,CAAC,CAAC;QACpF,IAAI,CAAC,MAAM,CAAC,0EAA0E,CAAC,CAAC;QAExF,IAAI,CAAC,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;KAqBX,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,oGAAoG,CAAC,CAAC;QAClH,IAAI,CAAC,MAAM,CAAC,8EAA8E,CAAC,CAAC;QAE5F,IAAI,CAAC,MAAM,CAAC;;;;;;;;;;;;;;;;;;;KAmBX,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,oFAAoF,CAAC,CAAC;QAClG,IAAI,CAAC,MAAM,CAAC,8DAA8D,CAAC,CAAC;QAC5E,uEAAuE;QACvE,IAAI,CAAC,MAAM,CACT,qJAAqJ,CACtJ,CAAC;QAEF,IAAI,CAAC,MAAM,CAAC;;;;;;;;;;;;;KAaX,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,4HAA4H,CAAC,CAAC;QAC1I,IAAI,CAAC,MAAM,CAAC,0GAA0G,CAAC,CAAC;IAC1H,CAAC;IAEQ,KAAK,CAAC,IAAI;QACjB,IAAI,CAAC,MAAM,CAAC,2DAA2D,CAAC,CAAC;QACzE,IAAI,CAAC,MAAM,CAAC,2CAA2C,CAAC,CAAC;QACzD,IAAI,CAAC,MAAM,CAAC,mDAAmD,CAAC,CAAC;QACjE,IAAI,CAAC,MAAM,CAAC,+CAA+C,CAAC,CAAC;IAC/D,CAAC;CACF"}
|