platform-types 1.10.802 → 1.10.804

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/account.d.ts CHANGED
@@ -183,6 +183,11 @@ declare global {
183
183
  */
184
184
  paymentRefSource?: PaymentReceivedSource;
185
185
  paymentRefId?: string;
186
+ /**
187
+ * On a refund obligation's in-transit debit (SK `RIT#{obligationId}`, `paymentRef*` naming the linked
188
+ * payment): the obligation whose refund the debit books. Absent on every other row.
189
+ */
190
+ refundObligationId?: string;
186
191
  }
187
192
  /**
188
193
  * `POST /account` — a new customer-ledger movement. Mirrors the request side of
package/dist/audit.d.ts CHANGED
@@ -164,6 +164,19 @@ declare global {
164
164
  * words stay on the attempt row.
165
165
  */
166
166
  | 'payment_attempt_resolved'
167
+ /**
168
+ * An operator closed one of the order's refund obligations (`POST /refund-obligations { mode: 'close' }`).
169
+ * `before`: `obligationId`, `state`, `holdReason?`. `after`: `obligationId`, `state` (`'closed'`), `by`
170
+ * (`'operator'`), `payout` (`'drawer'` | `'none'`) and the operator's reason as `'[present]'` |
171
+ * `'[absent]'` — presence only, the words stay on the obligation's `closure`.
172
+ */
173
+ | 'refund_obligation_closed'
174
+ /**
175
+ * An operator reopened one of the order's refund obligations held behind a `reimbursed` chargeback
176
+ * (`POST /refund-obligations { mode: 'reopen' }`). `before`: `obligationId`, `state` (`'held'`),
177
+ * `holdReason`. `after`: `obligationId`, `state`, `refundDueAt?` and the reason by presence only.
178
+ */
179
+ | 'refund_obligation_reopened'
167
180
  /** HISTORICAL: written only by the removed outbound MercadoPago refund; kept so old timeline rows still parse. */
168
181
  | 'payment_refunded'
169
182
  /** At least one till tender leg was appended (an absorbed replay writes none). */
@@ -8,15 +8,16 @@
8
8
  * order) and closes on its own when Mercado Pago reports the refund, when an
9
9
  * operator closes a payment attempt's resolution as `refunded`, or when a
10
10
  * chargeback settled the money back. An open dispute holds it; a lifted dispute
11
- * reopens it. Nothing here moves money or writes a ledger row: closure records a
12
- * fact.
11
+ * reopens it. Closure moves no money and writes no ledger row: it records a fact.
12
+ * The one ledger write is the creator's in-transit debit of a linked payment's
13
+ * credit ({@link RefundObligationLedgerCredit}), at creation.
13
14
  *
14
15
  * ⚠️ The stored row carries none of the main table's index-key attributes
15
16
  * (`status`, `customerId`, `dated`, `updatedAt`, `terminalId`, `inboxKey`), so it
16
17
  * joins no GSI: `state` replaces `status`, `revisedAt` replaces `updatedAt`.
17
18
  */
18
19
  Object.defineProperty(exports, "__esModule", { value: true });
19
- exports.REFUND_OBLIGATION_DUE_SOURCE = exports.REFUND_OBLIGATION_CLOSED_BY = exports.REFUND_OBLIGATION_HOLD_REASONS = exports.REFUND_OBLIGATION_STATES = exports.REFUND_OBLIGATION_KINDS = void 0;
20
+ exports.REFUND_OBLIGATION_PAYOUTS = exports.REFUND_OBLIGATION_ACTION_MODES = exports.REFUND_OBLIGATION_LIST_FILTERS = exports.REFUND_OBLIGATION_REASON_MAX = exports.REFUND_OBLIGATION_DUE_SOURCE = exports.REFUND_OBLIGATION_CLOSED_BY = exports.REFUND_OBLIGATION_HOLD_REASONS = exports.REFUND_OBLIGATION_STATES = exports.REFUND_OBLIGATION_KINDS = void 0;
20
21
  /**
21
22
  * - `provider` — paid through Mercado Pago; closes when the provider reports the
22
23
  * refund (`paymentId` is set).
@@ -40,7 +41,8 @@ exports.REFUND_OBLIGATION_STATES = ['awaiting-goods', 'open', 'overdue', 'held',
40
41
  * Why an obligation is `held`. `dispute-open` reopens on its own once the
41
42
  * dispute is lifted; `reimbursed` (Mercado Pago covered the seller) never does —
42
43
  * only an operator's decision moves it. A stored row with no `holdReason` reads
43
- * as `dispute-open`.
44
+ * as `dispute-open`. Once the operator reopened a `reimbursed` hold
45
+ * (`reimbursedDecision`), that chargeback no longer holds the obligation.
44
46
  */
45
47
  exports.REFUND_OBLIGATION_HOLD_REASONS = ['dispute-open', 'reimbursed'];
46
48
  /**
@@ -63,3 +65,14 @@ exports.REFUND_OBLIGATION_CLOSED_BY = [
63
65
  ];
64
66
  /** Where a {@link StatutoryInstant} came from: the platform global it was computed with. */
65
67
  exports.REFUND_OBLIGATION_DUE_SOURCE = 'global:refundObligationDueDays';
68
+ /** The longest operator `reason` `POST /refund-obligations` accepts, in characters after trimming. */
69
+ exports.REFUND_OBLIGATION_REASON_MAX = 500;
70
+ /**
71
+ * The `state` filter of `GET /refund-obligations`: one {@link RefundObligationState}, or `pending` — every
72
+ * state but `closed`, the operator's working queue.
73
+ */
74
+ exports.REFUND_OBLIGATION_LIST_FILTERS = [...exports.REFUND_OBLIGATION_STATES, 'pending'];
75
+ /** The modes of `POST /refund-obligations`. */
76
+ exports.REFUND_OBLIGATION_ACTION_MODES = ['close', 'reopen'];
77
+ /** The one payout `POST /refund-obligations { mode: 'close' }` can record: cash from the operator's till. */
78
+ exports.REFUND_OBLIGATION_PAYOUTS = ['drawer'];
@@ -734,6 +734,10 @@ exports.isSocketAction = isSocketAction;
734
734
  * {@link ProductRemovedFrameData} marker instead of a priced patch.
735
735
  * `catalogStatus` is carried for the same reason: a stock movement on a draft or
736
736
  * archived product becomes that marker too, never a republished row.
737
+ *
738
+ * `ivaType` is an INPUT to the shopper copy's `prices[].netOfIva`: the customer
739
+ * fan-out re-prices the frame, and without the rate a merged frame would leave a
740
+ * stale net beside a new gross. The customer copy still drops the Id itself.
737
741
  */
738
742
  exports.PRODUCT_STOCK_FRAME_FIELDS = [
739
743
  'stock',
@@ -745,6 +749,7 @@ exports.PRODUCT_STOCK_FRAME_FIELDS = [
745
749
  'catalogStatus',
746
750
  'updatedAt',
747
751
  'lastMovementAt',
752
+ 'ivaType',
748
753
  ];
749
754
  /* Agent diagnostic commands */
750
755
  /**
@@ -114,12 +114,15 @@ const LIVE_METADATA = {
114
114
  ownership: 'storefront-operation',
115
115
  excludedFromSnapshot: true,
116
116
  };
117
- const liveToggle = (key, labelKey, helpKey, label, help) => ({
117
+ const liveToggle = (key, labelKey, helpKey, label, help,
118
+ // Per key: a toggle that changes what a shopper sees for every store that has
119
+ // never written it ships `false`. Defaults to `true`, the three original toggles.
120
+ defaultValue = true) => ({
118
121
  ...LIVE_METADATA,
119
122
  key,
120
123
  allowedLayers: ['WEB#store'],
121
124
  storage: { source: 'store', override: 'ecommerce.config' },
122
- defaultValue: true,
125
+ defaultValue,
123
126
  valueType: 'boolean',
124
127
  valueSchema: { type: 'boolean' },
125
128
  literal: { kind: 'key', label: labelKey, help: helpKey, defaults: { label, help } },
@@ -145,6 +148,13 @@ exports.STOREFRONT_DESIGN_REGISTRY = {
145
148
  showIvaAlert: liveToggle('showIvaAlert', 'STOREFRONT_SHOW_IVA_ALERT_LABEL', 'STOREFRONT_SHOW_IVA_ALERT_HELP', 'Mostrar aviso de IVA', 'Mostrar el aviso de IVA incluido en los precios.'),
146
149
  showCurrencySelector: liveToggle('showCurrencySelector', 'STOREFRONT_SHOW_CURRENCY_SELECTOR_LABEL', 'STOREFRONT_SHOW_CURRENCY_SELECTOR_HELP', 'Mostrar selector de moneda', 'Permitir elegir la moneda de visualización en la tienda.'),
147
150
  enableSaveForLater: liveToggle('enableSaveForLater', 'STOREFRONT_ENABLE_SAVE_FOR_LATER_LABEL', 'STOREFRONT_ENABLE_SAVE_FOR_LATER_HELP', 'Permitir guardar para después', 'Mostrar los controles para guardar productos de la cesta para después.'),
151
+ /*
152
+ * Display only: every public price slot carries `netOfIva` whatever this says
153
+ * (absent only for a product with no declarable IVA rate), so a flip needs no
154
+ * catalogue refetch. The storefront shows the «+ IVA» line when this is on AND
155
+ * the block is present. Default off: a store opts in.
156
+ */
157
+ showNetPlusIva: liveToggle('showNetPlusIva', 'STOREFRONT_SHOW_NET_PLUS_IVA_LABEL', 'STOREFRONT_SHOW_NET_PLUS_IVA_HELP', 'Mostrar precio neto + IVA', 'Mostrar también el precio sin IVA, con la leyenda «+ IVA», junto al precio final. Nunca reemplaza al precio final.', false),
148
158
  prices: { ...LIVE_METADATA, storage: { source: 'catalogue' } },
149
159
  stock: { ...LIVE_METADATA, storage: { source: 'catalogue' } },
150
160
  checkout: { ...LIVE_METADATA, storage: { source: 'store' } },
package/dist/pricing.d.ts CHANGED
@@ -109,5 +109,43 @@ declare global {
109
109
  promo?: PricePromo;
110
110
  visibleOnStorefront?: boolean;
111
111
  } & CurrencyStamp);
112
+ /**
113
+ * Net-of-IVA display figures for one public price slot, computed server-side
114
+ * as `calculateItemNeto(figure, 1, ivaPercent, 1, 'decimal').neto` from the
115
+ * product's `ivaType`, each figure first rounded to the store's `priceDecimals`
116
+ * as it is charged — for a unit in the voucher's currency, the per-unit `neto`
117
+ * a new invoice prints for the same undiscounted unit (gross rounded to 2 dp
118
+ * first, then backed out). Absent, too, when a figure cannot be netted.
119
+ *
120
+ * ⚠️ DISPLAY ONLY: nothing charges, quotes, totals or invoices these. The
121
+ * charged figure is the slot's `amount`, always.
122
+ *
123
+ * Each net shares the stamp of the gross it nets, with no FX step: `amount`
124
+ * and `baseAmount` the slot's, `promo` the promo's, each break its own.
125
+ *
126
+ * Sent whatever `ecommerce.config.showNetPlusIva` says; that setting only
127
+ * decides whether the storefront renders it. ABSENT when the product carries
128
+ * no declarable IVA rate — never a 0 % fallback.
129
+ */
130
+ interface PublicPriceNet {
131
+ amount: number;
132
+ /** Present iff the slot carries `baseAmount`. */
133
+ baseAmount?: number;
134
+ /** Net of `promo.amount`; present iff the slot carries `promo`. */
135
+ promo?: number;
136
+ /** One per `breaks` entry of the slot, same `minQty`, same order. */
137
+ breaks?: Array<{
138
+ minQty: number;
139
+ amount: number;
140
+ }>;
141
+ }
142
+ /**
143
+ * A price slot as a PUBLIC read emits it (web catalogue reads, customer
144
+ * `products` frames). A read-time extension of {@link PriceSlot}, never
145
+ * stored: `Product.prices` stays `PriceSlot[]`, so no writer can persist a net.
146
+ */
147
+ type PublicPriceSlot = PriceSlot & {
148
+ netOfIva?: PublicPriceNet;
149
+ };
112
150
  }
113
151
  export {};
package/dist/product.d.ts CHANGED
@@ -32,8 +32,10 @@ declare global {
32
32
  type ProductUnitsInput = Omit<ProductUnits, 'unitRevision'>;
33
33
  /** The display declaration plus the purchase-unit factor; `unitRevision` stays server-only. */
34
34
  type PublicProductUnits = Pick<ProductUnits, 'baseUnit' | 'purchaseUnit' | 'packLabel' | 'baseUnitsPerPurchaseUnit'>;
35
- type PublicProduct = Omit<Partial<Product>, 'units' | 'unitRevisionGeneration'> & {
35
+ type PublicProduct = Omit<Partial<Product>, 'units' | 'unitRevisionGeneration' | 'prices'> & {
36
36
  units?: PublicProductUnits | null;
37
+ /** The shopper's one applicable slot, with its read-time `netOfIva` when the product is rated. */
38
+ prices?: PublicPriceSlot[];
37
39
  };
38
40
  /** Anonymous Web GET /products lookup; the tenant comes from the public store context. */
39
41
  interface PublicProductsByIdsInput {
@@ -7,8 +7,9 @@
7
7
  * order) and closes on its own when Mercado Pago reports the refund, when an
8
8
  * operator closes a payment attempt's resolution as `refunded`, or when a
9
9
  * chargeback settled the money back. An open dispute holds it; a lifted dispute
10
- * reopens it. Nothing here moves money or writes a ledger row: closure records a
11
- * fact.
10
+ * reopens it. Closure moves no money and writes no ledger row: it records a fact.
11
+ * The one ledger write is the creator's in-transit debit of a linked payment's
12
+ * credit ({@link RefundObligationLedgerCredit}), at creation.
12
13
  *
13
14
  * ⚠️ The stored row carries none of the main table's index-key attributes
14
15
  * (`status`, `customerId`, `dated`, `updatedAt`, `terminalId`, `inboxKey`), so it
@@ -37,7 +38,8 @@ export declare const REFUND_OBLIGATION_STATES: readonly ["awaiting-goods", "open
37
38
  * Why an obligation is `held`. `dispute-open` reopens on its own once the
38
39
  * dispute is lifted; `reimbursed` (Mercado Pago covered the seller) never does —
39
40
  * only an operator's decision moves it. A stored row with no `holdReason` reads
40
- * as `dispute-open`.
41
+ * as `dispute-open`. Once the operator reopened a `reimbursed` hold
42
+ * (`reimbursedDecision`), that chargeback no longer holds the obligation.
41
43
  */
42
44
  export declare const REFUND_OBLIGATION_HOLD_REASONS: readonly ["dispute-open", "reimbursed"];
43
45
  /**
@@ -54,6 +56,17 @@ export declare const REFUND_OBLIGATION_HOLD_REASONS: readonly ["dispute-open", "
54
56
  export declare const REFUND_OBLIGATION_CLOSED_BY: readonly ["detected-refund", "resolution-refunded", "operator", "chargeback", "api-refund"];
55
57
  /** Where a {@link StatutoryInstant} came from: the platform global it was computed with. */
56
58
  export declare const REFUND_OBLIGATION_DUE_SOURCE = "global:refundObligationDueDays";
59
+ /** The longest operator `reason` `POST /refund-obligations` accepts, in characters after trimming. */
60
+ export declare const REFUND_OBLIGATION_REASON_MAX = 500;
61
+ /**
62
+ * The `state` filter of `GET /refund-obligations`: one {@link RefundObligationState}, or `pending` — every
63
+ * state but `closed`, the operator's working queue.
64
+ */
65
+ export declare const REFUND_OBLIGATION_LIST_FILTERS: readonly ["awaiting-goods", "open", "overdue", "held", "closed", "pending"];
66
+ /** The modes of `POST /refund-obligations`. */
67
+ export declare const REFUND_OBLIGATION_ACTION_MODES: readonly ["close", "reopen"];
68
+ /** The one payout `POST /refund-obligations { mode: 'close' }` can record: cash from the operator's till. */
69
+ export declare const REFUND_OBLIGATION_PAYOUTS: readonly ["drawer"];
57
70
  declare global {
58
71
  type RefundObligationKind = (typeof REFUND_OBLIGATION_KINDS)[number];
59
72
  type RefundObligationState = (typeof REFUND_OBLIGATION_STATES)[number];
@@ -66,12 +79,32 @@ declare global {
66
79
  /** The rule it was computed from, e.g. `global:refundObligationDueDays`. */
67
80
  source: string;
68
81
  }
69
- /** The link credit an obligation's money was booked to, when there is one. */
82
+ /**
83
+ * The payment-link credit an obligation's money was booked to, when there is one: the customer's ledger
84
+ * still holds it as a credit, so the creator debits the share being refunded ("in transit") in its own
85
+ * transaction, one `ACCOUNT#` row per obligation.
86
+ */
70
87
  interface RefundObligationLedgerCredit {
71
- /** The `ACCOUNT#{storeId}` row's SK. */
88
+ /** The `ACCOUNT#{storeId}` credit row's SK — the per-source payment row's `accountId`. */
72
89
  accountId: string;
73
90
  /** The customer whose balance the credit moved. */
74
91
  customerId: string;
92
+ /** The partition of the payment the credit came from. */
93
+ source: PaymentReceivedSource;
94
+ /** The payment the credit came from: the per-source row's SK. */
95
+ paymentId: string;
96
+ }
97
+ /**
98
+ * The operator's decision that a `reimbursed` chargeback does not discharge the obligation (`POST
99
+ * /refund-obligations { mode: 'reopen' }`). While it stands, the payment's `reimbursed` chargeback no
100
+ * longer holds the obligation; a later hold (a new dispute) removes it.
101
+ */
102
+ interface RefundObligationReimbursedDecision {
103
+ by: 'operator';
104
+ /** Unix ms. */
105
+ at: number;
106
+ /** The store user who decided. */
107
+ actor?: string;
75
108
  }
76
109
  /** How an obligation was closed. */
77
110
  interface RefundObligationClosure {
@@ -111,6 +144,8 @@ declare global {
111
144
  holdReason?: RefundObligationHoldReason;
112
145
  /** The state a hold came from; a reopen returns to it (`overdue` returns to `open`). */
113
146
  heldFrom?: Exclude<RefundObligationState, 'held' | 'closed'>;
147
+ /** Set by the operator's reopen of a `reimbursed` hold; removed by any later hold. */
148
+ reimbursedDecision?: RefundObligationReimbursedDecision;
114
149
  /** Bumped by every move, for a compare-and-set. */
115
150
  revision: number;
116
151
  /** When the refund is due. Set by the move to `open`; removed by a hold. */
@@ -123,5 +158,75 @@ declare global {
123
158
  /** Unix ms of the last move. */
124
159
  revisedAt: number;
125
160
  }
161
+ type RefundObligationListFilter = (typeof REFUND_OBLIGATION_LIST_FILTERS)[number];
162
+ /**
163
+ * The query of `GET /refund-obligations` (App host, `staffToken`, the `payments` capability). Reads the
164
+ * token's store only, in obligation-id order (`orderId` first).
165
+ */
166
+ interface RefundObligationListQuery {
167
+ state?: RefundObligationListFilter;
168
+ /** Only this order's obligations (`ORD` plus 6–10 digits). */
169
+ orderId?: string;
170
+ /** Rows EVALUATED per page, 1–100 (default 25): a page can be short or empty with `nextCursor` present. */
171
+ limit?: number;
172
+ /** The previous page's `nextCursor`, bound to the store and to `state` + `orderId`. */
173
+ cursor?: string;
174
+ }
175
+ /**
176
+ * `data` of `GET /refund-obligations`. Page on `nextCursor`'s presence, never on the page's length. A
177
+ * `held` row always carries `holdReason` (a stored row with none reads as `dispute-open`): an open dispute
178
+ * offers no action; a `reimbursed` one awaits the operator's close or reopen.
179
+ */
180
+ interface RefundObligationListResponse {
181
+ obligations: RefundObligation[];
182
+ /** Opaque. Absent on the last page. */
183
+ nextCursor?: string;
184
+ }
185
+ /**
186
+ * `POST /refund-obligations` (App host, `adminToken`, the `payments` capability). Strict body.
187
+ *
188
+ * - `close` — the operator settled it: `closure.by: 'operator'`. From `open`, `overdue`, `awaiting-goods`
189
+ * or a `reimbursed` hold; never from a `dispute-open` hold. `reason` is required for an `offline` one
190
+ * and stored on `closure`. `payout: 'drawer'` (an `offline` one only) records the cash leaving the
191
+ * operator's till as one drawer `refund` event in the same transaction.
192
+ * - `reopen` — a `reimbursed` hold the operator decides is still owed: back to the state it was held
193
+ * from, with a fresh `refundDueAt` when that is `open`, and `reimbursedDecision` recorded so the same
194
+ * `reimbursed` chargeback never holds it again.
195
+ *
196
+ * `expectedRevision` is the `revision` of the row the operator acted on.
197
+ */
198
+ type RefundObligationActionRequest = {
199
+ mode: 'close';
200
+ /** The obligation's `obligationId`: `{orderId}#{parentId}#{kind}#{paymentId | 'till'}`, else 400. */
201
+ obligationId: string;
202
+ expectedRevision: number;
203
+ /** 1–{@link REFUND_OBLIGATION_REASON_MAX} characters after trimming. Required for `offline`. */
204
+ reason?: string;
205
+ payout?: (typeof REFUND_OBLIGATION_PAYOUTS)[number];
206
+ } | {
207
+ mode: 'reopen';
208
+ /** The obligation's `obligationId`: `{orderId}#{parentId}#{kind}#{paymentId | 'till'}`, else 400. */
209
+ obligationId: string;
210
+ expectedRevision: number;
211
+ /** 1–{@link REFUND_OBLIGATION_REASON_MAX} characters after trimming. Recorded by presence only. */
212
+ reason?: string;
213
+ };
214
+ /** `data` of a successful `POST /refund-obligations`: the obligation as it now stands. */
215
+ interface RefundObligationActionResponse {
216
+ obligation: RefundObligation;
217
+ }
218
+ /** `data` of `409 REFUND_OBLIGATION_CHANGED`: the obligation as it now stands — review it and resend. */
219
+ interface RefundObligationChangedData {
220
+ obligation: RefundObligation;
221
+ }
222
+ /**
223
+ * `data` of `409 REFUND_OBLIGATION_NOT_ACTIONABLE`: the state that refuses the mode — `closed` (with its
224
+ * `closure`, so a replay after success reads what it did), or `held` with its `holdReason`.
225
+ */
226
+ interface RefundObligationNotActionableData {
227
+ state: RefundObligationState;
228
+ holdReason?: RefundObligationHoldReason;
229
+ closure?: RefundObligationClosure;
230
+ }
126
231
  }
127
232
  export {};
@@ -7,8 +7,9 @@
7
7
  * order) and closes on its own when Mercado Pago reports the refund, when an
8
8
  * operator closes a payment attempt's resolution as `refunded`, or when a
9
9
  * chargeback settled the money back. An open dispute holds it; a lifted dispute
10
- * reopens it. Nothing here moves money or writes a ledger row: closure records a
11
- * fact.
10
+ * reopens it. Closure moves no money and writes no ledger row: it records a fact.
11
+ * The one ledger write is the creator's in-transit debit of a linked payment's
12
+ * credit ({@link RefundObligationLedgerCredit}), at creation.
12
13
  *
13
14
  * ⚠️ The stored row carries none of the main table's index-key attributes
14
15
  * (`status`, `customerId`, `dated`, `updatedAt`, `terminalId`, `inboxKey`), so it
@@ -37,7 +38,8 @@ export const REFUND_OBLIGATION_STATES = ['awaiting-goods', 'open', 'overdue', 'h
37
38
  * Why an obligation is `held`. `dispute-open` reopens on its own once the
38
39
  * dispute is lifted; `reimbursed` (Mercado Pago covered the seller) never does —
39
40
  * only an operator's decision moves it. A stored row with no `holdReason` reads
40
- * as `dispute-open`.
41
+ * as `dispute-open`. Once the operator reopened a `reimbursed` hold
42
+ * (`reimbursedDecision`), that chargeback no longer holds the obligation.
41
43
  */
42
44
  export const REFUND_OBLIGATION_HOLD_REASONS = ['dispute-open', 'reimbursed'];
43
45
  /**
@@ -60,3 +62,14 @@ export const REFUND_OBLIGATION_CLOSED_BY = [
60
62
  ];
61
63
  /** Where a {@link StatutoryInstant} came from: the platform global it was computed with. */
62
64
  export const REFUND_OBLIGATION_DUE_SOURCE = 'global:refundObligationDueDays';
65
+ /** The longest operator `reason` `POST /refund-obligations` accepts, in characters after trimming. */
66
+ export const REFUND_OBLIGATION_REASON_MAX = 500;
67
+ /**
68
+ * The `state` filter of `GET /refund-obligations`: one {@link RefundObligationState}, or `pending` — every
69
+ * state but `closed`, the operator's working queue.
70
+ */
71
+ export const REFUND_OBLIGATION_LIST_FILTERS = [...REFUND_OBLIGATION_STATES, 'pending'];
72
+ /** The modes of `POST /refund-obligations`. */
73
+ export const REFUND_OBLIGATION_ACTION_MODES = ['close', 'reopen'];
74
+ /** The one payout `POST /refund-obligations { mode: 'close' }` can record: cash from the operator's till. */
75
+ export const REFUND_OBLIGATION_PAYOUTS = ['drawer'];
package/dist/socket.d.ts CHANGED
@@ -172,8 +172,12 @@ export interface SocketMessage<T = unknown> {
172
172
  * {@link ProductRemovedFrameData} marker instead of a priced patch.
173
173
  * `catalogStatus` is carried for the same reason: a stock movement on a draft or
174
174
  * archived product becomes that marker too, never a republished row.
175
+ *
176
+ * `ivaType` is an INPUT to the shopper copy's `prices[].netOfIva`: the customer
177
+ * fan-out re-prices the frame, and without the rate a merged frame would leave a
178
+ * stale net beside a new gross. The customer copy still drops the Id itself.
175
179
  */
176
- export declare const PRODUCT_STOCK_FRAME_FIELDS: readonly ["stock", "prices", "cost", "currency", "hiddenFromStorefront", "disabled", "catalogStatus", "updatedAt", "lastMovementAt"];
180
+ export declare const PRODUCT_STOCK_FRAME_FIELDS: readonly ["stock", "prices", "cost", "currency", "hiddenFromStorefront", "disabled", "catalogStatus", "updatedAt", "lastMovementAt", "ivaType"];
177
181
  /**
178
182
  * `data` of a **partial** `products` frame — the projection every stock-moving
179
183
  * write announces, and the only `products` shape that is not a whole `Product`.
package/dist/socket.js CHANGED
@@ -730,6 +730,10 @@ export const isSocketAction = (value) => typeof value === 'string' && SOCKET_ACT
730
730
  * {@link ProductRemovedFrameData} marker instead of a priced patch.
731
731
  * `catalogStatus` is carried for the same reason: a stock movement on a draft or
732
732
  * archived product becomes that marker too, never a republished row.
733
+ *
734
+ * `ivaType` is an INPUT to the shopper copy's `prices[].netOfIva`: the customer
735
+ * fan-out re-prices the frame, and without the rate a merged frame would leave a
736
+ * stale net beside a new gross. The customer copy still drops the Id itself.
733
737
  */
734
738
  export const PRODUCT_STOCK_FRAME_FIELDS = [
735
739
  'stock',
@@ -741,6 +745,7 @@ export const PRODUCT_STOCK_FRAME_FIELDS = [
741
745
  'catalogStatus',
742
746
  'updatedAt',
743
747
  'lastMovementAt',
748
+ 'ivaType',
744
749
  ];
745
750
  /* Agent diagnostic commands */
746
751
  /**
@@ -1035,7 +1035,7 @@ export declare const STOREFRONT_DESIGN_REGISTRY: {
1035
1035
  readonly source: "store";
1036
1036
  readonly override: "ecommerce.config";
1037
1037
  };
1038
- readonly defaultValue: true;
1038
+ readonly defaultValue: boolean;
1039
1039
  readonly valueType: "boolean";
1040
1040
  readonly valueSchema: {
1041
1041
  readonly type: "boolean";
@@ -1061,7 +1061,7 @@ export declare const STOREFRONT_DESIGN_REGISTRY: {
1061
1061
  readonly source: "store";
1062
1062
  readonly override: "ecommerce.config";
1063
1063
  };
1064
- readonly defaultValue: true;
1064
+ readonly defaultValue: boolean;
1065
1065
  readonly valueType: "boolean";
1066
1066
  readonly valueSchema: {
1067
1067
  readonly type: "boolean";
@@ -1087,7 +1087,7 @@ export declare const STOREFRONT_DESIGN_REGISTRY: {
1087
1087
  readonly source: "store";
1088
1088
  readonly override: "ecommerce.config";
1089
1089
  };
1090
- readonly defaultValue: true;
1090
+ readonly defaultValue: boolean;
1091
1091
  readonly valueType: "boolean";
1092
1092
  readonly valueSchema: {
1093
1093
  readonly type: "boolean";
@@ -1106,6 +1106,32 @@ export declare const STOREFRONT_DESIGN_REGISTRY: {
1106
1106
  readonly ownership: "storefront-operation";
1107
1107
  readonly excludedFromSnapshot: true;
1108
1108
  };
1109
+ readonly showNetPlusIva: {
1110
+ readonly key: "showNetPlusIva";
1111
+ readonly allowedLayers: readonly ["WEB#store"];
1112
+ readonly storage: {
1113
+ readonly source: "store";
1114
+ readonly override: "ecommerce.config";
1115
+ };
1116
+ readonly defaultValue: boolean;
1117
+ readonly valueType: "boolean";
1118
+ readonly valueSchema: {
1119
+ readonly type: "boolean";
1120
+ };
1121
+ readonly literal: {
1122
+ readonly kind: "key";
1123
+ readonly label: "STOREFRONT_SHOW_NET_PLUS_IVA_LABEL";
1124
+ readonly help: "STOREFRONT_SHOW_NET_PLUS_IVA_HELP";
1125
+ readonly defaults: {
1126
+ readonly label: string;
1127
+ readonly help: string;
1128
+ };
1129
+ };
1130
+ readonly audience: "public";
1131
+ readonly lifecycle: "live";
1132
+ readonly ownership: "storefront-operation";
1133
+ readonly excludedFromSnapshot: true;
1134
+ };
1109
1135
  readonly prices: {
1110
1136
  readonly storage: {
1111
1137
  readonly source: "catalogue";
@@ -106,12 +106,15 @@ const LIVE_METADATA = {
106
106
  ownership: 'storefront-operation',
107
107
  excludedFromSnapshot: true,
108
108
  };
109
- const liveToggle = (key, labelKey, helpKey, label, help) => ({
109
+ const liveToggle = (key, labelKey, helpKey, label, help,
110
+ // Per key: a toggle that changes what a shopper sees for every store that has
111
+ // never written it ships `false`. Defaults to `true`, the three original toggles.
112
+ defaultValue = true) => ({
110
113
  ...LIVE_METADATA,
111
114
  key,
112
115
  allowedLayers: ['WEB#store'],
113
116
  storage: { source: 'store', override: 'ecommerce.config' },
114
- defaultValue: true,
117
+ defaultValue,
115
118
  valueType: 'boolean',
116
119
  valueSchema: { type: 'boolean' },
117
120
  literal: { kind: 'key', label: labelKey, help: helpKey, defaults: { label, help } },
@@ -137,6 +140,13 @@ export const STOREFRONT_DESIGN_REGISTRY = {
137
140
  showIvaAlert: liveToggle('showIvaAlert', 'STOREFRONT_SHOW_IVA_ALERT_LABEL', 'STOREFRONT_SHOW_IVA_ALERT_HELP', 'Mostrar aviso de IVA', 'Mostrar el aviso de IVA incluido en los precios.'),
138
141
  showCurrencySelector: liveToggle('showCurrencySelector', 'STOREFRONT_SHOW_CURRENCY_SELECTOR_LABEL', 'STOREFRONT_SHOW_CURRENCY_SELECTOR_HELP', 'Mostrar selector de moneda', 'Permitir elegir la moneda de visualización en la tienda.'),
139
142
  enableSaveForLater: liveToggle('enableSaveForLater', 'STOREFRONT_ENABLE_SAVE_FOR_LATER_LABEL', 'STOREFRONT_ENABLE_SAVE_FOR_LATER_HELP', 'Permitir guardar para después', 'Mostrar los controles para guardar productos de la cesta para después.'),
143
+ /*
144
+ * Display only: every public price slot carries `netOfIva` whatever this says
145
+ * (absent only for a product with no declarable IVA rate), so a flip needs no
146
+ * catalogue refetch. The storefront shows the «+ IVA» line when this is on AND
147
+ * the block is present. Default off: a store opts in.
148
+ */
149
+ showNetPlusIva: liveToggle('showNetPlusIva', 'STOREFRONT_SHOW_NET_PLUS_IVA_LABEL', 'STOREFRONT_SHOW_NET_PLUS_IVA_HELP', 'Mostrar precio neto + IVA', 'Mostrar también el precio sin IVA, con la leyenda «+ IVA», junto al precio final. Nunca reemplaza al precio final.', false),
140
150
  prices: { ...LIVE_METADATA, storage: { source: 'catalogue' } },
141
151
  stock: { ...LIVE_METADATA, storage: { source: 'catalogue' } },
142
152
  checkout: { ...LIVE_METADATA, storage: { source: 'store' } },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "platform-types",
3
- "version": "1.10.802",
3
+ "version": "1.10.804",
4
4
  "description": "Shared wire and entity contracts for the platform.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",