@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,239 @@
|
|
|
1
|
+
import { ValidationError } from '@sixtyninecommerce/core';
|
|
2
|
+
import { createSearchModule, escapeSearchFilterValue } from '../search/index.js';
|
|
3
|
+
import { fieldOf } from './types.js';
|
|
4
|
+
/** The most variants one `variants.find` answers. */
|
|
5
|
+
export const MAX_VARIANT_FIND_TAKE = 500;
|
|
6
|
+
/** The most products one `variants.find` search reads (`take / perProduct`, rounded up). */
|
|
7
|
+
export const MAX_VARIANT_FIND_PRODUCTS = 100;
|
|
8
|
+
const FOUND_VARIANT_PRODUCT_FIELDS = /* GraphQL */ `
|
|
9
|
+
id
|
|
10
|
+
name
|
|
11
|
+
slug
|
|
12
|
+
featuredAsset {
|
|
13
|
+
id
|
|
14
|
+
preview
|
|
15
|
+
}
|
|
16
|
+
`;
|
|
17
|
+
/**
|
|
18
|
+
* What a picker reads of a variant. `storePrice`, never core's `price` / `priceWithTax`: those
|
|
19
|
+
* throw for a variant the store has no price for, and one such variant would empty the answer.
|
|
20
|
+
*/
|
|
21
|
+
export const FOUND_VARIANT_FIELDS = /* GraphQL */ `
|
|
22
|
+
id
|
|
23
|
+
name
|
|
24
|
+
sku
|
|
25
|
+
enabled
|
|
26
|
+
storePrice {
|
|
27
|
+
price
|
|
28
|
+
priceWithTax
|
|
29
|
+
currencyCode
|
|
30
|
+
}
|
|
31
|
+
trackInventory
|
|
32
|
+
outOfStockThreshold
|
|
33
|
+
useGlobalOutOfStockThreshold
|
|
34
|
+
stockOnHand
|
|
35
|
+
stockAllocated
|
|
36
|
+
stockLevels {
|
|
37
|
+
stockLocationId
|
|
38
|
+
stockOnHand
|
|
39
|
+
stockAllocated
|
|
40
|
+
stockLocation {
|
|
41
|
+
id
|
|
42
|
+
name
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
`;
|
|
46
|
+
/** A found variant with its product: the selection of every list that answers variants flat. */
|
|
47
|
+
export const FOUND_VARIANT_WITH_PRODUCT_FIELDS = /* GraphQL */ `
|
|
48
|
+
${FOUND_VARIANT_FIELDS}
|
|
49
|
+
product {
|
|
50
|
+
${FOUND_VARIANT_PRODUCT_FIELDS}
|
|
51
|
+
}
|
|
52
|
+
`;
|
|
53
|
+
export const FIND_VARIANTS_BY_IDS_QUERY = /* GraphQL */ `
|
|
54
|
+
query CatalogFindVariantsByIds($options: ProductVariantListOptions) {
|
|
55
|
+
productVariants(options: $options) {
|
|
56
|
+
items {
|
|
57
|
+
${FOUND_VARIANT_WITH_PRODUCT_FIELDS}
|
|
58
|
+
}
|
|
59
|
+
totalItems
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
`;
|
|
63
|
+
/**
|
|
64
|
+
* The variants of some products, bounded PER PRODUCT (`variantList`, never `variants`, which the
|
|
65
|
+
* engine answers whole and then cuts at 1,000 without saying so).
|
|
66
|
+
*/
|
|
67
|
+
export const FIND_VARIANTS_OF_PRODUCTS_QUERY = /* GraphQL */ `
|
|
68
|
+
query CatalogFindVariantsOfProducts(
|
|
69
|
+
$options: ProductListOptions
|
|
70
|
+
$variantOptions: ProductVariantListOptions
|
|
71
|
+
) {
|
|
72
|
+
products(options: $options) {
|
|
73
|
+
items {
|
|
74
|
+
${FOUND_VARIANT_PRODUCT_FIELDS}
|
|
75
|
+
variantList(options: $variantOptions) {
|
|
76
|
+
items {
|
|
77
|
+
${FOUND_VARIANT_FIELDS}
|
|
78
|
+
}
|
|
79
|
+
totalItems
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
totalItems
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
`;
|
|
86
|
+
export function toFoundVariant(wire) {
|
|
87
|
+
const { stockLevels, product, ...rest } = wire;
|
|
88
|
+
return {
|
|
89
|
+
...rest,
|
|
90
|
+
stockLevels: stockLevels.map((level) => ({
|
|
91
|
+
stockLocationId: level.stockLocationId,
|
|
92
|
+
stockLocationName: level.stockLocation?.name ?? '',
|
|
93
|
+
stockOnHand: level.stockOnHand,
|
|
94
|
+
stockAllocated: level.stockAllocated,
|
|
95
|
+
})),
|
|
96
|
+
product: {
|
|
97
|
+
id: product.id,
|
|
98
|
+
name: product.name,
|
|
99
|
+
slug: product.slug,
|
|
100
|
+
featuredAsset: product.featuredAsset,
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function invalid(message) {
|
|
105
|
+
return new ValidationError({
|
|
106
|
+
code: 'VARIANT_FIND_INPUT_INVALID',
|
|
107
|
+
message,
|
|
108
|
+
status: 400,
|
|
109
|
+
service: 'vendure',
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
function wholeNumber(value, low, high) {
|
|
113
|
+
return typeof value === 'number' && Number.isInteger(value) && value >= low && value <= high;
|
|
114
|
+
}
|
|
115
|
+
/** A literal inside a regular expression the engine evaluates (Postgres `~*`). */
|
|
116
|
+
function escapeRegex(value) {
|
|
117
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
118
|
+
}
|
|
119
|
+
function criterionOf(input) {
|
|
120
|
+
const given = ['ids', 'term', 'skuPrefix'].filter((key) => input[key] !== undefined);
|
|
121
|
+
if (given.length !== 1) {
|
|
122
|
+
throw invalid(`Say which variants with exactly one of ids, term and skuPrefix; got ${given.length === 0 ? 'none' : given.join(' and ')}.`);
|
|
123
|
+
}
|
|
124
|
+
if (input.ids !== undefined) {
|
|
125
|
+
if (!Array.isArray(input.ids) || input.ids.some((id) => typeof id !== 'string' || id === '')) {
|
|
126
|
+
throw invalid('ids must be a list of variant ids.');
|
|
127
|
+
}
|
|
128
|
+
return { kind: 'ids', ids: [...new Set(input.ids)] };
|
|
129
|
+
}
|
|
130
|
+
const key = input.term !== undefined ? 'term' : 'skuPrefix';
|
|
131
|
+
const text = input[key];
|
|
132
|
+
if (typeof text !== 'string' || text.trim() === '') {
|
|
133
|
+
throw invalid(`${key} must be text to search for; an empty one finds nothing.`);
|
|
134
|
+
}
|
|
135
|
+
return key === 'term'
|
|
136
|
+
? { kind: 'term', term: text.trim() }
|
|
137
|
+
: { kind: 'skuPrefix', prefix: text.trim() };
|
|
138
|
+
}
|
|
139
|
+
/** The call's options with the currency the prices are asked in. */
|
|
140
|
+
function pricedIn(options, currencyCode) {
|
|
141
|
+
if (currencyCode === undefined)
|
|
142
|
+
return options;
|
|
143
|
+
if (typeof currencyCode !== 'string' || currencyCode.trim() === '') {
|
|
144
|
+
throw invalid('currencyCode must be an ISO 4217 code, or left out for the store default.');
|
|
145
|
+
}
|
|
146
|
+
return { ...options, tenant: { ...options?.tenant, currency: currencyCode } };
|
|
147
|
+
}
|
|
148
|
+
async function findByIds(transport, ids, take, options) {
|
|
149
|
+
if (ids.length > take) {
|
|
150
|
+
throw invalid(`ids names ${String(ids.length)} variants and take is ${String(take)}. Raise take, or ask for fewer.`);
|
|
151
|
+
}
|
|
152
|
+
if (ids.length === 0)
|
|
153
|
+
return { items: [], products: [] };
|
|
154
|
+
const list = await fieldOf(transport, FIND_VARIANTS_BY_IDS_QUERY, 'productVariants',
|
|
155
|
+
// Sorted so the engine's page is one total order; the answer is re-ordered below.
|
|
156
|
+
{ options: { filter: { id: { in: ids } }, take: ids.length, sort: { id: 'ASC' } } }, options);
|
|
157
|
+
const found = new Map(list.items.map((row) => [row.id, row]));
|
|
158
|
+
return {
|
|
159
|
+
items: ids.flatMap((id) => {
|
|
160
|
+
const row = found.get(id);
|
|
161
|
+
return row ? [toFoundVariant(row)] : [];
|
|
162
|
+
}),
|
|
163
|
+
products: [],
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
async function findBySearch(transport, criterion, take, perProduct, options, pricedOptions) {
|
|
167
|
+
const productCount = Math.ceil(take / perProduct);
|
|
168
|
+
if (productCount > MAX_VARIANT_FIND_PRODUCTS) {
|
|
169
|
+
throw invalid(`take ${String(take)} at ${String(perProduct)} per product reads ${String(productCount)} products; at most ${String(MAX_VARIANT_FIND_PRODUCTS)}. Raise perProduct or lower take.`);
|
|
170
|
+
}
|
|
171
|
+
// Which products, and in what order, is the index's answer (`search.index`, never a copy of
|
|
172
|
+
// it): relevance for a term, the product's name for a SKU prefix.
|
|
173
|
+
const hits = await createSearchModule(transport).index('products', criterion.kind === 'term'
|
|
174
|
+
? { term: criterion.term, take: productCount }
|
|
175
|
+
: {
|
|
176
|
+
term: '',
|
|
177
|
+
filters: [`skus STARTS WITH "${escapeSearchFilterValue(criterion.prefix)}"`],
|
|
178
|
+
sort: 'name',
|
|
179
|
+
take: productCount,
|
|
180
|
+
}, options);
|
|
181
|
+
const productIds = hits.items.map((hit) => hit.id);
|
|
182
|
+
if (productIds.length === 0)
|
|
183
|
+
return { items: [], products: [] };
|
|
184
|
+
const list = await fieldOf(transport, FIND_VARIANTS_OF_PRODUCTS_QUERY, 'products', {
|
|
185
|
+
options: { filter: { id: { in: productIds } }, take: productIds.length, sort: { id: 'ASC' } },
|
|
186
|
+
variantOptions: {
|
|
187
|
+
take: perProduct,
|
|
188
|
+
// A total order, so a bounded page is the same page on every read. By id alone: the
|
|
189
|
+
// engine applies the keys of a sort in the order its schema declares them, where `id`
|
|
190
|
+
// precedes `position`, so the `position, id` the pickers used to send was this order.
|
|
191
|
+
sort: { id: 'ASC' },
|
|
192
|
+
// Only a SKU search narrows the variants. A term matches the PRODUCT (its name, its
|
|
193
|
+
// description), and a variant's name is its options, so filtering variants by it would
|
|
194
|
+
// answer a product with nothing to pick.
|
|
195
|
+
...(criterion.kind === 'skuPrefix'
|
|
196
|
+
? { filter: { sku: { regex: `^${escapeRegex(criterion.prefix)}` } } }
|
|
197
|
+
: {}),
|
|
198
|
+
},
|
|
199
|
+
}, pricedOptions);
|
|
200
|
+
const read = new Map(list.items.map((product) => [product.id, product]));
|
|
201
|
+
const items = [];
|
|
202
|
+
const products = [];
|
|
203
|
+
for (const id of productIds) {
|
|
204
|
+
const room = take - items.length;
|
|
205
|
+
if (room <= 0)
|
|
206
|
+
break;
|
|
207
|
+
// The index can name a product the store no longer holds: it is updated after each change.
|
|
208
|
+
const product = read.get(id);
|
|
209
|
+
if (!product)
|
|
210
|
+
continue;
|
|
211
|
+
const rows = product.variantList.items.slice(0, room);
|
|
212
|
+
if (rows.length === 0)
|
|
213
|
+
continue;
|
|
214
|
+
for (const row of rows)
|
|
215
|
+
items.push(toFoundVariant({ ...row, product }));
|
|
216
|
+
products.push({ id: product.id, shown: rows.length, total: product.variantList.totalItems });
|
|
217
|
+
}
|
|
218
|
+
return { items, products };
|
|
219
|
+
}
|
|
220
|
+
/** `catalog.variants.find`; its contract is on `VariantsModule.find`. */
|
|
221
|
+
export async function findVariants(transport, input, options) {
|
|
222
|
+
if (typeof input !== 'object' || input === null)
|
|
223
|
+
throw invalid('find takes an input object.');
|
|
224
|
+
const criterion = criterionOf(input);
|
|
225
|
+
const { take, perProduct } = input;
|
|
226
|
+
if (!wholeNumber(take, 1, MAX_VARIANT_FIND_TAKE)) {
|
|
227
|
+
throw invalid(`take must be a whole number from 1 to ${String(MAX_VARIANT_FIND_TAKE)}.`);
|
|
228
|
+
}
|
|
229
|
+
const pricedOptions = pricedIn(options, input.currencyCode);
|
|
230
|
+
if (criterion.kind === 'ids') {
|
|
231
|
+
if (perProduct !== undefined)
|
|
232
|
+
throw invalid('perProduct bounds a search; ids takes none.');
|
|
233
|
+
return findByIds(transport, criterion.ids, take, pricedOptions);
|
|
234
|
+
}
|
|
235
|
+
if (perProduct !== undefined && !wholeNumber(perProduct, 1, take)) {
|
|
236
|
+
throw invalid(`perProduct must be a whole number from 1 to take (${String(take)}).`);
|
|
237
|
+
}
|
|
238
|
+
return findBySearch(transport, criterion, take, perProduct ?? Math.ceil(take / 10), options, pricedOptions);
|
|
239
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type Page, type Transport } from '@sixtyninecommerce/core';
|
|
2
2
|
import type { Call, ListOptions } from '../types.js';
|
|
3
|
-
import { type AssetRef, type Availability, type AvailabilityInput, type FacetValueRef, type LanguageCode, type PriceBasis, type TranslationInput, type VariantAvailabilityState } from './types.js';
|
|
3
|
+
import { type AssetRef, type Availability, type AvailabilityInput, type FacetValueRef, type LanguageCode, type PriceBasis, type TranslationInput, type VariantAvailabilityState, type WireAssetRef } from './types.js';
|
|
4
|
+
import { type FindVariantsInput, type FoundVariants } from './variant-find.js';
|
|
4
5
|
export interface StockLevel {
|
|
5
6
|
stockLocationId: string;
|
|
6
7
|
stockOnHand: number;
|
|
@@ -31,16 +32,32 @@ export interface VariantPriceInput {
|
|
|
31
32
|
price: number;
|
|
32
33
|
}
|
|
33
34
|
/**
|
|
34
|
-
* A
|
|
35
|
+
* A variant's price in the active store, in the currency of the request (the store's default,
|
|
36
|
+
* unless the call names another with `tenant.currency`). Integer minor units of `currencyCode`.
|
|
35
37
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* from `priceWithTax`: writing back the `price` it read would drop the shelf
|
|
42
|
-
* price by the whole VAT amount.
|
|
38
|
+
* `price` is ALWAYS net and `priceWithTax` ALWAYS gross, whatever the store's basis — core
|
|
39
|
+
* derives whichever side it does not store, at the rate of the store's default tax zone. A write
|
|
40
|
+
* states `price` in the STORE's basis (`priceBasis`), so a read-modify-write on a gross store
|
|
41
|
+
* (`pricesIncludeTax: true`) must start from `priceWithTax`: writing back the `price` it read
|
|
42
|
+
* would drop the shelf price by the whole VAT amount.
|
|
43
43
|
*/
|
|
44
|
+
export interface VariantStorePrice {
|
|
45
|
+
/** Net, always — never the figure to write back on a gross store. */
|
|
46
|
+
price: number;
|
|
47
|
+
/** Gross, always, at the store's default tax zone. */
|
|
48
|
+
priceWithTax: number;
|
|
49
|
+
currencyCode: string;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* One price the store STORES for a variant, in one currency: integer minor units on the store's
|
|
53
|
+
* basis (gross on a store with `pricesIncludeTax`, net otherwise), exactly what a write takes. A
|
|
54
|
+
* currency the store converts from another has no entry; see {@link ProductVariant.storePrice}.
|
|
55
|
+
*/
|
|
56
|
+
export interface VariantStoredPrice {
|
|
57
|
+
currencyCode: string;
|
|
58
|
+
price: number;
|
|
59
|
+
}
|
|
60
|
+
/** A product variant — the thing that has a SKU, a price and stock. */
|
|
44
61
|
export interface ProductVariant extends Availability<VariantAvailabilityState> {
|
|
45
62
|
id: string;
|
|
46
63
|
productId: string;
|
|
@@ -50,11 +67,23 @@ export interface ProductVariant extends Availability<VariantAvailabilityState> {
|
|
|
50
67
|
name: string;
|
|
51
68
|
sku: string;
|
|
52
69
|
enabled: boolean;
|
|
53
|
-
/**
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
70
|
+
/**
|
|
71
|
+
* The prices the active store stores for the variant, one per currency (see
|
|
72
|
+
* {@link VariantStoredPrice}); `[]` when it stores none.
|
|
73
|
+
*/
|
|
74
|
+
prices: VariantStoredPrice[];
|
|
75
|
+
/**
|
|
76
|
+
* The engine's on-hand total for the variant in the active store (core's `stockOnHand`, which
|
|
77
|
+
* per-location out-of-stock thresholds can adjust); `stockLevels` has the count at each location.
|
|
78
|
+
*/
|
|
79
|
+
stockOnHand: number;
|
|
80
|
+
/**
|
|
81
|
+
* The variant's price in the active store, or null when the store has no price for it in the
|
|
82
|
+
* request's currency: none stored there and none it converts from. Never 0 for a missing price;
|
|
83
|
+
* a 0 here is a price of 0. Needs an engine with `ProductVariant.storePrice` (vendure-server
|
|
84
|
+
* at or after #1504).
|
|
85
|
+
*/
|
|
86
|
+
storePrice: VariantStorePrice | null;
|
|
58
87
|
taxCategory: {
|
|
59
88
|
id: string;
|
|
60
89
|
name: string;
|
|
@@ -80,6 +109,36 @@ export interface ProductVariant extends Availability<VariantAvailabilityState> {
|
|
|
80
109
|
parcelCapacity: number | null;
|
|
81
110
|
/** Never null on read: an unset packing is `shared`, the engine's default. */
|
|
82
111
|
parcelPacking: ParcelPacking;
|
|
112
|
+
/** The fewest units one order line may carry; null for no minimum. */
|
|
113
|
+
minOrderQuantity: number | null;
|
|
114
|
+
/** The units a line's quantity moves in (6: 6, 12, 18 …); null for one. */
|
|
115
|
+
salesUnit: number | null;
|
|
116
|
+
/**
|
|
117
|
+
* Where the variant sits in its product's order (the dashboard's "Reorder"); null for a variant
|
|
118
|
+
* nobody placed, which {@link VariantsModule.list} puts after the placed ones.
|
|
119
|
+
*/
|
|
120
|
+
position: number | null;
|
|
121
|
+
/**
|
|
122
|
+
* What one unit costs the store: NET, whatever the store's price basis (`prices` may be gross),
|
|
123
|
+
* integer minor units of its default currency; null when unset. Informational: no price or tax
|
|
124
|
+
* reads it.
|
|
125
|
+
*/
|
|
126
|
+
cost: number | null;
|
|
127
|
+
packageWeightGrams: number | null;
|
|
128
|
+
packageLengthCm: number | null;
|
|
129
|
+
packageWidthCm: number | null;
|
|
130
|
+
packageHeightCm: number | null;
|
|
131
|
+
/**
|
|
132
|
+
* The variant's backorder rule; null follows the store's (`inherit`). A string on the wire: a
|
|
133
|
+
* newer engine may add a policy.
|
|
134
|
+
*/
|
|
135
|
+
backorderPolicy: VariantBackorderPolicy | (string & {}) | null;
|
|
136
|
+
/** The units a `limited` variant may sell below zero; null when unset. */
|
|
137
|
+
backorderLimit: number | null;
|
|
138
|
+
/** GS1 barcode (the product-feeds plugin's identifier); null when unset. */
|
|
139
|
+
gtin: string | null;
|
|
140
|
+
/** Manufacturer part number; null when unset. */
|
|
141
|
+
mpn: string | null;
|
|
83
142
|
stockLevels: StockLevel[];
|
|
84
143
|
options: Array<{
|
|
85
144
|
id: string;
|
|
@@ -143,7 +202,10 @@ interface VariantFields extends AvailabilityInput<VariantAvailabilityState> {
|
|
|
143
202
|
minOrderQuantity?: number | null;
|
|
144
203
|
/** The units a line's quantity moves in (6: 6, 12, 18 …); null for one. */
|
|
145
204
|
salesUnit?: number | null;
|
|
146
|
-
/**
|
|
205
|
+
/**
|
|
206
|
+
* What one unit costs the store: NET, whatever the store's price basis, integer minor units of
|
|
207
|
+
* its default currency; null clears it.
|
|
208
|
+
*/
|
|
147
209
|
cost?: number | null;
|
|
148
210
|
packageWeightGrams?: number | null;
|
|
149
211
|
packageLengthCm?: number | null;
|
|
@@ -185,7 +247,7 @@ export interface VariantPriceSource {
|
|
|
185
247
|
/**
|
|
186
248
|
* What the store charges in this currency, in minor units, on the STORE's basis: gross on a
|
|
187
249
|
* store with `pricesIncludeTax`, net otherwise — the basis a variant write takes, unlike
|
|
188
|
-
* {@link
|
|
250
|
+
* {@link VariantStorePrice.price}, which reads net everywhere. Null when nothing prices it: no
|
|
189
251
|
* stored price and no EUR price or exchange rate to convert from, or a currency the store
|
|
190
252
|
* marked not for sale.
|
|
191
253
|
*/
|
|
@@ -200,6 +262,41 @@ export interface VariantPriceSource {
|
|
|
200
262
|
/** The organization that shares the variant with the store; null for the store's own variant. */
|
|
201
263
|
organizationName: string | null;
|
|
202
264
|
}
|
|
265
|
+
/** A field {@link VariantsModule.list} can order a product's variants by. */
|
|
266
|
+
export type VariantSortField = 'position' | 'name' | 'sku' | 'createdAt' | 'updatedAt';
|
|
267
|
+
/** Options of {@link VariantsModule.list}. */
|
|
268
|
+
export interface VariantListOptions extends ListOptions {
|
|
269
|
+
/**
|
|
270
|
+
* Only the variants whose SKU OR name (in the request's language) contains this text, case
|
|
271
|
+
* insensitively. Blank or omitted: every variant.
|
|
272
|
+
*/
|
|
273
|
+
term?: string;
|
|
274
|
+
/**
|
|
275
|
+
* The order of the pages. Default `{ field: 'position', direction: 'ASC' }`: the order a
|
|
276
|
+
* merchant arranged the variants in, the ones never placed after the placed ones. The engine
|
|
277
|
+
* completes every sort with the variant id, so a page boundary never repeats or skips a row.
|
|
278
|
+
*/
|
|
279
|
+
sort?: {
|
|
280
|
+
field: VariantSortField;
|
|
281
|
+
direction: 'ASC' | 'DESC';
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
/** The variants {@link VariantsModule.optionSets} reads at most by default. */
|
|
285
|
+
export declare const DEFAULT_OPTION_SET_LIMIT = 1000;
|
|
286
|
+
/** The most variants one {@link VariantsModule.optionSets} call reads. */
|
|
287
|
+
export declare const MAX_OPTION_SET_LIMIT = 100000;
|
|
288
|
+
/** The option combinations a product's variants already have, as far as they were read. */
|
|
289
|
+
export interface VariantOptionSets {
|
|
290
|
+
/**
|
|
291
|
+
* One entry per variant read, in variant-id order: the ids of its options, sorted. A variant
|
|
292
|
+
* without options (a product's one default variant) reads `[]`.
|
|
293
|
+
*/
|
|
294
|
+
combinations: string[][];
|
|
295
|
+
/** How many variants the product has in the store. */
|
|
296
|
+
totalItems: number;
|
|
297
|
+
/** The product has more variants than were read (`limit`): a combination absent here may exist. */
|
|
298
|
+
truncated: boolean;
|
|
299
|
+
}
|
|
203
300
|
/** The engine's bound on one `revertPrice` call (`MAX_REVERT_VARIANTS`). */
|
|
204
301
|
export declare const MAX_REVERT_PRICE_VARIANTS = 500;
|
|
205
302
|
export interface CreateProductVariantInput extends VariantFields {
|
|
@@ -240,11 +337,99 @@ export interface UpdateProductVariantInput extends VariantFields {
|
|
|
240
337
|
* refuses".
|
|
241
338
|
*/
|
|
242
339
|
export interface VariantsModule {
|
|
243
|
-
|
|
340
|
+
/**
|
|
341
|
+
* One page of a product's variants (`limit` 1 to 1,000, default 25), in the order `sort` names
|
|
342
|
+
* and filtered by `term`; `page.total` is how many match. `for await` walks every page. Needs
|
|
343
|
+
* `ReadCatalog` or `ReadProduct`. An id this store does not hold answers an empty page.
|
|
344
|
+
*
|
|
345
|
+
* Refused before sending: `INVALID_PAGE_SIZE` (`ValidationError`, 400) for a `limit` outside
|
|
346
|
+
* 1 to 1,000; `INVALID_VARIANT_SORT` (`ValidationError`, 400) for a sort field or direction
|
|
347
|
+
* this method does not name.
|
|
348
|
+
*
|
|
349
|
+
* @effect read
|
|
350
|
+
*/
|
|
351
|
+
list(productId: string, options?: VariantListOptions): Promise<Page<ProductVariant>>;
|
|
352
|
+
/** @effect read */
|
|
244
353
|
get(id: string, options?: Call): Promise<ProductVariant | null>;
|
|
245
|
-
/**
|
|
354
|
+
/**
|
|
355
|
+
* The option combinations a product's variants already have, for a "create variants" form that
|
|
356
|
+
* must not offer a combination twice (the engine refuses one: "A ProductVariant with the
|
|
357
|
+
* selected options already exists"). Reads the variants in pages of up to 1,000, in id order, up
|
|
358
|
+
* to `limit` (default {@link DEFAULT_OPTION_SET_LIMIT}, at most {@link MAX_OPTION_SET_LIMIT});
|
|
359
|
+
* `truncated` says the product has more. Each page is one request: a high `limit` on a product
|
|
360
|
+
* with 100,000 variants is 100 of them. Needs `ReadCatalog` or `ReadProduct`; an id this store
|
|
361
|
+
* does not hold answers no combinations.
|
|
362
|
+
*
|
|
363
|
+
* Refused before sending: `INVALID_OPTION_SET_LIMIT` (`ValidationError`, 400) for a `limit`
|
|
364
|
+
* that is not a whole number from 1 to {@link MAX_OPTION_SET_LIMIT}.
|
|
365
|
+
*
|
|
366
|
+
* @effect read
|
|
367
|
+
*/
|
|
368
|
+
optionSets(productId: string, options?: Call & {
|
|
369
|
+
limit?: number;
|
|
370
|
+
}): Promise<VariantOptionSets>;
|
|
371
|
+
/**
|
|
372
|
+
* The variants a picker offers, each with its store price, its stock and its product: by id
|
|
373
|
+
* (`ids`), by a full-text search (`term`) or by the start of a SKU (`skuPrefix`). Exactly one
|
|
374
|
+
* of the three.
|
|
375
|
+
*
|
|
376
|
+
* - **`ids`** answers exactly those variants, in the order asked. An id the store does not
|
|
377
|
+
* hold is left out.
|
|
378
|
+
* - **A search reads products first**: the best `take / perProduct` products (rounded up) of
|
|
379
|
+
* the store's product index, then at most `perProduct` variants of each, in a stable order
|
|
380
|
+
* (by id; not the order a merchant arranged a product's variants in). `products` says per product how many of its variants match and how many `items` holds, so
|
|
381
|
+
* a caller can tell a short product from a cut-off one. The index is updated by a job after
|
|
382
|
+
* each change: a product created seconds ago may be missing.
|
|
383
|
+
* - **A hidden carrier variant is never answered**, by id or by search: the platform's own
|
|
384
|
+
* variant behind externally priced order lines is not catalogue.
|
|
385
|
+
* - **A disabled or unpriced variant IS answered** (`enabled`, `storePrice: null`): the engine
|
|
386
|
+
* refuses to add either to an order (`ORDER_LINE_VARIANT_UNPRICED` for the second).
|
|
387
|
+
*
|
|
388
|
+
* Needs `ReadCatalog` or `ReadProduct`. Refused before anything is sent
|
|
389
|
+
* (`VARIANT_FIND_INPUT_INVALID`, a `ValidationError`): none or several of `ids`, `term` and
|
|
390
|
+
* `skuPrefix`; a blank `term` or `skuPrefix`; `take` outside 1 to
|
|
391
|
+
* {@link MAX_VARIANT_FIND_TAKE}; `perProduct` outside 1 to `take`, or given with `ids`; more
|
|
392
|
+
* than {@link MAX_VARIANT_FIND_PRODUCTS} products; more distinct ids than `take`. By the
|
|
393
|
+
* engine: an id that is not an id at all (`ENTITY_NOT_FOUND`, a `NotFoundError`), a currency
|
|
394
|
+
* the store does not sell, and `SERVICE_UNAVAILABLE` (retryable) when the search service did
|
|
395
|
+
* not answer a search.
|
|
396
|
+
*
|
|
397
|
+
* @effect read
|
|
398
|
+
*/
|
|
399
|
+
find(input: FindVariantsInput, options?: Call): Promise<FoundVariants>;
|
|
400
|
+
/**
|
|
401
|
+
* Create variants, all or nothing: the engine creates the batch in one transaction. Needs
|
|
402
|
+
* `CreateCatalog` or `CreateProduct`. A `price` travels with `priceBasis` (see
|
|
403
|
+
* {@link PriceBasis}); its other currencies are converted until a write stores them.
|
|
404
|
+
*
|
|
405
|
+
* Refusals (nothing is written), besides the option-combination and basis refusals above:
|
|
406
|
+
* - `TRANSLATION_INPUT_INVALID` → `ValidationError` (400): a translation without a name
|
|
407
|
+
* (multi-region decision 106). One `details` entry per refused field, its message naming the
|
|
408
|
+
* language; the entries carry no `field` pointer.
|
|
409
|
+
* - `TRANSLATION_LANGUAGE_NOT_OFFERED` → `BusinessRuleError` (422): a translation in a
|
|
410
|
+
* language the store does not offer; `details[].field` points at the translation entry
|
|
411
|
+
* (`/input/<n>/translations/<i>`).
|
|
412
|
+
* - `FEED_IDENTIFIER_INVALID` → `ValidationError` (400): a GTIN that is not 8, 12, 13 or 14
|
|
413
|
+
* digits.
|
|
414
|
+
*
|
|
415
|
+
* @effect write
|
|
416
|
+
*/
|
|
246
417
|
create(inputs: CreateProductVariantInput[], options?: Call): Promise<ProductVariant[]>;
|
|
418
|
+
/** @effect write */
|
|
247
419
|
update(inputs: UpdateProductVariantInput[], options?: Call): Promise<ProductVariant[]>;
|
|
420
|
+
/**
|
|
421
|
+
* Soft-delete variants: they are no longer listed, and orders keep the lines that name them.
|
|
422
|
+
* Nothing in this SDK restores one. Needs `DeleteCatalog` or `DeleteProduct`.
|
|
423
|
+
*
|
|
424
|
+
* Refused before anything is deleted: `ENTITY_NOT_FOUND` (`NotFoundError`, 404) for a variant
|
|
425
|
+
* this store does not hold; `SHARED_PRODUCT_VARIANT_NOT_ALLOWED` (`PermissionDeniedError`, 403)
|
|
426
|
+
* for one another store also holds that you may not change there; `FIELD_GROUP_LOCKED`
|
|
427
|
+
* (`BusinessRuleError`, 422) while an app or API token owns one of its field groups;
|
|
428
|
+
* `EXTERNAL_LINE_CARRIER_PROTECTED` (422) for the platform's carrier. A variant the engine
|
|
429
|
+
* declines is `VARIANT_NOT_DELETED` (`ConflictError`, 409) with its reasons.
|
|
430
|
+
*
|
|
431
|
+
* @effect destructive
|
|
432
|
+
*/
|
|
248
433
|
delete(ids: string[], options?: Call): Promise<void>;
|
|
249
434
|
/**
|
|
250
435
|
* Set stock on hand per stock location — absolute values, one update. A
|
|
@@ -286,28 +471,50 @@ export interface VariantsModule {
|
|
|
286
471
|
currencyCodes?: readonly string[];
|
|
287
472
|
}): Promise<ProductVariant[]>;
|
|
288
473
|
}
|
|
289
|
-
export declare const VARIANT_FIELDS = "\n id\n productId\n createdAt\n updatedAt\n languageCode\n name\n sku\n enabled\n price\n
|
|
290
|
-
export declare const VARIANTS_QUERY = "\n query CatalogVariants($productId: ID!, $options: ProductVariantListOptions) {\n productVariants(productId: $productId, options: $options) {\n items { \n id\n productId\n createdAt\n updatedAt\n languageCode\n name\n sku\n enabled\n price\n
|
|
291
|
-
|
|
292
|
-
export declare const
|
|
293
|
-
export declare const
|
|
474
|
+
export declare const VARIANT_FIELDS = "\n id\n productId\n createdAt\n updatedAt\n languageCode\n name\n sku\n enabled\n storePrice {\n price\n priceWithTax\n currencyCode\n }\n prices {\n currencyCode\n price\n }\n stockOnHand\n taxCategory {\n id\n name\n }\n trackInventory\n outOfStockThreshold\n useGlobalOutOfStockThreshold\n stockLevels {\n stockLocationId\n stockOnHand\n stockAllocated\n }\n options {\n id\n code\n name\n groupId\n }\n featuredAsset { \n id\n name\n preview\n source\n type\n mimeType\n customFields {\n altText\n }\n }\n assets { \n id\n name\n preview\n source\n type\n mimeType\n customFields {\n altText\n }\n }\n facetValues { \n id\n code\n name\n facet {\n id\n code\n name\n }\n }\n translations {\n id\n languageCode\n name\n }\n customFields {\n taxClassKey\n availabilityState\n availableFrom\n preorderLimit\n parcelCapacity\n parcelPacking\n minOrderQuantity\n salesUnit\n position\n cost\n packageWeightGrams\n packageLengthCm\n packageWidthCm\n packageHeightCm\n backorderPolicy\n backorderLimit\n gtin\n mpn\n }\n";
|
|
475
|
+
export declare const VARIANTS_QUERY = "\n query CatalogVariants($productId: ID!, $options: ProductVariantListOptions) {\n productVariants(productId: $productId, options: $options) {\n items { \n id\n productId\n createdAt\n updatedAt\n languageCode\n name\n sku\n enabled\n storePrice {\n price\n priceWithTax\n currencyCode\n }\n prices {\n currencyCode\n price\n }\n stockOnHand\n taxCategory {\n id\n name\n }\n trackInventory\n outOfStockThreshold\n useGlobalOutOfStockThreshold\n stockLevels {\n stockLocationId\n stockOnHand\n stockAllocated\n }\n options {\n id\n code\n name\n groupId\n }\n featuredAsset { \n id\n name\n preview\n source\n type\n mimeType\n customFields {\n altText\n }\n }\n assets { \n id\n name\n preview\n source\n type\n mimeType\n customFields {\n altText\n }\n }\n facetValues { \n id\n code\n name\n facet {\n id\n code\n name\n }\n }\n translations {\n id\n languageCode\n name\n }\n customFields {\n taxClassKey\n availabilityState\n availableFrom\n preorderLimit\n parcelCapacity\n parcelPacking\n minOrderQuantity\n salesUnit\n position\n cost\n packageWeightGrams\n packageLengthCm\n packageWidthCm\n packageHeightCm\n backorderPolicy\n backorderLimit\n gtin\n mpn\n }\n }\n totalItems\n }\n }\n";
|
|
476
|
+
/** Two fields a row, for {@link VariantsModule.optionSets}: the id and its options' ids. */
|
|
477
|
+
export declare const VARIANT_OPTION_SETS_QUERY = "\n query CatalogVariantOptionSets($productId: ID!, $options: ProductVariantListOptions) {\n productVariants(productId: $productId, options: $options) {\n items {\n id\n options {\n id\n }\n }\n totalItems\n }\n }\n";
|
|
478
|
+
export declare const VARIANT_QUERY = "\n query CatalogVariant($id: ID!) {\n productVariant(id: $id) { \n id\n productId\n createdAt\n updatedAt\n languageCode\n name\n sku\n enabled\n storePrice {\n price\n priceWithTax\n currencyCode\n }\n prices {\n currencyCode\n price\n }\n stockOnHand\n taxCategory {\n id\n name\n }\n trackInventory\n outOfStockThreshold\n useGlobalOutOfStockThreshold\n stockLevels {\n stockLocationId\n stockOnHand\n stockAllocated\n }\n options {\n id\n code\n name\n groupId\n }\n featuredAsset { \n id\n name\n preview\n source\n type\n mimeType\n customFields {\n altText\n }\n }\n assets { \n id\n name\n preview\n source\n type\n mimeType\n customFields {\n altText\n }\n }\n facetValues { \n id\n code\n name\n facet {\n id\n code\n name\n }\n }\n translations {\n id\n languageCode\n name\n }\n customFields {\n taxClassKey\n availabilityState\n availableFrom\n preorderLimit\n parcelCapacity\n parcelPacking\n minOrderQuantity\n salesUnit\n position\n cost\n packageWeightGrams\n packageLengthCm\n packageWidthCm\n packageHeightCm\n backorderPolicy\n backorderLimit\n gtin\n mpn\n }\n }\n }\n";
|
|
479
|
+
export declare const CREATE_VARIANTS_MUTATION = "\n mutation CatalogCreateVariants($input: [CreateProductVariantInput!]!) {\n createProductVariants(input: $input) { \n id\n productId\n createdAt\n updatedAt\n languageCode\n name\n sku\n enabled\n storePrice {\n price\n priceWithTax\n currencyCode\n }\n prices {\n currencyCode\n price\n }\n stockOnHand\n taxCategory {\n id\n name\n }\n trackInventory\n outOfStockThreshold\n useGlobalOutOfStockThreshold\n stockLevels {\n stockLocationId\n stockOnHand\n stockAllocated\n }\n options {\n id\n code\n name\n groupId\n }\n featuredAsset { \n id\n name\n preview\n source\n type\n mimeType\n customFields {\n altText\n }\n }\n assets { \n id\n name\n preview\n source\n type\n mimeType\n customFields {\n altText\n }\n }\n facetValues { \n id\n code\n name\n facet {\n id\n code\n name\n }\n }\n translations {\n id\n languageCode\n name\n }\n customFields {\n taxClassKey\n availabilityState\n availableFrom\n preorderLimit\n parcelCapacity\n parcelPacking\n minOrderQuantity\n salesUnit\n position\n cost\n packageWeightGrams\n packageLengthCm\n packageWidthCm\n packageHeightCm\n backorderPolicy\n backorderLimit\n gtin\n mpn\n }\n }\n }\n";
|
|
480
|
+
export declare const UPDATE_VARIANTS_MUTATION = "\n mutation CatalogUpdateVariants($input: [UpdateProductVariantInput!]!) {\n updateProductVariants(input: $input) { \n id\n productId\n createdAt\n updatedAt\n languageCode\n name\n sku\n enabled\n storePrice {\n price\n priceWithTax\n currencyCode\n }\n prices {\n currencyCode\n price\n }\n stockOnHand\n taxCategory {\n id\n name\n }\n trackInventory\n outOfStockThreshold\n useGlobalOutOfStockThreshold\n stockLevels {\n stockLocationId\n stockOnHand\n stockAllocated\n }\n options {\n id\n code\n name\n groupId\n }\n featuredAsset { \n id\n name\n preview\n source\n type\n mimeType\n customFields {\n altText\n }\n }\n assets { \n id\n name\n preview\n source\n type\n mimeType\n customFields {\n altText\n }\n }\n facetValues { \n id\n code\n name\n facet {\n id\n code\n name\n }\n }\n translations {\n id\n languageCode\n name\n }\n customFields {\n taxClassKey\n availabilityState\n availableFrom\n preorderLimit\n parcelCapacity\n parcelPacking\n minOrderQuantity\n salesUnit\n position\n cost\n packageWeightGrams\n packageLengthCm\n packageWidthCm\n packageHeightCm\n backorderPolicy\n backorderLimit\n gtin\n mpn\n }\n }\n }\n";
|
|
294
481
|
export declare const DELETE_VARIANTS_MUTATION = "\n mutation CatalogDeleteVariants($ids: [ID!]!) {\n deleteProductVariants(ids: $ids) { \n result\n message\n }\n }\n";
|
|
295
482
|
/**
|
|
296
483
|
* A document of its own, never a field of `VARIANT_FIELDS`: every other variant read keeps
|
|
297
484
|
* working against an engine older than the field, and pays nothing for it.
|
|
298
485
|
*/
|
|
299
486
|
export declare const VARIANT_PRICE_SOURCES_QUERY = "\n query CatalogVariantPriceSources($id: ID!) {\n productVariant(id: $id) {\n id\n priceSources {\n currencyCode\n price\n source\n organizationPrice\n organizationName\n }\n }\n }\n";
|
|
300
|
-
export declare const REVERT_TO_ORGANIZATION_PRICE_MUTATION = "\n mutation CatalogRevertToOrganizationPrice($variantIds: [ID!]!, $currencyCodes: [CurrencyCode!]) {\n revertToOrganizationPrice(variantIds: $variantIds, currencyCodes: $currencyCodes) { \n id\n productId\n createdAt\n updatedAt\n languageCode\n name\n sku\n enabled\n price\n
|
|
487
|
+
export declare const REVERT_TO_ORGANIZATION_PRICE_MUTATION = "\n mutation CatalogRevertToOrganizationPrice($variantIds: [ID!]!, $currencyCodes: [CurrencyCode!]) {\n revertToOrganizationPrice(variantIds: $variantIds, currencyCodes: $currencyCodes) { \n id\n productId\n createdAt\n updatedAt\n languageCode\n name\n sku\n enabled\n storePrice {\n price\n priceWithTax\n currencyCode\n }\n prices {\n currencyCode\n price\n }\n stockOnHand\n taxCategory {\n id\n name\n }\n trackInventory\n outOfStockThreshold\n useGlobalOutOfStockThreshold\n stockLevels {\n stockLocationId\n stockOnHand\n stockAllocated\n }\n options {\n id\n code\n name\n groupId\n }\n featuredAsset { \n id\n name\n preview\n source\n type\n mimeType\n customFields {\n altText\n }\n }\n assets { \n id\n name\n preview\n source\n type\n mimeType\n customFields {\n altText\n }\n }\n facetValues { \n id\n code\n name\n facet {\n id\n code\n name\n }\n }\n translations {\n id\n languageCode\n name\n }\n customFields {\n taxClassKey\n availabilityState\n availableFrom\n preorderLimit\n parcelCapacity\n parcelPacking\n minOrderQuantity\n salesUnit\n position\n cost\n packageWeightGrams\n packageLengthCm\n packageWidthCm\n packageHeightCm\n backorderPolicy\n backorderLimit\n gtin\n mpn\n }\n }\n }\n";
|
|
301
488
|
/** The price basis the store stores, read on the SAME tenant as the write. */
|
|
302
489
|
export declare const PRICE_BASIS_QUERY = "\n query CatalogPriceBasis {\n activeChannel {\n pricesIncludeTax\n }\n }\n";
|
|
303
|
-
|
|
304
|
-
|
|
490
|
+
/** The variant fields read out of `customFields` as they are, null for an unset one. */
|
|
491
|
+
export declare const LIFTED_CUSTOM_FIELDS: readonly ["minOrderQuantity", "salesUnit", "position", "cost", "packageWeightGrams", "packageLengthCm", "packageWidthCm", "packageHeightCm", "backorderPolicy", "backorderLimit", "gtin", "mpn"];
|
|
492
|
+
type LiftedCustomField = (typeof LIFTED_CUSTOM_FIELDS)[number];
|
|
493
|
+
interface WireVariant extends Omit<ProductVariant, keyof Availability<string> | 'taxClassKey' | 'parcelCapacity' | 'parcelPacking' | LiftedCustomField | 'featuredAsset' | 'assets'> {
|
|
494
|
+
featuredAsset: WireAssetRef | null;
|
|
495
|
+
assets: WireAssetRef[];
|
|
496
|
+
customFields: (Partial<Availability<VariantAvailabilityState>> & Partial<Pick<ProductVariant, LiftedCustomField>> & {
|
|
305
497
|
taxClassKey?: string | null;
|
|
306
498
|
parcelCapacity?: number | null;
|
|
307
499
|
parcelPacking?: string | null;
|
|
308
500
|
}) | null;
|
|
309
501
|
}
|
|
502
|
+
/** Lift the custom fields to first-class fields. */
|
|
310
503
|
export declare function toVariant(wire: WireVariant): ProductVariant;
|
|
504
|
+
/**
|
|
505
|
+
* The engine's `ProductVariantListOptions` for {@link VariantListOptions}, without the page
|
|
506
|
+
* window. ONE sort key, never a tie-breaker beside it: graphql-js coerces an input object in the
|
|
507
|
+
* order its TYPE declares the fields, and `ProductVariantSortParameter` declares `id` before every
|
|
508
|
+
* field named here, so `{ position, id }` reaches the engine as `{ id, position }` and sorts by id
|
|
509
|
+
* alone (W10-113 finding). The engine completes the order itself: `productVariants(productId:)`
|
|
510
|
+
* (core's `getVariantsByProductId`) appends `id ASC` after the caller's key, which makes it total,
|
|
511
|
+
* so offset pages neither repeat nor skip a row even where `position` is null.
|
|
512
|
+
*/
|
|
513
|
+
export declare function variantListOptions(options: VariantListOptions | undefined): {
|
|
514
|
+
sort: Record<string, 'ASC' | 'DESC'>;
|
|
515
|
+
filter?: Record<string, unknown>;
|
|
516
|
+
filterOperator?: 'OR';
|
|
517
|
+
};
|
|
311
518
|
/** A write's prices and the basis it states them on. */
|
|
312
519
|
export interface PricedInput {
|
|
313
520
|
price?: number;
|