platform-types 1.10.733 → 1.10.735
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/dist/cjs/invoice.js +28 -8
- package/dist/cjs/store.js +72 -4
- package/dist/cjs/subscription.js +5 -1
- package/dist/invoice.d.ts +48 -7
- package/dist/invoice.js +27 -7
- package/dist/store.d.ts +69 -6
- package/dist/store.js +71 -3
- package/dist/subscription.d.ts +42 -3
- package/dist/subscription.js +4 -0
- package/package.json +1 -1
package/dist/cjs/invoice.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.INVOICE_DOCUMENT_REFUSAL_CODES = exports.INVOICE_ISSUANCE_REFUSAL_RECOVERY = exports.INVOICE_ISSUANCE_REFUSAL_CODES = exports.INVOICE_POST_VOUCHER_ERROR_CODES = void 0;
|
|
3
|
+
exports.INVOICE_NOT_AUTHORIZED_RECOVERIES = exports.INVOICE_DOCUMENT_REFUSAL_CODES = exports.INVOICE_ISSUANCE_REFUSAL_RECOVERY = exports.INVOICE_ISSUANCE_REFUSAL_CODES = exports.INVOICE_POST_VOUCHER_ERROR_CODES = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* The codes `POST /invoices` answers AFTER a voucher number was spent — ARCA
|
|
6
6
|
* was asked, or a CAEA number was claimed — as a runtime value the app maps.
|
|
@@ -87,13 +87,33 @@ exports.INVOICE_ISSUANCE_REFUSAL_RECOVERY = {
|
|
|
87
87
|
* store. Answered before any store read, render, print stamp, broadcast,
|
|
88
88
|
* staged PDF, print job or email.
|
|
89
89
|
* - `INVOICE_NOT_AUTHORIZED` · 409 — the row's `fiscalStatus` is `pending_cae`
|
|
90
|
-
* or `rejected`. `invoiceId
|
|
90
|
+
* or `rejected`. `invoiceId`, that `fiscalStatus` and a `recovery`
|
|
91
|
+
* (`INVOICE_NOT_AUTHORIZED_RECOVERIES`) ride beside `error`. A
|
|
91
92
|
* print refused here wrote nothing to the invoice and dispatched nothing.
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
* carries a CAE.
|
|
93
|
+
* What the client tells the operator is `recovery`'s to say, never
|
|
94
|
+
* re-derived here: a `pending_cae` row answers `retry` or `support` (an FCE
|
|
95
|
+
* voucher, a partial credit note, or a submit whose recorded voucher triple
|
|
96
|
+
* is incomplete), and a `rejected` row answers `final`. Whether to refuse at
|
|
97
|
+
* all reads `fiscalStatus` only: a row with none (issued before the field
|
|
98
|
+
* existed) is treated as authorized, whether or not it carries a CAE.
|
|
98
99
|
*/
|
|
99
100
|
exports.INVOICE_DOCUMENT_REFUSAL_CODES = ['INVOICE_NOT_FOUND', 'INVOICE_NOT_AUTHORIZED'];
|
|
101
|
+
/**
|
|
102
|
+
* What a client should tell the operator about a voucher the document routes
|
|
103
|
+
* refused with `INVOICE_NOT_AUTHORIZED` — the `recovery` beside `error` in that
|
|
104
|
+
* 409 body, decided server-side from the INVOICE row so a client never re-derives
|
|
105
|
+
* the drain's rules:
|
|
106
|
+
*
|
|
107
|
+
* - `retry` — `pending_cae`, and nothing on the row says the pending-invoice
|
|
108
|
+
* drain will hold it: try again later. The drain may still hold such a row
|
|
109
|
+
* when its order changed underneath it — that is decided against the order,
|
|
110
|
+
* not the row, and is not answered here.
|
|
111
|
+
* - `support` — `pending_cae`, and the row itself shows the drain will hold it
|
|
112
|
+
* rather than settle it: an FCE voucher (skipped), a PARTIAL credit note (its
|
|
113
|
+
* row carries `partialItems`, and the drain's full-order rebuild never
|
|
114
|
+
* reproduces it), or a submit whose recorded voucher triple is incomplete.
|
|
115
|
+
* Contact support. A return's own partial credit note can still be settled by
|
|
116
|
+
* that return's credit-note retry.
|
|
117
|
+
* - `final` — `rejected`. ARCA refused the voucher and nothing retries it.
|
|
118
|
+
*/
|
|
119
|
+
exports.INVOICE_NOT_AUTHORIZED_RECOVERIES = ['retry', 'support', 'final'];
|
package/dist/cjs/store.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.STORE_MODULE_ERROR_CODES = exports.isStoreModuleOn = exports.isStoreModuleKey = exports.STORE_MODULE_KEYS = exports.CUSTOM_DOMAIN_ROW_LIMIT = exports.CUSTOM_DOMAIN_SLOT_LIMIT = void 0;
|
|
3
|
+
exports.STORE_PATCH_ERROR_CODES = exports.STORE_MODULE_ERROR_CODES = exports.isStoreModuleOn = exports.isStoreModuleKey = exports.STORE_MODULE_KEYS = exports.CUSTOM_DOMAIN_ROW_LIMIT = exports.CUSTOM_DOMAIN_SLOT_LIMIT = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* How many custom-domain rows a store may hold that count: one active domain
|
|
6
6
|
* and one spare, so a replacement can be verified and provisioned before the
|
|
@@ -52,9 +52,11 @@ exports.isStoreModuleKey = isStoreModuleKey;
|
|
|
52
52
|
const isStoreModuleOn = (modules, module) => modules?.[module] !== false;
|
|
53
53
|
exports.isStoreModuleOn = isStoreModuleOn;
|
|
54
54
|
/**
|
|
55
|
-
* Every refusal code the store-module switches put on the wire
|
|
56
|
-
*
|
|
57
|
-
* plain USER
|
|
55
|
+
* Every refusal code the store-module switches put on the wire. Not listed
|
|
56
|
+
* here: `VALIDATION_FAILED` (a malformed body), and `STORE_CONFIG_FORBIDDEN` —
|
|
57
|
+
* the `PATCH /store` role refusal a plain USER gets for ANY privileged `config`
|
|
58
|
+
* leaf, `modules` included, judged before this module code runs. That one is in
|
|
59
|
+
* {@link STORE_PATCH_ERROR_CODES}:
|
|
58
60
|
*
|
|
59
61
|
* - `STORE_MODULE_UNKNOWN` (400) — `PATCH /store` named a key outside
|
|
60
62
|
* `STORE_MODULE_KEYS`; `data.module` carries it.
|
|
@@ -91,3 +93,69 @@ exports.STORE_MODULE_ERROR_CODES = [
|
|
|
91
93
|
'STORE_MODULE_SHIFTS_OPEN',
|
|
92
94
|
'STORE_MODULE_DISABLED',
|
|
93
95
|
];
|
|
96
|
+
/**
|
|
97
|
+
* The bare refusal codes `PATCH /store` (`stacks/lambdas/store/_patch.ts`, and
|
|
98
|
+
* the route's own sibling modules it calls) answers itself — `{ error, message }`
|
|
99
|
+
* with no `data`, unless noted:
|
|
100
|
+
*
|
|
101
|
+
* Role refusals, `403` — a plain USER writing a privileged section. Each is
|
|
102
|
+
* judged before any other check on that section:
|
|
103
|
+
* - `STORE_CONFIG_FORBIDDEN` — any privileged `config` leaf (`modules`,
|
|
104
|
+
* `stock`, `priceDecimals`, `changePrice`, `mandatory2fa`, …).
|
|
105
|
+
* - `STORE_ECOMMERCE_FORBIDDEN` — any `ecommerce` block.
|
|
106
|
+
* - `STORE_FISCAL_FIELD_FORBIDDEN` — a fiscal field of the store.
|
|
107
|
+
* - `STORE_JURISDICTION_FORBIDDEN` — `jurisdiction`.
|
|
108
|
+
* - `AFIP_RELACION_FLAG_FORBIDDEN` — `afip.wscdcEnabled` / `afip.fceEnabled`.
|
|
109
|
+
* - `FX_TABLE_FORBIDDEN` — the `currencies` exchange-rate table.
|
|
110
|
+
* - `FX_AUTO_UPDATE_FORBIDDEN` — `fxAutoUpdate`.
|
|
111
|
+
*
|
|
112
|
+
* Request refusals, `400`:
|
|
113
|
+
* - `FIELD_NOT_WRITABLE_HERE` — a field written through `POST /store`, not
|
|
114
|
+
* this route; a top-level `fields` array names them.
|
|
115
|
+
* - `AFIP_POINT_OF_SALE_NOT_CLEARABLE` — `null` sent for the punto de venta.
|
|
116
|
+
* - `CURRENCY_CATALOG_ID_UNKNOWN` — a `currencies` entry names an unknown or
|
|
117
|
+
* disabled catalog id.
|
|
118
|
+
* - `ARS_RATE_MUST_BE_ONE` — the peso entry's value is not exactly `1`.
|
|
119
|
+
* - `CURRENCY_RATE_ABOVE_CEILING` — a `currencies` value is above its ceiling.
|
|
120
|
+
* - `FX_CATALOG_ID_UNKNOWN` / `FX_SOURCE_ID_UNKNOWN` — an `fxAutoUpdate`
|
|
121
|
+
* binding names an unknown catalog id or rate source.
|
|
122
|
+
* - `DISPLAY_CURRENCY_NOT_INVOICEABLE` / `PRODUCT_CURRENCY_NOT_INVOICEABLE` — a
|
|
123
|
+
* store carrying an AFIP CUIT set `config.displayCurrency` /
|
|
124
|
+
* `config.defaultProductCurrency` to a non-oficial USD variant.
|
|
125
|
+
* - `PRICE_LIST_NOT_FOUND` — an `ecommerce` save names a
|
|
126
|
+
* `newCustomerPriceList` that does not exist (`store/_ecommercePatch.ts`).
|
|
127
|
+
*
|
|
128
|
+
* Maintenance mode (`{ mode: 'maintenance', level }`, `store/_patchMaintenance.ts`):
|
|
129
|
+
* - `FORBIDDEN` (403) — the caller is neither an ADMIN nor a MANAGER.
|
|
130
|
+
* - `STORE_NOT_FOUND` (404) — the store row is gone.
|
|
131
|
+
*
|
|
132
|
+
* ⚠️ Not repeated here because another tuple already publishes them:
|
|
133
|
+
* `VALIDATION_FAILED`, `PRODUCT_CURRENCY_NOT_SUBSCRIBED`
|
|
134
|
+
* (`PRODUCT_POST_ERROR_CODES`), `WAREHOUSE_NOT_FOUND` /
|
|
135
|
+
* `WAREHOUSE_INACTIVE` (a `channelWarehouses` target), and every
|
|
136
|
+
* `STORE_MODULE_*` code ({@link STORE_MODULE_ERROR_CODES}). Codes the route
|
|
137
|
+
* forwards from shared helpers (the write conflict, the CAEA punto-de-venta
|
|
138
|
+
* checks, the display-currency lock, the storefront fence) are not listed
|
|
139
|
+
* either. Cross-cutting refusals: check `GATING_ERROR_CODES` as well.
|
|
140
|
+
*/
|
|
141
|
+
exports.STORE_PATCH_ERROR_CODES = [
|
|
142
|
+
'STORE_CONFIG_FORBIDDEN',
|
|
143
|
+
'STORE_ECOMMERCE_FORBIDDEN',
|
|
144
|
+
'STORE_FISCAL_FIELD_FORBIDDEN',
|
|
145
|
+
'STORE_JURISDICTION_FORBIDDEN',
|
|
146
|
+
'AFIP_RELACION_FLAG_FORBIDDEN',
|
|
147
|
+
'FX_TABLE_FORBIDDEN',
|
|
148
|
+
'FX_AUTO_UPDATE_FORBIDDEN',
|
|
149
|
+
'FIELD_NOT_WRITABLE_HERE',
|
|
150
|
+
'AFIP_POINT_OF_SALE_NOT_CLEARABLE',
|
|
151
|
+
'CURRENCY_CATALOG_ID_UNKNOWN',
|
|
152
|
+
'ARS_RATE_MUST_BE_ONE',
|
|
153
|
+
'CURRENCY_RATE_ABOVE_CEILING',
|
|
154
|
+
'FX_CATALOG_ID_UNKNOWN',
|
|
155
|
+
'FX_SOURCE_ID_UNKNOWN',
|
|
156
|
+
'DISPLAY_CURRENCY_NOT_INVOICEABLE',
|
|
157
|
+
'PRODUCT_CURRENCY_NOT_INVOICEABLE',
|
|
158
|
+
'PRICE_LIST_NOT_FOUND',
|
|
159
|
+
'FORBIDDEN',
|
|
160
|
+
'STORE_NOT_FOUND',
|
|
161
|
+
];
|
package/dist/cjs/subscription.js
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
* enabled:false until they do.
|
|
31
31
|
*/
|
|
32
32
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
33
|
-
exports.FEATURE_KEYS = exports.isPaidPlanTier = exports.PLAN_CATALOGUE_ERROR_CODES = exports.PLAN_CATALOGUE_TEMPLATE_FIELDS = exports.PAID_PLAN_TIERS = exports.PLAN_TIERS = void 0;
|
|
33
|
+
exports.FEATURE_KEYS = exports.isPaidPlanTier = exports.PLAN_PRICE_SYNC_ERROR_CODES = exports.PLAN_CATALOGUE_ERROR_CODES = exports.PLAN_CATALOGUE_TEMPLATE_FIELDS = exports.PAID_PLAN_TIERS = exports.PLAN_TIERS = void 0;
|
|
34
34
|
/*
|
|
35
35
|
* Runtime tuples for the unions above.
|
|
36
36
|
*
|
|
@@ -79,6 +79,10 @@ exports.PLAN_CATALOGUE_ERROR_CODES = exhaustiveTuple()([
|
|
|
79
79
|
'PLAN_CATALOGUE_DRAFT_STALE',
|
|
80
80
|
'IDEMPOTENCY_CONFLICT',
|
|
81
81
|
]);
|
|
82
|
+
/** Every `error` code `POST /subscription/checkout` adds for a price the provider has not caught up with. */
|
|
83
|
+
exports.PLAN_PRICE_SYNC_ERROR_CODES = exhaustiveTuple()([
|
|
84
|
+
'PLAN_STRIPE_PRICE_STALE',
|
|
85
|
+
]);
|
|
82
86
|
/** Whether `value` names a paid tier — narrows an untyped read (a stored row, a global) to `PaidPlanTier`. */
|
|
83
87
|
const isPaidPlanTier = (value) => typeof value === 'string' && exports.PAID_PLAN_TIERS.includes(value);
|
|
84
88
|
exports.isPaidPlanTier = isPaidPlanTier;
|
package/dist/invoice.d.ts
CHANGED
|
@@ -354,6 +354,26 @@ declare global {
|
|
|
354
354
|
* Forward-only; nothing reads it as anything but a deadline.
|
|
355
355
|
*/
|
|
356
356
|
drainClaimUntil?: number;
|
|
357
|
+
/**
|
|
358
|
+
* `true` while a REJECTED row's order still shows it unsettled — the
|
|
359
|
+
* rejection committed, but the order's `invoices[]` entry could not be set to
|
|
360
|
+
* `rejected` in the same write. Written in that same rejection write, only
|
|
361
|
+
* then; REMOVEd by the repair that sets the entry — tried at once, then by the
|
|
362
|
+
* `order-copy-repair` queue's consumer, and by a pending-invoice drain pass
|
|
363
|
+
* that reaches the store's page (AFIP not known down, its AFIP client up).
|
|
364
|
+
* ABSENT on every other row, and forward-only.
|
|
365
|
+
*/
|
|
366
|
+
orderCopyStale?: true;
|
|
367
|
+
/**
|
|
368
|
+
* The rejecting caller's ORDER-trail origin, written beside `orderCopyStale`
|
|
369
|
+
* in the same write and REMOVEd with it, so whichever repairer reaches the
|
|
370
|
+
* row records the caller's settle rather than its own. Forward-only.
|
|
371
|
+
*/
|
|
372
|
+
orderCopyStaleOrigin?: Extract<OrderAuditOrigin, 'platform' | 'operator' | 'worker'>;
|
|
373
|
+
/** The rejecting caller's settle reason — ids only, code-authored. Beside `orderCopyStale`, REMOVEd with it. */
|
|
374
|
+
orderCopyStaleReason?: string;
|
|
375
|
+
/** The rejecting caller's actor `userId` (`''` = the system actor). Beside `orderCopyStale`, REMOVEd with it. */
|
|
376
|
+
orderCopyStaleActorId?: string;
|
|
357
377
|
invoicePrinted?: boolean;
|
|
358
378
|
/**
|
|
359
379
|
* Server-derived ms epoch, stamped by the WSS `ack` handler on an
|
|
@@ -1006,15 +1026,36 @@ export declare const INVOICE_ISSUANCE_REFUSAL_RECOVERY: {
|
|
|
1006
1026
|
* store. Answered before any store read, render, print stamp, broadcast,
|
|
1007
1027
|
* staged PDF, print job or email.
|
|
1008
1028
|
* - `INVOICE_NOT_AUTHORIZED` · 409 — the row's `fiscalStatus` is `pending_cae`
|
|
1009
|
-
* or `rejected`. `invoiceId
|
|
1029
|
+
* or `rejected`. `invoiceId`, that `fiscalStatus` and a `recovery`
|
|
1030
|
+
* (`INVOICE_NOT_AUTHORIZED_RECOVERIES`) ride beside `error`. A
|
|
1010
1031
|
* print refused here wrote nothing to the invoice and dispatched nothing.
|
|
1011
|
-
*
|
|
1012
|
-
*
|
|
1013
|
-
*
|
|
1014
|
-
*
|
|
1015
|
-
*
|
|
1016
|
-
* carries a CAE.
|
|
1032
|
+
* What the client tells the operator is `recovery`'s to say, never
|
|
1033
|
+
* re-derived here: a `pending_cae` row answers `retry` or `support` (an FCE
|
|
1034
|
+
* voucher, a partial credit note, or a submit whose recorded voucher triple
|
|
1035
|
+
* is incomplete), and a `rejected` row answers `final`. Whether to refuse at
|
|
1036
|
+
* all reads `fiscalStatus` only: a row with none (issued before the field
|
|
1037
|
+
* existed) is treated as authorized, whether or not it carries a CAE.
|
|
1017
1038
|
*/
|
|
1018
1039
|
export declare const INVOICE_DOCUMENT_REFUSAL_CODES: readonly ["INVOICE_NOT_FOUND", "INVOICE_NOT_AUTHORIZED"];
|
|
1019
1040
|
export type InvoiceDocumentRefusalCode = (typeof INVOICE_DOCUMENT_REFUSAL_CODES)[number];
|
|
1041
|
+
/**
|
|
1042
|
+
* What a client should tell the operator about a voucher the document routes
|
|
1043
|
+
* refused with `INVOICE_NOT_AUTHORIZED` — the `recovery` beside `error` in that
|
|
1044
|
+
* 409 body, decided server-side from the INVOICE row so a client never re-derives
|
|
1045
|
+
* the drain's rules:
|
|
1046
|
+
*
|
|
1047
|
+
* - `retry` — `pending_cae`, and nothing on the row says the pending-invoice
|
|
1048
|
+
* drain will hold it: try again later. The drain may still hold such a row
|
|
1049
|
+
* when its order changed underneath it — that is decided against the order,
|
|
1050
|
+
* not the row, and is not answered here.
|
|
1051
|
+
* - `support` — `pending_cae`, and the row itself shows the drain will hold it
|
|
1052
|
+
* rather than settle it: an FCE voucher (skipped), a PARTIAL credit note (its
|
|
1053
|
+
* row carries `partialItems`, and the drain's full-order rebuild never
|
|
1054
|
+
* reproduces it), or a submit whose recorded voucher triple is incomplete.
|
|
1055
|
+
* Contact support. A return's own partial credit note can still be settled by
|
|
1056
|
+
* that return's credit-note retry.
|
|
1057
|
+
* - `final` — `rejected`. ARCA refused the voucher and nothing retries it.
|
|
1058
|
+
*/
|
|
1059
|
+
export declare const INVOICE_NOT_AUTHORIZED_RECOVERIES: readonly ["retry", "support", "final"];
|
|
1060
|
+
export type InvoiceNotAuthorizedRecovery = (typeof INVOICE_NOT_AUTHORIZED_RECOVERIES)[number];
|
|
1020
1061
|
export {};
|
package/dist/invoice.js
CHANGED
|
@@ -84,13 +84,33 @@ export const INVOICE_ISSUANCE_REFUSAL_RECOVERY = {
|
|
|
84
84
|
* store. Answered before any store read, render, print stamp, broadcast,
|
|
85
85
|
* staged PDF, print job or email.
|
|
86
86
|
* - `INVOICE_NOT_AUTHORIZED` · 409 — the row's `fiscalStatus` is `pending_cae`
|
|
87
|
-
* or `rejected`. `invoiceId
|
|
87
|
+
* or `rejected`. `invoiceId`, that `fiscalStatus` and a `recovery`
|
|
88
|
+
* (`INVOICE_NOT_AUTHORIZED_RECOVERIES`) ride beside `error`. A
|
|
88
89
|
* print refused here wrote nothing to the invoice and dispatched nothing.
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
* carries a CAE.
|
|
90
|
+
* What the client tells the operator is `recovery`'s to say, never
|
|
91
|
+
* re-derived here: a `pending_cae` row answers `retry` or `support` (an FCE
|
|
92
|
+
* voucher, a partial credit note, or a submit whose recorded voucher triple
|
|
93
|
+
* is incomplete), and a `rejected` row answers `final`. Whether to refuse at
|
|
94
|
+
* all reads `fiscalStatus` only: a row with none (issued before the field
|
|
95
|
+
* existed) is treated as authorized, whether or not it carries a CAE.
|
|
95
96
|
*/
|
|
96
97
|
export const INVOICE_DOCUMENT_REFUSAL_CODES = ['INVOICE_NOT_FOUND', 'INVOICE_NOT_AUTHORIZED'];
|
|
98
|
+
/**
|
|
99
|
+
* What a client should tell the operator about a voucher the document routes
|
|
100
|
+
* refused with `INVOICE_NOT_AUTHORIZED` — the `recovery` beside `error` in that
|
|
101
|
+
* 409 body, decided server-side from the INVOICE row so a client never re-derives
|
|
102
|
+
* the drain's rules:
|
|
103
|
+
*
|
|
104
|
+
* - `retry` — `pending_cae`, and nothing on the row says the pending-invoice
|
|
105
|
+
* drain will hold it: try again later. The drain may still hold such a row
|
|
106
|
+
* when its order changed underneath it — that is decided against the order,
|
|
107
|
+
* not the row, and is not answered here.
|
|
108
|
+
* - `support` — `pending_cae`, and the row itself shows the drain will hold it
|
|
109
|
+
* rather than settle it: an FCE voucher (skipped), a PARTIAL credit note (its
|
|
110
|
+
* row carries `partialItems`, and the drain's full-order rebuild never
|
|
111
|
+
* reproduces it), or a submit whose recorded voucher triple is incomplete.
|
|
112
|
+
* Contact support. A return's own partial credit note can still be settled by
|
|
113
|
+
* that return's credit-note retry.
|
|
114
|
+
* - `final` — `rejected`. ARCA refused the voucher and nothing retries it.
|
|
115
|
+
*/
|
|
116
|
+
export const INVOICE_NOT_AUTHORIZED_RECOVERIES = ['retry', 'support', 'final'];
|
package/dist/store.d.ts
CHANGED
|
@@ -918,7 +918,7 @@ declare global {
|
|
|
918
918
|
* not finish); `cash` while any cash shift is still open
|
|
919
919
|
* (`409 STORE_MODULE_SHIFTS_OPEN` — `StoreModuleShiftsOpenData`).
|
|
920
920
|
*
|
|
921
|
-
* Enforced on the server for
|
|
921
|
+
* Enforced on the server for nine modules only:
|
|
922
922
|
* - `promotions` — applying one is refused `PROMOTION_NOT_ACTIVE` (the
|
|
923
923
|
* existing promotion refusal, not `STORE_MODULE_DISABLED`), a grant already
|
|
924
924
|
* frozen on a cart stays on the row but derives no money (its
|
|
@@ -945,8 +945,22 @@ declare global {
|
|
|
945
945
|
* settled `'skipped'` with reason `MODULE_OFF` at its send worker.
|
|
946
946
|
* - `cash` — a POS terminal activates WITHOUT a shift (no `shiftId`,
|
|
947
947
|
* living until its own expiry), and opening a shift (`POST /shifts`) is
|
|
948
|
-
* refused `403 STORE_MODULE_DISABLED
|
|
949
|
-
*
|
|
948
|
+
* refused `403 STORE_MODULE_DISABLED` — re-checked at commit, so an
|
|
949
|
+
* open that commits after the turn-off is refused (one committing
|
|
950
|
+
* inside the turn-off's own check-then-write window is accepted — see
|
|
951
|
+
* `docs/STORE.md` § Store module switches); every other `/shifts`
|
|
952
|
+
* endpoint (close, movements, reconcile, reads) stays reachable.
|
|
953
|
+
* - `customerAccounts` — the scheduled payment-reminder cron sends
|
|
954
|
+
* nothing for the store, and a scheduled reminder email already queued
|
|
955
|
+
* is dropped; the operator's per-customer send-reminder stays reachable.
|
|
956
|
+
* - `fiscalInvoicing` — "stop new, finish old": the CAEA request cron
|
|
957
|
+
* requests no new CAEA for the store and `AFIP_CERT_EXPIRY` is muted
|
|
958
|
+
* for it; a price-freezing seña over an order with no live factura
|
|
959
|
+
* freezes with no `invoiceId` (re-checked at commit) instead of being
|
|
960
|
+
* refused `DEPOSIT_FREEZE_REQUIRES_INVOICE`, and while that seña is held
|
|
961
|
+
* a re-price that moves the charged total is `409 ORDER_PRICE_FROZEN`,
|
|
962
|
+
* even after the module is back on. The CAEA inform cron, the return
|
|
963
|
+
* credit-note reconciler and operator-initiated invoicing are unchanged.
|
|
950
964
|
* Every other module is hide-only: its endpoints stay reachable. Public
|
|
951
965
|
* reads carry only `appointments`, `surveys`, `promotions` and
|
|
952
966
|
* `customerAccounts`. `PUT /platform/stores/{storeId}` refuses the leaf.
|
|
@@ -2032,9 +2046,11 @@ export declare const isStoreModuleKey: (value: unknown) => value is StoreModuleK
|
|
|
2032
2046
|
*/
|
|
2033
2047
|
export declare const isStoreModuleOn: (modules: StoreModules | null | undefined, module: StoreModuleKey) => boolean;
|
|
2034
2048
|
/**
|
|
2035
|
-
* Every refusal code the store-module switches put on the wire
|
|
2036
|
-
*
|
|
2037
|
-
* plain USER
|
|
2049
|
+
* Every refusal code the store-module switches put on the wire. Not listed
|
|
2050
|
+
* here: `VALIDATION_FAILED` (a malformed body), and `STORE_CONFIG_FORBIDDEN` —
|
|
2051
|
+
* the `PATCH /store` role refusal a plain USER gets for ANY privileged `config`
|
|
2052
|
+
* leaf, `modules` included, judged before this module code runs. That one is in
|
|
2053
|
+
* {@link STORE_PATCH_ERROR_CODES}:
|
|
2038
2054
|
*
|
|
2039
2055
|
* - `STORE_MODULE_UNKNOWN` (400) — `PATCH /store` named a key outside
|
|
2040
2056
|
* `STORE_MODULE_KEYS`; `data.module` carries it.
|
|
@@ -2147,3 +2163,50 @@ export type StoreModuleRefusalBody = {
|
|
|
2147
2163
|
data: StoreModuleRefusalDataByCode[Code];
|
|
2148
2164
|
};
|
|
2149
2165
|
}[StoreModuleErrorCode];
|
|
2166
|
+
/**
|
|
2167
|
+
* The bare refusal codes `PATCH /store` (`stacks/lambdas/store/_patch.ts`, and
|
|
2168
|
+
* the route's own sibling modules it calls) answers itself — `{ error, message }`
|
|
2169
|
+
* with no `data`, unless noted:
|
|
2170
|
+
*
|
|
2171
|
+
* Role refusals, `403` — a plain USER writing a privileged section. Each is
|
|
2172
|
+
* judged before any other check on that section:
|
|
2173
|
+
* - `STORE_CONFIG_FORBIDDEN` — any privileged `config` leaf (`modules`,
|
|
2174
|
+
* `stock`, `priceDecimals`, `changePrice`, `mandatory2fa`, …).
|
|
2175
|
+
* - `STORE_ECOMMERCE_FORBIDDEN` — any `ecommerce` block.
|
|
2176
|
+
* - `STORE_FISCAL_FIELD_FORBIDDEN` — a fiscal field of the store.
|
|
2177
|
+
* - `STORE_JURISDICTION_FORBIDDEN` — `jurisdiction`.
|
|
2178
|
+
* - `AFIP_RELACION_FLAG_FORBIDDEN` — `afip.wscdcEnabled` / `afip.fceEnabled`.
|
|
2179
|
+
* - `FX_TABLE_FORBIDDEN` — the `currencies` exchange-rate table.
|
|
2180
|
+
* - `FX_AUTO_UPDATE_FORBIDDEN` — `fxAutoUpdate`.
|
|
2181
|
+
*
|
|
2182
|
+
* Request refusals, `400`:
|
|
2183
|
+
* - `FIELD_NOT_WRITABLE_HERE` — a field written through `POST /store`, not
|
|
2184
|
+
* this route; a top-level `fields` array names them.
|
|
2185
|
+
* - `AFIP_POINT_OF_SALE_NOT_CLEARABLE` — `null` sent for the punto de venta.
|
|
2186
|
+
* - `CURRENCY_CATALOG_ID_UNKNOWN` — a `currencies` entry names an unknown or
|
|
2187
|
+
* disabled catalog id.
|
|
2188
|
+
* - `ARS_RATE_MUST_BE_ONE` — the peso entry's value is not exactly `1`.
|
|
2189
|
+
* - `CURRENCY_RATE_ABOVE_CEILING` — a `currencies` value is above its ceiling.
|
|
2190
|
+
* - `FX_CATALOG_ID_UNKNOWN` / `FX_SOURCE_ID_UNKNOWN` — an `fxAutoUpdate`
|
|
2191
|
+
* binding names an unknown catalog id or rate source.
|
|
2192
|
+
* - `DISPLAY_CURRENCY_NOT_INVOICEABLE` / `PRODUCT_CURRENCY_NOT_INVOICEABLE` — a
|
|
2193
|
+
* store carrying an AFIP CUIT set `config.displayCurrency` /
|
|
2194
|
+
* `config.defaultProductCurrency` to a non-oficial USD variant.
|
|
2195
|
+
* - `PRICE_LIST_NOT_FOUND` — an `ecommerce` save names a
|
|
2196
|
+
* `newCustomerPriceList` that does not exist (`store/_ecommercePatch.ts`).
|
|
2197
|
+
*
|
|
2198
|
+
* Maintenance mode (`{ mode: 'maintenance', level }`, `store/_patchMaintenance.ts`):
|
|
2199
|
+
* - `FORBIDDEN` (403) — the caller is neither an ADMIN nor a MANAGER.
|
|
2200
|
+
* - `STORE_NOT_FOUND` (404) — the store row is gone.
|
|
2201
|
+
*
|
|
2202
|
+
* ⚠️ Not repeated here because another tuple already publishes them:
|
|
2203
|
+
* `VALIDATION_FAILED`, `PRODUCT_CURRENCY_NOT_SUBSCRIBED`
|
|
2204
|
+
* (`PRODUCT_POST_ERROR_CODES`), `WAREHOUSE_NOT_FOUND` /
|
|
2205
|
+
* `WAREHOUSE_INACTIVE` (a `channelWarehouses` target), and every
|
|
2206
|
+
* `STORE_MODULE_*` code ({@link STORE_MODULE_ERROR_CODES}). Codes the route
|
|
2207
|
+
* forwards from shared helpers (the write conflict, the CAEA punto-de-venta
|
|
2208
|
+
* checks, the display-currency lock, the storefront fence) are not listed
|
|
2209
|
+
* either. Cross-cutting refusals: check `GATING_ERROR_CODES` as well.
|
|
2210
|
+
*/
|
|
2211
|
+
export declare const STORE_PATCH_ERROR_CODES: readonly ["STORE_CONFIG_FORBIDDEN", "STORE_ECOMMERCE_FORBIDDEN", "STORE_FISCAL_FIELD_FORBIDDEN", "STORE_JURISDICTION_FORBIDDEN", "AFIP_RELACION_FLAG_FORBIDDEN", "FX_TABLE_FORBIDDEN", "FX_AUTO_UPDATE_FORBIDDEN", "FIELD_NOT_WRITABLE_HERE", "AFIP_POINT_OF_SALE_NOT_CLEARABLE", "CURRENCY_CATALOG_ID_UNKNOWN", "ARS_RATE_MUST_BE_ONE", "CURRENCY_RATE_ABOVE_CEILING", "FX_CATALOG_ID_UNKNOWN", "FX_SOURCE_ID_UNKNOWN", "DISPLAY_CURRENCY_NOT_INVOICEABLE", "PRODUCT_CURRENCY_NOT_INVOICEABLE", "PRICE_LIST_NOT_FOUND", "FORBIDDEN", "STORE_NOT_FOUND"];
|
|
2212
|
+
export type StorePatchErrorCode = (typeof STORE_PATCH_ERROR_CODES)[number];
|
package/dist/store.js
CHANGED
|
@@ -47,9 +47,11 @@ export const isStoreModuleKey = (value) => typeof value === 'string' && STORE_MO
|
|
|
47
47
|
*/
|
|
48
48
|
export const isStoreModuleOn = (modules, module) => modules?.[module] !== false;
|
|
49
49
|
/**
|
|
50
|
-
* Every refusal code the store-module switches put on the wire
|
|
51
|
-
*
|
|
52
|
-
* plain USER
|
|
50
|
+
* Every refusal code the store-module switches put on the wire. Not listed
|
|
51
|
+
* here: `VALIDATION_FAILED` (a malformed body), and `STORE_CONFIG_FORBIDDEN` —
|
|
52
|
+
* the `PATCH /store` role refusal a plain USER gets for ANY privileged `config`
|
|
53
|
+
* leaf, `modules` included, judged before this module code runs. That one is in
|
|
54
|
+
* {@link STORE_PATCH_ERROR_CODES}:
|
|
53
55
|
*
|
|
54
56
|
* - `STORE_MODULE_UNKNOWN` (400) — `PATCH /store` named a key outside
|
|
55
57
|
* `STORE_MODULE_KEYS`; `data.module` carries it.
|
|
@@ -86,3 +88,69 @@ export const STORE_MODULE_ERROR_CODES = [
|
|
|
86
88
|
'STORE_MODULE_SHIFTS_OPEN',
|
|
87
89
|
'STORE_MODULE_DISABLED',
|
|
88
90
|
];
|
|
91
|
+
/**
|
|
92
|
+
* The bare refusal codes `PATCH /store` (`stacks/lambdas/store/_patch.ts`, and
|
|
93
|
+
* the route's own sibling modules it calls) answers itself — `{ error, message }`
|
|
94
|
+
* with no `data`, unless noted:
|
|
95
|
+
*
|
|
96
|
+
* Role refusals, `403` — a plain USER writing a privileged section. Each is
|
|
97
|
+
* judged before any other check on that section:
|
|
98
|
+
* - `STORE_CONFIG_FORBIDDEN` — any privileged `config` leaf (`modules`,
|
|
99
|
+
* `stock`, `priceDecimals`, `changePrice`, `mandatory2fa`, …).
|
|
100
|
+
* - `STORE_ECOMMERCE_FORBIDDEN` — any `ecommerce` block.
|
|
101
|
+
* - `STORE_FISCAL_FIELD_FORBIDDEN` — a fiscal field of the store.
|
|
102
|
+
* - `STORE_JURISDICTION_FORBIDDEN` — `jurisdiction`.
|
|
103
|
+
* - `AFIP_RELACION_FLAG_FORBIDDEN` — `afip.wscdcEnabled` / `afip.fceEnabled`.
|
|
104
|
+
* - `FX_TABLE_FORBIDDEN` — the `currencies` exchange-rate table.
|
|
105
|
+
* - `FX_AUTO_UPDATE_FORBIDDEN` — `fxAutoUpdate`.
|
|
106
|
+
*
|
|
107
|
+
* Request refusals, `400`:
|
|
108
|
+
* - `FIELD_NOT_WRITABLE_HERE` — a field written through `POST /store`, not
|
|
109
|
+
* this route; a top-level `fields` array names them.
|
|
110
|
+
* - `AFIP_POINT_OF_SALE_NOT_CLEARABLE` — `null` sent for the punto de venta.
|
|
111
|
+
* - `CURRENCY_CATALOG_ID_UNKNOWN` — a `currencies` entry names an unknown or
|
|
112
|
+
* disabled catalog id.
|
|
113
|
+
* - `ARS_RATE_MUST_BE_ONE` — the peso entry's value is not exactly `1`.
|
|
114
|
+
* - `CURRENCY_RATE_ABOVE_CEILING` — a `currencies` value is above its ceiling.
|
|
115
|
+
* - `FX_CATALOG_ID_UNKNOWN` / `FX_SOURCE_ID_UNKNOWN` — an `fxAutoUpdate`
|
|
116
|
+
* binding names an unknown catalog id or rate source.
|
|
117
|
+
* - `DISPLAY_CURRENCY_NOT_INVOICEABLE` / `PRODUCT_CURRENCY_NOT_INVOICEABLE` — a
|
|
118
|
+
* store carrying an AFIP CUIT set `config.displayCurrency` /
|
|
119
|
+
* `config.defaultProductCurrency` to a non-oficial USD variant.
|
|
120
|
+
* - `PRICE_LIST_NOT_FOUND` — an `ecommerce` save names a
|
|
121
|
+
* `newCustomerPriceList` that does not exist (`store/_ecommercePatch.ts`).
|
|
122
|
+
*
|
|
123
|
+
* Maintenance mode (`{ mode: 'maintenance', level }`, `store/_patchMaintenance.ts`):
|
|
124
|
+
* - `FORBIDDEN` (403) — the caller is neither an ADMIN nor a MANAGER.
|
|
125
|
+
* - `STORE_NOT_FOUND` (404) — the store row is gone.
|
|
126
|
+
*
|
|
127
|
+
* ⚠️ Not repeated here because another tuple already publishes them:
|
|
128
|
+
* `VALIDATION_FAILED`, `PRODUCT_CURRENCY_NOT_SUBSCRIBED`
|
|
129
|
+
* (`PRODUCT_POST_ERROR_CODES`), `WAREHOUSE_NOT_FOUND` /
|
|
130
|
+
* `WAREHOUSE_INACTIVE` (a `channelWarehouses` target), and every
|
|
131
|
+
* `STORE_MODULE_*` code ({@link STORE_MODULE_ERROR_CODES}). Codes the route
|
|
132
|
+
* forwards from shared helpers (the write conflict, the CAEA punto-de-venta
|
|
133
|
+
* checks, the display-currency lock, the storefront fence) are not listed
|
|
134
|
+
* either. Cross-cutting refusals: check `GATING_ERROR_CODES` as well.
|
|
135
|
+
*/
|
|
136
|
+
export const STORE_PATCH_ERROR_CODES = [
|
|
137
|
+
'STORE_CONFIG_FORBIDDEN',
|
|
138
|
+
'STORE_ECOMMERCE_FORBIDDEN',
|
|
139
|
+
'STORE_FISCAL_FIELD_FORBIDDEN',
|
|
140
|
+
'STORE_JURISDICTION_FORBIDDEN',
|
|
141
|
+
'AFIP_RELACION_FLAG_FORBIDDEN',
|
|
142
|
+
'FX_TABLE_FORBIDDEN',
|
|
143
|
+
'FX_AUTO_UPDATE_FORBIDDEN',
|
|
144
|
+
'FIELD_NOT_WRITABLE_HERE',
|
|
145
|
+
'AFIP_POINT_OF_SALE_NOT_CLEARABLE',
|
|
146
|
+
'CURRENCY_CATALOG_ID_UNKNOWN',
|
|
147
|
+
'ARS_RATE_MUST_BE_ONE',
|
|
148
|
+
'CURRENCY_RATE_ABOVE_CEILING',
|
|
149
|
+
'FX_CATALOG_ID_UNKNOWN',
|
|
150
|
+
'FX_SOURCE_ID_UNKNOWN',
|
|
151
|
+
'DISPLAY_CURRENCY_NOT_INVOICEABLE',
|
|
152
|
+
'PRODUCT_CURRENCY_NOT_INVOICEABLE',
|
|
153
|
+
'PRICE_LIST_NOT_FOUND',
|
|
154
|
+
'FORBIDDEN',
|
|
155
|
+
'STORE_NOT_FOUND',
|
|
156
|
+
];
|
package/dist/subscription.d.ts
CHANGED
|
@@ -780,11 +780,20 @@ declare global {
|
|
|
780
780
|
* place to echo a catalogue's payment-provider IDs.
|
|
781
781
|
*/
|
|
782
782
|
missingProviderIds: string[];
|
|
783
|
+
/**
|
|
784
|
+
* The charged billing cycles whose Stripe Price was minted at a different amount or currency
|
|
785
|
+
* than the row now publishes (its `stripePrice*Cents` / `stripePriceCurrency` stamp differs):
|
|
786
|
+
* Stripe checkout refuses them (`409 PLAN_STRIPE_PRICE_STALE`) until `seed-stripe-products`
|
|
787
|
+
* re-mints. A cycle with no stamp (a row seeded before the stamp existed) is never listed.
|
|
788
|
+
*/
|
|
789
|
+
staleStripePriceCycles: ('monthly' | 'annual')[];
|
|
783
790
|
/**
|
|
784
791
|
* Keys in the template row's `grants` overlay that the api does not
|
|
785
792
|
* declare (retired or misspelt), sorted. Inert — every reader ignores them
|
|
786
793
|
* and the code default applies — but stored, so they are drift: a `null`
|
|
787
|
-
* for that key on `PATCH /platform/billing/plans/grants
|
|
794
|
+
* for that key on `PATCH /platform/billing/plans/grants`, then
|
|
795
|
+
* `POST /platform/billing/plans/publish`, removes them (the PATCH alone
|
|
796
|
+
* writes only the draft).
|
|
788
797
|
*/
|
|
789
798
|
undeclaredGrantKeys: string[];
|
|
790
799
|
/**
|
|
@@ -1093,10 +1102,24 @@ declare global {
|
|
|
1093
1102
|
reconciledStores?: number;
|
|
1094
1103
|
/**
|
|
1095
1104
|
* A paid tier whose price, currency or name changed, with a currency set on the draft being
|
|
1096
|
-
* published (never `basico`, never when that currency is absent)
|
|
1097
|
-
*
|
|
1105
|
+
* published (never `basico`, never when that currency is absent). A live publish mints the
|
|
1106
|
+
* new Stripe Prices itself when Stripe already bills the tier (see `stripePriceMinted`), and
|
|
1107
|
+
* that mint also converges the Stripe Product's name on the published `name`. The MercadoPago
|
|
1108
|
+
* PreApproval plans, and a Product rename after a `name`-only publish (which mints nothing),
|
|
1109
|
+
* stay the seeders'.
|
|
1098
1110
|
*/
|
|
1099
1111
|
stripeSyncRequired: boolean;
|
|
1112
|
+
/**
|
|
1113
|
+
* Live publish only, and only on a tier whose price or currency moved while Stripe bills it
|
|
1114
|
+
* (its row carries a `stripeProductId`): `true` when the publish minted the new Stripe Prices
|
|
1115
|
+
* and stamped them on the row. `false` means this publish did NOT stamp the row, for one of
|
|
1116
|
+
* two reasons: the mint failed (an operator ERROR row `STRIPE_PLAN_PRICE_MINT_FAILED` is
|
|
1117
|
+
* written, and Stripe checkout refuses the tier with `409 PLAN_STRIPE_PRICE_STALE` until
|
|
1118
|
+
* `seed-stripe-products` re-mints), or a LATER publish moved the price before this mint's
|
|
1119
|
+
* stamp landed — superseded, so no ERROR row: that later publish mints its own. Absent
|
|
1120
|
+
* otherwise.
|
|
1121
|
+
*/
|
|
1122
|
+
stripePriceMinted?: boolean;
|
|
1100
1123
|
}
|
|
1101
1124
|
/** `data` of `POST /platform/billing/plans/publish`. */
|
|
1102
1125
|
interface PlanCataloguePublishResult {
|
|
@@ -1161,6 +1184,20 @@ declare global {
|
|
|
1161
1184
|
* revision moved: send the same request again.
|
|
1162
1185
|
*/
|
|
1163
1186
|
| 'PLAN_CATALOGUE_BUSY' | 'PLAN_CATALOGUE_NO_CHANGES' | 'PLAN_CATALOGUE_PUBLICATION_NOT_FOUND' | 'PLAN_CATALOGUE_REQUEST_EXPIRED' | 'PLAN_CATALOGUE_INVALID_CURSOR' | 'PLAN_CATALOGUE_DRAFT_STALE' | 'IDEMPOTENCY_CONFLICT';
|
|
1187
|
+
/**
|
|
1188
|
+
* The `error` codes `POST /subscription/checkout` adds when a published price
|
|
1189
|
+
* has not reached the provider that would bill it.
|
|
1190
|
+
*/
|
|
1191
|
+
type PlanPriceSyncErrorCode =
|
|
1192
|
+
/**
|
|
1193
|
+
* 409 · the store checks out through Stripe, and the Stripe Price on that
|
|
1194
|
+
* plan cycle was minted at a different amount or currency than the plan
|
|
1195
|
+
* now publishes (its stamp, `stripePrice*Cents` / `stripePriceCurrency`,
|
|
1196
|
+
* differs) — a checkout would bill the old price. Nothing was created; the
|
|
1197
|
+
* operator re-mints (`seed-stripe-products`). Carries `planTier` and
|
|
1198
|
+
* `billingCycle` like `PLAN_NOT_PURCHASABLE`.
|
|
1199
|
+
*/
|
|
1200
|
+
'PLAN_STRIPE_PRICE_STALE';
|
|
1164
1201
|
}
|
|
1165
1202
|
export type BillingProviderName = SubscriptionProvider;
|
|
1166
1203
|
export type InvoiceSummary = globalThis.InvoiceSummary;
|
|
@@ -1176,6 +1213,8 @@ export declare const PAID_PLAN_TIERS: readonly ["emprendedor", "profesional", "a
|
|
|
1176
1213
|
export declare const PLAN_CATALOGUE_TEMPLATE_FIELDS: readonly ["name", "description", "displayOrder", "isActive", "isPopular", "color", "priceMonthlyCents", "priceAnnualCents", "currency"];
|
|
1177
1214
|
/** Every `error` code the plan catalogue draft / publish routes add — the coverage test holds the handlers to it. */
|
|
1178
1215
|
export declare const PLAN_CATALOGUE_ERROR_CODES: readonly ["PLAN_CATALOGUE_REVISION_CONFLICT", "PLAN_CATALOGUE_BUSY", "PLAN_CATALOGUE_NO_CHANGES", "PLAN_CATALOGUE_PUBLICATION_NOT_FOUND", "PLAN_CATALOGUE_REQUEST_EXPIRED", "PLAN_CATALOGUE_INVALID_CURSOR", "PLAN_CATALOGUE_DRAFT_STALE", "IDEMPOTENCY_CONFLICT"];
|
|
1216
|
+
/** Every `error` code `POST /subscription/checkout` adds for a price the provider has not caught up with. */
|
|
1217
|
+
export declare const PLAN_PRICE_SYNC_ERROR_CODES: readonly ["PLAN_STRIPE_PRICE_STALE"];
|
|
1179
1218
|
/** Whether `value` names a paid tier — narrows an untyped read (a stored row, a global) to `PaidPlanTier`. */
|
|
1180
1219
|
export declare const isPaidPlanTier: (value: unknown) => value is PaidPlanTier;
|
|
1181
1220
|
/**
|
package/dist/subscription.js
CHANGED
|
@@ -76,6 +76,10 @@ export const PLAN_CATALOGUE_ERROR_CODES = exhaustiveTuple()([
|
|
|
76
76
|
'PLAN_CATALOGUE_DRAFT_STALE',
|
|
77
77
|
'IDEMPOTENCY_CONFLICT',
|
|
78
78
|
]);
|
|
79
|
+
/** Every `error` code `POST /subscription/checkout` adds for a price the provider has not caught up with. */
|
|
80
|
+
export const PLAN_PRICE_SYNC_ERROR_CODES = exhaustiveTuple()([
|
|
81
|
+
'PLAN_STRIPE_PRICE_STALE',
|
|
82
|
+
]);
|
|
79
83
|
/** Whether `value` names a paid tier — narrows an untyped read (a stored row, a global) to `PaidPlanTier`. */
|
|
80
84
|
export const isPaidPlanTier = (value) => typeof value === 'string' && PAID_PLAN_TIERS.includes(value);
|
|
81
85
|
/**
|