@sixtyninecommerce/admin 0.10.0 → 0.11.0
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/README.md +4347 -171
- package/dist/catalog/assets.d.ts +120 -8
- package/dist/catalog/assets.js +98 -12
- package/dist/catalog/collections.d.ts +279 -14
- package/dist/catalog/collections.js +246 -15
- package/dist/catalog/index.d.ts +9 -2
- package/dist/catalog/index.js +4 -0
- package/dist/catalog/products.d.ts +159 -19
- package/dist/catalog/products.js +88 -13
- package/dist/catalog/properties.d.ts +102 -14
- package/dist/catalog/properties.js +13 -0
- package/dist/catalog/recommendations.d.ts +261 -0
- package/dist/catalog/recommendations.js +145 -0
- package/dist/catalog/reviews.d.ts +368 -0
- package/dist/catalog/reviews.js +318 -0
- package/dist/catalog/types.d.ts +17 -1
- package/dist/catalog/types.js +10 -0
- package/dist/catalog/variant-find.d.ts +136 -0
- package/dist/catalog/variant-find.js +239 -0
- package/dist/catalog/variants.d.ts +233 -26
- package/dist/catalog/variants.js +125 -7
- package/dist/catalog/visibility.d.ts +20 -5
- package/dist/catalog/visibility.js +19 -1
- package/dist/client.d.ts +95 -9
- package/dist/client.js +35 -7
- package/dist/content/assets.d.ts +286 -0
- package/dist/content/assets.js +181 -0
- package/dist/content/items.d.ts +269 -0
- package/dist/content/items.js +170 -0
- package/dist/content/types.d.ts +282 -0
- package/dist/content/types.js +100 -0
- package/dist/customers/age-verification.d.ts +66 -0
- package/dist/customers/age-verification.js +79 -0
- package/dist/customers/credit.d.ts +263 -0
- package/dist/customers/credit.js +244 -0
- package/dist/customers/delivery-preferences.d.ts +120 -0
- package/dist/customers/delivery-preferences.js +97 -0
- package/dist/customers/groups.d.ts +207 -0
- package/dist/customers/groups.js +438 -0
- package/dist/customers/index.d.ts +447 -37
- package/dist/customers/index.js +313 -40
- package/dist/customers/invitation-status.d.ts +57 -0
- package/dist/customers/invitation-status.js +21 -0
- package/dist/customers/notes.d.ts +67 -0
- package/dist/customers/notes.js +51 -0
- package/dist/customers/notification-recipients.d.ts +97 -0
- package/dist/customers/notification-recipients.js +84 -0
- package/dist/customers/saved-lists.d.ts +42 -0
- package/dist/customers/saved-lists.js +61 -0
- package/dist/customers/vat.d.ts +83 -0
- package/dist/customers/vat.js +46 -0
- package/dist/customers/wire.d.ts +20 -0
- package/dist/customers/wire.js +35 -0
- package/dist/documents/ar.d.ts +307 -0
- package/dist/documents/ar.js +254 -0
- package/dist/documents/index.d.ts +731 -21
- package/dist/documents/index.js +436 -24
- package/dist/documents/pdf.d.ts +2 -0
- package/dist/documents/pdf.js +11 -0
- package/dist/fulfillments/create.d.ts +167 -0
- package/dist/fulfillments/create.js +216 -0
- package/dist/fulfillments/index.d.ts +44 -10
- package/dist/fulfillments/index.js +11 -2
- package/dist/fulfillments/payment-policy.d.ts +64 -0
- package/dist/fulfillments/payment-policy.js +140 -0
- package/dist/fulfillments/warehouse.d.ts +724 -0
- package/dist/fulfillments/warehouse.js +914 -0
- package/dist/geo/index.d.ts +119 -0
- package/dist/geo/index.js +107 -0
- package/dist/index.d.ts +123 -35
- package/dist/index.js +45 -12
- package/dist/integrations/afas-actions.d.ts +234 -0
- package/dist/integrations/afas-actions.js +310 -0
- package/dist/integrations/afas-types.d.ts +483 -0
- package/dist/integrations/afas-types.js +5 -0
- package/dist/integrations/afas.d.ts +234 -0
- package/dist/integrations/afas.js +290 -0
- package/dist/integrations/connections.d.ts +103 -0
- package/dist/integrations/connections.js +55 -0
- package/dist/integrations/esp.d.ts +313 -0
- package/dist/integrations/esp.js +169 -0
- package/dist/integrations/exact-online-types.d.ts +423 -0
- package/dist/integrations/exact-online-types.js +6 -0
- package/dist/integrations/exact-online.d.ts +248 -0
- package/dist/integrations/exact-online.js +376 -0
- package/dist/integrations/index.d.ts +29 -3
- package/dist/integrations/index.js +18 -3
- package/dist/integrations/pipeline-keys.d.ts +13 -0
- package/dist/integrations/pipeline-keys.js +22 -0
- package/dist/integrations/pipelines.d.ts +15 -14
- package/dist/integrations/pipelines.js +6 -22
- package/dist/integrations/types.d.ts +146 -0
- package/dist/locations/index.d.ts +66 -0
- package/dist/locations/index.js +31 -0
- package/dist/meta/index.d.ts +162 -0
- package/dist/orders/cancel-with-money.d.ts +227 -0
- package/dist/orders/cancel-with-money.js +153 -0
- package/dist/orders/commit-edit.d.ts +7 -1
- package/dist/orders/commit-edit.js +5 -1
- package/dist/orders/drafts.d.ts +800 -0
- package/dist/orders/drafts.js +771 -0
- package/dist/orders/fields.d.ts +245 -0
- package/dist/orders/fields.js +188 -0
- package/dist/orders/get.d.ts +29 -19
- package/dist/orders/get.js +17 -8
- package/dist/orders/index.d.ts +49 -9
- package/dist/orders/index.js +22 -2
- package/dist/orders/lifecycle.d.ts +128 -0
- package/dist/orders/lifecycle.js +158 -0
- package/dist/orders/line-price-preview.d.ts +7 -2
- package/dist/orders/list.d.ts +222 -0
- package/dist/orders/list.js +377 -0
- package/dist/orders/manual-pricing.d.ts +5 -0
- package/dist/orders/order-entry.d.ts +20 -7
- package/dist/orders/plan-edit.d.ts +1 -1
- package/dist/orders/plan-edit.js +4 -1
- package/dist/orders/settings.d.ts +201 -0
- package/dist/orders/settings.js +325 -0
- package/dist/orders/status.d.ts +159 -13
- package/dist/orders/status.js +21 -0
- package/dist/orders/surcharges.d.ts +8 -1
- package/dist/orders/surcharges.js +3 -2
- package/dist/payments/account-credit.d.ts +30 -0
- package/dist/payments/account-credit.js +19 -0
- package/dist/payments/ar.d.ts +292 -0
- package/dist/payments/ar.js +223 -0
- package/dist/payments/connected-account.d.ts +47 -0
- package/dist/payments/connected-account.js +61 -0
- package/dist/payments/credit-noted-fields.d.ts +12 -0
- package/dist/payments/credit-noted-fields.js +37 -0
- package/dist/payments/index.d.ts +257 -11
- package/dist/payments/index.js +131 -1
- package/dist/payments/methods.d.ts +303 -8
- package/dist/payments/methods.js +337 -7
- package/dist/payments/mollie-methods.d.ts +159 -0
- package/dist/payments/mollie-methods.js +141 -0
- package/dist/payments/payment-links.d.ts +180 -0
- package/dist/payments/payment-links.js +97 -0
- package/dist/payments/provider-keys.d.ts +150 -0
- package/dist/payments/provider-keys.js +118 -0
- package/dist/payments/providers.d.ts +86 -11
- package/dist/payments/providers.js +29 -0
- package/dist/payments/requests.d.ts +144 -0
- package/dist/payments/requests.js +92 -0
- package/dist/payments/store-credit-fields.d.ts +15 -0
- package/dist/payments/store-credit-fields.js +51 -0
- package/dist/pickups/index.d.ts +104 -0
- package/dist/pickups/index.js +105 -0
- package/dist/platform/channels.d.ts +132 -0
- package/dist/platform/channels.js +128 -0
- package/dist/platform/geo.d.ts +123 -0
- package/dist/platform/geo.js +144 -0
- package/dist/platform/tax.d.ts +154 -0
- package/dist/platform/tax.js +139 -0
- package/dist/pos/anomalies.d.ts +158 -0
- package/dist/pos/anomalies.js +64 -0
- package/dist/pos/assisted-selling.d.ts +79 -0
- package/dist/pos/assisted-selling.js +38 -0
- package/dist/pos/exchanges.d.ts +103 -0
- package/dist/pos/exchanges.js +22 -0
- package/dist/pos/gift-cards.d.ts +135 -0
- package/dist/pos/gift-cards.js +47 -0
- package/dist/pos/index.d.ts +2125 -32
- package/dist/pos/index.js +742 -4
- package/dist/pos/no-receipt.d.ts +94 -0
- package/dist/pos/no-receipt.js +25 -0
- package/dist/pos/offline-sales.d.ts +187 -0
- package/dist/pos/offline-sales.js +116 -0
- package/dist/pos/pay-by-link.d.ts +143 -0
- package/dist/pos/pay-by-link.js +57 -0
- package/dist/pos/quick-keys.d.ts +103 -0
- package/dist/pos/quick-keys.js +45 -0
- package/dist/pos/reports.d.ts +360 -0
- package/dist/pos/reports.js +62 -0
- package/dist/pos/returns.d.ts +217 -0
- package/dist/pos/returns.js +53 -0
- package/dist/pricing/bulk-coupons.d.ts +139 -0
- package/dist/pricing/bulk-coupons.js +112 -0
- package/dist/pricing/index.d.ts +174 -4
- package/dist/pricing/index.js +174 -1
- package/dist/pricing/price-lists.d.ts +604 -0
- package/dist/pricing/price-lists.js +600 -0
- package/dist/purchasing/alerts.d.ts +89 -0
- package/dist/purchasing/alerts.js +62 -0
- package/dist/purchasing/cost.d.ts +110 -0
- package/dist/purchasing/cost.js +86 -0
- package/dist/purchasing/index.d.ts +36 -0
- package/dist/purchasing/index.js +16 -0
- package/dist/purchasing/purchase-orders.d.ts +548 -0
- package/dist/purchasing/purchase-orders.js +491 -0
- package/dist/purchasing/replenishment.d.ts +281 -0
- package/dist/purchasing/replenishment.js +240 -0
- package/dist/purchasing/settings.d.ts +152 -0
- package/dist/purchasing/settings.js +181 -0
- package/dist/purchasing/suppliers.d.ts +476 -0
- package/dist/purchasing/suppliers.js +438 -0
- package/dist/quotes/index.d.ts +501 -0
- package/dist/quotes/index.js +439 -0
- package/dist/reports/index.d.ts +71 -8
- package/dist/reports/index.js +74 -11
- package/dist/returns/index.d.ts +614 -21
- package/dist/returns/index.js +695 -11
- package/dist/search/index.d.ts +76 -1
- package/dist/search/index.js +63 -0
- package/dist/shipping/definitions.d.ts +29 -0
- package/dist/shipping/definitions.js +47 -0
- package/dist/shipping/fulfillment-profiles.d.ts +174 -0
- package/dist/shipping/fulfillment-profiles.js +104 -0
- package/dist/shipping/hendriks.d.ts +97 -0
- package/dist/shipping/hendriks.js +50 -0
- package/dist/shipping/index.d.ts +48 -0
- package/dist/shipping/index.js +25 -0
- package/dist/shipping/methods.d.ts +198 -0
- package/dist/shipping/methods.js +240 -0
- package/dist/shipping/myparcel.d.ts +254 -0
- package/dist/shipping/myparcel.js +178 -0
- package/dist/shipping/parcel-count-suggestion.d.ts +2 -0
- package/dist/shipping/parcel-rule.d.ts +6 -5
- package/dist/shipping/parcel-rule.js +21 -23
- package/dist/shipping/rate-tables.d.ts +179 -0
- package/dist/shipping/rate-tables.js +184 -0
- package/dist/stock/index.d.ts +10 -3
- package/dist/stock/index.js +3 -0
- package/dist/stock/locations.d.ts +144 -0
- package/dist/stock/locations.js +168 -0
- package/dist/stock/transfers.d.ts +216 -43
- package/dist/stock/transfers.js +140 -13
- package/dist/stored-value/index.d.ts +214 -4
- package/dist/stored-value/index.js +152 -0
- package/dist/subscriptions/index.d.ts +682 -0
- package/dist/subscriptions/index.js +815 -0
- package/dist/tax/index.d.ts +76 -1
- package/dist/tax/index.js +50 -0
- package/dist/tenant/email-style.d.ts +102 -0
- package/dist/tenant/email-style.js +72 -0
- package/dist/tenant/email-templates.d.ts +66 -0
- package/dist/tenant/email-templates.js +54 -0
- package/dist/tenant/notifications.d.ts +23 -17
- package/dist/tenant/settings-sources.d.ts +1 -1
- package/dist/tenant/time-zone.d.ts +17 -0
- package/dist/tenant/time-zone.js +11 -0
- package/dist/types.d.ts +50 -3
- package/dist/users/index.d.ts +3 -0
- package/dist/users/index.js +2 -0
- package/dist/users/warehouses.d.ts +50 -0
- package/dist/users/warehouses.js +51 -0
- package/package.json +2 -2
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { type Page, type Transport } from '@sixtyninecommerce/core';
|
|
2
|
+
import type { Call } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* One order as a list shows it (`admin.orders.list`, `admin.customers.orders`): the totals, the
|
|
5
|
+
* status dimensions, who it is for, and the three company sources a display name reads
|
|
6
|
+
* (`billingAddress.company`, `shippingAddress.company`, the customer's address book).
|
|
7
|
+
*
|
|
8
|
+
* Money is an integer in minor units of the order's `currencyCode`.
|
|
9
|
+
*/
|
|
10
|
+
export interface OrderSummary {
|
|
11
|
+
id: string;
|
|
12
|
+
code: string;
|
|
13
|
+
state: string;
|
|
14
|
+
total: number;
|
|
15
|
+
totalWithTax: number;
|
|
16
|
+
currencyCode: string;
|
|
17
|
+
/** ISO-8601; null for an order not placed yet (a cart, a draft). */
|
|
18
|
+
orderPlacedAt: string | null;
|
|
19
|
+
customer: {
|
|
20
|
+
id: string;
|
|
21
|
+
firstName: string;
|
|
22
|
+
lastName: string;
|
|
23
|
+
emailAddress: string;
|
|
24
|
+
addresses: Array<{
|
|
25
|
+
company: string | null;
|
|
26
|
+
defaultBillingAddress: boolean | null;
|
|
27
|
+
defaultShippingAddress: boolean | null;
|
|
28
|
+
}> | null;
|
|
29
|
+
} | null;
|
|
30
|
+
billingAddress: {
|
|
31
|
+
company: string | null;
|
|
32
|
+
} | null;
|
|
33
|
+
shippingAddress: {
|
|
34
|
+
company: string | null;
|
|
35
|
+
} | null;
|
|
36
|
+
lines: Array<{
|
|
37
|
+
quantity: number;
|
|
38
|
+
}>;
|
|
39
|
+
payments: Array<{
|
|
40
|
+
id: string;
|
|
41
|
+
state: string;
|
|
42
|
+
}> | null;
|
|
43
|
+
customFields: {
|
|
44
|
+
externalOrderId: string | null;
|
|
45
|
+
externalPlatform: string | null;
|
|
46
|
+
isGift: boolean | null;
|
|
47
|
+
/** The status dimensions; null until the engine has set them on an older order. */
|
|
48
|
+
paymentStatus: string | null;
|
|
49
|
+
fulfillmentStatus: string | null;
|
|
50
|
+
returnStatus: string | null;
|
|
51
|
+
lifecycleStatus: string | null;
|
|
52
|
+
statusOverrides: {
|
|
53
|
+
fulfillmentHoldReason: string | null;
|
|
54
|
+
} | null;
|
|
55
|
+
} | null;
|
|
56
|
+
/**
|
|
57
|
+
* Set when the caller's customer-data level blanked part of the row (an app installation below
|
|
58
|
+
* `customerData: full`): read an empty name or company as "not granted", never as "none".
|
|
59
|
+
*/
|
|
60
|
+
redacted?: true;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Which orders a list holds. Every key narrows it; several keys are combined with AND. An empty
|
|
64
|
+
* list (`state: []`) matches nothing.
|
|
65
|
+
*/
|
|
66
|
+
export interface OrderListFilter {
|
|
67
|
+
ids?: readonly string[];
|
|
68
|
+
/** Any of these engine states (`PaymentSettled`, `Draft`, …). */
|
|
69
|
+
state?: readonly string[];
|
|
70
|
+
/**
|
|
71
|
+
* The order code. `startsWith` and `contains` ignore case; `contains` treats `%` and `_` as
|
|
72
|
+
* wildcards.
|
|
73
|
+
*/
|
|
74
|
+
code?: {
|
|
75
|
+
eq?: string;
|
|
76
|
+
contains?: string;
|
|
77
|
+
startsWith?: string;
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* When the order was placed. `isNull: true` keeps the orders never placed (carts, drafts),
|
|
81
|
+
* `false` the placed ones. `before`/`after` are ISO-8601 instants WITH an offset or `Z`, both
|
|
82
|
+
* exclusive; an order never placed matches neither.
|
|
83
|
+
*/
|
|
84
|
+
orderPlacedAt?: {
|
|
85
|
+
isNull?: boolean;
|
|
86
|
+
before?: string;
|
|
87
|
+
after?: string;
|
|
88
|
+
};
|
|
89
|
+
/** True for a cart its shopper still has open; a draft, placed or cancelled order is not. */
|
|
90
|
+
active?: boolean;
|
|
91
|
+
currencyCode?: string;
|
|
92
|
+
/**
|
|
93
|
+
* The platform an imported order came from (`woocommerce`, …); `null` keeps only the orders
|
|
94
|
+
* that were not imported.
|
|
95
|
+
*/
|
|
96
|
+
externalPlatform?: string | null;
|
|
97
|
+
/** Any of these payment dimensions (`paid`, `partially_paid`, …). */
|
|
98
|
+
paymentStatus?: readonly string[];
|
|
99
|
+
/** Any of these lifecycles (`open`, `completed`, …). */
|
|
100
|
+
lifecycleStatus?: readonly string[];
|
|
101
|
+
/** Part of the customer's last name, ignoring case. */
|
|
102
|
+
customerLastName?: string;
|
|
103
|
+
}
|
|
104
|
+
/** The fields an order list sorts on. */
|
|
105
|
+
export type OrderListSortField = 'orderPlacedAt' | 'createdAt' | 'updatedAt' | 'code' | 'state' | 'total' | 'totalWithTax' | 'customerLastName';
|
|
106
|
+
export declare const ORDER_LIST_SORT_FIELDS: readonly OrderListSortField[];
|
|
107
|
+
export interface OrderListSort {
|
|
108
|
+
field: OrderListSortField;
|
|
109
|
+
direction: 'ASC' | 'DESC';
|
|
110
|
+
}
|
|
111
|
+
export interface OrderListOptions extends Call {
|
|
112
|
+
filter?: OrderListFilter;
|
|
113
|
+
sort?: OrderListSort;
|
|
114
|
+
/** Rows to skip, 0 when omitted. */
|
|
115
|
+
skip?: number;
|
|
116
|
+
/** Rows per page, 1 to {@link MAX_ORDER_LIST_TAKE}; 25 when omitted. */
|
|
117
|
+
take?: number;
|
|
118
|
+
}
|
|
119
|
+
/** The engine's `adminListQueryLimit`: a larger page is refused. */
|
|
120
|
+
export declare const MAX_ORDER_LIST_TAKE = 1000;
|
|
121
|
+
export declare const ORDER_SUMMARY_FIELDS = "\n id\n code\n state\n total\n totalWithTax\n currencyCode\n orderPlacedAt\n customer {\n id\n firstName\n lastName\n emailAddress\n addresses {\n company\n defaultBillingAddress\n defaultShippingAddress\n }\n }\n billingAddress {\n company\n }\n shippingAddress {\n company\n }\n lines {\n quantity\n }\n payments {\n id\n state\n }\n customFields {\n externalOrderId\n externalPlatform\n isGift\n paymentStatus\n fulfillmentStatus\n returnStatus\n lifecycleStatus\n statusOverrides {\n fulfillmentHoldReason\n }\n }\n";
|
|
122
|
+
export declare const ORDERS_LIST_QUERY = "\n query OrdersList($options: OrderListOptions) {\n orders(options: $options) {\n items {\n \n id\n code\n state\n total\n totalWithTax\n currencyCode\n orderPlacedAt\n customer {\n id\n firstName\n lastName\n emailAddress\n addresses {\n company\n defaultBillingAddress\n defaultShippingAddress\n }\n }\n billingAddress {\n company\n }\n shippingAddress {\n company\n }\n lines {\n quantity\n }\n payments {\n id\n state\n }\n customFields {\n externalOrderId\n externalPlatform\n isGift\n paymentStatus\n fulfillmentStatus\n returnStatus\n lifecycleStatus\n statusOverrides {\n fulfillmentHoldReason\n }\n }\n\n }\n totalItems\n }\n }\n";
|
|
123
|
+
export declare const ORDERS_COUNT_QUERY = "\n query OrdersCount($options: OrderListOptions) {\n orders(options: $options) {\n totalItems\n }\n }\n";
|
|
124
|
+
export declare const CUSTOMER_ORDERS_QUERY = "\n query CustomerOrders($id: ID!, $options: OrderListOptions) {\n customer(id: $id) {\n id\n orders(options: $options) {\n items {\n \n id\n code\n state\n total\n totalWithTax\n currencyCode\n orderPlacedAt\n customer {\n id\n firstName\n lastName\n emailAddress\n addresses {\n company\n defaultBillingAddress\n defaultShippingAddress\n }\n }\n billingAddress {\n company\n }\n shippingAddress {\n company\n }\n lines {\n quantity\n }\n payments {\n id\n state\n }\n customFields {\n externalOrderId\n externalPlatform\n isGift\n paymentStatus\n fulfillmentStatus\n returnStatus\n lifecycleStatus\n statusOverrides {\n fulfillmentHoldReason\n }\n }\n\n }\n totalItems\n }\n }\n }\n";
|
|
125
|
+
/** The Admin API's `OrderFilterParameter` for a typed filter; unknown keys are refused. */
|
|
126
|
+
export declare function toOrderFilterParameter(filter: OrderListFilter | undefined): Record<string, unknown>;
|
|
127
|
+
export interface OrderListModule {
|
|
128
|
+
/**
|
|
129
|
+
* One page of the store's orders, with `total` the exact count of every order the filter
|
|
130
|
+
* matches. Needs `ReadOrder`.
|
|
131
|
+
*
|
|
132
|
+
* - **Carts are orders too.** A cart a shopper never checked out, and a draft staff never placed,
|
|
133
|
+
* are listed unless the filter leaves them out (`orderPlacedAt: { isNull: false }`).
|
|
134
|
+
* - **Sorting by `orderPlacedAt` descending puts the never-placed rows FIRST** (the database
|
|
135
|
+
* sorts an empty date above every date). To show the newest placed order first, list the
|
|
136
|
+
* placed orders, then continue with `orderPlacedAt: { isNull: true }` sorted by `createdAt`.
|
|
137
|
+
* - `page.next()` asks for the following page with the same filter and sort; `skip` starts
|
|
138
|
+
* somewhere else.
|
|
139
|
+
*
|
|
140
|
+
* Refused before anything is asked: `INVALID_ORDER_LIST_OPTIONS` (`ValidationError`, 400) for a
|
|
141
|
+
* filter key or operator it does not list, a date without an offset, a sort field it does not
|
|
142
|
+
* list, or `take`/`skip` out of range.
|
|
143
|
+
*
|
|
144
|
+
* @effect read
|
|
145
|
+
*/
|
|
146
|
+
list(options?: OrderListOptions): Promise<Page<OrderSummary>>;
|
|
147
|
+
/**
|
|
148
|
+
* How many of the store's orders the filter matches, without reading any. Carts count unless
|
|
149
|
+
* the filter leaves them out. Needs `ReadOrder`. Refused like {@link list}.
|
|
150
|
+
*
|
|
151
|
+
* @effect read
|
|
152
|
+
*/
|
|
153
|
+
count(filter?: OrderListFilter, options?: Call): Promise<number>;
|
|
154
|
+
}
|
|
155
|
+
export declare function createOrderListModule(transport: Transport): OrderListModule;
|
|
156
|
+
/**
|
|
157
|
+
* One customer's orders, as `customers.orders` reads them: the same rows, filter, sort and paging
|
|
158
|
+
* as `orders.list`, or `null` when the store holds no customer with that id.
|
|
159
|
+
*/
|
|
160
|
+
export declare function listCustomerOrders(transport: Transport, customerId: string, options: OrderListOptions | undefined): Promise<Page<OrderSummary> | null>;
|
|
161
|
+
/** The most orders `customers.recentOrders` answers. */
|
|
162
|
+
export declare const MAX_RECENT_ORDERS = 20;
|
|
163
|
+
/**
|
|
164
|
+
* One line of a customer's earlier order: what was bought, and how many. The members are named
|
|
165
|
+
* as on every other order line of this SDK (`orders.get`, `orders.drafts`).
|
|
166
|
+
*/
|
|
167
|
+
export interface RecentOrderLine {
|
|
168
|
+
id: string;
|
|
169
|
+
/** 0 for a line that was cancelled on the order. */
|
|
170
|
+
quantity: number;
|
|
171
|
+
/**
|
|
172
|
+
* Whether the line is priced gross. `customFields.unitPriceOverride` is stated in this basis,
|
|
173
|
+
* which follows the customer's tax zone, not the store's setting: a store that prices gross
|
|
174
|
+
* still holds net lines for a customer in a tax-exclusive country.
|
|
175
|
+
*/
|
|
176
|
+
listPriceIncludesTax: boolean;
|
|
177
|
+
/**
|
|
178
|
+
* The variant as it is NOW (its name and SKU may have changed since the order). A line an
|
|
179
|
+
* external system priced sits on the platform's hidden carrier variant: read it through
|
|
180
|
+
* `catalog.variants.find({ ids })`, which leaves such a variant out, before offering it.
|
|
181
|
+
*/
|
|
182
|
+
productVariant: {
|
|
183
|
+
id: string;
|
|
184
|
+
name: string;
|
|
185
|
+
sku: string;
|
|
186
|
+
product: {
|
|
187
|
+
id: string;
|
|
188
|
+
name: string;
|
|
189
|
+
};
|
|
190
|
+
};
|
|
191
|
+
customFields: {
|
|
192
|
+
/**
|
|
193
|
+
* The unit price the line states in place of the catalogue's, in minor units of the
|
|
194
|
+
* order's currency and in the line's basis (`listPriceIncludesTax`); null for a line the
|
|
195
|
+
* catalogue priced.
|
|
196
|
+
*/
|
|
197
|
+
unitPriceOverride: number | null;
|
|
198
|
+
/** True when that price arrived with the line (an import, a quote, a till price). */
|
|
199
|
+
unitPriceImported: boolean | null;
|
|
200
|
+
} | null;
|
|
201
|
+
}
|
|
202
|
+
/** A placed order of a customer, with its lines. */
|
|
203
|
+
export interface RecentOrder {
|
|
204
|
+
id: string;
|
|
205
|
+
code: string;
|
|
206
|
+
/** ISO-8601. */
|
|
207
|
+
orderPlacedAt: string;
|
|
208
|
+
/** Minor units of `currencyCode`. */
|
|
209
|
+
totalWithTax: number;
|
|
210
|
+
currencyCode: string;
|
|
211
|
+
lines: RecentOrderLine[];
|
|
212
|
+
}
|
|
213
|
+
export interface RecentOrdersOptions extends Call {
|
|
214
|
+
/** How many orders, 1 to {@link MAX_RECENT_ORDERS}; 5 when omitted. */
|
|
215
|
+
take?: number;
|
|
216
|
+
}
|
|
217
|
+
export declare const CUSTOMER_RECENT_ORDERS_QUERY = "\n query CustomerRecentOrders($id: ID!, $options: OrderListOptions) {\n customer(id: $id) {\n id\n orders(options: $options) {\n items {\n id\n code\n orderPlacedAt\n totalWithTax\n currencyCode\n lines {\n id\n quantity\n listPriceIncludesTax\n productVariant {\n id\n name\n sku\n product {\n id\n name\n }\n }\n customFields {\n unitPriceOverride\n unitPriceImported\n }\n }\n }\n totalItems\n }\n }\n }\n";
|
|
218
|
+
/**
|
|
219
|
+
* A customer's last placed orders, newest first, each with its lines, as `customers.recentOrders`
|
|
220
|
+
* reads them; `null` when the store holds no customer with that id.
|
|
221
|
+
*/
|
|
222
|
+
export declare function listCustomerRecentOrders(transport: Transport, customerId: string, options: RecentOrdersOptions | undefined): Promise<RecentOrder[] | null>;
|
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
import { pageFromVendureList, readOffsetCursor, UpstreamError, ValidationError, } from '@sixtyninecommerce/core';
|
|
2
|
+
import { redactionWatcher } from '../customer-data-redaction.js';
|
|
3
|
+
export const ORDER_LIST_SORT_FIELDS = [
|
|
4
|
+
'orderPlacedAt',
|
|
5
|
+
'createdAt',
|
|
6
|
+
'updatedAt',
|
|
7
|
+
'code',
|
|
8
|
+
'state',
|
|
9
|
+
'total',
|
|
10
|
+
'totalWithTax',
|
|
11
|
+
'customerLastName',
|
|
12
|
+
];
|
|
13
|
+
/** The engine's `adminListQueryLimit`: a larger page is refused. */
|
|
14
|
+
export const MAX_ORDER_LIST_TAKE = 1000;
|
|
15
|
+
const DEFAULT_TAKE = 25;
|
|
16
|
+
export const ORDER_SUMMARY_FIELDS = /* GraphQL */ `
|
|
17
|
+
id
|
|
18
|
+
code
|
|
19
|
+
state
|
|
20
|
+
total
|
|
21
|
+
totalWithTax
|
|
22
|
+
currencyCode
|
|
23
|
+
orderPlacedAt
|
|
24
|
+
customer {
|
|
25
|
+
id
|
|
26
|
+
firstName
|
|
27
|
+
lastName
|
|
28
|
+
emailAddress
|
|
29
|
+
addresses {
|
|
30
|
+
company
|
|
31
|
+
defaultBillingAddress
|
|
32
|
+
defaultShippingAddress
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
billingAddress {
|
|
36
|
+
company
|
|
37
|
+
}
|
|
38
|
+
shippingAddress {
|
|
39
|
+
company
|
|
40
|
+
}
|
|
41
|
+
lines {
|
|
42
|
+
quantity
|
|
43
|
+
}
|
|
44
|
+
payments {
|
|
45
|
+
id
|
|
46
|
+
state
|
|
47
|
+
}
|
|
48
|
+
customFields {
|
|
49
|
+
externalOrderId
|
|
50
|
+
externalPlatform
|
|
51
|
+
isGift
|
|
52
|
+
paymentStatus
|
|
53
|
+
fulfillmentStatus
|
|
54
|
+
returnStatus
|
|
55
|
+
lifecycleStatus
|
|
56
|
+
statusOverrides {
|
|
57
|
+
fulfillmentHoldReason
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
`;
|
|
61
|
+
export const ORDERS_LIST_QUERY = /* GraphQL */ `
|
|
62
|
+
query OrdersList($options: OrderListOptions) {
|
|
63
|
+
orders(options: $options) {
|
|
64
|
+
items {
|
|
65
|
+
${ORDER_SUMMARY_FIELDS}
|
|
66
|
+
}
|
|
67
|
+
totalItems
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
`;
|
|
71
|
+
export const ORDERS_COUNT_QUERY = /* GraphQL */ `
|
|
72
|
+
query OrdersCount($options: OrderListOptions) {
|
|
73
|
+
orders(options: $options) {
|
|
74
|
+
totalItems
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
`;
|
|
78
|
+
export const CUSTOMER_ORDERS_QUERY = /* GraphQL */ `
|
|
79
|
+
query CustomerOrders($id: ID!, $options: OrderListOptions) {
|
|
80
|
+
customer(id: $id) {
|
|
81
|
+
id
|
|
82
|
+
orders(options: $options) {
|
|
83
|
+
items {
|
|
84
|
+
${ORDER_SUMMARY_FIELDS}
|
|
85
|
+
}
|
|
86
|
+
totalItems
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
`;
|
|
91
|
+
function invalid(message) {
|
|
92
|
+
return new ValidationError({
|
|
93
|
+
code: 'INVALID_ORDER_LIST_OPTIONS',
|
|
94
|
+
message,
|
|
95
|
+
status: 400,
|
|
96
|
+
service: 'vendure',
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
function stringList(value, path) {
|
|
100
|
+
if (!Array.isArray(value) || value.some((item) => typeof item !== 'string')) {
|
|
101
|
+
throw invalid(`${path} must be a list of strings.`);
|
|
102
|
+
}
|
|
103
|
+
return [...value];
|
|
104
|
+
}
|
|
105
|
+
function text(value, path) {
|
|
106
|
+
if (typeof value !== 'string')
|
|
107
|
+
throw invalid(`${path} must be a string.`);
|
|
108
|
+
return value;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* An instant the engine compares without guessing a zone: a string with no offset would be read
|
|
112
|
+
* in the database server's zone, so a range would shift by hours with the server.
|
|
113
|
+
*/
|
|
114
|
+
const INSTANT = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:\d{2})$/;
|
|
115
|
+
function instant(value, path) {
|
|
116
|
+
if (typeof value !== 'string' || !INSTANT.test(value) || Number.isNaN(Date.parse(value))) {
|
|
117
|
+
throw invalid(`${path} must be an ISO-8601 instant with an offset or Z.`);
|
|
118
|
+
}
|
|
119
|
+
return value;
|
|
120
|
+
}
|
|
121
|
+
function escapeRegex(value) {
|
|
122
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
123
|
+
}
|
|
124
|
+
/** The Admin API's `OrderFilterParameter` for a typed filter; unknown keys are refused. */
|
|
125
|
+
export function toOrderFilterParameter(filter) {
|
|
126
|
+
if (filter === undefined)
|
|
127
|
+
return {};
|
|
128
|
+
if (typeof filter !== 'object' || filter === null || Array.isArray(filter)) {
|
|
129
|
+
throw invalid('filter must be an object.');
|
|
130
|
+
}
|
|
131
|
+
const out = {};
|
|
132
|
+
for (const [key, value] of Object.entries(filter)) {
|
|
133
|
+
if (value === undefined)
|
|
134
|
+
continue;
|
|
135
|
+
switch (key) {
|
|
136
|
+
case 'ids':
|
|
137
|
+
out.id = { in: stringList(value, 'filter.ids') };
|
|
138
|
+
break;
|
|
139
|
+
case 'state':
|
|
140
|
+
case 'paymentStatus':
|
|
141
|
+
case 'lifecycleStatus':
|
|
142
|
+
out[key] = { in: stringList(value, `filter.${key}`) };
|
|
143
|
+
break;
|
|
144
|
+
case 'code': {
|
|
145
|
+
const code = value;
|
|
146
|
+
if (typeof code !== 'object' || code === null)
|
|
147
|
+
throw invalid('filter.code must be an object.');
|
|
148
|
+
const operators = {};
|
|
149
|
+
for (const [operator, operand] of Object.entries(code)) {
|
|
150
|
+
if (operand === undefined)
|
|
151
|
+
continue;
|
|
152
|
+
const path = `filter.code.${operator}`;
|
|
153
|
+
if (operator === 'eq' || operator === 'contains')
|
|
154
|
+
operators[operator] = text(operand, path);
|
|
155
|
+
else if (operator === 'startsWith')
|
|
156
|
+
operators.regex = `^${escapeRegex(text(operand, path))}`;
|
|
157
|
+
else
|
|
158
|
+
throw invalid(`${path} is not a code filter; use eq, contains or startsWith.`);
|
|
159
|
+
}
|
|
160
|
+
out.code = operators;
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
case 'orderPlacedAt': {
|
|
164
|
+
const placed = value;
|
|
165
|
+
if (typeof placed !== 'object' || placed === null) {
|
|
166
|
+
throw invalid('filter.orderPlacedAt must be an object.');
|
|
167
|
+
}
|
|
168
|
+
const operators = {};
|
|
169
|
+
for (const [operator, operand] of Object.entries(placed)) {
|
|
170
|
+
if (operand === undefined)
|
|
171
|
+
continue;
|
|
172
|
+
const path = `filter.orderPlacedAt.${operator}`;
|
|
173
|
+
if (operator === 'isNull') {
|
|
174
|
+
if (typeof operand !== 'boolean')
|
|
175
|
+
throw invalid(`${path} must be a boolean.`);
|
|
176
|
+
operators.isNull = operand;
|
|
177
|
+
}
|
|
178
|
+
else if (operator === 'before' || operator === 'after') {
|
|
179
|
+
operators[operator] = instant(operand, path);
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
throw invalid(`${path} is not a date filter; use isNull, before or after.`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
out.orderPlacedAt = operators;
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
case 'active':
|
|
189
|
+
if (typeof value !== 'boolean')
|
|
190
|
+
throw invalid('filter.active must be a boolean.');
|
|
191
|
+
out.active = { eq: value };
|
|
192
|
+
break;
|
|
193
|
+
case 'currencyCode':
|
|
194
|
+
out.currencyCode = { eq: text(value, 'filter.currencyCode') };
|
|
195
|
+
break;
|
|
196
|
+
case 'externalPlatform':
|
|
197
|
+
out.externalPlatform =
|
|
198
|
+
value === null ? { isNull: true } : { eq: text(value, 'filter.externalPlatform') };
|
|
199
|
+
break;
|
|
200
|
+
case 'customerLastName':
|
|
201
|
+
out.customerLastName = { contains: text(value, 'filter.customerLastName') };
|
|
202
|
+
break;
|
|
203
|
+
default:
|
|
204
|
+
throw invalid(`filter.${key} is not an order list filter.`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return out;
|
|
208
|
+
}
|
|
209
|
+
function toOrderSort(sort) {
|
|
210
|
+
if (sort === undefined)
|
|
211
|
+
return undefined;
|
|
212
|
+
if (typeof sort !== 'object' ||
|
|
213
|
+
sort === null ||
|
|
214
|
+
!ORDER_LIST_SORT_FIELDS.includes(sort.field) ||
|
|
215
|
+
(sort.direction !== 'ASC' && sort.direction !== 'DESC')) {
|
|
216
|
+
throw invalid(`sort must be { field: ${ORDER_LIST_SORT_FIELDS.join(' | ')}, direction: ASC | DESC }.`);
|
|
217
|
+
}
|
|
218
|
+
return { [sort.field]: sort.direction };
|
|
219
|
+
}
|
|
220
|
+
function pageBounds(options) {
|
|
221
|
+
const take = options?.take ?? DEFAULT_TAKE;
|
|
222
|
+
const skip = options?.skip ?? 0;
|
|
223
|
+
if (!Number.isInteger(take) || take < 1 || take > MAX_ORDER_LIST_TAKE) {
|
|
224
|
+
throw invalid(`take must be a whole number from 1 to ${String(MAX_ORDER_LIST_TAKE)}.`);
|
|
225
|
+
}
|
|
226
|
+
if (!Number.isInteger(skip) || skip < 0)
|
|
227
|
+
throw invalid('skip must be a whole number of 0 or more.');
|
|
228
|
+
return { skip, take };
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Pages through one order list. `read` answers the list (or `null` when its owner is gone); each
|
|
232
|
+
* following page re-sends the same filter, sort and per-call options, so a page cannot walk
|
|
233
|
+
* another store's orders.
|
|
234
|
+
*/
|
|
235
|
+
async function listOrders(read, options) {
|
|
236
|
+
const { skip, take } = pageBounds(options);
|
|
237
|
+
const filter = toOrderFilterParameter(options?.filter);
|
|
238
|
+
const sort = toOrderSort(options?.sort);
|
|
239
|
+
const fetchPage = async (pageSkip) => {
|
|
240
|
+
const redaction = redactionWatcher();
|
|
241
|
+
const list = await read({
|
|
242
|
+
options: {
|
|
243
|
+
skip: pageSkip,
|
|
244
|
+
take,
|
|
245
|
+
...(Object.keys(filter).length > 0 ? { filter, filterOperator: 'AND' } : {}),
|
|
246
|
+
...(sort ? { sort } : {}),
|
|
247
|
+
},
|
|
248
|
+
}, redaction.onExtensions);
|
|
249
|
+
if (list === null)
|
|
250
|
+
return null;
|
|
251
|
+
return pageFromVendureList({ items: list.items.map((item) => redaction.mark(item)), totalItems: list.totalItems }, pageSkip, take, async (cursor) => {
|
|
252
|
+
const next = await fetchPage(readOffsetCursor(cursor));
|
|
253
|
+
if (next === null) {
|
|
254
|
+
throw new UpstreamError({
|
|
255
|
+
code: 'UNEXPECTED_RESPONSE',
|
|
256
|
+
message: 'The customer was gone by the next page of their orders.',
|
|
257
|
+
status: 502,
|
|
258
|
+
service: 'vendure',
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
return next;
|
|
262
|
+
});
|
|
263
|
+
};
|
|
264
|
+
return fetchPage(skip);
|
|
265
|
+
}
|
|
266
|
+
export function createOrderListModule(transport) {
|
|
267
|
+
return {
|
|
268
|
+
async list(options) {
|
|
269
|
+
const page = await listOrders(async (variables, onExtensions) => {
|
|
270
|
+
const data = await transport.graphql({ api: 'admin', query: ORDERS_LIST_QUERY, variables, onExtensions }, options);
|
|
271
|
+
return data.orders;
|
|
272
|
+
}, options);
|
|
273
|
+
// `read` above never answers null: the store's own list always exists.
|
|
274
|
+
return page;
|
|
275
|
+
},
|
|
276
|
+
async count(filter, options) {
|
|
277
|
+
const parameter = toOrderFilterParameter(filter);
|
|
278
|
+
const data = await transport.graphql({
|
|
279
|
+
api: 'admin',
|
|
280
|
+
query: ORDERS_COUNT_QUERY,
|
|
281
|
+
variables: {
|
|
282
|
+
options: {
|
|
283
|
+
// Never 0: Vendure passes it through and TypeORM then sends no LIMIT, so a
|
|
284
|
+
// "count" would load every matching order. One row costs nothing.
|
|
285
|
+
take: 1,
|
|
286
|
+
...(Object.keys(parameter).length > 0
|
|
287
|
+
? { filter: parameter, filterOperator: 'AND' }
|
|
288
|
+
: {}),
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
}, options);
|
|
292
|
+
return data.orders.totalItems;
|
|
293
|
+
},
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* One customer's orders, as `customers.orders` reads them: the same rows, filter, sort and paging
|
|
298
|
+
* as `orders.list`, or `null` when the store holds no customer with that id.
|
|
299
|
+
*/
|
|
300
|
+
export async function listCustomerOrders(transport, customerId, options) {
|
|
301
|
+
return listOrders(async (variables, onExtensions) => {
|
|
302
|
+
const data = await transport.graphql({
|
|
303
|
+
api: 'admin',
|
|
304
|
+
query: CUSTOMER_ORDERS_QUERY,
|
|
305
|
+
variables: { id: customerId, ...variables },
|
|
306
|
+
onExtensions,
|
|
307
|
+
}, options);
|
|
308
|
+
return data.customer?.orders ?? null;
|
|
309
|
+
}, options);
|
|
310
|
+
}
|
|
311
|
+
/** The most orders `customers.recentOrders` answers. */
|
|
312
|
+
export const MAX_RECENT_ORDERS = 20;
|
|
313
|
+
const DEFAULT_RECENT_ORDERS = 5;
|
|
314
|
+
export const CUSTOMER_RECENT_ORDERS_QUERY = /* GraphQL */ `
|
|
315
|
+
query CustomerRecentOrders($id: ID!, $options: OrderListOptions) {
|
|
316
|
+
customer(id: $id) {
|
|
317
|
+
id
|
|
318
|
+
orders(options: $options) {
|
|
319
|
+
items {
|
|
320
|
+
id
|
|
321
|
+
code
|
|
322
|
+
orderPlacedAt
|
|
323
|
+
totalWithTax
|
|
324
|
+
currencyCode
|
|
325
|
+
lines {
|
|
326
|
+
id
|
|
327
|
+
quantity
|
|
328
|
+
listPriceIncludesTax
|
|
329
|
+
productVariant {
|
|
330
|
+
id
|
|
331
|
+
name
|
|
332
|
+
sku
|
|
333
|
+
product {
|
|
334
|
+
id
|
|
335
|
+
name
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
customFields {
|
|
339
|
+
unitPriceOverride
|
|
340
|
+
unitPriceImported
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
totalItems
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
`;
|
|
349
|
+
/**
|
|
350
|
+
* A customer's last placed orders, newest first, each with its lines, as `customers.recentOrders`
|
|
351
|
+
* reads them; `null` when the store holds no customer with that id.
|
|
352
|
+
*/
|
|
353
|
+
export async function listCustomerRecentOrders(transport, customerId, options) {
|
|
354
|
+
const { take = DEFAULT_RECENT_ORDERS, ...call } = options ?? {};
|
|
355
|
+
if (!Number.isInteger(take) || take < 1 || take > MAX_RECENT_ORDERS) {
|
|
356
|
+
throw invalid(`take must be a whole number from 1 to ${String(MAX_RECENT_ORDERS)}.`);
|
|
357
|
+
}
|
|
358
|
+
const data = await transport.graphql({
|
|
359
|
+
api: 'admin',
|
|
360
|
+
query: CUSTOMER_RECENT_ORDERS_QUERY,
|
|
361
|
+
variables: {
|
|
362
|
+
id: customerId,
|
|
363
|
+
options: {
|
|
364
|
+
take,
|
|
365
|
+
// Placed orders only: sorted on its own, `orderPlacedAt` descending lists the carts
|
|
366
|
+
// and drafts (no date) first.
|
|
367
|
+
filter: { orderPlacedAt: { isNull: false } },
|
|
368
|
+
// ONE key, on purpose. The engine applies the keys of a sort in the order its schema
|
|
369
|
+
// declares them, not the order they are sent in, and `id` is declared before
|
|
370
|
+
// `orderPlacedAt`: an id "tie-breaker" here sorted the orders by id (found live).
|
|
371
|
+
sort: { orderPlacedAt: 'DESC' },
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
}, call);
|
|
375
|
+
// The document selects exactly the members of `RecentOrder`: the answer is the wire's.
|
|
376
|
+
return data.customer ? data.customer.orders.items : null;
|
|
377
|
+
}
|
|
@@ -161,6 +161,11 @@ export interface OrderManualPricingModule {
|
|
|
161
161
|
* neither `unitPriceOverride` nor `priceOverrideReason` (it asks for nothing); a negative price;
|
|
162
162
|
* `unitPriceOverride: null` on a line an external system priced (`orders.createOrRecover`
|
|
163
163
|
* external lines), which has no catalogue price to fall back to: state the price instead.
|
|
164
|
+
*
|
|
165
|
+
* `ORDER_LINE_VARIANT_UNPRICED` (`BusinessRuleError`, 422; absent from an engine released before
|
|
166
|
+
* 2026-10-10): `unitPriceOverride: null` on a line that states a manual price while its variant
|
|
167
|
+
* has no price in the store, which would leave the line nothing to charge. Nothing is written:
|
|
168
|
+
* state the price instead, or set a price for the variant in the store first.
|
|
164
169
|
*/
|
|
165
170
|
setLinePrices(orderId: string, input: SetLinePricesInput, options?: Call): Promise<OrderDiscounts>;
|
|
166
171
|
/**
|
|
@@ -13,19 +13,27 @@ export type ExternalLinePriceBasis = 'net' | 'gross';
|
|
|
13
13
|
/**
|
|
14
14
|
* What is going to happen to the goods.
|
|
15
15
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* a
|
|
19
|
-
*
|
|
20
|
-
*
|
|
16
|
+
* Commerce ACTS on it. Nothing here creates a fulfilment or picks a shipping
|
|
17
|
+
* method, but the value decides whether the order needs a shipping method to be
|
|
18
|
+
* placed and whether a fulfilment of it owes a delivery charge. It is recorded
|
|
19
|
+
* as the order's `platform.fulfilment` metafield (only the platform writes it),
|
|
20
|
+
* so a document, a WMS push or a merchant can also read back what you asked for.
|
|
21
21
|
*
|
|
22
22
|
* - `pickup` — collected at a location. Needs no shipping method and no
|
|
23
|
-
* address.
|
|
23
|
+
* address. Handed over through an ordinary fulfilment, which adds no delivery
|
|
24
|
+
* charge and is not held to a fulfilment profile's minimum.
|
|
24
25
|
* - `ship` — shipped. The order still needs a shipping method before it can
|
|
25
26
|
* leave `Draft`, and `transitionTo: 'ArrangingPayment'` on an order that has
|
|
26
27
|
* none is refused by the platform's own placement gate, not by this call.
|
|
28
|
+
* Delivery charges and profile minimums apply as for any delivered order.
|
|
27
29
|
* - `none` — neither shipped nor collected: a service, a subscription set-up,
|
|
28
|
-
* a fee.
|
|
30
|
+
* a fee. Needs no shipping method, owes no delivery charge and takes no
|
|
31
|
+
* profile minimum. The order is marked as having nothing to ship, so it
|
|
32
|
+
* completes on its own once it is paid (after the store's completion grace
|
|
33
|
+
* period). It may not hold goods that are stock-tracked: such a catalog line
|
|
34
|
+
* is refused `LINE_NEEDS_FULFILMENT` here, and so is placing (or modifying)
|
|
35
|
+
* the order to carry one later. Send goods as a `pickup` order, a service as
|
|
36
|
+
* an external line.
|
|
29
37
|
*/
|
|
30
38
|
export type ExternalOrderFulfilment = 'pickup' | 'ship' | 'none';
|
|
31
39
|
/**
|
|
@@ -478,6 +486,11 @@ export interface OrderEntryModule {
|
|
|
478
486
|
* - `LINE_DUPLICATE_VARIANT` — two catalog lines name the same variant.
|
|
479
487
|
* `details` carries the second one's `position` and the first one's
|
|
480
488
|
* `firstPosition`. Send one line with the quantity you want.
|
|
489
|
+
* - `LINE_NEEDS_FULFILMENT` — a catalog line whose variant is stock-tracked on
|
|
490
|
+
* an order with `fulfilment: 'none'`. Nothing ships or is handed over on
|
|
491
|
+
* such an order, so nothing would ever sell or release that stock.
|
|
492
|
+
* `details` carries its `position` and `variantId`. Send the order as
|
|
493
|
+
* `pickup` (or `ship`), or the service as an external line.
|
|
481
494
|
* - `EXTERNAL_LINE_PROMOTION_UNSUPPORTED` — a promotion discounted one of your
|
|
482
495
|
* externally priced lines. An order-level promotion is shared across every
|
|
483
496
|
* line of an order by the engine, so the platform refuses rather than
|
|
@@ -422,7 +422,7 @@ export interface OrderEditPlan {
|
|
|
422
422
|
* the order-edit plan, so on an older one this call alone fails validation and
|
|
423
423
|
* no other order call does.
|
|
424
424
|
*/
|
|
425
|
-
export declare const PLAN_ORDER_EDIT_QUERY = "\n query PlanOrderEdit($orderId: ID!, $diff: OrderEditDiffInput!) {\n planOrderEdit(orderId: $orderId, diff: $diff) {\n orderId\n planHash\n orderVersion\n steps {\n kind\n input\n moneyEffect\n }\n refund {\n paymentId\n amount\n }\n overpayment {\n amount\n currencyCode\n surchargeIds\n refund {\n available\n code\n message\n }\n accountCredit {\n available\n code\n message\n }\n refundWhenChosen {\n paymentId\n amount\n }\n }\n returnState\n blockers {\n code\n message\n details\n }\n notices {\n code\n message\n details\n }\n payment {\n collected\n reason\n method\n }\n preview {\n currencyCode\n subTotal\n subTotalWithTax\n shipping\n shippingWithTax\n surcharges\n surchargesWithTax\n total\n totalWithTax\n taxSummary {\n description\n taxRate\n taxBase\n taxTotal\n }\n totalWithTaxBefore\n }\n }\n }\n";
|
|
425
|
+
export declare const PLAN_ORDER_EDIT_QUERY = "\n query PlanOrderEdit($orderId: ID!, $diff: OrderEditDiffInput!) {\n planOrderEdit(orderId: $orderId, diff: $diff) {\n orderId\n planHash\n orderVersion\n steps {\n kind\n input\n moneyEffect\n }\n refund {\n paymentId\n amount\n }\n overpayment {\n amount\n currencyCode\n surchargeIds\n refund {\n available\n code\n message\n book\n }\n accountCredit {\n available\n code\n message\n book\n }\n refundWhenChosen {\n paymentId\n amount\n }\n }\n returnState\n blockers {\n code\n message\n details\n }\n notices {\n code\n message\n details\n }\n payment {\n collected\n reason\n method\n }\n preview {\n currencyCode\n subTotal\n subTotalWithTax\n shipping\n shippingWithTax\n surcharges\n surchargesWithTax\n total\n totalWithTax\n taxSummary {\n description\n taxRate\n taxBase\n taxTotal\n }\n totalWithTaxBefore\n }\n }\n }\n";
|
|
426
426
|
export interface OrderPlanEditModule {
|
|
427
427
|
/**
|
|
428
428
|
* How an edit of a placed order would be carried out, and what the order
|