@endora-commerce/contracts 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 +34 -0
- package/dist/actor.d.ts +79 -0
- package/dist/actor.d.ts.map +1 -0
- package/dist/actor.js +41 -0
- package/dist/actor.js.map +1 -0
- package/dist/addresses.d.ts +134 -0
- package/dist/addresses.d.ts.map +1 -0
- package/dist/addresses.js +16 -0
- package/dist/addresses.js.map +1 -0
- package/dist/admin-actions.d.ts +367 -0
- package/dist/admin-actions.d.ts.map +1 -0
- package/dist/admin-actions.js +287 -0
- package/dist/admin-actions.js.map +1 -0
- package/dist/admin-contributions.d.ts +518 -0
- package/dist/admin-contributions.d.ts.map +1 -0
- package/dist/admin-contributions.js +495 -0
- package/dist/admin-contributions.js.map +1 -0
- package/dist/admin-i18n.d.ts +135 -0
- package/dist/admin-i18n.d.ts.map +1 -0
- package/dist/admin-i18n.js +72 -0
- package/dist/admin-i18n.js.map +1 -0
- package/dist/admin-notifications.d.ts +55 -0
- package/dist/admin-notifications.d.ts.map +1 -0
- package/dist/admin-notifications.js +16 -0
- package/dist/admin-notifications.js.map +1 -0
- package/dist/admin-roles.d.ts +125 -0
- package/dist/admin-roles.d.ts.map +1 -0
- package/dist/admin-roles.js +2 -0
- package/dist/admin-roles.js.map +1 -0
- package/dist/admin-users.d.ts +178 -0
- package/dist/admin-users.d.ts.map +1 -0
- package/dist/admin-users.js +14 -0
- package/dist/admin-users.js.map +1 -0
- package/dist/admin.d.ts +243 -0
- package/dist/admin.d.ts.map +1 -0
- package/dist/admin.js +246 -0
- package/dist/admin.js.map +1 -0
- package/dist/analytics.d.ts +123 -0
- package/dist/analytics.d.ts.map +1 -0
- package/dist/analytics.js +68 -0
- package/dist/analytics.js.map +1 -0
- package/dist/api-keys.d.ts +97 -0
- package/dist/api-keys.d.ts.map +1 -0
- package/dist/api-keys.js +64 -0
- package/dist/api-keys.js.map +1 -0
- package/dist/assets-library.d.ts +684 -0
- package/dist/assets-library.d.ts.map +1 -0
- package/dist/assets-library.js +181 -0
- package/dist/assets-library.js.map +1 -0
- package/dist/audit-logs.d.ts +141 -0
- package/dist/audit-logs.d.ts.map +1 -0
- package/dist/audit-logs.js +31 -0
- package/dist/audit-logs.js.map +1 -0
- package/dist/auth.d.ts +174 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +27 -0
- package/dist/auth.js.map +1 -0
- package/dist/blog.d.ts +669 -0
- package/dist/blog.d.ts.map +1 -0
- package/dist/blog.js +360 -0
- package/dist/blog.js.map +1 -0
- package/dist/capabilities.d.ts +40 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +38 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/carts.d.ts +1367 -0
- package/dist/carts.d.ts.map +1 -0
- package/dist/carts.js +405 -0
- package/dist/carts.js.map +1 -0
- package/dist/catalog.d.ts +2855 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +1543 -0
- package/dist/catalog.js.map +1 -0
- package/dist/cms.d.ts +872 -0
- package/dist/cms.d.ts.map +1 -0
- package/dist/cms.js +468 -0
- package/dist/cms.js.map +1 -0
- package/dist/common.d.ts +82 -0
- package/dist/common.d.ts.map +1 -0
- package/dist/common.js +72 -0
- package/dist/common.js.map +1 -0
- package/dist/comparisons.d.ts +487 -0
- package/dist/comparisons.d.ts.map +1 -0
- package/dist/comparisons.js +221 -0
- package/dist/comparisons.js.map +1 -0
- package/dist/credentials.d.ts +292 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +142 -0
- package/dist/credentials.js.map +1 -0
- package/dist/credit-limits.d.ts +111 -0
- package/dist/credit-limits.d.ts.map +1 -0
- package/dist/credit-limits.js +35 -0
- package/dist/credit-limits.js.map +1 -0
- package/dist/currencies.d.ts +127 -0
- package/dist/currencies.d.ts.map +1 -0
- package/dist/currencies.js +20 -0
- package/dist/currencies.js.map +1 -0
- package/dist/custom-fields.d.ts +345 -0
- package/dist/custom-fields.d.ts.map +1 -0
- package/dist/custom-fields.js +185 -0
- package/dist/custom-fields.js.map +1 -0
- package/dist/customer-accounts.d.ts +690 -0
- package/dist/customer-accounts.d.ts.map +1 -0
- package/dist/customer-accounts.js +41 -0
- package/dist/customer-accounts.js.map +1 -0
- package/dist/customers.d.ts +305 -0
- package/dist/customers.d.ts.map +1 -0
- package/dist/customers.js +158 -0
- package/dist/customers.js.map +1 -0
- package/dist/dictionary.d.ts +580 -0
- package/dist/dictionary.d.ts.map +1 -0
- package/dist/dictionary.js +297 -0
- package/dist/dictionary.js.map +1 -0
- package/dist/email-address.d.ts +62 -0
- package/dist/email-address.d.ts.map +1 -0
- package/dist/email-address.js +64 -0
- package/dist/email-address.js.map +1 -0
- package/dist/email.d.ts +175 -0
- package/dist/email.d.ts.map +1 -0
- package/dist/email.js +45 -0
- package/dist/email.js.map +1 -0
- package/dist/envelopes.d.ts +15 -0
- package/dist/envelopes.d.ts.map +1 -0
- package/dist/envelopes.js +16 -0
- package/dist/envelopes.js.map +1 -0
- package/dist/environment-inputs.d.ts +306 -0
- package/dist/environment-inputs.d.ts.map +1 -0
- package/dist/environment-inputs.js +277 -0
- package/dist/environment-inputs.js.map +1 -0
- package/dist/erp-connector.d.ts +52 -0
- package/dist/erp-connector.d.ts.map +1 -0
- package/dist/erp-connector.js +34 -0
- package/dist/erp-connector.js.map +1 -0
- package/dist/errors.d.ts +455 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +532 -0
- package/dist/errors.js.map +1 -0
- package/dist/google-analytics.d.ts +181 -0
- package/dist/google-analytics.d.ts.map +1 -0
- package/dist/google-analytics.js +176 -0
- package/dist/google-analytics.js.map +1 -0
- package/dist/google-tag-manager.d.ts +111 -0
- package/dist/google-tag-manager.d.ts.map +1 -0
- package/dist/google-tag-manager.js +129 -0
- package/dist/google-tag-manager.js.map +1 -0
- package/dist/i18n.d.ts +69 -0
- package/dist/i18n.d.ts.map +1 -0
- package/dist/i18n.js +59 -0
- package/dist/i18n.js.map +1 -0
- package/dist/import-export.d.ts +63 -0
- package/dist/import-export.d.ts.map +1 -0
- package/dist/import-export.js +37 -0
- package/dist/import-export.js.map +1 -0
- package/dist/index.d.ts +82 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +126 -0
- package/dist/index.js.map +1 -0
- package/dist/inventory.d.ts +673 -0
- package/dist/inventory.d.ts.map +1 -0
- package/dist/inventory.js +412 -0
- package/dist/inventory.js.map +1 -0
- package/dist/invoice-ledger.d.ts +366 -0
- package/dist/invoice-ledger.d.ts.map +1 -0
- package/dist/invoice-ledger.js +114 -0
- package/dist/invoice-ledger.js.map +1 -0
- package/dist/invoices.d.ts +845 -0
- package/dist/invoices.d.ts.map +1 -0
- package/dist/invoices.js +314 -0
- package/dist/invoices.js.map +1 -0
- package/dist/kernel.d.ts +49 -0
- package/dist/kernel.d.ts.map +1 -0
- package/dist/kernel.js +19 -0
- package/dist/kernel.js.map +1 -0
- package/dist/languages.d.ts +122 -0
- package/dist/languages.d.ts.map +1 -0
- package/dist/languages.js +24 -0
- package/dist/languages.js.map +1 -0
- package/dist/linkedin-ads.d.ts +167 -0
- package/dist/linkedin-ads.d.ts.map +1 -0
- package/dist/linkedin-ads.js +156 -0
- package/dist/linkedin-ads.js.map +1 -0
- package/dist/megamenu.d.ts +556 -0
- package/dist/megamenu.d.ts.map +1 -0
- package/dist/megamenu.js +186 -0
- package/dist/megamenu.js.map +1 -0
- package/dist/meta-ads.d.ts +126 -0
- package/dist/meta-ads.d.ts.map +1 -0
- package/dist/meta-ads.js +112 -0
- package/dist/meta-ads.js.map +1 -0
- package/dist/mfa.d.ts +274 -0
- package/dist/mfa.d.ts.map +1 -0
- package/dist/mfa.js +187 -0
- package/dist/mfa.js.map +1 -0
- package/dist/modules.d.ts +1706 -0
- package/dist/modules.d.ts.map +1 -0
- package/dist/modules.js +1390 -0
- package/dist/modules.js.map +1 -0
- package/dist/newsletter.d.ts +611 -0
- package/dist/newsletter.d.ts.map +1 -0
- package/dist/newsletter.js +345 -0
- package/dist/newsletter.js.map +1 -0
- package/dist/orders.d.ts +1175 -0
- package/dist/orders.d.ts.map +1 -0
- package/dist/orders.js +630 -0
- package/dist/orders.js.map +1 -0
- package/dist/organizations.d.ts +938 -0
- package/dist/organizations.d.ts.map +1 -0
- package/dist/organizations.js +418 -0
- package/dist/organizations.js.map +1 -0
- package/dist/pagination.d.ts +21 -0
- package/dist/pagination.d.ts.map +1 -0
- package/dist/pagination.js +22 -0
- package/dist/pagination.js.map +1 -0
- package/dist/payment-methods.d.ts +472 -0
- package/dist/payment-methods.d.ts.map +1 -0
- package/dist/payment-methods.js +175 -0
- package/dist/payment-methods.js.map +1 -0
- package/dist/payment-return-url.d.ts +53 -0
- package/dist/payment-return-url.d.ts.map +1 -0
- package/dist/payment-return-url.js +35 -0
- package/dist/payment-return-url.js.map +1 -0
- package/dist/payments.d.ts +386 -0
- package/dist/payments.d.ts.map +1 -0
- package/dist/payments.js +84 -0
- package/dist/payments.js.map +1 -0
- package/dist/pim-connector.d.ts +60 -0
- package/dist/pim-connector.d.ts.map +1 -0
- package/dist/pim-connector.js +43 -0
- package/dist/pim-connector.js.map +1 -0
- package/dist/pim-field-path.d.ts +6 -0
- package/dist/pim-field-path.d.ts.map +1 -0
- package/dist/pim-field-path.js +101 -0
- package/dist/pim-field-path.js.map +1 -0
- package/dist/platform-language.d.ts +20 -0
- package/dist/platform-language.d.ts.map +1 -0
- package/dist/platform-language.js +22 -0
- package/dist/platform-language.js.map +1 -0
- package/dist/price-lists.d.ts +685 -0
- package/dist/price-lists.d.ts.map +1 -0
- package/dist/price-lists.js +330 -0
- package/dist/price-lists.js.map +1 -0
- package/dist/product-feeds.d.ts +2837 -0
- package/dist/product-feeds.d.ts.map +1 -0
- package/dist/product-feeds.js +1504 -0
- package/dist/product-feeds.js.map +1 -0
- package/dist/product-scope-overrides.d.ts +134 -0
- package/dist/product-scope-overrides.d.ts.map +1 -0
- package/dist/product-scope-overrides.js +82 -0
- package/dist/product-scope-overrides.js.map +1 -0
- package/dist/product-value-resolver.d.ts +88 -0
- package/dist/product-value-resolver.d.ts.map +1 -0
- package/dist/product-value-resolver.js +128 -0
- package/dist/product-value-resolver.js.map +1 -0
- package/dist/promotions.d.ts +678 -0
- package/dist/promotions.d.ts.map +1 -0
- package/dist/promotions.js +479 -0
- package/dist/promotions.js.map +1 -0
- package/dist/prompt-actions.d.ts +582 -0
- package/dist/prompt-actions.d.ts.map +1 -0
- package/dist/prompt-actions.js +221 -0
- package/dist/prompt-actions.js.map +1 -0
- package/dist/pwa.d.ts +293 -0
- package/dist/pwa.d.ts.map +1 -0
- package/dist/pwa.js +204 -0
- package/dist/pwa.js.map +1 -0
- package/dist/quick-order.d.ts +340 -0
- package/dist/quick-order.d.ts.map +1 -0
- package/dist/quick-order.js +177 -0
- package/dist/quick-order.js.map +1 -0
- package/dist/quote-requests.d.ts +538 -0
- package/dist/quote-requests.d.ts.map +1 -0
- package/dist/quote-requests.js +308 -0
- package/dist/quote-requests.js.map +1 -0
- package/dist/returns.d.ts +774 -0
- package/dist/returns.d.ts.map +1 -0
- package/dist/returns.js +389 -0
- package/dist/returns.js.map +1 -0
- package/dist/sales-channels.d.ts +392 -0
- package/dist/sales-channels.d.ts.map +1 -0
- package/dist/sales-channels.js +285 -0
- package/dist/sales-channels.js.map +1 -0
- package/dist/scope-notice.d.ts +60 -0
- package/dist/scope-notice.d.ts.map +1 -0
- package/dist/scope-notice.js +56 -0
- package/dist/scope-notice.js.map +1 -0
- package/dist/search.d.ts +321 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +160 -0
- package/dist/search.js.map +1 -0
- package/dist/seo.d.ts +113 -0
- package/dist/seo.d.ts.map +1 -0
- package/dist/seo.js +63 -0
- package/dist/seo.js.map +1 -0
- package/dist/settings.d.ts +453 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +337 -0
- package/dist/settings.js.map +1 -0
- package/dist/shipments.d.ts +140 -0
- package/dist/shipments.d.ts.map +1 -0
- package/dist/shipments.js +14 -0
- package/dist/shipments.js.map +1 -0
- package/dist/shipping-methods.d.ts +350 -0
- package/dist/shipping-methods.d.ts.map +1 -0
- package/dist/shipping-methods.js +99 -0
- package/dist/shipping-methods.js.map +1 -0
- package/dist/shopping-lists.d.ts +122 -0
- package/dist/shopping-lists.d.ts.map +1 -0
- package/dist/shopping-lists.js +92 -0
- package/dist/shopping-lists.js.map +1 -0
- package/dist/taxes.d.ts +106 -0
- package/dist/taxes.d.ts.map +1 -0
- package/dist/taxes.js +80 -0
- package/dist/taxes.js.map +1 -0
- package/dist/text-normalization.d.ts +199 -0
- package/dist/text-normalization.d.ts.map +1 -0
- package/dist/text-normalization.js +205 -0
- package/dist/text-normalization.js.map +1 -0
- package/dist/transactional-emails.d.ts +459 -0
- package/dist/transactional-emails.d.ts.map +1 -0
- package/dist/transactional-emails.js +212 -0
- package/dist/transactional-emails.js.map +1 -0
- package/dist/webhooks.d.ts +69 -0
- package/dist/webhooks.d.ts.map +1 -0
- package/dist/webhooks.js +53 -0
- package/dist/webhooks.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,938 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { type FulfilmentStrategy } from './inventory.js';
|
|
3
|
+
/**
|
|
4
|
+
* Organizations, customer accounts, addresses, invitations — Source of truth
|
|
5
|
+
* per Principle V. Drives US2 + US3.
|
|
6
|
+
* See specs/001-b2b-platform-foundation/contracts/organizations.contract.md.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Organization lifecycle status (feature 026 consolidation).
|
|
10
|
+
*
|
|
11
|
+
* - `pending_verification` — newly registered, blocks transactions until
|
|
12
|
+
* moderator approves (manual moderation mode) or auto-activated.
|
|
13
|
+
* - `active` — may transact normally.
|
|
14
|
+
* - `blocked` — operator-blocked (replaces the legacy `suspended`); the
|
|
15
|
+
* Organization cannot place Orders or Quote Requests; reversible.
|
|
16
|
+
* - `rejected` — moderator rejected at registration; terminal.
|
|
17
|
+
*/
|
|
18
|
+
export declare const organizationStatusSchema: z.ZodEnum<{
|
|
19
|
+
active: "active";
|
|
20
|
+
rejected: "rejected";
|
|
21
|
+
blocked: "blocked";
|
|
22
|
+
pending_verification: "pending_verification";
|
|
23
|
+
}>;
|
|
24
|
+
export type OrganizationStatus = z.infer<typeof organizationStatusSchema>;
|
|
25
|
+
export declare const vatStatusSchema: z.ZodEnum<{
|
|
26
|
+
vat_payer: "vat_payer";
|
|
27
|
+
vat_exempt: "vat_exempt";
|
|
28
|
+
reverse_charge: "reverse_charge";
|
|
29
|
+
}>;
|
|
30
|
+
export type VatStatus = z.infer<typeof vatStatusSchema>;
|
|
31
|
+
/**
|
|
32
|
+
* Feature 056 — per-organization credit-inheritance mode. Platform-admin only.
|
|
33
|
+
*
|
|
34
|
+
* - `shared_pool` — a descendant with no own credit limit draws against the
|
|
35
|
+
* nearest ancestor's pool; concurrent draws across the subtree are serialized
|
|
36
|
+
* on the owning ancestor's row (zero double-spend).
|
|
37
|
+
* - `independent_default` — the inherited amount is each descendant's own
|
|
38
|
+
* effective limit; draws are independent of siblings.
|
|
39
|
+
*
|
|
40
|
+
* `null` on an Organization ⇒ fall back to the Settings global default
|
|
41
|
+
* (`organizations.hierarchy.credit_inheritance_mode`, factory `shared_pool`).
|
|
42
|
+
*/
|
|
43
|
+
export declare const creditInheritanceModeSchema: z.ZodEnum<{
|
|
44
|
+
shared_pool: "shared_pool";
|
|
45
|
+
independent_default: "independent_default";
|
|
46
|
+
}>;
|
|
47
|
+
export type CreditInheritanceMode = z.infer<typeof creditInheritanceModeSchema>;
|
|
48
|
+
export declare const addressKindSchema: z.ZodEnum<{
|
|
49
|
+
delivery: "delivery";
|
|
50
|
+
billing: "billing";
|
|
51
|
+
}>;
|
|
52
|
+
export type AddressKind = z.infer<typeof addressKindSchema>;
|
|
53
|
+
export declare const organizationSchema: z.ZodObject<{
|
|
54
|
+
id: z.ZodString;
|
|
55
|
+
name: z.ZodString;
|
|
56
|
+
taxId: z.ZodString;
|
|
57
|
+
status: z.ZodEnum<{
|
|
58
|
+
active: "active";
|
|
59
|
+
rejected: "rejected";
|
|
60
|
+
blocked: "blocked";
|
|
61
|
+
pending_verification: "pending_verification";
|
|
62
|
+
}>;
|
|
63
|
+
vatStatus: z.ZodEnum<{
|
|
64
|
+
vat_payer: "vat_payer";
|
|
65
|
+
vat_exempt: "vat_exempt";
|
|
66
|
+
reverse_charge: "reverse_charge";
|
|
67
|
+
}>;
|
|
68
|
+
isPersonal: z.ZodOptional<z.ZodBoolean>;
|
|
69
|
+
registeredAddress: z.ZodObject<{
|
|
70
|
+
street: z.ZodString;
|
|
71
|
+
city: z.ZodString;
|
|
72
|
+
postalCode: z.ZodString;
|
|
73
|
+
country: z.ZodString;
|
|
74
|
+
companyName: z.ZodOptional<z.ZodString>;
|
|
75
|
+
taxId: z.ZodOptional<z.ZodString>;
|
|
76
|
+
recipientName: z.ZodOptional<z.ZodString>;
|
|
77
|
+
phone: z.ZodOptional<z.ZodString>;
|
|
78
|
+
}, z.core.$strip>;
|
|
79
|
+
fulfilmentStrategy: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
80
|
+
any: "any";
|
|
81
|
+
default_first: "default_first";
|
|
82
|
+
lowest_stock_first: "lowest_stock_first";
|
|
83
|
+
highest_stock_first: "highest_stock_first";
|
|
84
|
+
defined_order: "defined_order";
|
|
85
|
+
}>>>;
|
|
86
|
+
fulfilmentStrategyWarehouseOrder: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
|
|
87
|
+
parentId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
88
|
+
path: z.ZodOptional<z.ZodString>;
|
|
89
|
+
creditInheritanceMode: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
90
|
+
shared_pool: "shared_pool";
|
|
91
|
+
independent_default: "independent_default";
|
|
92
|
+
}>>>;
|
|
93
|
+
createdAt: z.ZodString;
|
|
94
|
+
updatedAt: z.ZodString;
|
|
95
|
+
}, z.core.$strip>;
|
|
96
|
+
export type Organization = z.infer<typeof organizationSchema>;
|
|
97
|
+
/**
|
|
98
|
+
* A single node in an organization subtree / ancestor chain. `depth` is the
|
|
99
|
+
* node's absolute depth in the tree (root = 0). Returned pre-order (subtree) or
|
|
100
|
+
* nearest-first (ancestors).
|
|
101
|
+
*/
|
|
102
|
+
export declare const organizationTreeNodeSchema: z.ZodObject<{
|
|
103
|
+
id: z.ZodString;
|
|
104
|
+
name: z.ZodString;
|
|
105
|
+
parentId: z.ZodNullable<z.ZodString>;
|
|
106
|
+
depth: z.ZodNumber;
|
|
107
|
+
status: z.ZodEnum<{
|
|
108
|
+
active: "active";
|
|
109
|
+
rejected: "rejected";
|
|
110
|
+
blocked: "blocked";
|
|
111
|
+
pending_verification: "pending_verification";
|
|
112
|
+
}>;
|
|
113
|
+
}, z.core.$strip>;
|
|
114
|
+
export type OrganizationTreeNode = z.infer<typeof organizationTreeNodeSchema>;
|
|
115
|
+
/** `GET /admin/organizations/:id/subtree` — descendants (incl. self), pre-order. */
|
|
116
|
+
export declare const organizationSubtreeResponseSchema: z.ZodObject<{
|
|
117
|
+
items: z.ZodArray<z.ZodObject<{
|
|
118
|
+
id: z.ZodString;
|
|
119
|
+
name: z.ZodString;
|
|
120
|
+
parentId: z.ZodNullable<z.ZodString>;
|
|
121
|
+
depth: z.ZodNumber;
|
|
122
|
+
status: z.ZodEnum<{
|
|
123
|
+
active: "active";
|
|
124
|
+
rejected: "rejected";
|
|
125
|
+
blocked: "blocked";
|
|
126
|
+
pending_verification: "pending_verification";
|
|
127
|
+
}>;
|
|
128
|
+
}, z.core.$strip>>;
|
|
129
|
+
}, z.core.$strip>;
|
|
130
|
+
export type OrganizationSubtreeResponse = z.infer<typeof organizationSubtreeResponseSchema>;
|
|
131
|
+
/** `GET /admin/organizations/:id/ancestors` — ancestor chain, nearest-first. */
|
|
132
|
+
export declare const organizationAncestorsResponseSchema: z.ZodObject<{
|
|
133
|
+
items: z.ZodArray<z.ZodObject<{
|
|
134
|
+
id: z.ZodString;
|
|
135
|
+
name: z.ZodString;
|
|
136
|
+
parentId: z.ZodNullable<z.ZodString>;
|
|
137
|
+
depth: z.ZodNumber;
|
|
138
|
+
status: z.ZodEnum<{
|
|
139
|
+
active: "active";
|
|
140
|
+
rejected: "rejected";
|
|
141
|
+
blocked: "blocked";
|
|
142
|
+
pending_verification: "pending_verification";
|
|
143
|
+
}>;
|
|
144
|
+
}, z.core.$strip>>;
|
|
145
|
+
}, z.core.$strip>;
|
|
146
|
+
export type OrganizationAncestorsResponse = z.infer<typeof organizationAncestorsResponseSchema>;
|
|
147
|
+
/**
|
|
148
|
+
* `POST /admin/organizations/:id/parent` — assign / move / detach parent.
|
|
149
|
+
* `parentId = null` makes `:id` a root. Path maintenance + cycle/depth checks
|
|
150
|
+
* are guaranteed server-side (this is the only writable path for `parentId`).
|
|
151
|
+
*/
|
|
152
|
+
export declare const assignOrganizationParentRequestSchema: z.ZodObject<{
|
|
153
|
+
parentId: z.ZodNullable<z.ZodString>;
|
|
154
|
+
}, z.core.$strip>;
|
|
155
|
+
export type AssignOrganizationParentRequest = z.infer<typeof assignOrganizationParentRequestSchema>;
|
|
156
|
+
/**
|
|
157
|
+
* `PUT /admin/organizations/:id/credit-inheritance-mode` — platform-admin only.
|
|
158
|
+
* `mode = null` ⇒ fall back to the Settings global default.
|
|
159
|
+
*/
|
|
160
|
+
export declare const setCreditInheritanceModeRequestSchema: z.ZodObject<{
|
|
161
|
+
mode: z.ZodNullable<z.ZodEnum<{
|
|
162
|
+
shared_pool: "shared_pool";
|
|
163
|
+
independent_default: "independent_default";
|
|
164
|
+
}>>;
|
|
165
|
+
}, z.core.$strip>;
|
|
166
|
+
export type SetCreditInheritanceModeRequest = z.infer<typeof setCreditInheritanceModeRequestSchema>;
|
|
167
|
+
export declare const customerAccountSchema: z.ZodObject<{
|
|
168
|
+
id: z.ZodString;
|
|
169
|
+
organizationId: z.ZodString;
|
|
170
|
+
email: z.ZodString;
|
|
171
|
+
firstName: z.ZodString;
|
|
172
|
+
lastName: z.ZodString;
|
|
173
|
+
role: z.ZodEnum<{
|
|
174
|
+
organization_admin: "organization_admin";
|
|
175
|
+
regular_user: "regular_user";
|
|
176
|
+
}>;
|
|
177
|
+
emailVerifiedAt: z.ZodNullable<z.ZodString>;
|
|
178
|
+
twoFactorEnabled: z.ZodBoolean;
|
|
179
|
+
createdAt: z.ZodString;
|
|
180
|
+
updatedAt: z.ZodString;
|
|
181
|
+
}, z.core.$strip>;
|
|
182
|
+
export type CustomerAccount = z.infer<typeof customerAccountSchema>;
|
|
183
|
+
export declare const addressSchema: z.ZodObject<{
|
|
184
|
+
id: z.ZodString;
|
|
185
|
+
organizationId: z.ZodString;
|
|
186
|
+
kind: z.ZodEnum<{
|
|
187
|
+
delivery: "delivery";
|
|
188
|
+
billing: "billing";
|
|
189
|
+
}>;
|
|
190
|
+
recipientName: z.ZodString;
|
|
191
|
+
street: z.ZodString;
|
|
192
|
+
city: z.ZodString;
|
|
193
|
+
postalCode: z.ZodString;
|
|
194
|
+
country: z.ZodString;
|
|
195
|
+
phone: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
196
|
+
isDefault: z.ZodBoolean;
|
|
197
|
+
}, z.core.$strip>;
|
|
198
|
+
export type Address = z.infer<typeof addressSchema>;
|
|
199
|
+
export declare const registerOrganizationRequestSchema: z.ZodObject<{
|
|
200
|
+
organization: z.ZodObject<{
|
|
201
|
+
name: z.ZodString;
|
|
202
|
+
taxId: z.ZodString;
|
|
203
|
+
registeredAddress: z.ZodObject<{
|
|
204
|
+
street: z.ZodString;
|
|
205
|
+
city: z.ZodString;
|
|
206
|
+
postalCode: z.ZodString;
|
|
207
|
+
country: z.ZodString;
|
|
208
|
+
}, z.core.$strip>;
|
|
209
|
+
vatStatus: z.ZodOptional<z.ZodEnum<{
|
|
210
|
+
vat_payer: "vat_payer";
|
|
211
|
+
vat_exempt: "vat_exempt";
|
|
212
|
+
reverse_charge: "reverse_charge";
|
|
213
|
+
}>>;
|
|
214
|
+
}, z.core.$strip>;
|
|
215
|
+
firstUser: z.ZodObject<{
|
|
216
|
+
email: z.ZodString;
|
|
217
|
+
password: z.ZodString;
|
|
218
|
+
firstName: z.ZodString;
|
|
219
|
+
lastName: z.ZodString;
|
|
220
|
+
}, z.core.$strip>;
|
|
221
|
+
acceptedTermsVersion: z.ZodString;
|
|
222
|
+
}, z.core.$strip>;
|
|
223
|
+
export type RegisterOrganizationRequest = z.infer<typeof registerOrganizationRequestSchema>;
|
|
224
|
+
export declare const emailVerificationRequestSchema: z.ZodObject<{
|
|
225
|
+
token: z.ZodString;
|
|
226
|
+
}, z.core.$strip>;
|
|
227
|
+
export declare const passwordResetRequestSchema: z.ZodObject<{
|
|
228
|
+
email: z.ZodString;
|
|
229
|
+
}, z.core.$strip>;
|
|
230
|
+
export declare const passwordResetConfirmSchema: z.ZodObject<{
|
|
231
|
+
token: z.ZodString;
|
|
232
|
+
newPassword: z.ZodString;
|
|
233
|
+
}, z.core.$strip>;
|
|
234
|
+
export declare const customerLoginRequestSchema: z.ZodObject<{
|
|
235
|
+
email: z.ZodString;
|
|
236
|
+
password: z.ZodString;
|
|
237
|
+
}, z.core.$strip>;
|
|
238
|
+
/**
|
|
239
|
+
* Outcome of the anonymous-cart → customer-cart merge that runs inside the
|
|
240
|
+
* customer-login flow (feature 037-cart-merge-on-login).
|
|
241
|
+
*
|
|
242
|
+
* Internal shape — split between two `noop_*` variants so the audit /
|
|
243
|
+
* observability paths can distinguish "anon cart was empty" from "no anon
|
|
244
|
+
* cart was supplied". The HTTP-facing shape collapses both into a single
|
|
245
|
+
* `'noop'`; see `cartMergeOutcomePublicSchema` below.
|
|
246
|
+
*/
|
|
247
|
+
export declare const cartMergeOutcomeSchema: z.ZodObject<{
|
|
248
|
+
outcome: z.ZodEnum<{
|
|
249
|
+
adopted: "adopted";
|
|
250
|
+
merged: "merged";
|
|
251
|
+
noop_empty: "noop_empty";
|
|
252
|
+
noop_no_anon: "noop_no_anon";
|
|
253
|
+
}>;
|
|
254
|
+
movedLineCount: z.ZodNumber;
|
|
255
|
+
summedLineCount: z.ZodNumber;
|
|
256
|
+
destinationCartId: z.ZodString;
|
|
257
|
+
}, z.core.$strip>;
|
|
258
|
+
export type CartMergeOutcome = z.infer<typeof cartMergeOutcomeSchema>;
|
|
259
|
+
/**
|
|
260
|
+
* Public (HTTP) narrowing of `cartMergeOutcomeSchema`. The storefront only
|
|
261
|
+
* needs three buckets to decide whether to surface the merge-confirmation
|
|
262
|
+
* toast (`adopted | merged → toast`, `noop → silent`) and the destination
|
|
263
|
+
* cart id for the next cart read.
|
|
264
|
+
*/
|
|
265
|
+
export declare const cartMergeOutcomePublicSchema: z.ZodObject<{
|
|
266
|
+
outcome: z.ZodEnum<{
|
|
267
|
+
adopted: "adopted";
|
|
268
|
+
merged: "merged";
|
|
269
|
+
noop: "noop";
|
|
270
|
+
}>;
|
|
271
|
+
destinationCartId: z.ZodString;
|
|
272
|
+
}, z.core.$strip>;
|
|
273
|
+
export type CartMergeOutcomePublic = z.infer<typeof cartMergeOutcomePublicSchema>;
|
|
274
|
+
/**
|
|
275
|
+
* Customer login response. The `cartMerge` field is populated when the
|
|
276
|
+
* login carries an anonymous-cart cookie; `null` when no anon cookie was
|
|
277
|
+
* supplied; `outcome: 'noop'` when the cookie was supplied but had no
|
|
278
|
+
* observable effect (no anon cart, or the anon cart was empty).
|
|
279
|
+
*/
|
|
280
|
+
export declare const customerLoginResponseSchema: z.ZodObject<{
|
|
281
|
+
data: z.ZodObject<{
|
|
282
|
+
customerAccount: z.ZodObject<{
|
|
283
|
+
id: z.ZodString;
|
|
284
|
+
email: z.ZodString;
|
|
285
|
+
organizationId: z.ZodNullable<z.ZodString>;
|
|
286
|
+
role: z.ZodEnum<{
|
|
287
|
+
organization_admin: "organization_admin";
|
|
288
|
+
regular_user: "regular_user";
|
|
289
|
+
}>;
|
|
290
|
+
twoFactorEnabled: z.ZodBoolean;
|
|
291
|
+
}, z.core.$strip>;
|
|
292
|
+
cartMerge: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
293
|
+
outcome: z.ZodEnum<{
|
|
294
|
+
adopted: "adopted";
|
|
295
|
+
merged: "merged";
|
|
296
|
+
noop: "noop";
|
|
297
|
+
}>;
|
|
298
|
+
destinationCartId: z.ZodString;
|
|
299
|
+
}, z.core.$strip>>>;
|
|
300
|
+
}, z.core.$strip>;
|
|
301
|
+
}, z.core.$strip>;
|
|
302
|
+
export type CustomerLoginResponse = z.infer<typeof customerLoginResponseSchema>;
|
|
303
|
+
export declare const changePasswordRequestSchema: z.ZodObject<{
|
|
304
|
+
currentPassword: z.ZodString;
|
|
305
|
+
newPassword: z.ZodString;
|
|
306
|
+
}, z.core.$strip>;
|
|
307
|
+
export declare const createAddressRequestSchema: z.ZodObject<{
|
|
308
|
+
kind: z.ZodEnum<{
|
|
309
|
+
delivery: "delivery";
|
|
310
|
+
billing: "billing";
|
|
311
|
+
}>;
|
|
312
|
+
recipientName: z.ZodString;
|
|
313
|
+
street: z.ZodString;
|
|
314
|
+
city: z.ZodString;
|
|
315
|
+
postalCode: z.ZodString;
|
|
316
|
+
country: z.ZodString;
|
|
317
|
+
phone: z.ZodOptional<z.ZodString>;
|
|
318
|
+
isDefault: z.ZodOptional<z.ZodBoolean>;
|
|
319
|
+
}, z.core.$strip>;
|
|
320
|
+
export type CreateAddressRequest = z.infer<typeof createAddressRequestSchema>;
|
|
321
|
+
export declare const updateAddressRequestSchema: z.ZodObject<{
|
|
322
|
+
kind: z.ZodOptional<z.ZodEnum<{
|
|
323
|
+
delivery: "delivery";
|
|
324
|
+
billing: "billing";
|
|
325
|
+
}>>;
|
|
326
|
+
recipientName: z.ZodOptional<z.ZodString>;
|
|
327
|
+
street: z.ZodOptional<z.ZodString>;
|
|
328
|
+
city: z.ZodOptional<z.ZodString>;
|
|
329
|
+
postalCode: z.ZodOptional<z.ZodString>;
|
|
330
|
+
country: z.ZodOptional<z.ZodString>;
|
|
331
|
+
phone: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
332
|
+
isDefault: z.ZodOptional<z.ZodOptional<z.ZodBoolean>>;
|
|
333
|
+
}, z.core.$strip>;
|
|
334
|
+
export type UpdateAddressRequest = z.infer<typeof updateAddressRequestSchema>;
|
|
335
|
+
export declare const inviteMemberRequestSchema: z.ZodObject<{
|
|
336
|
+
email: z.ZodString;
|
|
337
|
+
role: z.ZodOptional<z.ZodEnum<{
|
|
338
|
+
organization_admin: "organization_admin";
|
|
339
|
+
regular_user: "regular_user";
|
|
340
|
+
}>>;
|
|
341
|
+
}, z.core.$strip>;
|
|
342
|
+
export declare const acceptInvitationRequestSchema: z.ZodObject<{
|
|
343
|
+
password: z.ZodString;
|
|
344
|
+
firstName: z.ZodString;
|
|
345
|
+
lastName: z.ZodString;
|
|
346
|
+
}, z.core.$strip>;
|
|
347
|
+
export declare const changeMemberRoleRequestSchema: z.ZodObject<{
|
|
348
|
+
role: z.ZodEnum<{
|
|
349
|
+
organization_admin: "organization_admin";
|
|
350
|
+
regular_user: "regular_user";
|
|
351
|
+
}>;
|
|
352
|
+
}, z.core.$strip>;
|
|
353
|
+
/** Platform admin — PATCH `/admin/organizations/:id` */
|
|
354
|
+
export declare const adminPatchOrganizationRequestSchema: z.ZodObject<{
|
|
355
|
+
name: z.ZodOptional<z.ZodString>;
|
|
356
|
+
vatStatus: z.ZodOptional<z.ZodEnum<{
|
|
357
|
+
vat_payer: "vat_payer";
|
|
358
|
+
vat_exempt: "vat_exempt";
|
|
359
|
+
reverse_charge: "reverse_charge";
|
|
360
|
+
}>>;
|
|
361
|
+
status: z.ZodOptional<z.ZodEnum<{
|
|
362
|
+
active: "active";
|
|
363
|
+
rejected: "rejected";
|
|
364
|
+
blocked: "blocked";
|
|
365
|
+
pending_verification: "pending_verification";
|
|
366
|
+
}>>;
|
|
367
|
+
orderConfirmationEmails: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
368
|
+
fulfilmentStrategy: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
369
|
+
any: "any";
|
|
370
|
+
default_first: "default_first";
|
|
371
|
+
lowest_stock_first: "lowest_stock_first";
|
|
372
|
+
highest_stock_first: "highest_stock_first";
|
|
373
|
+
defined_order: "defined_order";
|
|
374
|
+
}>>>;
|
|
375
|
+
fulfilmentStrategyWarehouseOrder: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
|
|
376
|
+
customFieldValues: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
377
|
+
expectedUpdatedAt: z.ZodOptional<z.ZodString>;
|
|
378
|
+
}, z.core.$strip>;
|
|
379
|
+
/** Platform admin — POST `/admin/organizations/:id/recover-admin-access` */
|
|
380
|
+
export declare const adminRecoverOrgAccessRequestSchema: z.ZodObject<{
|
|
381
|
+
promoteCustomerAccountId: z.ZodString;
|
|
382
|
+
}, z.core.$strip>;
|
|
383
|
+
/** Platform admin — POST `/admin/organizations/:id/members` (direct create) */
|
|
384
|
+
export declare const adminDirectMemberRequestSchema: z.ZodObject<{
|
|
385
|
+
email: z.ZodString;
|
|
386
|
+
firstName: z.ZodString;
|
|
387
|
+
lastName: z.ZodString;
|
|
388
|
+
password: z.ZodString;
|
|
389
|
+
role: z.ZodOptional<z.ZodEnum<{
|
|
390
|
+
organization_admin: "organization_admin";
|
|
391
|
+
regular_user: "regular_user";
|
|
392
|
+
}>>;
|
|
393
|
+
}, z.core.$strip>;
|
|
394
|
+
/** Platform admin — PATCH member role */
|
|
395
|
+
export declare const adminPatchMemberRoleRequestSchema: z.ZodObject<{
|
|
396
|
+
role: z.ZodEnum<{
|
|
397
|
+
organization_admin: "organization_admin";
|
|
398
|
+
regular_user: "regular_user";
|
|
399
|
+
}>;
|
|
400
|
+
expectedUpdatedAt: z.ZodOptional<z.ZodString>;
|
|
401
|
+
}, z.core.$strip>;
|
|
402
|
+
/**
|
|
403
|
+
* Feature 056 (T032) — Platform admin — PATCH member roll-up capability.
|
|
404
|
+
* When enabled, this customer login sees/acts across its organization's subtree.
|
|
405
|
+
*/
|
|
406
|
+
export declare const adminSetMemberRollupRequestSchema: z.ZodObject<{
|
|
407
|
+
subtreeRollupEnabled: z.ZodBoolean;
|
|
408
|
+
expectedUpdatedAt: z.ZodOptional<z.ZodString>;
|
|
409
|
+
}, z.core.$strip>;
|
|
410
|
+
export type AdminSetMemberRollupRequest = z.infer<typeof adminSetMemberRollupRequestSchema>;
|
|
411
|
+
/** Platform admin — PATCH `/admin/organizations/:id/members/:customerAccountId` (profile) */
|
|
412
|
+
export declare const adminPatchMemberProfileRequestSchema: z.ZodObject<{
|
|
413
|
+
firstName: z.ZodOptional<z.ZodString>;
|
|
414
|
+
lastName: z.ZodOptional<z.ZodString>;
|
|
415
|
+
email: z.ZodOptional<z.ZodString>;
|
|
416
|
+
expectedUpdatedAt: z.ZodOptional<z.ZodString>;
|
|
417
|
+
}, z.core.$strip>;
|
|
418
|
+
export declare const registerOrganizationResponseSchema: z.ZodObject<{
|
|
419
|
+
organization: z.ZodObject<{
|
|
420
|
+
id: z.ZodString;
|
|
421
|
+
name: z.ZodString;
|
|
422
|
+
taxId: z.ZodString;
|
|
423
|
+
status: z.ZodEnum<{
|
|
424
|
+
active: "active";
|
|
425
|
+
rejected: "rejected";
|
|
426
|
+
blocked: "blocked";
|
|
427
|
+
pending_verification: "pending_verification";
|
|
428
|
+
}>;
|
|
429
|
+
vatStatus: z.ZodEnum<{
|
|
430
|
+
vat_payer: "vat_payer";
|
|
431
|
+
vat_exempt: "vat_exempt";
|
|
432
|
+
reverse_charge: "reverse_charge";
|
|
433
|
+
}>;
|
|
434
|
+
isPersonal: z.ZodOptional<z.ZodBoolean>;
|
|
435
|
+
registeredAddress: z.ZodObject<{
|
|
436
|
+
street: z.ZodString;
|
|
437
|
+
city: z.ZodString;
|
|
438
|
+
postalCode: z.ZodString;
|
|
439
|
+
country: z.ZodString;
|
|
440
|
+
companyName: z.ZodOptional<z.ZodString>;
|
|
441
|
+
taxId: z.ZodOptional<z.ZodString>;
|
|
442
|
+
recipientName: z.ZodOptional<z.ZodString>;
|
|
443
|
+
phone: z.ZodOptional<z.ZodString>;
|
|
444
|
+
}, z.core.$strip>;
|
|
445
|
+
fulfilmentStrategy: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
446
|
+
any: "any";
|
|
447
|
+
default_first: "default_first";
|
|
448
|
+
lowest_stock_first: "lowest_stock_first";
|
|
449
|
+
highest_stock_first: "highest_stock_first";
|
|
450
|
+
defined_order: "defined_order";
|
|
451
|
+
}>>>;
|
|
452
|
+
fulfilmentStrategyWarehouseOrder: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
|
|
453
|
+
parentId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
454
|
+
path: z.ZodOptional<z.ZodString>;
|
|
455
|
+
creditInheritanceMode: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
456
|
+
shared_pool: "shared_pool";
|
|
457
|
+
independent_default: "independent_default";
|
|
458
|
+
}>>>;
|
|
459
|
+
createdAt: z.ZodString;
|
|
460
|
+
updatedAt: z.ZodString;
|
|
461
|
+
}, z.core.$strip>;
|
|
462
|
+
customerAccount: z.ZodObject<{
|
|
463
|
+
id: z.ZodString;
|
|
464
|
+
organizationId: z.ZodString;
|
|
465
|
+
email: z.ZodString;
|
|
466
|
+
firstName: z.ZodString;
|
|
467
|
+
lastName: z.ZodString;
|
|
468
|
+
role: z.ZodEnum<{
|
|
469
|
+
organization_admin: "organization_admin";
|
|
470
|
+
regular_user: "regular_user";
|
|
471
|
+
}>;
|
|
472
|
+
emailVerifiedAt: z.ZodNullable<z.ZodString>;
|
|
473
|
+
twoFactorEnabled: z.ZodBoolean;
|
|
474
|
+
createdAt: z.ZodString;
|
|
475
|
+
updatedAt: z.ZodString;
|
|
476
|
+
}, z.core.$strip>;
|
|
477
|
+
emailVerificationSent: z.ZodBoolean;
|
|
478
|
+
}, z.core.$strip>;
|
|
479
|
+
export type RegisterOrganizationResponse = z.infer<typeof registerOrganizationResponseSchema>;
|
|
480
|
+
/**
|
|
481
|
+
* One row of the admin Organization picker.
|
|
482
|
+
*
|
|
483
|
+
* A **projection**, not the `GET /api/v1/admin/organizations` envelope: the
|
|
484
|
+
* picker renders a label, a status pill and nothing else, and it commits the
|
|
485
|
+
* `id`. `version` rides along because a caller that picks an Organization in
|
|
486
|
+
* order to write to it needs the optimistic-concurrency token it already had.
|
|
487
|
+
*
|
|
488
|
+
* Published because `@endora-commerce/admin-kit` builds this request itself
|
|
489
|
+
* (feature 091's P2 — the picker moved into the kit and rebuilt its call from
|
|
490
|
+
* the published `apiClient`), so the shape crosses a package boundary and
|
|
491
|
+
* Principle II puts it here. Before P2 it was declared in
|
|
492
|
+
* `admin/src/modules/organizations/api/organizations-picker-client.ts`, where a
|
|
493
|
+
* kit component could only reach it by importing a module's admin code.
|
|
494
|
+
*
|
|
495
|
+
* The status is `organizationStatusSchema` and not a picker-local enum: the four
|
|
496
|
+
* members the picker filters on are exactly that schema's, so a second name
|
|
497
|
+
* would be two spellings of one set with nothing keeping them equal.
|
|
498
|
+
*/
|
|
499
|
+
export declare const organizationPickerListItemSchema: z.ZodObject<{
|
|
500
|
+
id: z.ZodString;
|
|
501
|
+
name: z.ZodString;
|
|
502
|
+
legalName: z.ZodNullable<z.ZodString>;
|
|
503
|
+
status: z.ZodEnum<{
|
|
504
|
+
active: "active";
|
|
505
|
+
rejected: "rejected";
|
|
506
|
+
blocked: "blocked";
|
|
507
|
+
pending_verification: "pending_verification";
|
|
508
|
+
}>;
|
|
509
|
+
countryCode: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
510
|
+
salesRepAdminUserIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
511
|
+
memberCount: z.ZodOptional<z.ZodNumber>;
|
|
512
|
+
version: z.ZodNumber;
|
|
513
|
+
}, z.core.$strip>;
|
|
514
|
+
export type OrganizationPickerListItem = z.infer<typeof organizationPickerListItemSchema>;
|
|
515
|
+
/** One page of picker rows. `nextCursor` is `null` on the last page. */
|
|
516
|
+
export declare const organizationPickerPageSchema: z.ZodObject<{
|
|
517
|
+
items: z.ZodArray<z.ZodObject<{
|
|
518
|
+
id: z.ZodString;
|
|
519
|
+
name: z.ZodString;
|
|
520
|
+
legalName: z.ZodNullable<z.ZodString>;
|
|
521
|
+
status: z.ZodEnum<{
|
|
522
|
+
active: "active";
|
|
523
|
+
rejected: "rejected";
|
|
524
|
+
blocked: "blocked";
|
|
525
|
+
pending_verification: "pending_verification";
|
|
526
|
+
}>;
|
|
527
|
+
countryCode: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
528
|
+
salesRepAdminUserIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
529
|
+
memberCount: z.ZodOptional<z.ZodNumber>;
|
|
530
|
+
version: z.ZodNumber;
|
|
531
|
+
}, z.core.$strip>>;
|
|
532
|
+
nextCursor: z.ZodNullable<z.ZodString>;
|
|
533
|
+
}, z.core.$strip>;
|
|
534
|
+
export type OrganizationPickerPage = z.infer<typeof organizationPickerPageSchema>;
|
|
535
|
+
export declare const salesRepAssignmentSchema: z.ZodObject<{
|
|
536
|
+
id: z.ZodString;
|
|
537
|
+
organizationId: z.ZodString;
|
|
538
|
+
adminUserId: z.ZodString;
|
|
539
|
+
displayName: z.ZodString;
|
|
540
|
+
email: z.ZodString;
|
|
541
|
+
assignedAt: z.ZodString;
|
|
542
|
+
assignedByAdminUserId: z.ZodNullable<z.ZodString>;
|
|
543
|
+
}, z.core.$strip>;
|
|
544
|
+
export type SalesRepAssignment = z.infer<typeof salesRepAssignmentSchema>;
|
|
545
|
+
export declare const assignSalesRepRequestSchema: z.ZodObject<{
|
|
546
|
+
adminUserId: z.ZodString;
|
|
547
|
+
}, z.core.$strip>;
|
|
548
|
+
export type AssignSalesRepRequest = z.infer<typeof assignSalesRepRequestSchema>;
|
|
549
|
+
export declare const salesRepOrganizationSchema: z.ZodObject<{
|
|
550
|
+
organizationId: z.ZodString;
|
|
551
|
+
name: z.ZodString;
|
|
552
|
+
openRfqCount: z.ZodNumber;
|
|
553
|
+
assignedAt: z.ZodString;
|
|
554
|
+
}, z.core.$strip>;
|
|
555
|
+
export type SalesRepOrganization = z.infer<typeof salesRepOrganizationSchema>;
|
|
556
|
+
export type VatValidationProvider = 'vies' | 'mf_pl' | 'format_only';
|
|
557
|
+
export type VatValidationOutcome = 'validated' | 'failed' | 'deferred' | 'unverified';
|
|
558
|
+
/** The JSONB snapshot the organisation's registered address is stored as. */
|
|
559
|
+
export interface OrganizationRegisteredAddress {
|
|
560
|
+
street: string;
|
|
561
|
+
city: string;
|
|
562
|
+
postalCode: string;
|
|
563
|
+
country: string;
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* An organisation as it crosses a module boundary — a plain shape, never the
|
|
567
|
+
* ORM entity (FR-011). `nameSearch` is absent: it is a derived column the
|
|
568
|
+
* entity hooks maintain, "never read or written by callers directly", and
|
|
569
|
+
* publishing it would invite exactly that.
|
|
570
|
+
*/
|
|
571
|
+
export interface OrganizationRecord {
|
|
572
|
+
id: string;
|
|
573
|
+
name: string;
|
|
574
|
+
legalName: string | null;
|
|
575
|
+
taxId: string;
|
|
576
|
+
status: OrganizationStatus;
|
|
577
|
+
vatStatus: VatStatus;
|
|
578
|
+
isPersonal: boolean;
|
|
579
|
+
customerGroupId: string | null;
|
|
580
|
+
registeredAddress: OrganizationRegisteredAddress;
|
|
581
|
+
orderConfirmationEmails: string[];
|
|
582
|
+
vatValidatedAt: Date | null;
|
|
583
|
+
vatValidationProvider: VatValidationProvider | null;
|
|
584
|
+
vatValidationOutcome: VatValidationOutcome | null;
|
|
585
|
+
blockedReason: string | null;
|
|
586
|
+
blockedAt: Date | null;
|
|
587
|
+
rejectedReason: string | null;
|
|
588
|
+
rejectedAt: Date | null;
|
|
589
|
+
approvedAt: Date | null;
|
|
590
|
+
approvedByAdminUserId: string | null;
|
|
591
|
+
requiresCartApproval: boolean;
|
|
592
|
+
fulfilmentStrategy: FulfilmentStrategy | null;
|
|
593
|
+
fulfilmentStrategyWarehouseOrder: string[] | null;
|
|
594
|
+
parentId: string | null;
|
|
595
|
+
/** Materialised ancestor chain `'/<rootId>/…/<thisId>/'`. */
|
|
596
|
+
path: string;
|
|
597
|
+
creditInheritanceMode: CreditInheritanceMode | null;
|
|
598
|
+
customFieldValues: Record<string, unknown>;
|
|
599
|
+
/** Optimistic-lock token. Pass it back on a versioned write. */
|
|
600
|
+
version: number;
|
|
601
|
+
createdAt: Date;
|
|
602
|
+
updatedAt: Date;
|
|
603
|
+
deletedAt: Date | null;
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* Container name: `organizationDetailsPort`. Owner: `organizations`.
|
|
607
|
+
*
|
|
608
|
+
* The union of what eleven modules measurably ask for when they read the
|
|
609
|
+
* organisation row itself: 24 of the 47 inbound sites are `em.findOne` /
|
|
610
|
+
* `em.find` on the entity, and between them they touch nearly every column.
|
|
611
|
+
*
|
|
612
|
+
* **Why this is a second port and not a wider `OrganizationSnapshot`.** The
|
|
613
|
+
* kernel's `OrganizationReadPort` (`src/kernel/ports/organizations.ts`) is the
|
|
614
|
+
* *tenancy projection* — `{ id, status }` plus the two questions Principle XI
|
|
615
|
+
* asks — and D-55 settled it at what its callers use. `organizationTaxProfilePort`
|
|
616
|
+
* already declined to widen it, in those words, for the same reason: a tax
|
|
617
|
+
* profile is one consumer's question. So is a name picker, and so is a
|
|
618
|
+
* fulfilment override. Widening the snapshot to carry them would make the
|
|
619
|
+
* kernel declare a domain record.
|
|
620
|
+
*
|
|
621
|
+
* The name search is here rather than in each caller because it is not a
|
|
622
|
+
* `LIKE` on `name`: the column that answers it is the diacritic-folded
|
|
623
|
+
* `nameSearch`, and two of the three existing callers query `name` instead —
|
|
624
|
+
* so "a search for lodz finds Łódź" holds in one of them and not in the others.
|
|
625
|
+
*
|
|
626
|
+
* When `organizations` is off every method fails closed. The module is the
|
|
627
|
+
* platform's one tenant concept, so in practice the gate cannot close; it is
|
|
628
|
+
* registered anyway, because an exception carved into the port machinery costs
|
|
629
|
+
* more than the predicate does.
|
|
630
|
+
*/
|
|
631
|
+
export interface OrganizationDetailsPort {
|
|
632
|
+
findById(id: string): Promise<OrganizationRecord | null>;
|
|
633
|
+
findByIds(ids: readonly string[]): Promise<OrganizationRecord[]>;
|
|
634
|
+
/** How many of these ids exist — the `count === ids.length` existence check. */
|
|
635
|
+
countByIds(ids: readonly string[]): Promise<number>;
|
|
636
|
+
/**
|
|
637
|
+
* Diacritic-insensitive name search over `nameSearch`, ordered by name.
|
|
638
|
+
* An empty `query` returns the first `limit` organisations.
|
|
639
|
+
*/
|
|
640
|
+
searchByName(query: string, limit: number): Promise<OrganizationRecord[]>;
|
|
641
|
+
/** The same search, ids only — for the order list's organisation filter. */
|
|
642
|
+
searchIdsByName(query: string): Promise<string[]>;
|
|
643
|
+
}
|
|
644
|
+
/**
|
|
645
|
+
* Diacritic-insensitive normalisation for the organisation's `name_search`
|
|
646
|
+
* column and for any query string matched against it.
|
|
647
|
+
*
|
|
648
|
+
* The character fold itself is `foldDiacritics` in `text-normalization.ts`,
|
|
649
|
+
* shared with `admin/` and reachable from `storefront/` (issue #240): it strips
|
|
650
|
+
* every Unicode combining mark through NFD decomposition and then maps the
|
|
651
|
+
* handful of precomposed Latin letters NFD does not decompose (notably Polish
|
|
652
|
+
* `ł`/`Ł`, Scandinavian `ø`/`Ø`, Croatian `đ`/`Đ`, Icelandic `ð`/`Ð`,
|
|
653
|
+
* `þ`/`Þ`, German `ß`, ligatures `æ` and `œ`). What is specific to an
|
|
654
|
+
* organisation name is the whitespace policy below, and only that: a name typed
|
|
655
|
+
* with a double space must match one stored with a single one.
|
|
656
|
+
*
|
|
657
|
+
* Published as a **function, not a port** (FR-013): it is pure over its
|
|
658
|
+
* argument, so switching `organizations` off does not change the answer, and a
|
|
659
|
+
* gated port answering 503 to "fold these diacritics" would be a bug. The
|
|
660
|
+
* entity's `@BeforeCreate` / `@BeforeUpdate` hooks and `orders`' list filter
|
|
661
|
+
* both call it, and they must agree or the filter silently stops matching.
|
|
662
|
+
*
|
|
663
|
+
* That agreement is why the fold is characterised rather than merely tested:
|
|
664
|
+
* `backend/test/unit/organizations/name-search-fold-characterisation.test.ts`
|
|
665
|
+
* pins the output for every input this function can meet, because a change here
|
|
666
|
+
* re-folds nothing already written to `name_search` and reports no error when
|
|
667
|
+
* the two stop agreeing.
|
|
668
|
+
*
|
|
669
|
+
* Node natives only (Principle IV).
|
|
670
|
+
*/
|
|
671
|
+
export declare function normalizeOrganizationName(input: string): string;
|
|
672
|
+
/**
|
|
673
|
+
* Thrown when the organisation a read names does not exist. The kernel's
|
|
674
|
+
* `OrganizationReadPort` has documented it as `assertCanTransact`'s failure
|
|
675
|
+
* mode since D-32 while the class itself lived in a module, which is the gap
|
|
676
|
+
* this publication closes.
|
|
677
|
+
*/
|
|
678
|
+
export declare class OrganizationNotFoundError extends Error {
|
|
679
|
+
readonly organizationId: string;
|
|
680
|
+
constructor(organizationId: string);
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
* Thrown when a write is attempted for an organisation whose status forbids
|
|
684
|
+
* transacting. Four modules — `carts`, `orders`, `quote_requests` and the
|
|
685
|
+
* external order intake — catch it by class to turn it into a 409 envelope,
|
|
686
|
+
* which is why it is published here rather than being a port: an error is a
|
|
687
|
+
* shape, and `DictionaryReferenceError` in `dictionary.ts` set the precedent.
|
|
688
|
+
*/
|
|
689
|
+
export declare class OrganizationCannotTransactError extends Error {
|
|
690
|
+
readonly organizationId: string;
|
|
691
|
+
readonly status: Exclude<OrganizationStatus, 'active'>;
|
|
692
|
+
constructor(organizationId: string, status: Exclude<OrganizationStatus, 'active'>);
|
|
693
|
+
}
|
|
694
|
+
/** Where a subtree's credit limit is held, and under which mode. */
|
|
695
|
+
export interface OrganizationCreditOwner {
|
|
696
|
+
/** Nearest ancestor-or-self holding a `CreditLimit` row, or null when none exists. */
|
|
697
|
+
readonly ownerOrgId: string | null;
|
|
698
|
+
/** Effective mode: the owner's per-org column, else the Settings global default. */
|
|
699
|
+
readonly mode: CreditInheritanceMode;
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* Container name: `organizationInheritancePort`. Owner: `organizations`.
|
|
703
|
+
*
|
|
704
|
+
* `credit_limits` is the only consumer: it asks which organisation in the
|
|
705
|
+
* hierarchy actually holds the limit that applies here.
|
|
706
|
+
*
|
|
707
|
+
* **Owner off:** the seam fails closed — resolving this port throws
|
|
708
|
+
* `ModuleDisabledError` and the call answers 503 `MODULE_DISABLED`, so nothing
|
|
709
|
+
* half-executes. Whether `organizations` has an off state at all is its manifest's
|
|
710
|
+
* `activation` to say, not this line's: a module declaring
|
|
711
|
+
* `nonDeactivatable` never enters one.
|
|
712
|
+
*/
|
|
713
|
+
export interface OrganizationInheritancePort {
|
|
714
|
+
creditOwner(organizationId: string): Promise<OrganizationCreditOwner>;
|
|
715
|
+
}
|
|
716
|
+
/** What a cart-approval-policy write answers with. */
|
|
717
|
+
export interface CartApprovalPolicyWriteResult {
|
|
718
|
+
readonly organization: OrganizationRecord;
|
|
719
|
+
/**
|
|
720
|
+
* `false` when the row already carried the requested value, so nothing was
|
|
721
|
+
* written and nothing was audited. It is part of the return type rather than
|
|
722
|
+
* something the caller re-derives from a read, because the caller's cascade
|
|
723
|
+
* hangs off it: `carts` resets its pending and approved carts when — and only
|
|
724
|
+
* when — the policy actually moved to `false`.
|
|
725
|
+
*/
|
|
726
|
+
readonly changed: boolean;
|
|
727
|
+
}
|
|
728
|
+
/**
|
|
729
|
+
* Container name: `organizationCartApprovalWritePort`. Owner: `organizations`.
|
|
730
|
+
*
|
|
731
|
+
* The per-organisation "an Org Admin must approve a cart before checkout"
|
|
732
|
+
* policy (feature 027 US4). `carts` drives both surfaces that flip it — the
|
|
733
|
+
* platform-admin route and the Org-Admin self-service one — but the column is
|
|
734
|
+
* this module's, so the operation is (issue #175, D-78 step 1).
|
|
735
|
+
*
|
|
736
|
+
* The write runs through `CommandBus.run`, so it carries the audit row it had
|
|
737
|
+
* never had while `carts` was writing the column directly, with the actor
|
|
738
|
+
* derived from the caller's ambient context (Constitution XIII). The cart
|
|
739
|
+
* cascade that follows a switch-off stays with `carts`: those are its rows, and
|
|
740
|
+
* they are audited in its own per-cart trail.
|
|
741
|
+
*
|
|
742
|
+
* This module is non-deactivatable, so the gate the port registration applies
|
|
743
|
+
* cannot be reached; the registration is a `providePort` anyway, for the reason
|
|
744
|
+
* its siblings give.
|
|
745
|
+
*/
|
|
746
|
+
export interface OrganizationCartApprovalWritePort {
|
|
747
|
+
setCartApprovalPolicy(organizationId: string, requiresCartApproval: boolean): Promise<CartApprovalPolicyWriteResult>;
|
|
748
|
+
}
|
|
749
|
+
/** The three allow-list kinds an organisation can restrict. */
|
|
750
|
+
export type OrganizationAllowListKind = 'paymentMethodIds' | 'deliveryMethodIds' | 'warehouseIds';
|
|
751
|
+
/**
|
|
752
|
+
* Container name: `organizationRestrictionPort`. Owner: `organizations`.
|
|
753
|
+
*
|
|
754
|
+
* `null` means "no restriction configured — everything is allowed", and it is
|
|
755
|
+
* deliberately part of the return type rather than something a caller infers
|
|
756
|
+
* from a thrown error. That is the worked example the composition checklist
|
|
757
|
+
* cites for putting a degrade inside the owner's implementation: a consumer
|
|
758
|
+
* that caught an exception here would turn a fail-closed edge into a
|
|
759
|
+
* fail-open one.
|
|
760
|
+
*
|
|
761
|
+
* **Owner off:** the seam fails closed — resolving this port throws
|
|
762
|
+
* `ModuleDisabledError` and the call answers 503 `MODULE_DISABLED`, so nothing
|
|
763
|
+
* half-executes. Whether `organizations` has an off state at all is its manifest's
|
|
764
|
+
* `activation` to say, not this line's: a module declaring
|
|
765
|
+
* `nonDeactivatable` never enters one.
|
|
766
|
+
*/
|
|
767
|
+
export interface OrganizationRestrictionPort {
|
|
768
|
+
allowedIdsFor(organizationId: string, kind: OrganizationAllowListKind): Promise<string[] | null>;
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* Container name: `personalOrganizationPort`. Owner: `organizations`.
|
|
772
|
+
*
|
|
773
|
+
* Feature 051 — a B2C customer is backed by a single-member personal
|
|
774
|
+
* organisation, so ordering, RFQ, credit and invoicing work and the tenant
|
|
775
|
+
* guard isolates each individual as their own tenant. There is no
|
|
776
|
+
* "no-organization" path (Principle XI), which is why this is idempotent
|
|
777
|
+
* rather than a create.
|
|
778
|
+
*
|
|
779
|
+
* Takes the account **id**, not the account: the entity that used to cross
|
|
780
|
+
* here is the shape feature 075 removes, and the second `EntityManager`
|
|
781
|
+
* argument went with it — the one caller already flushes the account before
|
|
782
|
+
* calling.
|
|
783
|
+
*
|
|
784
|
+
* **Owner off:** the seam fails closed — resolving this port throws
|
|
785
|
+
* `ModuleDisabledError` and the call answers 503 `MODULE_DISABLED`, so nothing
|
|
786
|
+
* half-executes. Whether `organizations` has an off state at all is its manifest's
|
|
787
|
+
* `activation` to say, not this line's: a module declaring
|
|
788
|
+
* `nonDeactivatable` never enters one.
|
|
789
|
+
*/
|
|
790
|
+
export interface PersonalOrganizationPort {
|
|
791
|
+
ensureForCustomerAccount(customerAccountId: string): Promise<OrganizationRecord>;
|
|
792
|
+
/**
|
|
793
|
+
* D-178 — the organisation an account is moved **to** when an operator
|
|
794
|
+
* detaches it from a company, and the one it would already be in had it never
|
|
795
|
+
* joined one.
|
|
796
|
+
*
|
|
797
|
+
* It differs from {@link ensureForCustomerAccount} in exactly one way, and
|
|
798
|
+
* the difference is the whole reason it exists: that method answers with the
|
|
799
|
+
* account's *current* organisation when it has one, so an account inside a
|
|
800
|
+
* company gets that company back. This one always answers with the account's
|
|
801
|
+
* **own** personal organisation, provisioning it if it has never existed.
|
|
802
|
+
*
|
|
803
|
+
* It writes no membership. Binding the account is the caller's write on
|
|
804
|
+
* `customer_accounts`' side of the boundary
|
|
805
|
+
* (`CustomerAccountLifecycleWritePort.detachToPersonalOrganization`), because
|
|
806
|
+
* the authority check and the "an organisation keeps an administrator" guard
|
|
807
|
+
* that must precede it are `customers`' policy.
|
|
808
|
+
*
|
|
809
|
+
* Idempotent: the personal organisation's `taxId` is derived from the account
|
|
810
|
+
* id, so a second call re-finds the row rather than creating a second one.
|
|
811
|
+
*/
|
|
812
|
+
provisionPersonalOrganization(customerAccountId: string): Promise<OrganizationRecord>;
|
|
813
|
+
/**
|
|
814
|
+
* Feature 051, the other end of the same rule — the retention sweep's
|
|
815
|
+
* cascade. Once the single member of a personal organisation has been
|
|
816
|
+
* anonymised, the organisation is left with nobody in it and its name is
|
|
817
|
+
* derived from that person's name, so it is scrubbed and soft-deleted too.
|
|
818
|
+
*
|
|
819
|
+
* Answers `null`, and writes nothing, in every case where the cascade does
|
|
820
|
+
* not apply: an org-less account, an organisation that is not personal, one
|
|
821
|
+
* already soft-deleted, and one that still has a live member. That is why it
|
|
822
|
+
* takes the **account** id rather than the organisation's — the caller
|
|
823
|
+
* (`customers`' anonymisation sweep) knows which customer it just scrubbed
|
|
824
|
+
* and must not be the one deciding whether the organisation qualifies.
|
|
825
|
+
*
|
|
826
|
+
* Idempotent: a second call over the same account finds the organisation
|
|
827
|
+
* already soft-deleted and answers `null`.
|
|
828
|
+
*/
|
|
829
|
+
anonymizeIfOrphaned(customerAccountId: string): Promise<OrganizationRecord | null>;
|
|
830
|
+
}
|
|
831
|
+
/** One sales-rep ↔ organisation assignment row. */
|
|
832
|
+
export interface SalesRepAssignmentRow {
|
|
833
|
+
readonly id: string;
|
|
834
|
+
readonly organizationId: string;
|
|
835
|
+
readonly adminUserId: string;
|
|
836
|
+
readonly assignedByAdminUserId?: string | null;
|
|
837
|
+
readonly createdAt: Date;
|
|
838
|
+
}
|
|
839
|
+
/**
|
|
840
|
+
* Container name: `organizationSalesRepScopePort`. Owner: `organizations`.
|
|
841
|
+
*
|
|
842
|
+
* The sales-rep assignment relation as other modules see it. `quote_requests`
|
|
843
|
+
* scopes an admin's RFQ list with it; the admin surfaces read it to decide
|
|
844
|
+
* whether a rep may see an organisation at all.
|
|
845
|
+
*
|
|
846
|
+
* **Owner off:** the seam fails closed — resolving this port throws
|
|
847
|
+
* `ModuleDisabledError` and the call answers 503 `MODULE_DISABLED`, so nothing
|
|
848
|
+
* half-executes. Whether `organizations` has an off state at all is its manifest's
|
|
849
|
+
* `activation` to say, not this line's: a module declaring
|
|
850
|
+
* `nonDeactivatable` never enters one.
|
|
851
|
+
*/
|
|
852
|
+
export interface SalesRepAssignmentPort {
|
|
853
|
+
canSeeOrganization(adminUserId: string, organizationId: string): Promise<boolean>;
|
|
854
|
+
listAssignedOrganizationIds(adminUserId: string): Promise<string[]>;
|
|
855
|
+
listForOrganization(organizationId: string): Promise<SalesRepAssignmentRow[]>;
|
|
856
|
+
assign(input: {
|
|
857
|
+
organizationId: string;
|
|
858
|
+
adminUserId: string;
|
|
859
|
+
assignedByAdminUserId?: string | null;
|
|
860
|
+
}): Promise<SalesRepAssignmentRow>;
|
|
861
|
+
unassign(input: {
|
|
862
|
+
organizationId: string;
|
|
863
|
+
adminUserId: string;
|
|
864
|
+
}): Promise<boolean>;
|
|
865
|
+
}
|
|
866
|
+
/** The address a VAT registry hands back when it recognises the tax id. */
|
|
867
|
+
export interface VatReturnedAddress {
|
|
868
|
+
line1?: string | null;
|
|
869
|
+
line2?: string | null;
|
|
870
|
+
postalCode?: string | null;
|
|
871
|
+
city?: string | null;
|
|
872
|
+
countryCode?: string | null;
|
|
873
|
+
}
|
|
874
|
+
export interface VatValidationResult {
|
|
875
|
+
outcome: VatValidationOutcome;
|
|
876
|
+
legalName: string | null;
|
|
877
|
+
address: VatReturnedAddress | null;
|
|
878
|
+
errorKind: string | null;
|
|
879
|
+
}
|
|
880
|
+
/**
|
|
881
|
+
* Container name: `vatValidatorPort`. Owner: `organizations`.
|
|
882
|
+
*
|
|
883
|
+
* Pluggable VAT-ID validator (feature 026 US7), published so `customers` can
|
|
884
|
+
* name the shape without naming a file in `organizations`.
|
|
885
|
+
*
|
|
886
|
+
* **Owner off:** the seam fails closed — resolving the port throws
|
|
887
|
+
* `ModuleDisabledError` and the call answers 503 `MODULE_DISABLED`. That is
|
|
888
|
+
* not the same thing as the `deferred` outcome below: `deferred` is the
|
|
889
|
+
* *registry* being unreachable, which the caller may retry, while a refused
|
|
890
|
+
* resolution says the platform is not offering the check at all.
|
|
891
|
+
*
|
|
892
|
+
* Every adapter MUST degrade safely: a transient network failure or a
|
|
893
|
+
* provider-side 5xx returns `{ outcome: 'deferred', errorKind: … }` rather
|
|
894
|
+
* than throwing. A clean "not registered" response returns
|
|
895
|
+
* `{ outcome: 'failed', errorKind: 'not_found' }`. Only `validated` carries
|
|
896
|
+
* the optional `legalName` + `address` payloads the auto-fill flow consumes.
|
|
897
|
+
*/
|
|
898
|
+
export interface VatValidator {
|
|
899
|
+
readonly provider: VatValidationProvider;
|
|
900
|
+
validate(input: {
|
|
901
|
+
taxId: string;
|
|
902
|
+
/** Optional country hint extracted upstream (VIES needs the country split). */
|
|
903
|
+
countryCode?: string | undefined;
|
|
904
|
+
}): Promise<VatValidationResult>;
|
|
905
|
+
}
|
|
906
|
+
/**
|
|
907
|
+
* Container name: `organizationTaxProfilePort`. Owner: `organizations`.
|
|
908
|
+
*
|
|
909
|
+
* The Organization facts a VAT rate depends on (T143c).
|
|
910
|
+
*
|
|
911
|
+
* `country` is nullable because the caller's fallback is a business rule
|
|
912
|
+
* (`'PL'`, in the Quote Requests resolver) and belongs where that rule is
|
|
913
|
+
* written, not here — a port that invented a country would make an
|
|
914
|
+
* unregistered address indistinguishable from a Polish one.
|
|
915
|
+
*
|
|
916
|
+
* Deliberately not a widening of the kernel's `OrganizationSnapshot`. That
|
|
917
|
+
* shape is the tenancy projection every module reads; a tax profile is one
|
|
918
|
+
* consumer's question, and D-55 settled the snapshot at what its callers
|
|
919
|
+
* actually use.
|
|
920
|
+
*
|
|
921
|
+
* **Owner off:** the seam fails closed — resolving the port throws
|
|
922
|
+
* `ModuleDisabledError` and the call answers 503 `MODULE_DISABLED`. The Quote
|
|
923
|
+
* Requests tax closure deliberately carries no `catch` (issue #84): quoting
|
|
924
|
+
* 0 % on an operator's behalf is worse than failing.
|
|
925
|
+
*
|
|
926
|
+
* It is declared here rather than in `organizations`' own `./backend` because
|
|
927
|
+
* a port's type argument is a contract type and never the provider's file
|
|
928
|
+
* (composition checklist item 3). The production composition root resolves this
|
|
929
|
+
* name, and `specs/110-instance-repository/` T118 moves that read into
|
|
930
|
+
* `@endora-commerce/platform`, where naming a module is D-52/D-53's refusal.
|
|
931
|
+
*/
|
|
932
|
+
export interface OrganizationTaxProfilePort {
|
|
933
|
+
taxProfileOf(organizationId: string): Promise<{
|
|
934
|
+
vatStatus: 'vat_payer' | 'vat_exempt' | 'reverse_charge';
|
|
935
|
+
country: string | null;
|
|
936
|
+
} | null>;
|
|
937
|
+
}
|
|
938
|
+
//# sourceMappingURL=organizations.d.ts.map
|