platform-types 1.10.777 → 1.10.778
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/index.js +1 -0
- package/dist/cjs/notification.js +19 -1
- package/dist/cjs/socket.js +11 -0
- package/dist/cjs/store.js +8 -0
- package/dist/cjs/wholesaleRequest.js +25 -0
- package/dist/customer.d.ts +15 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/notification.d.ts +25 -2
- package/dist/notification.js +19 -1
- package/dist/socket.d.ts +1 -1
- package/dist/socket.js +11 -0
- package/dist/store.d.ts +23 -2
- package/dist/store.js +8 -0
- package/dist/wholesaleRequest.d.ts +161 -0
- package/dist/wholesaleRequest.js +22 -0
- package/package.json +1 -1
package/dist/cjs/index.js
CHANGED
|
@@ -121,6 +121,7 @@ __exportStar(require("./user.js"), exports);
|
|
|
121
121
|
__exportStar(require("./userActivity.js"), exports);
|
|
122
122
|
__exportStar(require("./valuation.js"), exports);
|
|
123
123
|
__exportStar(require("./webhook.js"), exports);
|
|
124
|
+
__exportStar(require("./wholesaleRequest.js"), exports);
|
|
124
125
|
__exportStar(require("./wire.js"), exports);
|
|
125
126
|
__exportStar(require("./workItem.js"), exports);
|
|
126
127
|
__exportStar(require("./zone.js"), exports);
|
package/dist/cjs/notification.js
CHANGED
|
@@ -6,7 +6,7 @@ exports.WEB_NOTIFICATIONS_MAX_LIMIT = exports.CUSTOMER_NOTIFICATION_TYPES = expo
|
|
|
6
6
|
// legacy opt-ins and explicit channel maps remain source data on USER rows.
|
|
7
7
|
// Addressed ERROR / ML_FACTURADOR_COLLISION / ML_SELLER_SWITCHED /
|
|
8
8
|
// ML_CONNECTION_BROKEN / MENTION / CUSTOMER_PENDING_APPROVAL /
|
|
9
|
-
// PAYMENT_ATTEMPT_RESOLUTION do not select a producer subscriber audience;
|
|
9
|
+
// PAYMENT_ATTEMPT_RESOLUTION / CUSTOMER_WHOLESALE_REQUEST do not select a producer subscriber audience;
|
|
10
10
|
// the consumer still reads the live USER row for each delivery channel.
|
|
11
11
|
// AFIP_CERT_EXPIRY is seeded on the founding user and uses the subscriber index.
|
|
12
12
|
// Exported as a real enum consumed by api and app; adding an indexed type
|
|
@@ -199,6 +199,24 @@ var NotificationTypeEnum;
|
|
|
199
199
|
* re-opens rings again.
|
|
200
200
|
*/
|
|
201
201
|
NotificationTypeEnum["PAYMENT_ATTEMPT_RESOLUTION"] = "PAYMENT_ATTEMPT_RESOLUTION";
|
|
202
|
+
/**
|
|
203
|
+
* A signed-in storefront buyer asked for a wholesale account
|
|
204
|
+
* (`POST /user { mode: 'wholesale-request' }`) and the request waits in the
|
|
205
|
+
* operator queue (`GET /customers?mode=wholesale-requests`). Names the buyer
|
|
206
|
+
* by name only — never their email or CUIT.
|
|
207
|
+
*
|
|
208
|
+
* ⚠️ ADMIN-ONLY, and its own preference key. The producer fans out to every
|
|
209
|
+
* non-disabled ADMIN of the store (`listActiveAdmins`) — the tier that reads
|
|
210
|
+
* the queue and decides it — so a client offers the
|
|
211
|
+
* `CUSTOMER_WHOLESALE_REQUEST` toggle to ADMINs only. No legacy opt-in scan:
|
|
212
|
+
* the consumer enforces explicit type/channel preferences
|
|
213
|
+
* (`notificationPreferences.CUSTOMER_WHOLESALE_REQUEST`), default-on when
|
|
214
|
+
* absent. Additive — no backfill or consumer migration owed.
|
|
215
|
+
*
|
|
216
|
+
* ⚠️ Carries `wholesaleRequestRef` and NEVER a top-level `customerId` (an
|
|
217
|
+
* audience — the bell would reach the buyer's own storefront socket).
|
|
218
|
+
*/
|
|
219
|
+
NotificationTypeEnum["CUSTOMER_WHOLESALE_REQUEST"] = "CUSTOMER_WHOLESALE_REQUEST";
|
|
202
220
|
})(NotificationTypeEnum || (exports.NotificationTypeEnum = NotificationTypeEnum = {}));
|
|
203
221
|
/**
|
|
204
222
|
* The notification types a CUSTOMER bell can carry today; each links through
|
package/dist/cjs/socket.js
CHANGED
|
@@ -691,6 +691,17 @@ exports.SOCKET_ACTIONS = [
|
|
|
691
691
|
* where the role and scope gates sit.
|
|
692
692
|
*/
|
|
693
693
|
'workItems',
|
|
694
|
+
/**
|
|
695
|
+
* BE → the store's ADMIN-TIER operator sockets when a buyer's wholesale
|
|
696
|
+
* request is submitted or decided. Carries the `WholesaleRequest` row as it
|
|
697
|
+
* now stands (company data included), so the queue can patch in place.
|
|
698
|
+
*
|
|
699
|
+
* ⚠️ Admin tier only — `wsPostStore(..., { audience: 'operator', lowTierData:
|
|
700
|
+
* null })`: the queue is an admin-tier read, so a USER or PRINTER socket
|
|
701
|
+
* receives nothing. The buyer follows their own request on the `'customers'`
|
|
702
|
+
* action instead (`WholesaleRequestStatusFrame`).
|
|
703
|
+
*/
|
|
704
|
+
'wholesaleRequests',
|
|
694
705
|
];
|
|
695
706
|
/** Runtime guard — narrows an untrusted string to a known action. */
|
|
696
707
|
const isSocketAction = (value) => typeof value === 'string' && exports.SOCKET_ACTIONS.includes(value);
|
package/dist/cjs/store.js
CHANGED
|
@@ -139,6 +139,13 @@ exports.STORE_MODULE_ERROR_CODES = [
|
|
|
139
139
|
* entry naming no list of the store, with `data: { field, value }` where
|
|
140
140
|
* `field` is `<catalog>[<row>].availability.priceLists[<entry>]`.
|
|
141
141
|
*
|
|
142
|
+
* Request refusal, `409`:
|
|
143
|
+
* - `WHOLESALE_LIST_REQUIRED` — an `ecommerce` save turns
|
|
144
|
+
* `config.wholesaleRequests` on while the store holds no
|
|
145
|
+
* `audienceClass: 'wholesale'` list (`store/_ecommercePatch.ts`), with
|
|
146
|
+
* `data: { field: 'ecommerce.config.wholesaleRequests' }`. The platform PUT
|
|
147
|
+
* answers it too.
|
|
148
|
+
*
|
|
142
149
|
* Maintenance mode (`{ mode: 'maintenance', level }`, `store/_patchMaintenance.ts`):
|
|
143
150
|
* - `FORBIDDEN` (403) — the caller is neither an ADMIN nor a MANAGER.
|
|
144
151
|
* - `STORE_NOT_FOUND` (404) — the store row is gone.
|
|
@@ -170,6 +177,7 @@ exports.STORE_PATCH_ERROR_CODES = [
|
|
|
170
177
|
'DISPLAY_CURRENCY_NOT_INVOICEABLE',
|
|
171
178
|
'PRODUCT_CURRENCY_NOT_INVOICEABLE',
|
|
172
179
|
'PRICE_LIST_NOT_FOUND',
|
|
180
|
+
'WHOLESALE_LIST_REQUIRED',
|
|
173
181
|
'FORBIDDEN',
|
|
174
182
|
'STORE_NOT_FOUND',
|
|
175
183
|
];
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* A signed-in storefront buyer's request for a wholesale account, and the
|
|
4
|
+
* operator queue that decides it.
|
|
5
|
+
*
|
|
6
|
+
* One row per customer (`WHOLESALEREQ#{storeId}` / `{customerId}`). A new
|
|
7
|
+
* request overwrites the previous one only once that one is decided, so a
|
|
8
|
+
* customer holds at most one pending request.
|
|
9
|
+
*
|
|
10
|
+
* The flow is offered only while the store's
|
|
11
|
+
* `ecommerce.config.wholesaleRequests` is `true` (absent = off).
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.WHOLESALE_REQUEST_REASON_MAX = exports.WHOLESALE_REQUEST_PHONE_MAX = exports.WHOLESALE_REQUEST_MESSAGE_MAX = exports.WHOLESALE_REQUEST_ACTIVITY_MAX = exports.WHOLESALE_REQUEST_RAZON_SOCIAL_MAX = exports.WHOLESALE_REQUESTS_PAGE_MAX = exports.WHOLESALE_REQUEST_STATES = void 0;
|
|
15
|
+
/** The three states a request moves through. */
|
|
16
|
+
exports.WHOLESALE_REQUEST_STATES = ['pending', 'approved', 'declined'];
|
|
17
|
+
/** `GET /customers?mode=wholesale-requests` page ceiling; the default page is 50. */
|
|
18
|
+
exports.WHOLESALE_REQUESTS_PAGE_MAX = 100;
|
|
19
|
+
/** Character ceilings on the buyer's free text, counted after trimming. */
|
|
20
|
+
exports.WHOLESALE_REQUEST_RAZON_SOCIAL_MAX = 200;
|
|
21
|
+
exports.WHOLESALE_REQUEST_ACTIVITY_MAX = 120;
|
|
22
|
+
exports.WHOLESALE_REQUEST_MESSAGE_MAX = 1000;
|
|
23
|
+
exports.WHOLESALE_REQUEST_PHONE_MAX = 30;
|
|
24
|
+
/** Character ceiling on the operator's decline reason, counted after trimming. */
|
|
25
|
+
exports.WHOLESALE_REQUEST_REASON_MAX = 500;
|
package/dist/customer.d.ts
CHANGED
|
@@ -1238,6 +1238,15 @@ declare global {
|
|
|
1238
1238
|
* On BOTH surfaces; `[]` when the subject has none.
|
|
1239
1239
|
*/
|
|
1240
1240
|
recentPurchases: CustomerRecentPurchaseExportEntry[];
|
|
1241
|
+
/**
|
|
1242
|
+
* The subject's wholesale-account requests, on BOTH surfaces: the one filed
|
|
1243
|
+
* under their own id plus any filed under a merged-away id folded into them
|
|
1244
|
+
* (the same folded ids, and the same cap, as the financial collections) —
|
|
1245
|
+
* the company data submitted and its state, never the decline reason or the
|
|
1246
|
+
* deciding operator. Absent when there is none (and from servers predating
|
|
1247
|
+
* the request flow).
|
|
1248
|
+
*/
|
|
1249
|
+
wholesaleRequests?: WholesaleRequestExportEntry[];
|
|
1241
1250
|
/**
|
|
1242
1251
|
* Per COLLECTION, and honest: `true` means the read stopped before the
|
|
1243
1252
|
* end of a partition, folded financial IDs were omitted at the cap, or whole
|
|
@@ -1261,6 +1270,12 @@ declare global {
|
|
|
1261
1270
|
favorites: boolean;
|
|
1262
1271
|
/** `true` when folded ids past the cap were not read. */
|
|
1263
1272
|
recentPurchases: boolean;
|
|
1273
|
+
/**
|
|
1274
|
+
* Present when `wholesaleRequests` is, or when merged-away ids were cut
|
|
1275
|
+
* at the folded-id cap — then `true`: a request filed under an omitted id
|
|
1276
|
+
* may be missing.
|
|
1277
|
+
*/
|
|
1278
|
+
wholesaleRequests?: boolean;
|
|
1264
1279
|
};
|
|
1265
1280
|
}
|
|
1266
1281
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -97,6 +97,7 @@ export * from './user.ts';
|
|
|
97
97
|
export * from './userActivity.ts';
|
|
98
98
|
export * from './valuation.ts';
|
|
99
99
|
export * from './webhook.ts';
|
|
100
|
+
export * from './wholesaleRequest.ts';
|
|
100
101
|
export * from './wire.ts';
|
|
101
102
|
export * from './workItem.ts';
|
|
102
103
|
export * from './zone.ts';
|
package/dist/index.js
CHANGED
|
@@ -105,6 +105,7 @@ export * from "./user.js";
|
|
|
105
105
|
export * from "./userActivity.js";
|
|
106
106
|
export * from "./valuation.js";
|
|
107
107
|
export * from "./webhook.js";
|
|
108
|
+
export * from "./wholesaleRequest.js";
|
|
108
109
|
export * from "./wire.js";
|
|
109
110
|
export * from "./workItem.js";
|
|
110
111
|
export * from "./zone.js";
|
package/dist/notification.d.ts
CHANGED
|
@@ -177,7 +177,25 @@ export declare enum NotificationTypeEnum {
|
|
|
177
177
|
* nothing. An attempt an operator closed (`resolved`) and a later approval
|
|
178
178
|
* re-opens rings again.
|
|
179
179
|
*/
|
|
180
|
-
PAYMENT_ATTEMPT_RESOLUTION = "PAYMENT_ATTEMPT_RESOLUTION"
|
|
180
|
+
PAYMENT_ATTEMPT_RESOLUTION = "PAYMENT_ATTEMPT_RESOLUTION",
|
|
181
|
+
/**
|
|
182
|
+
* A signed-in storefront buyer asked for a wholesale account
|
|
183
|
+
* (`POST /user { mode: 'wholesale-request' }`) and the request waits in the
|
|
184
|
+
* operator queue (`GET /customers?mode=wholesale-requests`). Names the buyer
|
|
185
|
+
* by name only — never their email or CUIT.
|
|
186
|
+
*
|
|
187
|
+
* ⚠️ ADMIN-ONLY, and its own preference key. The producer fans out to every
|
|
188
|
+
* non-disabled ADMIN of the store (`listActiveAdmins`) — the tier that reads
|
|
189
|
+
* the queue and decides it — so a client offers the
|
|
190
|
+
* `CUSTOMER_WHOLESALE_REQUEST` toggle to ADMINs only. No legacy opt-in scan:
|
|
191
|
+
* the consumer enforces explicit type/channel preferences
|
|
192
|
+
* (`notificationPreferences.CUSTOMER_WHOLESALE_REQUEST`), default-on when
|
|
193
|
+
* absent. Additive — no backfill or consumer migration owed.
|
|
194
|
+
*
|
|
195
|
+
* ⚠️ Carries `wholesaleRequestRef` and NEVER a top-level `customerId` (an
|
|
196
|
+
* audience — the bell would reach the buyer's own storefront socket).
|
|
197
|
+
*/
|
|
198
|
+
CUSTOMER_WHOLESALE_REQUEST = "CUSTOMER_WHOLESALE_REQUEST"
|
|
181
199
|
}
|
|
182
200
|
/**
|
|
183
201
|
* The notification types a CUSTOMER bell can carry today; each links through
|
|
@@ -290,6 +308,11 @@ declare global {
|
|
|
290
308
|
* POINTER, not an audience — see {@link PendingCustomerRef}.
|
|
291
309
|
*/
|
|
292
310
|
pendingCustomerRef?: PendingCustomerRef;
|
|
311
|
+
/**
|
|
312
|
+
* `CUSTOMER_WHOLESALE_REQUEST` only: which request to open. A POINTER, not
|
|
313
|
+
* an audience — see {@link WholesaleRequestRef}.
|
|
314
|
+
*/
|
|
315
|
+
wholesaleRequestRef?: WholesaleRequestRef;
|
|
293
316
|
/** `MENTION` only: the colleague who wrote the mention (a snapshot). */
|
|
294
317
|
actor?: NotificationActor;
|
|
295
318
|
userId?: string;
|
|
@@ -353,7 +376,7 @@ declare global {
|
|
|
353
376
|
* customer socket carry — the stored row minus the operator-only pointers.
|
|
354
377
|
* A union keyed on `type`; `ORDER` is its only member today.
|
|
355
378
|
*/
|
|
356
|
-
type CustomerNotification = Omit<NotificationInterface, 'cartRef' | 'pendingCustomerRef' | 'TableName' | 'type' | 'orderId'> & {
|
|
379
|
+
type CustomerNotification = Omit<NotificationInterface, 'cartRef' | 'pendingCustomerRef' | 'wholesaleRequestRef' | 'TableName' | 'type' | 'orderId'> & {
|
|
357
380
|
type: NotificationTypeEnum.ORDER;
|
|
358
381
|
/** Set on every customer row: the order the bell is about. */
|
|
359
382
|
orderId: string;
|
package/dist/notification.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// legacy opt-ins and explicit channel maps remain source data on USER rows.
|
|
4
4
|
// Addressed ERROR / ML_FACTURADOR_COLLISION / ML_SELLER_SWITCHED /
|
|
5
5
|
// ML_CONNECTION_BROKEN / MENTION / CUSTOMER_PENDING_APPROVAL /
|
|
6
|
-
// PAYMENT_ATTEMPT_RESOLUTION do not select a producer subscriber audience;
|
|
6
|
+
// PAYMENT_ATTEMPT_RESOLUTION / CUSTOMER_WHOLESALE_REQUEST do not select a producer subscriber audience;
|
|
7
7
|
// the consumer still reads the live USER row for each delivery channel.
|
|
8
8
|
// AFIP_CERT_EXPIRY is seeded on the founding user and uses the subscriber index.
|
|
9
9
|
// Exported as a real enum consumed by api and app; adding an indexed type
|
|
@@ -196,6 +196,24 @@ export var NotificationTypeEnum;
|
|
|
196
196
|
* re-opens rings again.
|
|
197
197
|
*/
|
|
198
198
|
NotificationTypeEnum["PAYMENT_ATTEMPT_RESOLUTION"] = "PAYMENT_ATTEMPT_RESOLUTION";
|
|
199
|
+
/**
|
|
200
|
+
* A signed-in storefront buyer asked for a wholesale account
|
|
201
|
+
* (`POST /user { mode: 'wholesale-request' }`) and the request waits in the
|
|
202
|
+
* operator queue (`GET /customers?mode=wholesale-requests`). Names the buyer
|
|
203
|
+
* by name only — never their email or CUIT.
|
|
204
|
+
*
|
|
205
|
+
* ⚠️ ADMIN-ONLY, and its own preference key. The producer fans out to every
|
|
206
|
+
* non-disabled ADMIN of the store (`listActiveAdmins`) — the tier that reads
|
|
207
|
+
* the queue and decides it — so a client offers the
|
|
208
|
+
* `CUSTOMER_WHOLESALE_REQUEST` toggle to ADMINs only. No legacy opt-in scan:
|
|
209
|
+
* the consumer enforces explicit type/channel preferences
|
|
210
|
+
* (`notificationPreferences.CUSTOMER_WHOLESALE_REQUEST`), default-on when
|
|
211
|
+
* absent. Additive — no backfill or consumer migration owed.
|
|
212
|
+
*
|
|
213
|
+
* ⚠️ Carries `wholesaleRequestRef` and NEVER a top-level `customerId` (an
|
|
214
|
+
* audience — the bell would reach the buyer's own storefront socket).
|
|
215
|
+
*/
|
|
216
|
+
NotificationTypeEnum["CUSTOMER_WHOLESALE_REQUEST"] = "CUSTOMER_WHOLESALE_REQUEST";
|
|
199
217
|
})(NotificationTypeEnum || (NotificationTypeEnum = {}));
|
|
200
218
|
/**
|
|
201
219
|
* The notification types a CUSTOMER bell can carry today; each links through
|
package/dist/socket.d.ts
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
* A client must ignore actions it does not own rather than assume it
|
|
27
27
|
* receives all of them.
|
|
28
28
|
*/
|
|
29
|
-
export declare const SOCKET_ACTIONS: readonly ["account", "appointments", "appointmentWaitlist", "attendance", "attributes", "automation-rules", "baskets", "cart", "brands", "cash", "catalogOperation", "categories", "campaigns", "customers", "customerNote", "customerAddress", "customerContact", "deliveries", "globals", "inventory", "invoices", "literals", "loyalty", "orders", "presupuestos", "products", "promotions", "segments", "returns", "rma", "templates", "services", "service-templates", "shifts", "stores", "suppliers", "supplier-invoice", "support", "surveys", "users", "warehouses", "zones", "favorites", "webhooks", "account-delete", "baskets-delete", "cart-delete", "log-delete", "notifications", "support-message", "payment_received", "mp_payment_status_changed", "payment_linked", "payment_unlinked", "mercadopago", "mercadopago_dynamic_qr_created", "mercadopago_static_qr_created", "mp_hook_log_appended", "mp_ipn_log_appended", "orderPaymentAttempt", "orderDelivery", "paymentAttemptChanged", "stripe", "subscription", "caea", "print", "print-order", "print-invoice", "print-product", "print-tag", "print_job_failed", "request_printers", "printers_changed", "agent_status_changed", "print_rules_changed", "printers_active", "agent_command", "maintenance", "currency_auto_updated", "drain_progress", "integration_event_appended", "userActivityRecorded", "mercadolibre_settlement_period", "customDomain", "purchaseOrders", "cycleCounts", "stockTransfers", "workItems"];
|
|
29
|
+
export declare const SOCKET_ACTIONS: readonly ["account", "appointments", "appointmentWaitlist", "attendance", "attributes", "automation-rules", "baskets", "cart", "brands", "cash", "catalogOperation", "categories", "campaigns", "customers", "customerNote", "customerAddress", "customerContact", "deliveries", "globals", "inventory", "invoices", "literals", "loyalty", "orders", "presupuestos", "products", "promotions", "segments", "returns", "rma", "templates", "services", "service-templates", "shifts", "stores", "suppliers", "supplier-invoice", "support", "surveys", "users", "warehouses", "zones", "favorites", "webhooks", "account-delete", "baskets-delete", "cart-delete", "log-delete", "notifications", "support-message", "payment_received", "mp_payment_status_changed", "payment_linked", "payment_unlinked", "mercadopago", "mercadopago_dynamic_qr_created", "mercadopago_static_qr_created", "mp_hook_log_appended", "mp_ipn_log_appended", "orderPaymentAttempt", "orderDelivery", "paymentAttemptChanged", "stripe", "subscription", "caea", "print", "print-order", "print-invoice", "print-product", "print-tag", "print_job_failed", "request_printers", "printers_changed", "agent_status_changed", "print_rules_changed", "printers_active", "agent_command", "maintenance", "currency_auto_updated", "drain_progress", "integration_event_appended", "userActivityRecorded", "mercadolibre_settlement_period", "customDomain", "purchaseOrders", "cycleCounts", "stockTransfers", "workItems", "wholesaleRequests"];
|
|
30
30
|
/** Union of every server→client data-frame action. */
|
|
31
31
|
export type SocketAction = (typeof SOCKET_ACTIONS)[number];
|
|
32
32
|
/**
|
package/dist/socket.js
CHANGED
|
@@ -688,6 +688,17 @@ export const SOCKET_ACTIONS = [
|
|
|
688
688
|
* where the role and scope gates sit.
|
|
689
689
|
*/
|
|
690
690
|
'workItems',
|
|
691
|
+
/**
|
|
692
|
+
* BE → the store's ADMIN-TIER operator sockets when a buyer's wholesale
|
|
693
|
+
* request is submitted or decided. Carries the `WholesaleRequest` row as it
|
|
694
|
+
* now stands (company data included), so the queue can patch in place.
|
|
695
|
+
*
|
|
696
|
+
* ⚠️ Admin tier only — `wsPostStore(..., { audience: 'operator', lowTierData:
|
|
697
|
+
* null })`: the queue is an admin-tier read, so a USER or PRINTER socket
|
|
698
|
+
* receives nothing. The buyer follows their own request on the `'customers'`
|
|
699
|
+
* action instead (`WholesaleRequestStatusFrame`).
|
|
700
|
+
*/
|
|
701
|
+
'wholesaleRequests',
|
|
691
702
|
];
|
|
692
703
|
/** Runtime guard — narrows an untrusted string to a known action. */
|
|
693
704
|
export const isSocketAction = (value) => typeof value === 'string' && SOCKET_ACTIONS.includes(value);
|
package/dist/store.d.ts
CHANGED
|
@@ -146,6 +146,18 @@ declare global {
|
|
|
146
146
|
* frame), so the storefront can say the account needs approval.
|
|
147
147
|
*/
|
|
148
148
|
registrationMode?: 'open' | 'approval';
|
|
149
|
+
/**
|
|
150
|
+
* Whether a signed-in storefront buyer may ask for a wholesale account
|
|
151
|
+
* (`POST /user { mode: 'wholesale-request' }`). Absent or `false` = off:
|
|
152
|
+
* the request route refuses `403 WHOLESALE_REQUESTS_DISABLED`. Explicit on
|
|
153
|
+
* purpose — a store may hold wholesale-class lists for customers it assigns
|
|
154
|
+
* itself without inviting requests. Turning it on requires at least one
|
|
155
|
+
* `audienceClass: 'wholesale'` list (`409 WHOLESALE_LIST_REQUIRED`).
|
|
156
|
+
* Written by `PATCH /store` (ADMIN) and `PUT /platform/stores/{storeId}`
|
|
157
|
+
* (MANAGER). SENT TO SHOPPERS (web `GET /store` and the customer `stores`
|
|
158
|
+
* frame), so the storefront can offer the request.
|
|
159
|
+
*/
|
|
160
|
+
wholesaleRequests?: boolean;
|
|
149
161
|
/**
|
|
150
162
|
* How long a storefront online payment holds the order, in whole
|
|
151
163
|
* minutes: the payment attempt's `expiresAt` and its Checkout Pro
|
|
@@ -198,9 +210,11 @@ declare global {
|
|
|
198
210
|
/** Sparse tenant PATCH shape; live null values reset to registry defaults and are never stored.
|
|
199
211
|
* An unknown newCustomerPriceList refuses 400 PRICE_LIST_NOT_FOUND with
|
|
200
212
|
* data: { field: 'ecommerce.config.newCustomerPriceList', value: number }; nothing written.
|
|
213
|
+
* `wholesaleRequests: true` on a store with no `audienceClass: 'wholesale'` list
|
|
214
|
+
* refuses 409 WHOLESALE_LIST_REQUIRED; nothing written.
|
|
201
215
|
*/
|
|
202
216
|
interface EcommercePatchInput {
|
|
203
|
-
config?: Pick<NonNullable<Ecommerce['config']>, 'showDefaultPriceList' | 'newCustomerPriceList' | 'registrationMode' | 'paymentHoldMinutes'> & StorefrontLiveSettingsPatch;
|
|
217
|
+
config?: Pick<NonNullable<Ecommerce['config']>, 'showDefaultPriceList' | 'newCustomerPriceList' | 'registrationMode' | 'wholesaleRequests' | 'paymentHoldMinutes'> & StorefrontLiveSettingsPatch;
|
|
204
218
|
sidebar?: Ecommerce['sidebar'];
|
|
205
219
|
home?: Omit<NonNullable<Ecommerce['home']>, 'displayOrders' | 'displayProfile'>;
|
|
206
220
|
themeColors?: Ecommerce['themeColors'];
|
|
@@ -2398,6 +2412,13 @@ export type StoreModuleRefusalBody = {
|
|
|
2398
2412
|
* entry naming no list of the store, with `data: { field, value }` where
|
|
2399
2413
|
* `field` is `<catalog>[<row>].availability.priceLists[<entry>]`.
|
|
2400
2414
|
*
|
|
2415
|
+
* Request refusal, `409`:
|
|
2416
|
+
* - `WHOLESALE_LIST_REQUIRED` — an `ecommerce` save turns
|
|
2417
|
+
* `config.wholesaleRequests` on while the store holds no
|
|
2418
|
+
* `audienceClass: 'wholesale'` list (`store/_ecommercePatch.ts`), with
|
|
2419
|
+
* `data: { field: 'ecommerce.config.wholesaleRequests' }`. The platform PUT
|
|
2420
|
+
* answers it too.
|
|
2421
|
+
*
|
|
2401
2422
|
* Maintenance mode (`{ mode: 'maintenance', level }`, `store/_patchMaintenance.ts`):
|
|
2402
2423
|
* - `FORBIDDEN` (403) — the caller is neither an ADMIN nor a MANAGER.
|
|
2403
2424
|
* - `STORE_NOT_FOUND` (404) — the store row is gone.
|
|
@@ -2411,5 +2432,5 @@ export type StoreModuleRefusalBody = {
|
|
|
2411
2432
|
* checks, the display-currency lock, the storefront fence) are not listed
|
|
2412
2433
|
* either. Cross-cutting refusals: check `GATING_ERROR_CODES` as well.
|
|
2413
2434
|
*/
|
|
2414
|
-
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"];
|
|
2435
|
+
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", "WHOLESALE_LIST_REQUIRED", "FORBIDDEN", "STORE_NOT_FOUND"];
|
|
2415
2436
|
export type StorePatchErrorCode = (typeof STORE_PATCH_ERROR_CODES)[number];
|
package/dist/store.js
CHANGED
|
@@ -134,6 +134,13 @@ export const STORE_MODULE_ERROR_CODES = [
|
|
|
134
134
|
* entry naming no list of the store, with `data: { field, value }` where
|
|
135
135
|
* `field` is `<catalog>[<row>].availability.priceLists[<entry>]`.
|
|
136
136
|
*
|
|
137
|
+
* Request refusal, `409`:
|
|
138
|
+
* - `WHOLESALE_LIST_REQUIRED` — an `ecommerce` save turns
|
|
139
|
+
* `config.wholesaleRequests` on while the store holds no
|
|
140
|
+
* `audienceClass: 'wholesale'` list (`store/_ecommercePatch.ts`), with
|
|
141
|
+
* `data: { field: 'ecommerce.config.wholesaleRequests' }`. The platform PUT
|
|
142
|
+
* answers it too.
|
|
143
|
+
*
|
|
137
144
|
* Maintenance mode (`{ mode: 'maintenance', level }`, `store/_patchMaintenance.ts`):
|
|
138
145
|
* - `FORBIDDEN` (403) — the caller is neither an ADMIN nor a MANAGER.
|
|
139
146
|
* - `STORE_NOT_FOUND` (404) — the store row is gone.
|
|
@@ -165,6 +172,7 @@ export const STORE_PATCH_ERROR_CODES = [
|
|
|
165
172
|
'DISPLAY_CURRENCY_NOT_INVOICEABLE',
|
|
166
173
|
'PRODUCT_CURRENCY_NOT_INVOICEABLE',
|
|
167
174
|
'PRICE_LIST_NOT_FOUND',
|
|
175
|
+
'WHOLESALE_LIST_REQUIRED',
|
|
168
176
|
'FORBIDDEN',
|
|
169
177
|
'STORE_NOT_FOUND',
|
|
170
178
|
];
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A signed-in storefront buyer's request for a wholesale account, and the
|
|
3
|
+
* operator queue that decides it.
|
|
4
|
+
*
|
|
5
|
+
* One row per customer (`WHOLESALEREQ#{storeId}` / `{customerId}`). A new
|
|
6
|
+
* request overwrites the previous one only once that one is decided, so a
|
|
7
|
+
* customer holds at most one pending request.
|
|
8
|
+
*
|
|
9
|
+
* The flow is offered only while the store's
|
|
10
|
+
* `ecommerce.config.wholesaleRequests` is `true` (absent = off).
|
|
11
|
+
*/
|
|
12
|
+
/** The three states a request moves through. */
|
|
13
|
+
export declare const WHOLESALE_REQUEST_STATES: readonly ["pending", "approved", "declined"];
|
|
14
|
+
/** `GET /customers?mode=wholesale-requests` page ceiling; the default page is 50. */
|
|
15
|
+
export declare const WHOLESALE_REQUESTS_PAGE_MAX = 100;
|
|
16
|
+
/** Character ceilings on the buyer's free text, counted after trimming. */
|
|
17
|
+
export declare const WHOLESALE_REQUEST_RAZON_SOCIAL_MAX = 200;
|
|
18
|
+
export declare const WHOLESALE_REQUEST_ACTIVITY_MAX = 120;
|
|
19
|
+
export declare const WHOLESALE_REQUEST_MESSAGE_MAX = 1000;
|
|
20
|
+
export declare const WHOLESALE_REQUEST_PHONE_MAX = 30;
|
|
21
|
+
/** Character ceiling on the operator's decline reason, counted after trimming. */
|
|
22
|
+
export declare const WHOLESALE_REQUEST_REASON_MAX = 500;
|
|
23
|
+
declare global {
|
|
24
|
+
type WholesaleRequestState = (typeof WHOLESALE_REQUEST_STATES)[number];
|
|
25
|
+
/**
|
|
26
|
+
* The company data a buyer submits. `cuit`, `razonSocial` and `condFiscal`
|
|
27
|
+
* are required; the rest is optional.
|
|
28
|
+
*
|
|
29
|
+
* ⚠️ PII under Ley 25.326. It reaches the operator queue and the buyer's own
|
|
30
|
+
* data export, and never a bell, a log line or an ERROR row.
|
|
31
|
+
*/
|
|
32
|
+
interface WholesaleRequestCompany {
|
|
33
|
+
/** 11 digits with a valid check digit, stored digits-only. */
|
|
34
|
+
cuit: string;
|
|
35
|
+
razonSocial: string;
|
|
36
|
+
/** A `condFiscal` code from `FISCAL_CONDITIONS`. */
|
|
37
|
+
condFiscal: number;
|
|
38
|
+
activity?: string;
|
|
39
|
+
phone?: string;
|
|
40
|
+
message?: string;
|
|
41
|
+
}
|
|
42
|
+
/** Web `POST /user` body that submits a request. */
|
|
43
|
+
interface WholesaleRequestInput extends WholesaleRequestCompany {
|
|
44
|
+
mode: 'wholesale-request';
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* What the BUYER sees of their request: web `GET /user?mode=wholesale-request`
|
|
48
|
+
* (`data`, or `data: null` when they never asked), the submit's answer and
|
|
49
|
+
* the status frame. Never the decline reason, the deciding operator or the
|
|
50
|
+
* list it moved them to.
|
|
51
|
+
*/
|
|
52
|
+
interface WholesaleRequestStatus {
|
|
53
|
+
status: WholesaleRequestState;
|
|
54
|
+
/** Unix ms the request was submitted. */
|
|
55
|
+
createdAt: number;
|
|
56
|
+
/** Unix ms of the decision. Absent while pending. */
|
|
57
|
+
decidedAt?: number;
|
|
58
|
+
}
|
|
59
|
+
/** The operator's view of one request (admin tier only). */
|
|
60
|
+
interface WholesaleRequest extends WholesaleRequestCompany {
|
|
61
|
+
customerId: string;
|
|
62
|
+
status: WholesaleRequestState;
|
|
63
|
+
createdAt: number;
|
|
64
|
+
updatedAt?: number;
|
|
65
|
+
decidedAt?: number;
|
|
66
|
+
/** The deciding operator's user id. */
|
|
67
|
+
decidedBy?: string;
|
|
68
|
+
/** On approval: the wholesale-class list the customer was moved to. */
|
|
69
|
+
priceList?: number;
|
|
70
|
+
/** On decline: the operator's note. Operator-only, never sent to the buyer. */
|
|
71
|
+
reason?: string;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Where the requesting customer stands now, read off the CUSTOMER row when
|
|
75
|
+
* the queue page is served. A request whose customer is gone is listed with
|
|
76
|
+
* that state, never dropped.
|
|
77
|
+
*/
|
|
78
|
+
type WholesaleRequestCustomerState = 'active' | 'disabled' | 'missing' | 'anonymized' | 'merged';
|
|
79
|
+
/** One `GET /customers?mode=wholesale-requests` item. */
|
|
80
|
+
interface WholesaleRequestQueueEntry extends WholesaleRequest {
|
|
81
|
+
customer: {
|
|
82
|
+
state: WholesaleRequestCustomerState;
|
|
83
|
+
fullName?: string;
|
|
84
|
+
/** The customer's CURRENT stored list. */
|
|
85
|
+
priceList?: number;
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* `GET /customers?mode=wholesale-requests` answer. `LastEvaluatedKey` is an
|
|
90
|
+
* opaque cursor, sent back as `?startKey=`; present (with `truncated: true`)
|
|
91
|
+
* only while more rows may follow.
|
|
92
|
+
*/
|
|
93
|
+
interface WholesaleRequestsQueueResponse {
|
|
94
|
+
message: string;
|
|
95
|
+
data: WholesaleRequestQueueEntry[];
|
|
96
|
+
LastEvaluatedKey?: string;
|
|
97
|
+
truncated?: boolean;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* App `POST /customers` body that decides a request. `'approved'` requires a
|
|
101
|
+
* wholesale-class `priceList` and refuses a `reason`; `'declined'` refuses a
|
|
102
|
+
* `priceList`. `createdAt` is the request's own, as the queue served it: a
|
|
103
|
+
* request declined and resubmitted since is a different request, refused
|
|
104
|
+
* `409 WHOLESALE_REQUEST_NOT_PENDING` rather than decided unseen.
|
|
105
|
+
*/
|
|
106
|
+
type WholesaleDecisionInput = {
|
|
107
|
+
mode: 'wholesale-decision';
|
|
108
|
+
customerId: string;
|
|
109
|
+
createdAt: number;
|
|
110
|
+
decision: 'approved';
|
|
111
|
+
priceList: number;
|
|
112
|
+
} | {
|
|
113
|
+
mode: 'wholesale-decision';
|
|
114
|
+
customerId: string;
|
|
115
|
+
createdAt: number;
|
|
116
|
+
decision: 'declined';
|
|
117
|
+
reason?: string;
|
|
118
|
+
};
|
|
119
|
+
/**
|
|
120
|
+
* App `POST /customers { mode: 'wholesale-decision' }` answer: the request as
|
|
121
|
+
* it now stands. `fiscalIdentityApplied` rides an APPROVAL only — `true` when
|
|
122
|
+
* the submitted CUIT, razón social and condición fiscal were written into
|
|
123
|
+
* `Customer.afip`; `false` when they were not, because the customer already
|
|
124
|
+
* held an `afip` entry or a top-level `cuit` naming another taxpayer (then
|
|
125
|
+
* neither `afip` nor `cuit` is written, and the list still moves).
|
|
126
|
+
*/
|
|
127
|
+
interface WholesaleDecisionResponse {
|
|
128
|
+
message: string;
|
|
129
|
+
data: WholesaleRequest;
|
|
130
|
+
fiscalIdentityApplied?: boolean;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* The `customers` frame a buyer's own socket receives when their request is
|
|
134
|
+
* decided. Carries no `priceList`: the CUSTOMER row's own `customers` frame
|
|
135
|
+
* carries that on approval.
|
|
136
|
+
*/
|
|
137
|
+
interface WholesaleRequestStatusFrame {
|
|
138
|
+
customerId: string;
|
|
139
|
+
wholesaleRequest: WholesaleRequestStatus;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Which request a `CUSTOMER_WHOLESALE_REQUEST` operator bell is about. A
|
|
143
|
+
* POINTER, never an audience — the top-level `customerId` would deliver the
|
|
144
|
+
* bell to the buyer. Operator surfaces only.
|
|
145
|
+
*/
|
|
146
|
+
interface WholesaleRequestRef {
|
|
147
|
+
customerId: string;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* The request as it appears in the customer's own data export (both
|
|
151
|
+
* surfaces): the company data they submitted and the state, never the
|
|
152
|
+
* decline reason or the deciding operator.
|
|
153
|
+
*/
|
|
154
|
+
interface WholesaleRequestExportEntry extends WholesaleRequestCompany {
|
|
155
|
+
/** The id the request was filed under — the subject's, or a merged-away id folded into it. */
|
|
156
|
+
customerId: string;
|
|
157
|
+
status: WholesaleRequestState;
|
|
158
|
+
createdAt: number;
|
|
159
|
+
decidedAt?: number;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A signed-in storefront buyer's request for a wholesale account, and the
|
|
3
|
+
* operator queue that decides it.
|
|
4
|
+
*
|
|
5
|
+
* One row per customer (`WHOLESALEREQ#{storeId}` / `{customerId}`). A new
|
|
6
|
+
* request overwrites the previous one only once that one is decided, so a
|
|
7
|
+
* customer holds at most one pending request.
|
|
8
|
+
*
|
|
9
|
+
* The flow is offered only while the store's
|
|
10
|
+
* `ecommerce.config.wholesaleRequests` is `true` (absent = off).
|
|
11
|
+
*/
|
|
12
|
+
/** The three states a request moves through. */
|
|
13
|
+
export const WHOLESALE_REQUEST_STATES = ['pending', 'approved', 'declined'];
|
|
14
|
+
/** `GET /customers?mode=wholesale-requests` page ceiling; the default page is 50. */
|
|
15
|
+
export const WHOLESALE_REQUESTS_PAGE_MAX = 100;
|
|
16
|
+
/** Character ceilings on the buyer's free text, counted after trimming. */
|
|
17
|
+
export const WHOLESALE_REQUEST_RAZON_SOCIAL_MAX = 200;
|
|
18
|
+
export const WHOLESALE_REQUEST_ACTIVITY_MAX = 120;
|
|
19
|
+
export const WHOLESALE_REQUEST_MESSAGE_MAX = 1000;
|
|
20
|
+
export const WHOLESALE_REQUEST_PHONE_MAX = 30;
|
|
21
|
+
/** Character ceiling on the operator's decline reason, counted after trimming. */
|
|
22
|
+
export const WHOLESALE_REQUEST_REASON_MAX = 500;
|