platform-types 1.10.836 → 1.10.837
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/customer.js +4 -1
- package/dist/cjs/guestOrderStatus.js +21 -8
- package/dist/cjs/store.js +63 -1
- package/dist/cjs/subscription.js +1 -0
- package/dist/customer.d.ts +60 -2
- package/dist/customer.js +2 -0
- package/dist/guestOrderStatus.d.ts +49 -7
- package/dist/guestOrderStatus.js +20 -7
- package/dist/paymentAttempt.d.ts +12 -0
- package/dist/store.d.ts +98 -2
- package/dist/store.js +61 -0
- package/dist/subscription.d.ts +2 -2
- package/dist/subscription.js +1 -0
- package/package.json +1 -1
package/dist/cjs/customer.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CUSTOMER_DISCOUNT_MAX = exports.CUSTOMER_ACQUISITION_CHANNELS = exports.CUSTOMER_LIFECYCLE_STAGES = exports.CUSTOMER_KINDS = void 0;
|
|
3
|
+
exports.isWhatsappNoticesOptedIn = exports.CUSTOMER_DISCOUNT_MAX = exports.CUSTOMER_ACQUISITION_CHANNELS = exports.CUSTOMER_LIFECYCLE_STAGES = exports.CUSTOMER_KINDS = void 0;
|
|
4
4
|
exports.CUSTOMER_KINDS = ['person', 'company'];
|
|
5
5
|
exports.CUSTOMER_LIFECYCLE_STAGES = ['lead', 'active', 'inactive'];
|
|
6
6
|
exports.CUSTOMER_ACQUISITION_CHANNELS = ['storefront', 'pos', 'marketplace', 'import', 'manual'];
|
|
@@ -11,3 +11,6 @@ exports.CUSTOMER_ACQUISITION_CHANNELS = ['storefront', 'pos', 'marketplace', 'im
|
|
|
11
11
|
* `discount` unchanged (or omits it) still saves.
|
|
12
12
|
*/
|
|
13
13
|
exports.CUSTOMER_DISCOUNT_MAX = 50;
|
|
14
|
+
/** Whether `notices` records a standing transactional WhatsApp opt-in: `optIn` present and `optOut` absent. */
|
|
15
|
+
const isWhatsappNoticesOptedIn = (notices) => notices?.optIn !== undefined && notices.optOut === undefined;
|
|
16
|
+
exports.isWhatsappNoticesOptedIn = isWhatsappNoticesOptedIn;
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* Guest order status link — the
|
|
4
|
-
*
|
|
5
|
-
* link to the address stored on the order.
|
|
3
|
+
* Guest order status link — the page a buyer with no account opens from the
|
|
4
|
+
* order email (`/pedido/{token}`), the one consent it can give there, and the
|
|
5
|
+
* route that mails a fresh link to the address stored on the order.
|
|
6
6
|
*
|
|
7
|
-
* The token (`gs1.…`) is a bearer credential over exactly ONE order
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
7
|
+
* The token (`gs1.…`) is a bearer credential over exactly ONE order. It
|
|
8
|
+
* authorises the read and exactly ONE write: the transactional WhatsApp consent
|
|
9
|
+
* grant for the order's own customer in that store
|
|
10
|
+
* (`POST /orders/status/whatsapp-opt-in`, {@link GuestOrderWhatsappOptInRequest}).
|
|
11
|
+
* Nothing else — no cart write, payment, cancellation, withdrawal or export.
|
|
12
|
+
* Both routes authorise it identically. It carries no expiry; it is refused
|
|
13
|
+
* once the order was delivered (or cancelled) more than `guestStatusLinkDaysAfterDelivery` days ago — unless a
|
|
11
14
|
* purchase withdrawal on it is not final or a refund on it is not closed — and
|
|
12
15
|
* every earlier link dies when a recovery or an operator revokes it.
|
|
13
16
|
*
|
|
@@ -16,7 +19,7 @@
|
|
|
16
19
|
* code mailed to the order's address, so the token still authorises none.
|
|
17
20
|
*/
|
|
18
21
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
-
exports.GUEST_ORDER_STATUS_LINK_TEMPLATE = exports.GUEST_ORDER_STATUS_ERROR_CODES = void 0;
|
|
22
|
+
exports.GUEST_ORDER_STATUS_LINK_TEMPLATE = exports.GUEST_ORDER_WHATSAPP_OPT_IN_ERROR_CODES = exports.GUEST_ORDER_STATUS_ERROR_CODES = void 0;
|
|
20
23
|
/**
|
|
21
24
|
* The refusals the guest status routes answer themselves.
|
|
22
25
|
*
|
|
@@ -28,5 +31,15 @@ exports.GUEST_ORDER_STATUS_LINK_TEMPLATE = exports.GUEST_ORDER_STATUS_ERROR_CODE
|
|
|
28
31
|
* `POST /orders/status/recover`.
|
|
29
32
|
*/
|
|
30
33
|
exports.GUEST_ORDER_STATUS_ERROR_CODES = ['GUEST_STATUS_TOKEN_INVALID'];
|
|
34
|
+
/**
|
|
35
|
+
* The refusals `POST /orders/status/whatsapp-opt-in` answers itself, past the
|
|
36
|
+
* token (which refuses `GUEST_STATUS_TOKEN_INVALID` exactly as the read does).
|
|
37
|
+
*
|
|
38
|
+
* - WHATSAPP_OPT_IN_UNAVAILABLE (409): the offer does not hold for this order —
|
|
39
|
+
* the store's messaging is unavailable, the order is cancelled, delivered or
|
|
40
|
+
* disabled, carries no phone, or its customer row is no longer live. Nothing
|
|
41
|
+
* is written. One code for every reason.
|
|
42
|
+
*/
|
|
43
|
+
exports.GUEST_ORDER_WHATSAPP_OPT_IN_ERROR_CODES = ['WHATSAPP_OPT_IN_UNAVAILABLE'];
|
|
31
44
|
/** The transactional email template that mails a guest their (new) status link. */
|
|
32
45
|
exports.GUEST_ORDER_STATUS_LINK_TEMPLATE = 'guest-order-status-link';
|
package/dist/cjs/store.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CHANGE_OF_MIND_WINDOW_SOURCE = exports.CHANGE_OF_MIND_RETURN_DAYS_MAX = exports.CHANGE_OF_MIND_REFUND_AS = exports.CHANGE_OF_MIND_RETURN_SHIPPING_PAYERS = exports.STORE_PATCH_ERROR_CODES = exports.STORE_MODULE_ERROR_CODES = exports.isStoreModuleOn = exports.isStoreModuleKey = exports.STORE_MODULE_KEYS = exports.STOREFRONT_METHOD_KINDS = exports.STORE_ONBOARDING_REVIEW_AREAS = exports.CUSTOM_DOMAIN_ROW_LIMIT = exports.CUSTOM_DOMAIN_SLOT_LIMIT = void 0;
|
|
3
|
+
exports.resolveStoreMessaging = exports.STORE_MESSAGING_SIGNATURE_MAX = exports.STORE_MESSAGING_DEFAULTS = exports.STORE_MESSAGE_NOTICES = exports.CHANGE_OF_MIND_WINDOW_SOURCE = exports.CHANGE_OF_MIND_RETURN_DAYS_MAX = exports.CHANGE_OF_MIND_REFUND_AS = exports.CHANGE_OF_MIND_RETURN_SHIPPING_PAYERS = exports.STORE_PATCH_ERROR_CODES = exports.STORE_MODULE_ERROR_CODES = exports.isStoreModuleOn = exports.isStoreModuleKey = exports.STORE_MODULE_KEYS = exports.STOREFRONT_METHOD_KINDS = exports.STORE_ONBOARDING_REVIEW_AREAS = 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
|
|
@@ -119,6 +119,7 @@ exports.STORE_MODULE_ERROR_CODES = [
|
|
|
119
119
|
* - `AFIP_RELACION_FLAG_FORBIDDEN` — `afip.wscdcEnabled` / `afip.fceEnabled`.
|
|
120
120
|
* - `FX_TABLE_FORBIDDEN` — the `currencies` exchange-rate table.
|
|
121
121
|
* - `FX_AUTO_UPDATE_FORBIDDEN` — `fxAutoUpdate`.
|
|
122
|
+
* - `STORE_MESSAGING_FORBIDDEN` — the `messaging` customer-messaging settings.
|
|
122
123
|
*
|
|
123
124
|
* Request refusals, `400`:
|
|
124
125
|
* - `FIELD_NOT_WRITABLE_HERE` — a field written through `POST /store`, not
|
|
@@ -197,6 +198,7 @@ exports.STORE_PATCH_ERROR_CODES = [
|
|
|
197
198
|
'NET_PLUS_IVA_REQUIRES_RI',
|
|
198
199
|
'DATA_FISCAL_URL_INVALID',
|
|
199
200
|
'STORE_PUBLIC_HOST_MISSING',
|
|
201
|
+
'STORE_MESSAGING_FORBIDDEN',
|
|
200
202
|
'FORBIDDEN',
|
|
201
203
|
'STORE_NOT_FOUND',
|
|
202
204
|
];
|
|
@@ -208,3 +210,63 @@ exports.CHANGE_OF_MIND_REFUND_AS = ['refund', 'store-credit'];
|
|
|
208
210
|
exports.CHANGE_OF_MIND_RETURN_DAYS_MAX = 365;
|
|
209
211
|
/** The source of a change-of-mind deadline: the store's own setting, not a statutory row. */
|
|
210
212
|
exports.CHANGE_OF_MIND_WINDOW_SOURCE = 'store:changeOfMindReturns';
|
|
213
|
+
/**
|
|
214
|
+
* Every `StoreMessageNotice`, in the order the settings screen lists them —
|
|
215
|
+
* the keys `Store.integrations.messaging` switches. `UncoveredStoreMessageNotices`
|
|
216
|
+
* fails `typecheck` naming a notice the union gains and this tuple lacks.
|
|
217
|
+
*/
|
|
218
|
+
exports.STORE_MESSAGE_NOTICES = [
|
|
219
|
+
'orderReady',
|
|
220
|
+
'orderShipped',
|
|
221
|
+
'serviceOrderReceived',
|
|
222
|
+
'serviceOrderQuoted',
|
|
223
|
+
'serviceOrderApproved',
|
|
224
|
+
'serviceOrderReady',
|
|
225
|
+
'serviceOrderCancelled',
|
|
226
|
+
'serviceOrderReturnedUnrepaired',
|
|
227
|
+
'serviceOrderAbandoned',
|
|
228
|
+
'serviceOrderOnHold',
|
|
229
|
+
'serviceOrderResumed',
|
|
230
|
+
'appointmentReminder',
|
|
231
|
+
'paymentReminder',
|
|
232
|
+
];
|
|
233
|
+
/**
|
|
234
|
+
* What an ABSENT `messaging` key reads: status notices and appointment
|
|
235
|
+
* reminders on, payment reminders off, the SMS fallback on.
|
|
236
|
+
*/
|
|
237
|
+
exports.STORE_MESSAGING_DEFAULTS = {
|
|
238
|
+
orderReady: true,
|
|
239
|
+
orderShipped: true,
|
|
240
|
+
serviceOrderReceived: true,
|
|
241
|
+
serviceOrderQuoted: true,
|
|
242
|
+
serviceOrderApproved: true,
|
|
243
|
+
serviceOrderReady: true,
|
|
244
|
+
serviceOrderCancelled: true,
|
|
245
|
+
serviceOrderReturnedUnrepaired: true,
|
|
246
|
+
serviceOrderAbandoned: true,
|
|
247
|
+
serviceOrderOnHold: true,
|
|
248
|
+
serviceOrderResumed: true,
|
|
249
|
+
appointmentReminder: true,
|
|
250
|
+
paymentReminder: false,
|
|
251
|
+
smsFallback: true,
|
|
252
|
+
};
|
|
253
|
+
/** The firma cap — the same one `sms.signature` has. */
|
|
254
|
+
exports.STORE_MESSAGING_SIGNATURE_MAX = 80;
|
|
255
|
+
/**
|
|
256
|
+
* Every switch of a store's messaging settings, decided: per key, the stored
|
|
257
|
+
* boolean, else its `STORE_MESSAGING_DEFAULTS` value (a stored non-boolean
|
|
258
|
+
* reads as absent). `signature` falls back to `sms.signature` only when
|
|
259
|
+
* `messaging.signature` is absent; a stored `''` is kept and means no firma.
|
|
260
|
+
*/
|
|
261
|
+
const resolveStoreMessaging = (integrations) => {
|
|
262
|
+
const leaf = integrations?.messaging;
|
|
263
|
+
const resolved = { ...exports.STORE_MESSAGING_DEFAULTS };
|
|
264
|
+
for (const key of [...exports.STORE_MESSAGE_NOTICES, 'smsFallback']) {
|
|
265
|
+
const stored = leaf?.[key];
|
|
266
|
+
if (typeof stored === 'boolean')
|
|
267
|
+
resolved[key] = stored;
|
|
268
|
+
}
|
|
269
|
+
const signature = typeof leaf?.signature === 'string' ? leaf.signature : integrations?.sms?.signature;
|
|
270
|
+
return typeof signature === 'string' ? { ...resolved, signature } : resolved;
|
|
271
|
+
};
|
|
272
|
+
exports.resolveStoreMessaging = resolveStoreMessaging;
|
package/dist/cjs/subscription.js
CHANGED
package/dist/customer.d.ts
CHANGED
|
@@ -8,6 +8,8 @@ export declare const CUSTOMER_ACQUISITION_CHANNELS: readonly ["storefront", "pos
|
|
|
8
8
|
* `discount` unchanged (or omits it) still saves.
|
|
9
9
|
*/
|
|
10
10
|
export declare const CUSTOMER_DISCOUNT_MAX = 50;
|
|
11
|
+
/** Whether `notices` records a standing transactional WhatsApp opt-in: `optIn` present and `optOut` absent. */
|
|
12
|
+
export declare const isWhatsappNoticesOptedIn: (notices: CustomerWhatsappNotices | undefined) => boolean;
|
|
11
13
|
declare global {
|
|
12
14
|
/** Exact identity matches within the token's store; no stored identity fields are returned. */
|
|
13
15
|
interface CustomerDuplicateCandidate {
|
|
@@ -95,8 +97,62 @@ declare global {
|
|
|
95
97
|
/** Per-customer, not per-channel — one unsubscribe link covers every channel. */
|
|
96
98
|
unsubscribeToken?: string;
|
|
97
99
|
}
|
|
98
|
-
/**
|
|
99
|
-
|
|
100
|
+
/**
|
|
101
|
+
* Where a transactional WhatsApp grant or withdrawal was given:
|
|
102
|
+
* `back-office` (staff, `POST /customers`), `storefront-post-purchase` (the
|
|
103
|
+
* one-tap offer after an order is placed — the signed-in banner through web
|
|
104
|
+
* `POST /user` with `whatsappOptInOrigin: 'post-purchase'`, or a guest's
|
|
105
|
+
* `POST /orders/status/whatsapp-opt-in`) and `storefront-profile` (the
|
|
106
|
+
* shopper's own profile toggle, web `POST /user`).
|
|
107
|
+
*/
|
|
108
|
+
type WhatsappNoticeSource = 'back-office' | 'storefront-post-purchase' | 'storefront-profile';
|
|
109
|
+
/**
|
|
110
|
+
* Provenance of one transactional WhatsApp grant or withdrawal.
|
|
111
|
+
* Server-written only. Carries NO phone number and NO IP, unlike
|
|
112
|
+
* `ChannelConsentStamp` (deliberately not extended), and not who acted.
|
|
113
|
+
*/
|
|
114
|
+
interface WhatsappNoticeStamp {
|
|
115
|
+
/** ms epoch. */
|
|
116
|
+
ts: number;
|
|
117
|
+
source: WhatsappNoticeSource;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* `Customer.whatsappNotices`: the customer's consent to the store's
|
|
121
|
+
* transactional WhatsApp notices (order and service-order status,
|
|
122
|
+
* reminders). Per customer per store, since the CUSTOMER row is
|
|
123
|
+
* store-scoped. Separate from `CustomerMarketing`, and never marketing
|
|
124
|
+
* consent.
|
|
125
|
+
*
|
|
126
|
+
* Opted in ⇔ `optIn` present AND `optOut` absent; read it through
|
|
127
|
+
* `isWhatsappNoticesOptedIn`. A grant SETs `optIn` and REMOVEs `optOut`; a
|
|
128
|
+
* withdrawal SETs `optOut` and keeps `optIn`. Resending the current state
|
|
129
|
+
* changes nothing and does not re-stamp; a withdrawal from a customer who
|
|
130
|
+
* never opted in is recorded. Not a history: it holds the latest grant and
|
|
131
|
+
* the latest withdrawal only. ⚠️ Absent is NOT consent.
|
|
132
|
+
*/
|
|
133
|
+
interface CustomerWhatsappNotices {
|
|
134
|
+
optIn?: WhatsappNoticeStamp;
|
|
135
|
+
optOut?: WhatsappNoticeStamp;
|
|
136
|
+
}
|
|
137
|
+
/** Write shape: `whatsappNotices` is server-owned, and `whatsappOptIn` is the directive that moves it. */
|
|
138
|
+
type CustomerUpsertInput = Partial<Omit<Customer, 'whatsappNotices'>> & PhotoUploadControls & {
|
|
139
|
+
/**
|
|
140
|
+
* `POST /customers` (source `back-office`) and web `POST /user` (source
|
|
141
|
+
* `storefront-profile`): `true` grants, `false` withdraws, absent changes
|
|
142
|
+
* nothing. Never stored. Staff MAY grant, because this is not marketing
|
|
143
|
+
* consent. A storefront grant acts only while `Store.messagingAvailable`
|
|
144
|
+
* holds and is otherwise dropped; a withdrawal always acts.
|
|
145
|
+
*/
|
|
146
|
+
whatsappOptIn?: boolean;
|
|
147
|
+
/**
|
|
148
|
+
* Web `POST /user` only: `'post-purchase'` names the grant as the one-tap
|
|
149
|
+
* offer after an order (`whatsappOptInOffer` on the order read), so the
|
|
150
|
+
* stamp's source is `storefront-post-purchase` instead of
|
|
151
|
+
* `storefront-profile`. A directive, never stored, and ignored unless
|
|
152
|
+
* `whatsappOptIn` is `true`.
|
|
153
|
+
*/
|
|
154
|
+
whatsappOptInOrigin?: 'post-purchase';
|
|
155
|
+
};
|
|
100
156
|
/**
|
|
101
157
|
* The query string of the customers LIST read — `GET /customers` with no
|
|
102
158
|
* `customerId`, `list` or `email`. Every present filter AND-composes: a row is
|
|
@@ -568,6 +624,8 @@ declare global {
|
|
|
568
624
|
*/
|
|
569
625
|
mergeBalanceCarried?: boolean;
|
|
570
626
|
marketing?: CustomerMarketing;
|
|
627
|
+
/** Transactional WhatsApp consent for this store — see `CustomerWhatsappNotices`. Server-written. */
|
|
628
|
+
whatsappNotices?: CustomerWhatsappNotices;
|
|
571
629
|
/** Optional notification mail only; transactional mail cannot be disabled. */
|
|
572
630
|
notificationPreferences?: CustomerNotificationPreferences;
|
|
573
631
|
minBuy?: number;
|
package/dist/customer.js
CHANGED
|
@@ -8,3 +8,5 @@ export const CUSTOMER_ACQUISITION_CHANNELS = ['storefront', 'pos', 'marketplace'
|
|
|
8
8
|
* `discount` unchanged (or omits it) still saves.
|
|
9
9
|
*/
|
|
10
10
|
export const CUSTOMER_DISCOUNT_MAX = 50;
|
|
11
|
+
/** Whether `notices` records a standing transactional WhatsApp opt-in: `optIn` present and `optOut` absent. */
|
|
12
|
+
export const isWhatsappNoticesOptedIn = (notices) => notices?.optIn !== undefined && notices.optOut === undefined;
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Guest order status link — the
|
|
3
|
-
*
|
|
4
|
-
* link to the address stored on the order.
|
|
2
|
+
* Guest order status link — the page a buyer with no account opens from the
|
|
3
|
+
* order email (`/pedido/{token}`), the one consent it can give there, and the
|
|
4
|
+
* route that mails a fresh link to the address stored on the order.
|
|
5
5
|
*
|
|
6
|
-
* The token (`gs1.…`) is a bearer credential over exactly ONE order
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* The token (`gs1.…`) is a bearer credential over exactly ONE order. It
|
|
7
|
+
* authorises the read and exactly ONE write: the transactional WhatsApp consent
|
|
8
|
+
* grant for the order's own customer in that store
|
|
9
|
+
* (`POST /orders/status/whatsapp-opt-in`, {@link GuestOrderWhatsappOptInRequest}).
|
|
10
|
+
* Nothing else — no cart write, payment, cancellation, withdrawal or export.
|
|
11
|
+
* Both routes authorise it identically. It carries no expiry; it is refused
|
|
12
|
+
* once the order was delivered (or cancelled) more than `guestStatusLinkDaysAfterDelivery` days ago — unless a
|
|
10
13
|
* purchase withdrawal on it is not final or a refund on it is not closed — and
|
|
11
14
|
* every earlier link dies when a recovery or an operator revokes it.
|
|
12
15
|
*
|
|
@@ -26,6 +29,17 @@
|
|
|
26
29
|
*/
|
|
27
30
|
export declare const GUEST_ORDER_STATUS_ERROR_CODES: readonly ["GUEST_STATUS_TOKEN_INVALID"];
|
|
28
31
|
export type GuestOrderStatusErrorCode = (typeof GUEST_ORDER_STATUS_ERROR_CODES)[number];
|
|
32
|
+
/**
|
|
33
|
+
* The refusals `POST /orders/status/whatsapp-opt-in` answers itself, past the
|
|
34
|
+
* token (which refuses `GUEST_STATUS_TOKEN_INVALID` exactly as the read does).
|
|
35
|
+
*
|
|
36
|
+
* - WHATSAPP_OPT_IN_UNAVAILABLE (409): the offer does not hold for this order —
|
|
37
|
+
* the store's messaging is unavailable, the order is cancelled, delivered or
|
|
38
|
+
* disabled, carries no phone, or its customer row is no longer live. Nothing
|
|
39
|
+
* is written. One code for every reason.
|
|
40
|
+
*/
|
|
41
|
+
export declare const GUEST_ORDER_WHATSAPP_OPT_IN_ERROR_CODES: readonly ["WHATSAPP_OPT_IN_UNAVAILABLE"];
|
|
42
|
+
export type GuestOrderWhatsappOptInErrorCode = (typeof GUEST_ORDER_WHATSAPP_OPT_IN_ERROR_CODES)[number];
|
|
29
43
|
/** The transactional email template that mails a guest their (new) status link. */
|
|
30
44
|
export declare const GUEST_ORDER_STATUS_LINK_TEMPLATE: "guest-order-status-link";
|
|
31
45
|
declare global {
|
|
@@ -115,6 +129,17 @@ declare global {
|
|
|
115
129
|
returnRequests?: OrderReturnRequestView[];
|
|
116
130
|
/** Whether a return request can be opened now. Absent only when the return requests could not be read whole. */
|
|
117
131
|
returnRequestEligibility?: OrderReturnRequestEligibility;
|
|
132
|
+
/**
|
|
133
|
+
* Present, and `true`, only when the post-purchase «Avisarme por WhatsApp
|
|
134
|
+
* sobre este pedido» may be offered: the store's messaging is available
|
|
135
|
+
* (`Store.messagingAvailable`), the order is not cancelled, delivered or
|
|
136
|
+
* disabled, it carries a phone (its customer's or the guest contact's),
|
|
137
|
+
* and its customer row is live and NOT opted in
|
|
138
|
+
* (`Customer.whatsappNotices`). Accept it with
|
|
139
|
+
* `POST /orders/status/whatsapp-opt-in`. Carries no phone. Absent too when
|
|
140
|
+
* the offer could not be computed — the read never fails for it.
|
|
141
|
+
*/
|
|
142
|
+
whatsappOptInOffer?: true;
|
|
118
143
|
contact: {
|
|
119
144
|
/** The stored address, masked (e.g. `j***@d***.com`). */
|
|
120
145
|
emailMasked: string;
|
|
@@ -131,4 +156,21 @@ declare global {
|
|
|
131
156
|
orderId: string;
|
|
132
157
|
email: string;
|
|
133
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* `POST /orders/status/whatsapp-opt-in` body (strict): the guest status token
|
|
161
|
+
* of the order whose post-purchase WhatsApp offer (`whatsappOptInOffer`) is
|
|
162
|
+
* accepted. The token is authorised exactly as `GET /orders/status` does it
|
|
163
|
+
* (one `401 GUEST_STATUS_TOKEN_INVALID` for every refusal; a malformed body
|
|
164
|
+
* too). Then the grant: `200` {@link GuestOrderWhatsappOptInResult} when the
|
|
165
|
+
* customer is now opted in — freshly stamped `{ ts, source:
|
|
166
|
+
* 'storefront-post-purchase' }`, or already opted in (nothing written, never
|
|
167
|
+
* re-stamped) — else `409 WHATSAPP_OPT_IN_UNAVAILABLE`, nothing written.
|
|
168
|
+
*/
|
|
169
|
+
interface GuestOrderWhatsappOptInRequest {
|
|
170
|
+
token: string;
|
|
171
|
+
}
|
|
172
|
+
/** `data` of a `200` `POST /orders/status/whatsapp-opt-in`. */
|
|
173
|
+
interface GuestOrderWhatsappOptInResult {
|
|
174
|
+
whatsappNoticesOptedIn: true;
|
|
175
|
+
}
|
|
134
176
|
}
|
package/dist/guestOrderStatus.js
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Guest order status link — the
|
|
3
|
-
*
|
|
4
|
-
* link to the address stored on the order.
|
|
2
|
+
* Guest order status link — the page a buyer with no account opens from the
|
|
3
|
+
* order email (`/pedido/{token}`), the one consent it can give there, and the
|
|
4
|
+
* route that mails a fresh link to the address stored on the order.
|
|
5
5
|
*
|
|
6
|
-
* The token (`gs1.…`) is a bearer credential over exactly ONE order
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* The token (`gs1.…`) is a bearer credential over exactly ONE order. It
|
|
7
|
+
* authorises the read and exactly ONE write: the transactional WhatsApp consent
|
|
8
|
+
* grant for the order's own customer in that store
|
|
9
|
+
* (`POST /orders/status/whatsapp-opt-in`, {@link GuestOrderWhatsappOptInRequest}).
|
|
10
|
+
* Nothing else — no cart write, payment, cancellation, withdrawal or export.
|
|
11
|
+
* Both routes authorise it identically. It carries no expiry; it is refused
|
|
12
|
+
* once the order was delivered (or cancelled) more than `guestStatusLinkDaysAfterDelivery` days ago — unless a
|
|
10
13
|
* purchase withdrawal on it is not final or a refund on it is not closed — and
|
|
11
14
|
* every earlier link dies when a recovery or an operator revokes it.
|
|
12
15
|
*
|
|
@@ -25,5 +28,15 @@
|
|
|
25
28
|
* `POST /orders/status/recover`.
|
|
26
29
|
*/
|
|
27
30
|
export const GUEST_ORDER_STATUS_ERROR_CODES = ['GUEST_STATUS_TOKEN_INVALID'];
|
|
31
|
+
/**
|
|
32
|
+
* The refusals `POST /orders/status/whatsapp-opt-in` answers itself, past the
|
|
33
|
+
* token (which refuses `GUEST_STATUS_TOKEN_INVALID` exactly as the read does).
|
|
34
|
+
*
|
|
35
|
+
* - WHATSAPP_OPT_IN_UNAVAILABLE (409): the offer does not hold for this order —
|
|
36
|
+
* the store's messaging is unavailable, the order is cancelled, delivered or
|
|
37
|
+
* disabled, carries no phone, or its customer row is no longer live. Nothing
|
|
38
|
+
* is written. One code for every reason.
|
|
39
|
+
*/
|
|
40
|
+
export const GUEST_ORDER_WHATSAPP_OPT_IN_ERROR_CODES = ['WHATSAPP_OPT_IN_UNAVAILABLE'];
|
|
28
41
|
/** The transactional email template that mails a guest their (new) status link. */
|
|
29
42
|
export const GUEST_ORDER_STATUS_LINK_TEMPLATE = 'guest-order-status-link';
|
package/dist/paymentAttempt.d.ts
CHANGED
|
@@ -145,6 +145,18 @@ declare global {
|
|
|
145
145
|
returnRequests?: OrderReturnRequestView[];
|
|
146
146
|
/** Whether a return request can be opened now. Absent only when the return requests could not be read whole. */
|
|
147
147
|
returnRequestEligibility?: OrderReturnRequestEligibility;
|
|
148
|
+
/**
|
|
149
|
+
* Point read (`?orderId=`) only, never the list. Present, and `true`, only
|
|
150
|
+
* when the post-purchase «Avisarme por WhatsApp sobre este pedido» may be
|
|
151
|
+
* offered: the store's messaging is available (`Store.messagingAvailable`),
|
|
152
|
+
* the order is not cancelled, delivered or disabled, it carries a phone
|
|
153
|
+
* (`customer.phone` or the guest contact's), and the order's customer row
|
|
154
|
+
* is live and NOT opted in (`Customer.whatsappNotices`). Accept it with web
|
|
155
|
+
* `POST /user` `{ whatsappOptIn: true, whatsappOptInOrigin: 'post-purchase' }`.
|
|
156
|
+
* Carries no phone. Absent too when the offer could not be computed — the
|
|
157
|
+
* order read never fails for it.
|
|
158
|
+
*/
|
|
159
|
+
whatsappOptInOffer?: true;
|
|
148
160
|
};
|
|
149
161
|
/**
|
|
150
162
|
* `data` of an `orderPaymentAttempt` socket frame, sent to the order's own
|
package/dist/store.d.ts
CHANGED
|
@@ -298,7 +298,8 @@ declare global {
|
|
|
298
298
|
* Platform switch for store-paid customer messaging (SMS today). `false`
|
|
299
299
|
* or absent: no store-paid message is sent, and the app hides every store
|
|
300
300
|
* messaging surface. App-only (`forwardToTenants: 'app'`), so absent from
|
|
301
|
-
* the storefront's unauthenticated response
|
|
301
|
+
* the storefront's unauthenticated response: the storefront reads
|
|
302
|
+
* `Store.messagingAvailable` instead, which folds this switch in.
|
|
302
303
|
*/
|
|
303
304
|
tenantMessagingEnabled?: boolean;
|
|
304
305
|
}
|
|
@@ -634,6 +635,16 @@ declare global {
|
|
|
634
635
|
* first such removal. No request body may set it.
|
|
635
636
|
*/
|
|
636
637
|
adminRemovalGeneration?: number;
|
|
638
|
+
/**
|
|
639
|
+
* Web `GET /store` only, always a boolean on a 200: `true` when the
|
|
640
|
+
* `tenantMessagingEnabled` platform global is on and at least one
|
|
641
|
+
* `StoreMessageNotice` resolves on (`resolveStoreMessaging`). Computed when
|
|
642
|
+
* the route is read, never stored or writable. Not on `stores` frames or the
|
|
643
|
+
* preview frame, where absent reads `false`. Checkout hides «Avisarme por
|
|
644
|
+
* WhatsApp» when it is `false`, and a storefront opt-in sent while it is
|
|
645
|
+
* `false` is dropped.
|
|
646
|
+
*/
|
|
647
|
+
messagingAvailable?: boolean;
|
|
637
648
|
storeId: string;
|
|
638
649
|
createdAt: number;
|
|
639
650
|
/** Unix ms — BE-stamped on every `POST`/`PATCH /store` write. Always present on written rows. */
|
|
@@ -1417,7 +1428,15 @@ declare global {
|
|
|
1417
1428
|
interface StoreIntegrations {
|
|
1418
1429
|
afip?: Afip;
|
|
1419
1430
|
mercadopago?: Mercadopago;
|
|
1431
|
+
/**
|
|
1432
|
+
* Per-store SMS entitlement and firma. Kept READABLE for migration: the
|
|
1433
|
+
* app writes `messaging` instead, and `PATCH /store` still accepts `sms`
|
|
1434
|
+
* for builds that have not moved. `messaging` never reads `sms.enabled`;
|
|
1435
|
+
* it falls back to `sms.signature` only while its own `signature` is absent.
|
|
1436
|
+
*/
|
|
1420
1437
|
sms?: SmsIntegration;
|
|
1438
|
+
/** The store's customer-messaging settings — see `StoreMessagingIntegration`. */
|
|
1439
|
+
messaging?: StoreMessagingIntegration;
|
|
1421
1440
|
gmail?: Gmail;
|
|
1422
1441
|
mercadolibre?: Mercadolibre;
|
|
1423
1442
|
tiendanube?: Tiendanube;
|
|
@@ -1427,6 +1446,37 @@ declare global {
|
|
|
1427
1446
|
enabled?: boolean;
|
|
1428
1447
|
signature?: string;
|
|
1429
1448
|
}
|
|
1449
|
+
/**
|
|
1450
|
+
* One store-paid customer message a store switches on or off — one of
|
|
1451
|
+
* `STORE_MESSAGE_NOTICES`. Each maps to exactly one notice the api emits.
|
|
1452
|
+
* `orderShipped` covers dispatch (shipped and delivered); `serviceOrderQuoted`
|
|
1453
|
+
* covers the quote-sent notice and the `quoted` status fallback alike.
|
|
1454
|
+
*/
|
|
1455
|
+
type StoreMessageNotice = 'orderReady' | 'orderShipped' | 'serviceOrderReceived' | 'serviceOrderQuoted' | 'serviceOrderApproved' | 'serviceOrderReady' | 'serviceOrderCancelled' | 'serviceOrderReturnedUnrepaired' | 'serviceOrderAbandoned' | 'serviceOrderOnHold' | 'serviceOrderResumed' | 'appointmentReminder' | 'paymentReminder';
|
|
1456
|
+
/**
|
|
1457
|
+
* `Store.integrations.messaging`. Written by `PATCH /store` only (ADMIN,
|
|
1458
|
+
* SUPERVISOR, MANAGER; a PRINTER claim is refused), merged key by key, so a
|
|
1459
|
+
* body naming one switch leaves the others as stored. An absent key reads
|
|
1460
|
+
* its `STORE_MESSAGING_DEFAULTS` value: status notices and appointment
|
|
1461
|
+
* reminders on, payment reminders off, `smsFallback` on. Read it through
|
|
1462
|
+
* `resolveStoreMessaging`, never off the raw keys. Sending is gated by the
|
|
1463
|
+
* `tenantMessagingEnabled` platform global as well.
|
|
1464
|
+
*/
|
|
1465
|
+
interface StoreMessagingIntegration extends Partial<Record<StoreMessageNotice, boolean>> {
|
|
1466
|
+
/** «Si WhatsApp falla, enviar por SMS». The SMS goes out only on a WhatsApp `failed`/`undelivered` status. */
|
|
1467
|
+
smsFallback?: boolean;
|
|
1468
|
+
/**
|
|
1469
|
+
* Firma, at most 80 characters after trimming (the cap `sms.signature`
|
|
1470
|
+
* has). Absent falls back to `sms.signature`; `''` means no firma.
|
|
1471
|
+
*/
|
|
1472
|
+
signature?: string;
|
|
1473
|
+
}
|
|
1474
|
+
/** `resolveStoreMessaging`'s answer: every switch decided. */
|
|
1475
|
+
interface ResolvedStoreMessaging extends Record<StoreMessageNotice, boolean> {
|
|
1476
|
+
smsFallback: boolean;
|
|
1477
|
+
/** Absent when neither `messaging.signature` nor `sms.signature` is stored. */
|
|
1478
|
+
signature?: string;
|
|
1479
|
+
}
|
|
1430
1480
|
interface Gmail {
|
|
1431
1481
|
connected?: boolean;
|
|
1432
1482
|
senderEmail?: string;
|
|
@@ -1962,6 +2012,13 @@ declare global {
|
|
|
1962
2012
|
* still broadcasts the row as it stands.
|
|
1963
2013
|
*/
|
|
1964
2014
|
onboardingReviewAdd?: StoreOnboardingReviewArea[];
|
|
2015
|
+
/**
|
|
2016
|
+
* `PATCH /store` only (the closed `POST /store` refuses it
|
|
2017
|
+
* `FIELD_NOT_WRITABLE_HERE`). Merged key by key over the stored leaf; an
|
|
2018
|
+
* undeclared key is a 400. A plain USER is refused 403
|
|
2019
|
+
* `STORE_MESSAGING_FORBIDDEN`.
|
|
2020
|
+
*/
|
|
2021
|
+
messaging?: StoreMessagingIntegration;
|
|
1965
2022
|
}
|
|
1966
2023
|
/**
|
|
1967
2024
|
* How the storefront offers a `paymentMethods` row — one of
|
|
@@ -2639,6 +2696,7 @@ export type StoreModuleRefusalBody = {
|
|
|
2639
2696
|
* - `AFIP_RELACION_FLAG_FORBIDDEN` — `afip.wscdcEnabled` / `afip.fceEnabled`.
|
|
2640
2697
|
* - `FX_TABLE_FORBIDDEN` — the `currencies` exchange-rate table.
|
|
2641
2698
|
* - `FX_AUTO_UPDATE_FORBIDDEN` — `fxAutoUpdate`.
|
|
2699
|
+
* - `STORE_MESSAGING_FORBIDDEN` — the `messaging` customer-messaging settings.
|
|
2642
2700
|
*
|
|
2643
2701
|
* Request refusals, `400`:
|
|
2644
2702
|
* - `FIELD_NOT_WRITABLE_HERE` — a field written through `POST /store`, not
|
|
@@ -2694,7 +2752,7 @@ export type StoreModuleRefusalBody = {
|
|
|
2694
2752
|
* checks, the display-currency lock, the storefront fence) are not listed
|
|
2695
2753
|
* either. Cross-cutting refusals: check `GATING_ERROR_CODES` as well.
|
|
2696
2754
|
*/
|
|
2697
|
-
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", "DELIVERY_FEE_INVALID", "WHOLESALE_LIST_REQUIRED", "NET_PLUS_IVA_REQUIRES_RI", "DATA_FISCAL_URL_INVALID", "STORE_PUBLIC_HOST_MISSING", "FORBIDDEN", "STORE_NOT_FOUND"];
|
|
2755
|
+
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", "DELIVERY_FEE_INVALID", "WHOLESALE_LIST_REQUIRED", "NET_PLUS_IVA_REQUIRES_RI", "DATA_FISCAL_URL_INVALID", "STORE_PUBLIC_HOST_MISSING", "STORE_MESSAGING_FORBIDDEN", "FORBIDDEN", "STORE_NOT_FOUND"];
|
|
2698
2756
|
export type StorePatchErrorCode = (typeof STORE_PATCH_ERROR_CODES)[number];
|
|
2699
2757
|
/** Who pays the return shipping under a store's change-of-mind policy. */
|
|
2700
2758
|
export declare const CHANGE_OF_MIND_RETURN_SHIPPING_PAYERS: readonly ["merchant", "shopper"];
|
|
@@ -2716,3 +2774,41 @@ declare global {
|
|
|
2716
2774
|
refundAs: ChangeOfMindRefundAs;
|
|
2717
2775
|
}
|
|
2718
2776
|
}
|
|
2777
|
+
/**
|
|
2778
|
+
* Every `StoreMessageNotice`, in the order the settings screen lists them —
|
|
2779
|
+
* the keys `Store.integrations.messaging` switches. `UncoveredStoreMessageNotices`
|
|
2780
|
+
* fails `typecheck` naming a notice the union gains and this tuple lacks.
|
|
2781
|
+
*/
|
|
2782
|
+
export declare const STORE_MESSAGE_NOTICES: readonly ["orderReady", "orderShipped", "serviceOrderReceived", "serviceOrderQuoted", "serviceOrderApproved", "serviceOrderReady", "serviceOrderCancelled", "serviceOrderReturnedUnrepaired", "serviceOrderAbandoned", "serviceOrderOnHold", "serviceOrderResumed", "appointmentReminder", "paymentReminder"];
|
|
2783
|
+
type AssertNoUncoveredStoreMessageNotice<T extends never> = T;
|
|
2784
|
+
export type UncoveredStoreMessageNotices = AssertNoUncoveredStoreMessageNotice<Exclude<StoreMessageNotice, (typeof STORE_MESSAGE_NOTICES)[number]>>;
|
|
2785
|
+
/**
|
|
2786
|
+
* What an ABSENT `messaging` key reads: status notices and appointment
|
|
2787
|
+
* reminders on, payment reminders off, the SMS fallback on.
|
|
2788
|
+
*/
|
|
2789
|
+
export declare const STORE_MESSAGING_DEFAULTS: {
|
|
2790
|
+
readonly orderReady: true;
|
|
2791
|
+
readonly orderShipped: true;
|
|
2792
|
+
readonly serviceOrderReceived: true;
|
|
2793
|
+
readonly serviceOrderQuoted: true;
|
|
2794
|
+
readonly serviceOrderApproved: true;
|
|
2795
|
+
readonly serviceOrderReady: true;
|
|
2796
|
+
readonly serviceOrderCancelled: true;
|
|
2797
|
+
readonly serviceOrderReturnedUnrepaired: true;
|
|
2798
|
+
readonly serviceOrderAbandoned: true;
|
|
2799
|
+
readonly serviceOrderOnHold: true;
|
|
2800
|
+
readonly serviceOrderResumed: true;
|
|
2801
|
+
readonly appointmentReminder: true;
|
|
2802
|
+
readonly paymentReminder: false;
|
|
2803
|
+
readonly smsFallback: true;
|
|
2804
|
+
};
|
|
2805
|
+
/** The firma cap — the same one `sms.signature` has. */
|
|
2806
|
+
export declare const STORE_MESSAGING_SIGNATURE_MAX = 80;
|
|
2807
|
+
/**
|
|
2808
|
+
* Every switch of a store's messaging settings, decided: per key, the stored
|
|
2809
|
+
* boolean, else its `STORE_MESSAGING_DEFAULTS` value (a stored non-boolean
|
|
2810
|
+
* reads as absent). `signature` falls back to `sms.signature` only when
|
|
2811
|
+
* `messaging.signature` is absent; a stored `''` is kept and means no firma.
|
|
2812
|
+
*/
|
|
2813
|
+
export declare const resolveStoreMessaging: (integrations: Pick<StoreIntegrations, "messaging" | "sms"> | undefined) => ResolvedStoreMessaging;
|
|
2814
|
+
export {};
|
package/dist/store.js
CHANGED
|
@@ -114,6 +114,7 @@ export const STORE_MODULE_ERROR_CODES = [
|
|
|
114
114
|
* - `AFIP_RELACION_FLAG_FORBIDDEN` — `afip.wscdcEnabled` / `afip.fceEnabled`.
|
|
115
115
|
* - `FX_TABLE_FORBIDDEN` — the `currencies` exchange-rate table.
|
|
116
116
|
* - `FX_AUTO_UPDATE_FORBIDDEN` — `fxAutoUpdate`.
|
|
117
|
+
* - `STORE_MESSAGING_FORBIDDEN` — the `messaging` customer-messaging settings.
|
|
117
118
|
*
|
|
118
119
|
* Request refusals, `400`:
|
|
119
120
|
* - `FIELD_NOT_WRITABLE_HERE` — a field written through `POST /store`, not
|
|
@@ -192,6 +193,7 @@ export const STORE_PATCH_ERROR_CODES = [
|
|
|
192
193
|
'NET_PLUS_IVA_REQUIRES_RI',
|
|
193
194
|
'DATA_FISCAL_URL_INVALID',
|
|
194
195
|
'STORE_PUBLIC_HOST_MISSING',
|
|
196
|
+
'STORE_MESSAGING_FORBIDDEN',
|
|
195
197
|
'FORBIDDEN',
|
|
196
198
|
'STORE_NOT_FOUND',
|
|
197
199
|
];
|
|
@@ -203,3 +205,62 @@ export const CHANGE_OF_MIND_REFUND_AS = ['refund', 'store-credit'];
|
|
|
203
205
|
export const CHANGE_OF_MIND_RETURN_DAYS_MAX = 365;
|
|
204
206
|
/** The source of a change-of-mind deadline: the store's own setting, not a statutory row. */
|
|
205
207
|
export const CHANGE_OF_MIND_WINDOW_SOURCE = 'store:changeOfMindReturns';
|
|
208
|
+
/**
|
|
209
|
+
* Every `StoreMessageNotice`, in the order the settings screen lists them —
|
|
210
|
+
* the keys `Store.integrations.messaging` switches. `UncoveredStoreMessageNotices`
|
|
211
|
+
* fails `typecheck` naming a notice the union gains and this tuple lacks.
|
|
212
|
+
*/
|
|
213
|
+
export const STORE_MESSAGE_NOTICES = [
|
|
214
|
+
'orderReady',
|
|
215
|
+
'orderShipped',
|
|
216
|
+
'serviceOrderReceived',
|
|
217
|
+
'serviceOrderQuoted',
|
|
218
|
+
'serviceOrderApproved',
|
|
219
|
+
'serviceOrderReady',
|
|
220
|
+
'serviceOrderCancelled',
|
|
221
|
+
'serviceOrderReturnedUnrepaired',
|
|
222
|
+
'serviceOrderAbandoned',
|
|
223
|
+
'serviceOrderOnHold',
|
|
224
|
+
'serviceOrderResumed',
|
|
225
|
+
'appointmentReminder',
|
|
226
|
+
'paymentReminder',
|
|
227
|
+
];
|
|
228
|
+
/**
|
|
229
|
+
* What an ABSENT `messaging` key reads: status notices and appointment
|
|
230
|
+
* reminders on, payment reminders off, the SMS fallback on.
|
|
231
|
+
*/
|
|
232
|
+
export const STORE_MESSAGING_DEFAULTS = {
|
|
233
|
+
orderReady: true,
|
|
234
|
+
orderShipped: true,
|
|
235
|
+
serviceOrderReceived: true,
|
|
236
|
+
serviceOrderQuoted: true,
|
|
237
|
+
serviceOrderApproved: true,
|
|
238
|
+
serviceOrderReady: true,
|
|
239
|
+
serviceOrderCancelled: true,
|
|
240
|
+
serviceOrderReturnedUnrepaired: true,
|
|
241
|
+
serviceOrderAbandoned: true,
|
|
242
|
+
serviceOrderOnHold: true,
|
|
243
|
+
serviceOrderResumed: true,
|
|
244
|
+
appointmentReminder: true,
|
|
245
|
+
paymentReminder: false,
|
|
246
|
+
smsFallback: true,
|
|
247
|
+
};
|
|
248
|
+
/** The firma cap — the same one `sms.signature` has. */
|
|
249
|
+
export const STORE_MESSAGING_SIGNATURE_MAX = 80;
|
|
250
|
+
/**
|
|
251
|
+
* Every switch of a store's messaging settings, decided: per key, the stored
|
|
252
|
+
* boolean, else its `STORE_MESSAGING_DEFAULTS` value (a stored non-boolean
|
|
253
|
+
* reads as absent). `signature` falls back to `sms.signature` only when
|
|
254
|
+
* `messaging.signature` is absent; a stored `''` is kept and means no firma.
|
|
255
|
+
*/
|
|
256
|
+
export const resolveStoreMessaging = (integrations) => {
|
|
257
|
+
const leaf = integrations?.messaging;
|
|
258
|
+
const resolved = { ...STORE_MESSAGING_DEFAULTS };
|
|
259
|
+
for (const key of [...STORE_MESSAGE_NOTICES, 'smsFallback']) {
|
|
260
|
+
const stored = leaf?.[key];
|
|
261
|
+
if (typeof stored === 'boolean')
|
|
262
|
+
resolved[key] = stored;
|
|
263
|
+
}
|
|
264
|
+
const signature = typeof leaf?.signature === 'string' ? leaf.signature : integrations?.sms?.signature;
|
|
265
|
+
return typeof signature === 'string' ? { ...resolved, signature } : resolved;
|
|
266
|
+
};
|
package/dist/subscription.d.ts
CHANGED
|
@@ -100,7 +100,7 @@ declare global {
|
|
|
100
100
|
* exhausts this union (a `switch`, a `Record<FeatureKey, …>`) still has to
|
|
101
101
|
* handle the new member in the same change.
|
|
102
102
|
*/
|
|
103
|
-
type FeatureKey = 'maxOrdersMonth' | 'maxInvoicesMonth' | 'maxProducts' | 'maxUsers' | 'maxCustomers' | 'maxWarehouses' | 'priceListsMax' | 'webhooks' | 'afipInvoicing' | 'suppliers' | 'domesticPayments' | 'stripePayments' | 'cashManagement' | 'importExport' | 'advancedReports' | 'customBranding' | 'prioritySupport' | 'aiFeatures' | 'mobileApp' | 'customDomain' | 'advancedPricing' | 'marketplaceChannels' | 'storefront' | 'loyalty' | 'marketing' | 'mandatory2fa';
|
|
103
|
+
type FeatureKey = 'maxOrdersMonth' | 'maxInvoicesMonth' | 'maxProducts' | 'maxUsers' | 'maxCustomers' | 'maxWarehouses' | 'priceListsMax' | 'webhooks' | 'monthlyMessageAllowance' | 'afipInvoicing' | 'suppliers' | 'domesticPayments' | 'stripePayments' | 'cashManagement' | 'importExport' | 'advancedReports' | 'customBranding' | 'prioritySupport' | 'aiFeatures' | 'mobileApp' | 'customDomain' | 'advancedPricing' | 'marketplaceChannels' | 'storefront' | 'loyalty' | 'marketing' | 'mandatory2fa';
|
|
104
104
|
/** Resolved entitlements for a specific tenant (matrix + overrides applied). */
|
|
105
105
|
type ResolvedEntitlements = Record<FeatureKey, Entitlement>;
|
|
106
106
|
/**
|
|
@@ -1238,7 +1238,7 @@ export declare const isPaidPlanTier: (value: unknown) => value is PaidPlanTier;
|
|
|
1238
1238
|
* metered / lifetime cap PASSES THROUGH — a new cap silently unbounded.
|
|
1239
1239
|
* Checklist: `docs/PLANS_AND_ENTITLEMENTS.md` in the api repo.
|
|
1240
1240
|
*/
|
|
1241
|
-
export declare const FEATURE_KEYS: readonly ["afipInvoicing", "suppliers", "advancedReports", "cashManagement", "importExport", "domesticPayments", "stripePayments", "aiFeatures", "mobileApp", "customBranding", "customDomain", "prioritySupport", "advancedPricing", "marketplaceChannels", "storefront", "loyalty", "marketing", "mandatory2fa", "maxUsers", "maxProducts", "maxCustomers", "maxWarehouses", "priceListsMax", "webhooks", "maxOrdersMonth", "maxInvoicesMonth"];
|
|
1241
|
+
export declare const FEATURE_KEYS: readonly ["afipInvoicing", "suppliers", "advancedReports", "cashManagement", "importExport", "domesticPayments", "stripePayments", "aiFeatures", "mobileApp", "customBranding", "customDomain", "prioritySupport", "advancedPricing", "marketplaceChannels", "storefront", "loyalty", "marketing", "mandatory2fa", "maxUsers", "maxProducts", "maxCustomers", "maxWarehouses", "priceListsMax", "webhooks", "maxOrdersMonth", "maxInvoicesMonth", "monthlyMessageAllowance"];
|
|
1242
1242
|
type AssertNoUncoveredFeatureKey<T extends never> = T;
|
|
1243
1243
|
export type UncoveredFeatureKeys = AssertNoUncoveredFeatureKey<Exclude<FeatureKey, (typeof FEATURE_KEYS)[number]>>;
|
|
1244
1244
|
export {};
|
package/dist/subscription.js
CHANGED