platform-types 1.10.734 → 1.10.736
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/fiscalConditions.js +89 -0
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/store.js +72 -4
- package/dist/cjs/subscription.js +5 -1
- package/dist/fiscalConditions.d.ts +40 -0
- package/dist/fiscalConditions.js +86 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/order.d.ts +24 -4
- 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
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FISCAL_CONDITIONS = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* The ARCA fiscal-condition catalogue — the ONE definition. It maps each legacy
|
|
6
|
+
* `condFiscal` code to its display name, its ARCA `DocTipo` and the `CbteTipo`
|
|
7
|
+
* family that issuance resolves for it.
|
|
8
|
+
*
|
|
9
|
+
* Deliberately NOT `declare global`: it is a runtime value, so import it:
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { FISCAL_CONDITIONS } from 'platform-types';
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* The api re-exports this exact binding from `stacks/services/fiscalCatalogs.ts`,
|
|
16
|
+
* which is where invoice issuance reads it.
|
|
17
|
+
*
|
|
18
|
+
* ⚠️ **`condFiscal` is NOT a unique key.** Code `32` has two rows: «Iva Exento»
|
|
19
|
+
* (`DocTipo 80`, a domestic CUIT holder) and «Cliente del Exterior» (`DocTipo 91`).
|
|
20
|
+
* To NAME a code, prefer its `DocTipo 80` row and fall back to its only row, so
|
|
21
|
+
* `32` reads «Iva Exento» and `99`/`96` read Consumidor Final (spelled
|
|
22
|
+
* differently on the two rows):
|
|
23
|
+
*
|
|
24
|
+
* ```ts
|
|
25
|
+
* const rows = FISCAL_CONDITIONS.filter((c) => c.condFiscal === code);
|
|
26
|
+
* const name = (rows.find((c) => c.DocTipo === 80) ?? rows[0])?.name;
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* `undefined` means a code this catalogue does not hold — issuance refuses such
|
|
30
|
+
* an order rather than guessing, so render it as unknown, never as a default.
|
|
31
|
+
*
|
|
32
|
+
* Provenance: these are AFIP-standardized catalogues, identical for every
|
|
33
|
+
* tenant, so a reviewed and versioned file is their home rather than a DynamoDB
|
|
34
|
+
* row an operator could silently edit. This is a byte-identical snapshot of the
|
|
35
|
+
* retired `STORE#CONFIG` row, cross-checked against both dev and prod, with ONE
|
|
36
|
+
* deliberate divergence: id 5's `CbteTipo.NC`/`ND` are corrected (see that row).
|
|
37
|
+
*
|
|
38
|
+
* `CbteTipo.NVC` is declared by `FiscalCondition` but was never populated on the
|
|
39
|
+
* live row and nothing reads it: the one hardcoded non-Responsable-Inscripto
|
|
40
|
+
* fallback in issuance sets its own literal `NVC: 16`. The `0` here is an inert
|
|
41
|
+
* placeholder that satisfies the type, not a real AFIP code.
|
|
42
|
+
*/
|
|
43
|
+
exports.FISCAL_CONDITIONS = [
|
|
44
|
+
{
|
|
45
|
+
id: 1,
|
|
46
|
+
name: 'Consumidor Final',
|
|
47
|
+
condFiscal: 99,
|
|
48
|
+
DocTipo: 99,
|
|
49
|
+
CbteTipo: { FAC: 6, REC: 9, NC: 8, ND: 7, NVC: 0 },
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: 2,
|
|
53
|
+
name: 'Responsable Inscripto',
|
|
54
|
+
condFiscal: 30,
|
|
55
|
+
DocTipo: 80,
|
|
56
|
+
CbteTipo: { FAC: 1, REC: 4, NC: 3, ND: 2, NVC: 0 },
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
id: 3,
|
|
60
|
+
name: 'Responsable Monotributo',
|
|
61
|
+
condFiscal: 20,
|
|
62
|
+
DocTipo: 80,
|
|
63
|
+
CbteTipo: { FAC: 1, REC: 4, NC: 3, ND: 2, NVC: 0 },
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: 4,
|
|
67
|
+
name: 'Iva Exento',
|
|
68
|
+
condFiscal: 32,
|
|
69
|
+
DocTipo: 80,
|
|
70
|
+
CbteTipo: { FAC: 6, REC: 9, NC: 8, ND: 7, NVC: 0 },
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
id: 5,
|
|
74
|
+
name: 'Cliente del Exterior',
|
|
75
|
+
condFiscal: 32,
|
|
76
|
+
DocTipo: 91,
|
|
77
|
+
// NC/ND corrected from the legacy snapshot, which had them transposed vs
|
|
78
|
+
// RG 5762 (52 = ND, 53 = NC). `.CbteTipo` is unreachable at runtime here:
|
|
79
|
+
// a `condFiscal` 32 lookup resolves to id 4, not id 5.
|
|
80
|
+
CbteTipo: { FAC: 51, REC: 54, NC: 53, ND: 52, NVC: 0 },
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
id: 6,
|
|
84
|
+
name: 'CONSUMIDOR FINAL',
|
|
85
|
+
condFiscal: 96,
|
|
86
|
+
DocTipo: 96,
|
|
87
|
+
CbteTipo: { FAC: 6, REC: 9, NC: 8, ND: 7, NVC: 0 },
|
|
88
|
+
},
|
|
89
|
+
];
|
package/dist/cjs/index.js
CHANGED
|
@@ -52,6 +52,7 @@ __exportStar(require("./customerTimeline.js"), exports);
|
|
|
52
52
|
__exportStar(require("./cycleCount.js"), exports);
|
|
53
53
|
__exportStar(require("./delivery.js"), exports);
|
|
54
54
|
__exportStar(require("./favorite.js"), exports);
|
|
55
|
+
__exportStar(require("./fiscalConditions.js"), exports);
|
|
55
56
|
__exportStar(require("./gating.js"), exports);
|
|
56
57
|
__exportStar(require("./holdingCost.js"), exports);
|
|
57
58
|
__exportStar(require("./demo.js"), exports);
|
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;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ARCA fiscal-condition catalogue — the ONE definition. It maps each legacy
|
|
3
|
+
* `condFiscal` code to its display name, its ARCA `DocTipo` and the `CbteTipo`
|
|
4
|
+
* family that issuance resolves for it.
|
|
5
|
+
*
|
|
6
|
+
* Deliberately NOT `declare global`: it is a runtime value, so import it:
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { FISCAL_CONDITIONS } from 'platform-types';
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* The api re-exports this exact binding from `stacks/services/fiscalCatalogs.ts`,
|
|
13
|
+
* which is where invoice issuance reads it.
|
|
14
|
+
*
|
|
15
|
+
* ⚠️ **`condFiscal` is NOT a unique key.** Code `32` has two rows: «Iva Exento»
|
|
16
|
+
* (`DocTipo 80`, a domestic CUIT holder) and «Cliente del Exterior» (`DocTipo 91`).
|
|
17
|
+
* To NAME a code, prefer its `DocTipo 80` row and fall back to its only row, so
|
|
18
|
+
* `32` reads «Iva Exento» and `99`/`96` read Consumidor Final (spelled
|
|
19
|
+
* differently on the two rows):
|
|
20
|
+
*
|
|
21
|
+
* ```ts
|
|
22
|
+
* const rows = FISCAL_CONDITIONS.filter((c) => c.condFiscal === code);
|
|
23
|
+
* const name = (rows.find((c) => c.DocTipo === 80) ?? rows[0])?.name;
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* `undefined` means a code this catalogue does not hold — issuance refuses such
|
|
27
|
+
* an order rather than guessing, so render it as unknown, never as a default.
|
|
28
|
+
*
|
|
29
|
+
* Provenance: these are AFIP-standardized catalogues, identical for every
|
|
30
|
+
* tenant, so a reviewed and versioned file is their home rather than a DynamoDB
|
|
31
|
+
* row an operator could silently edit. This is a byte-identical snapshot of the
|
|
32
|
+
* retired `STORE#CONFIG` row, cross-checked against both dev and prod, with ONE
|
|
33
|
+
* deliberate divergence: id 5's `CbteTipo.NC`/`ND` are corrected (see that row).
|
|
34
|
+
*
|
|
35
|
+
* `CbteTipo.NVC` is declared by `FiscalCondition` but was never populated on the
|
|
36
|
+
* live row and nothing reads it: the one hardcoded non-Responsable-Inscripto
|
|
37
|
+
* fallback in issuance sets its own literal `NVC: 16`. The `0` here is an inert
|
|
38
|
+
* placeholder that satisfies the type, not a real AFIP code.
|
|
39
|
+
*/
|
|
40
|
+
export declare const FISCAL_CONDITIONS: FiscalCondition[];
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ARCA fiscal-condition catalogue — the ONE definition. It maps each legacy
|
|
3
|
+
* `condFiscal` code to its display name, its ARCA `DocTipo` and the `CbteTipo`
|
|
4
|
+
* family that issuance resolves for it.
|
|
5
|
+
*
|
|
6
|
+
* Deliberately NOT `declare global`: it is a runtime value, so import it:
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { FISCAL_CONDITIONS } from 'platform-types';
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* The api re-exports this exact binding from `stacks/services/fiscalCatalogs.ts`,
|
|
13
|
+
* which is where invoice issuance reads it.
|
|
14
|
+
*
|
|
15
|
+
* ⚠️ **`condFiscal` is NOT a unique key.** Code `32` has two rows: «Iva Exento»
|
|
16
|
+
* (`DocTipo 80`, a domestic CUIT holder) and «Cliente del Exterior» (`DocTipo 91`).
|
|
17
|
+
* To NAME a code, prefer its `DocTipo 80` row and fall back to its only row, so
|
|
18
|
+
* `32` reads «Iva Exento» and `99`/`96` read Consumidor Final (spelled
|
|
19
|
+
* differently on the two rows):
|
|
20
|
+
*
|
|
21
|
+
* ```ts
|
|
22
|
+
* const rows = FISCAL_CONDITIONS.filter((c) => c.condFiscal === code);
|
|
23
|
+
* const name = (rows.find((c) => c.DocTipo === 80) ?? rows[0])?.name;
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* `undefined` means a code this catalogue does not hold — issuance refuses such
|
|
27
|
+
* an order rather than guessing, so render it as unknown, never as a default.
|
|
28
|
+
*
|
|
29
|
+
* Provenance: these are AFIP-standardized catalogues, identical for every
|
|
30
|
+
* tenant, so a reviewed and versioned file is their home rather than a DynamoDB
|
|
31
|
+
* row an operator could silently edit. This is a byte-identical snapshot of the
|
|
32
|
+
* retired `STORE#CONFIG` row, cross-checked against both dev and prod, with ONE
|
|
33
|
+
* deliberate divergence: id 5's `CbteTipo.NC`/`ND` are corrected (see that row).
|
|
34
|
+
*
|
|
35
|
+
* `CbteTipo.NVC` is declared by `FiscalCondition` but was never populated on the
|
|
36
|
+
* live row and nothing reads it: the one hardcoded non-Responsable-Inscripto
|
|
37
|
+
* fallback in issuance sets its own literal `NVC: 16`. The `0` here is an inert
|
|
38
|
+
* placeholder that satisfies the type, not a real AFIP code.
|
|
39
|
+
*/
|
|
40
|
+
export const FISCAL_CONDITIONS = [
|
|
41
|
+
{
|
|
42
|
+
id: 1,
|
|
43
|
+
name: 'Consumidor Final',
|
|
44
|
+
condFiscal: 99,
|
|
45
|
+
DocTipo: 99,
|
|
46
|
+
CbteTipo: { FAC: 6, REC: 9, NC: 8, ND: 7, NVC: 0 },
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: 2,
|
|
50
|
+
name: 'Responsable Inscripto',
|
|
51
|
+
condFiscal: 30,
|
|
52
|
+
DocTipo: 80,
|
|
53
|
+
CbteTipo: { FAC: 1, REC: 4, NC: 3, ND: 2, NVC: 0 },
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
id: 3,
|
|
57
|
+
name: 'Responsable Monotributo',
|
|
58
|
+
condFiscal: 20,
|
|
59
|
+
DocTipo: 80,
|
|
60
|
+
CbteTipo: { FAC: 1, REC: 4, NC: 3, ND: 2, NVC: 0 },
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
id: 4,
|
|
64
|
+
name: 'Iva Exento',
|
|
65
|
+
condFiscal: 32,
|
|
66
|
+
DocTipo: 80,
|
|
67
|
+
CbteTipo: { FAC: 6, REC: 9, NC: 8, ND: 7, NVC: 0 },
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
id: 5,
|
|
71
|
+
name: 'Cliente del Exterior',
|
|
72
|
+
condFiscal: 32,
|
|
73
|
+
DocTipo: 91,
|
|
74
|
+
// NC/ND corrected from the legacy snapshot, which had them transposed vs
|
|
75
|
+
// RG 5762 (52 = ND, 53 = NC). `.CbteTipo` is unreachable at runtime here:
|
|
76
|
+
// a `condFiscal` 32 lookup resolves to id 4, not id 5.
|
|
77
|
+
CbteTipo: { FAC: 51, REC: 54, NC: 53, ND: 52, NVC: 0 },
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
id: 6,
|
|
81
|
+
name: 'CONSUMIDOR FINAL',
|
|
82
|
+
condFiscal: 96,
|
|
83
|
+
DocTipo: 96,
|
|
84
|
+
CbteTipo: { FAC: 6, REC: 9, NC: 8, ND: 7, NVC: 0 },
|
|
85
|
+
},
|
|
86
|
+
];
|
package/dist/index.d.ts
CHANGED
|
@@ -28,6 +28,7 @@ export * from './customerTimeline.ts';
|
|
|
28
28
|
export * from './cycleCount.ts';
|
|
29
29
|
export * from './delivery.ts';
|
|
30
30
|
export * from './favorite.ts';
|
|
31
|
+
export * from './fiscalConditions.ts';
|
|
31
32
|
export * from './gating.ts';
|
|
32
33
|
export * from './holdingCost.ts';
|
|
33
34
|
export * from './demo.ts';
|
package/dist/index.js
CHANGED
|
@@ -36,6 +36,7 @@ export * from "./customerTimeline.js";
|
|
|
36
36
|
export * from "./cycleCount.js";
|
|
37
37
|
export * from "./delivery.js";
|
|
38
38
|
export * from "./favorite.js";
|
|
39
|
+
export * from "./fiscalConditions.js";
|
|
39
40
|
export * from "./gating.js";
|
|
40
41
|
export * from "./holdingCost.js";
|
|
41
42
|
export * from "./demo.js";
|
package/dist/order.d.ts
CHANGED
|
@@ -953,11 +953,31 @@ declare global {
|
|
|
953
953
|
* its own — method ids are per-catalog ordinals.
|
|
954
954
|
*/
|
|
955
955
|
deliveryMethod?: number;
|
|
956
|
+
/**
|
|
957
|
+
* The receptor the order is invoiced to, as the creating client stated it.
|
|
958
|
+
*
|
|
959
|
+
* ⚠️ **Every key is optional, and readers must tolerate each one absent.**
|
|
960
|
+
* That is what the writers persist, not a loosening: the storefront checkout
|
|
961
|
+
* validates this object with every key optional and writes it verbatim (an
|
|
962
|
+
* empty object included), the presupuesto conversion passes the operator's
|
|
963
|
+
* object through, and only the operator create requires `condFiscal`.
|
|
964
|
+
*
|
|
965
|
+
* - `razonSocial` is routinely absent: a Consumidor Final receptor has no
|
|
966
|
+
* legal name, and none may be invented for one.
|
|
967
|
+
* - `condFiscalName` is display-only and usually absent. Never read it for
|
|
968
|
+
* meaning: derive the name from `condFiscal` with the published
|
|
969
|
+
* `FISCAL_CONDITIONS` catalogue (its docblock gives the lookup, since
|
|
970
|
+
* `condFiscal` alone is not a unique key there).
|
|
971
|
+
* - `condFiscal` and `cuit` absent are a PERSISTABLE state, not an
|
|
972
|
+
* invoiceable one: issuing a factura refuses the order with a coded `400`
|
|
973
|
+
* (`INVOICE_METHOD_COND_FISCAL_INVALID`, `INVOICE_METHOD_CUIT_MISSING`)
|
|
974
|
+
* until the operator completes it.
|
|
975
|
+
*/
|
|
956
976
|
invoiceMethod?: {
|
|
957
|
-
condFiscal
|
|
958
|
-
condFiscalName
|
|
959
|
-
cuit
|
|
960
|
-
razonSocial
|
|
977
|
+
condFiscal?: number;
|
|
978
|
+
condFiscalName?: string;
|
|
979
|
+
cuit?: string;
|
|
980
|
+
razonSocial?: string;
|
|
961
981
|
/**
|
|
962
982
|
* Explicit per-order ARCA receptor identity, decoupled from condFiscal
|
|
963
983
|
* (ARCA DocTipo: 80 = CUIT, 96 = DNI, 99 = Consumidor Final — a
|
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
|
/**
|