@sixtyninecommerce/admin 0.9.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 +4598 -128
- 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 +318 -17
- package/dist/catalog/products.js +182 -14
- 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 +282 -25
- package/dist/catalog/variants.js +173 -25
- package/dist/catalog/visibility.d.ts +20 -5
- package/dist/catalog/visibility.js +19 -1
- package/dist/client.d.ts +116 -9
- package/dist/client.js +41 -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 +121 -10
- package/dist/fulfillments/index.js +120 -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 +129 -30
- package/dist/index.js +47 -9
- 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 +40 -0
- package/dist/integrations/index.js +24 -0
- package/dist/integrations/pipeline-keys.d.ts +13 -0
- package/dist/integrations/pipeline-keys.js +22 -0
- package/dist/integrations/pipelines.d.ts +114 -0
- package/dist/integrations/pipelines.js +46 -0
- package/dist/integrations/types.d.ts +322 -0
- package/dist/integrations/types.js +8 -0
- package/dist/jobs/bulk-action-run.d.ts +11 -2
- package/dist/jobs/bulk-action-run.js +4 -5
- 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/bulk.d.ts +75 -0
- package/dist/orders/bulk.js +150 -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/deposit-policy.d.ts +103 -0
- package/dist/orders/deposit-policy.js +202 -0
- 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 +125 -5
- package/dist/orders/index.js +35 -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-discounts.d.ts +11 -2
- package/dist/orders/manual-discounts.js +2 -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 +263 -10
- package/dist/payments/index.js +133 -1
- package/dist/payments/methods.d.ts +332 -0
- package/dist/payments/methods.js +363 -0
- 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 +177 -4
- package/dist/pricing/index.js +176 -1
- package/dist/pricing/price-lists.d.ts +604 -0
- package/dist/pricing/price-lists.js +600 -0
- package/dist/pricing/vouchers.d.ts +103 -0
- package/dist/pricing/vouchers.js +69 -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 +818 -0
- package/dist/returns/index.js +844 -0
- package/dist/search/index.d.ts +174 -0
- package/dist/search/index.js +125 -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 +51 -4
- 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
package/dist/pricing/index.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { type Page, type Transport } from '@sixtyninecommerce/core';
|
|
2
|
-
import type
|
|
3
|
-
import type { Call } from '../types.js';
|
|
2
|
+
import { type ConfigurableOperation, type ConfigurableOperationInput, type LanguageCode } from '../catalog/types.js';
|
|
3
|
+
import type { Call, ConfigurableOperationDefinition, ListOptions } from '../types.js';
|
|
4
|
+
import { type PricingBulkCouponsModule } from './bulk-coupons.js';
|
|
5
|
+
import { type PricingPriceListsModule } from './price-lists.js';
|
|
6
|
+
import { type PricingVouchersModule } from './vouchers.js';
|
|
4
7
|
/**
|
|
5
8
|
* Promotions at the register (headless spec §9.2 `pricing`; incentives spec §5,
|
|
6
9
|
* sprint 1): which promotions a register can offer, coupons on the order it is
|
|
@@ -33,6 +36,13 @@ import type { Call } from '../types.js';
|
|
|
33
36
|
export interface PricingModule {
|
|
34
37
|
promotions: PricingPromotionsModule;
|
|
35
38
|
coupons: PricingCouponsModule;
|
|
39
|
+
/** Personal vouchers: templates, issuing, a customer's vouchers (`./vouchers.ts`). */
|
|
40
|
+
vouchers: PricingVouchersModule;
|
|
41
|
+
/**
|
|
42
|
+
* The store's B2B price lists: the lists, their entries, assignments and order rules, and
|
|
43
|
+
* bulk enable/disable/delete (`./price-lists.ts`).
|
|
44
|
+
*/
|
|
45
|
+
priceLists: PricingPriceListsModule;
|
|
36
46
|
/**
|
|
37
47
|
* The order's discounts as they stand: its coupon codes, the order-level
|
|
38
48
|
* discounts, and each line's discounts, every one naming the promotion it came
|
|
@@ -42,6 +52,80 @@ export interface PricingModule {
|
|
|
42
52
|
discounts(orderId: string, options?: Call): Promise<OrderDiscounts>;
|
|
43
53
|
}
|
|
44
54
|
export interface PricingPromotionsModule {
|
|
55
|
+
/**
|
|
56
|
+
* One page of the store's promotions (`limit` 1 to 1,000, default 25), every state and date
|
|
57
|
+
* window: what a back office lists, unlike {@link active}. Walk them all with `for await`:
|
|
58
|
+
* every following page re-sends the same filters, sort and store.
|
|
59
|
+
*
|
|
60
|
+
* - `term` (trimmed; a blank one is ignored) matches a case-insensitive part of the name, in
|
|
61
|
+
* ANY of its languages, or of the coupon code. A row found through another language's name
|
|
62
|
+
* answers that language's `name`. EXCEPT while sorted by `name`: the engine then reads the
|
|
63
|
+
* name in the request's language only (the store's default language where a promotion has
|
|
64
|
+
* none in it), so a term matches no other language; sort by another key to search them all.
|
|
65
|
+
* - `enabled` keeps only the enabled (or disabled) ones; their date window is not judged.
|
|
66
|
+
* - `sort`: one key; the engine's own order when omitted.
|
|
67
|
+
*
|
|
68
|
+
* The store's auto-managed order-rule promotion is never listed (see {@link active}).
|
|
69
|
+
*
|
|
70
|
+
* Refused before sending: `INVALID_PAGE_SIZE` (`ValidationError`, 400) for a `limit` outside
|
|
71
|
+
* 1 to 1,000; `INVALID_PROMOTION_SORT` (`ValidationError`, 400) for a sort field or direction
|
|
72
|
+
* this method does not name; `INVALID_PROMOTION_FILTER` (`ValidationError`, 400) for a `term`
|
|
73
|
+
* that is not a string or an `enabled` that is not a boolean.
|
|
74
|
+
*
|
|
75
|
+
* @effect read
|
|
76
|
+
* @permission ReadPromotion
|
|
77
|
+
*/
|
|
78
|
+
list(options?: PromotionListOptions): Promise<Page<PromotionListItem>>;
|
|
79
|
+
/**
|
|
80
|
+
* One promotion of this store with its translations, conditions and actions as stored (the
|
|
81
|
+
* stacking guard included), or `null` when the store has none by that id (another store's
|
|
82
|
+
* answers the same).
|
|
83
|
+
*
|
|
84
|
+
* The store's auto-managed order-rule promotion (the id an "Order discount" on an order names)
|
|
85
|
+
* is answered with `customFields.managedBy` set: it is read-only, every change and the delete
|
|
86
|
+
* are refused `MANAGED_PROMOTION_NOT_ALLOWED`; its rules are set on the price lists
|
|
87
|
+
* (`priceLists.orderRules`). A merchant's promotion answers `managedBy: null`.
|
|
88
|
+
*
|
|
89
|
+
* @effect read
|
|
90
|
+
* @permission ReadPromotion
|
|
91
|
+
*/
|
|
92
|
+
get(id: string, options?: Call): Promise<PromotionDetail | null>;
|
|
93
|
+
/**
|
|
94
|
+
* Delete a promotion of this store. It stops applying: an order priced after the delete no
|
|
95
|
+
* longer gets its discount, and its coupon code (and every bulk code generated for it) is no
|
|
96
|
+
* longer accepted.
|
|
97
|
+
*
|
|
98
|
+
* Refusals: `ENTITY_NOT_FOUND` (`NotFoundError`, 404) for an id this store does not hold (one
|
|
99
|
+
* answer for another store's and an unknown one), `SHARED_PROMOTION_NOT_ALLOWED` (403) for a
|
|
100
|
+
* promotion other stores hold too, `MANAGED_PROMOTION_NOT_ALLOWED` (`PermissionDeniedError`,
|
|
101
|
+
* 403) for the store's auto-managed order-rule promotion, and `PROMOTION_NOT_DELETED`
|
|
102
|
+
* (`ConflictError`, 409) should the engine answer that it kept it.
|
|
103
|
+
*
|
|
104
|
+
* @effect destructive
|
|
105
|
+
* @permission DeletePromotion
|
|
106
|
+
*/
|
|
107
|
+
delete(id: string, options?: Call): Promise<void>;
|
|
108
|
+
/**
|
|
109
|
+
* The conditions a promotion of this store can carry, each with its arguments, in the
|
|
110
|
+
* language of the request. Two the engine registers are left out because a caller never sets
|
|
111
|
+
* them: the stacking guard (`promotion_stacking_guard`, which {@link create} and
|
|
112
|
+
* {@link update} add themselves) and the price-list order-rule condition
|
|
113
|
+
* (`price_list_order_rules`, refused on every promotion but the store's auto-managed one).
|
|
114
|
+
*
|
|
115
|
+
* `args[].required` is NOT the enforced rule (see `ConfigArgDefinition.required`).
|
|
116
|
+
*
|
|
117
|
+
* @effect read
|
|
118
|
+
* @permission ReadPromotion
|
|
119
|
+
*/
|
|
120
|
+
conditionDefinitions(options?: Call): Promise<ConfigurableOperationDefinition[]>;
|
|
121
|
+
/**
|
|
122
|
+
* The actions a promotion of this store can carry, as {@link conditionDefinitions} answers the
|
|
123
|
+
* conditions: the price-list order-rule action (`price_list_order_rules`) is left out.
|
|
124
|
+
*
|
|
125
|
+
* @effect read
|
|
126
|
+
* @permission ReadPromotion
|
|
127
|
+
*/
|
|
128
|
+
actionDefinitions(options?: Call): Promise<ConfigurableOperationDefinition[]>;
|
|
45
129
|
/**
|
|
46
130
|
* The store's promotions that can apply right now: enabled, inside their date
|
|
47
131
|
* window, not used up, and — with `customerId` — open to that customer (a
|
|
@@ -58,9 +142,17 @@ export interface PricingPromotionsModule {
|
|
|
58
142
|
* location of this store that the credential may act at
|
|
59
143
|
* (`LOCATION_NOT_IN_CHANNEL` / `LOCATION_NOT_ALLOWED`).
|
|
60
144
|
*
|
|
145
|
+
* The store's auto-managed order-rule promotion is never listed: it applies
|
|
146
|
+
* the order rules of the store's price lists (`priceLists.orderRules`), is no
|
|
147
|
+
* offer, and is managed by the platform. Its discount still shows on an order
|
|
148
|
+
* ("Order discount", {@link PricingOrdersModule.discounts}), naming that
|
|
149
|
+
* promotion's id.
|
|
150
|
+
*
|
|
61
151
|
* Needs `ReadPromotion`, `CreateOrder` or `OperatePos`. A `Page` because every
|
|
62
152
|
* list in this SDK is one; the engine answers the whole list, so it is always
|
|
63
153
|
* the last page.
|
|
154
|
+
*
|
|
155
|
+
* @effect read
|
|
64
156
|
*/
|
|
65
157
|
active(filter?: ActivePromotionsFilter, options?: Call): Promise<Page<ActivePromotion>>;
|
|
66
158
|
/**
|
|
@@ -82,12 +174,18 @@ export interface PricingPromotionsModule {
|
|
|
82
174
|
* targeting or set argument the engine cannot read, a second set condition or
|
|
83
175
|
* a set action without its condition (`argument: "conditions"`), or a set
|
|
84
176
|
* condition without its action or a second copy of a set action
|
|
85
|
-
* (`argument: "actions"`), judged on `update` for the pair the update leaves
|
|
177
|
+
* (`argument: "actions"`), judged on `update` for the pair the update leaves,
|
|
178
|
+
* or the price-list order-rule pair `price_list_order_rules`, which only the
|
|
179
|
+
* store's own auto-managed promotion carries (`argument: "conditions"` or
|
|
180
|
+
* `"actions"`: order rules are set on a price list); `extensions.details` names the condition and
|
|
86
181
|
* argument), `LOCATION_NOT_IN_CHANNEL` (a location of another store, or not
|
|
87
182
|
* an id), `LOCATION_NOT_ALLOWED` (outside the credential's location
|
|
88
183
|
* restriction), `FACET_VALUE_NOT_FOUND` / `COLLECTION_NOT_FOUND`
|
|
89
184
|
* (`NotFoundError`, 404: a set component names a facet value or collection
|
|
90
185
|
* this store does not have; another store's answers the same).
|
|
186
|
+
*
|
|
187
|
+
* @effect write
|
|
188
|
+
* @permission CreatePromotion
|
|
91
189
|
*/
|
|
92
190
|
create(input: CreatePromotionInput, options?: Call): Promise<PricingPromotion>;
|
|
93
191
|
/**
|
|
@@ -95,7 +193,10 @@ export interface PricingPromotionsModule {
|
|
|
95
193
|
* replace the whole list (the guard is kept as on create). Needs
|
|
96
194
|
* `UpdatePromotion`.
|
|
97
195
|
*
|
|
98
|
-
* Refusals: those of {@link PricingPromotionsModule.create},
|
|
196
|
+
* Refusals: those of {@link PricingPromotionsModule.create},
|
|
197
|
+
* `MANAGED_PROMOTION_NOT_ALLOWED` (`PermissionDeniedError`, 403) for the
|
|
198
|
+
* store's auto-managed order-rule promotion (the id an "Order discount" on an
|
|
199
|
+
* order names; change the price list's order rules instead), and
|
|
99
200
|
* `MISSING_CONDITIONS_ERROR` (`BusinessRuleError`, 422) for one case: the input
|
|
100
201
|
* does not name `conditions`, the STORED promotion has none (an imported
|
|
101
202
|
* coupon, a seed: no guard was ever added), and the result would have no coupon
|
|
@@ -103,6 +204,9 @@ export interface PricingPromotionsModule {
|
|
|
103
204
|
* conditions from the stored ones, and the guard is added only to conditions
|
|
104
205
|
* the input sends: send `conditions` (even `[]`) to keep such a promotion
|
|
105
206
|
* without a code.
|
|
207
|
+
*
|
|
208
|
+
* @effect write
|
|
209
|
+
* @permission UpdatePromotion
|
|
106
210
|
*/
|
|
107
211
|
update(input: UpdatePromotionInput, options?: Call): Promise<PricingPromotion>;
|
|
108
212
|
}
|
|
@@ -252,7 +356,71 @@ export interface PricingPromotion {
|
|
|
252
356
|
priority: number | null;
|
|
253
357
|
};
|
|
254
358
|
}
|
|
359
|
+
/** What {@link PricingPromotionsModule.list} can sort by. */
|
|
360
|
+
export type PromotionSortField = 'name' | 'couponCode' | 'startsAt' | 'endsAt' | 'createdAt' | 'updatedAt';
|
|
361
|
+
export declare const PROMOTION_SORT_FIELDS: readonly PromotionSortField[];
|
|
362
|
+
export interface PromotionListOptions extends ListOptions {
|
|
363
|
+
/**
|
|
364
|
+
* A part of the name (any language, unless sorted by `name`: see `list`) or of the coupon code,
|
|
365
|
+
* capitals ignored; trimmed.
|
|
366
|
+
*/
|
|
367
|
+
term?: string;
|
|
368
|
+
/** Only the enabled (`true`) or the disabled (`false`) ones. */
|
|
369
|
+
enabled?: boolean;
|
|
370
|
+
/** ONE sort key; the engine's own order when omitted. */
|
|
371
|
+
sort?: {
|
|
372
|
+
field: PromotionSortField;
|
|
373
|
+
direction: 'ASC' | 'DESC';
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
/** A promotion as {@link PricingPromotionsModule.list} answers it. */
|
|
377
|
+
export interface PromotionListItem {
|
|
378
|
+
id: string;
|
|
379
|
+
/** In the request's language, or the language whose name a `term` matched. */
|
|
380
|
+
name: string;
|
|
381
|
+
description: string;
|
|
382
|
+
couponCode: string | null;
|
|
383
|
+
enabled: boolean;
|
|
384
|
+
/** ISO-8601 instants; null for an open start or end. */
|
|
385
|
+
startsAt: string | null;
|
|
386
|
+
endsAt: string | null;
|
|
387
|
+
usageLimit: number | null;
|
|
388
|
+
perCustomerUsageLimit: number | null;
|
|
389
|
+
createdAt: string;
|
|
390
|
+
updatedAt: string;
|
|
391
|
+
customFields: {
|
|
392
|
+
combineWithB2b: boolean | null;
|
|
393
|
+
combineWithOtherPromotions: boolean | null;
|
|
394
|
+
priority: number | null;
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
/** A promotion as {@link PricingPromotionsModule.get} answers it. */
|
|
398
|
+
export interface PromotionDetail extends Omit<PromotionListItem, 'customFields'> {
|
|
399
|
+
translations: Array<{
|
|
400
|
+
id: string;
|
|
401
|
+
languageCode: LanguageCode;
|
|
402
|
+
name: string;
|
|
403
|
+
description: string;
|
|
404
|
+
}>;
|
|
405
|
+
/** As stored, the stacking guard (`promotion_stacking_guard`) included. */
|
|
406
|
+
conditions: ConfigurableOperation[];
|
|
407
|
+
actions: ConfigurableOperation[];
|
|
408
|
+
customFields: PromotionListItem['customFields'] & {
|
|
409
|
+
/**
|
|
410
|
+
* Set only on the store's auto-managed order-rule promotion (`price-list-order-rules`): a
|
|
411
|
+
* platform service owns it, and every change and the delete are refused. `null` for a
|
|
412
|
+
* merchant's promotion.
|
|
413
|
+
*/
|
|
414
|
+
managedBy: string | null;
|
|
415
|
+
};
|
|
416
|
+
}
|
|
255
417
|
export interface PricingCouponsModule {
|
|
418
|
+
/**
|
|
419
|
+
* Unique codes generated in bulk for a promotion with a coupon code (`./bulk-coupons.ts`):
|
|
420
|
+
* the groups, their codes, generating, switching a code or a group off, deleting a group, and
|
|
421
|
+
* a group's codes as CSV.
|
|
422
|
+
*/
|
|
423
|
+
bulk: PricingBulkCouponsModule;
|
|
256
424
|
/**
|
|
257
425
|
* Apply a coupon code — a promotion's own code or a unique code generated for
|
|
258
426
|
* it — to a DRAFT order of this store: a back-office draft, or an order
|
|
@@ -397,6 +565,11 @@ export declare const ORDER_DISCOUNTS_FIELDS = "\n id\n code\n state\n curren
|
|
|
397
565
|
export declare const ACTIVE_PROMOTIONS_QUERY = "\n query ActivePromotions($locationId: ID, $customerId: ID) {\n activePromotions(locationId: $locationId, customerId: $customerId) {\n id\n name\n description\n startsAt\n endsAt\n requiresCouponCode\n usageLimit\n perCustomerUsageLimit\n conditions { code args { name value } summary }\n actions { code args { name value } summary }\n summary\n }\n }\n";
|
|
398
566
|
export declare const CREATE_PROMOTION_MUTATION = "\n mutation CreatePromotion($input: CreatePromotionInput!) {\n createPromotion(input: $input) {\n ... on Promotion { \n id\n name\n description\n enabled\n couponCode\n startsAt\n endsAt\n usageLimit\n perCustomerUsageLimit\n conditions { code args { name value } }\n actions { code args { name value } }\n customFields { combineWithB2b combineWithOtherPromotions priority }\n }\n ... on ErrorResult { errorCode message }\n }\n }\n";
|
|
399
567
|
export declare const UPDATE_PROMOTION_MUTATION = "\n mutation UpdatePromotion($input: UpdatePromotionInput!) {\n updatePromotion(input: $input) {\n ... on Promotion { \n id\n name\n description\n enabled\n couponCode\n startsAt\n endsAt\n usageLimit\n perCustomerUsageLimit\n conditions { code args { name value } }\n actions { code args { name value } }\n customFields { combineWithB2b combineWithOtherPromotions priority }\n }\n ... on ErrorResult { errorCode message }\n }\n }\n";
|
|
568
|
+
export declare const PROMOTIONS_QUERY = "\n query StorePromotions($options: PromotionListOptions) {\n promotions(options: $options) {\n items {\n \n id\n name\n description\n couponCode\n enabled\n startsAt\n endsAt\n usageLimit\n perCustomerUsageLimit\n createdAt\n updatedAt\n\n customFields { combineWithB2b combineWithOtherPromotions priority }\n }\n totalItems\n }\n }\n";
|
|
569
|
+
export declare const PROMOTION_QUERY = "\n query StorePromotion($id: ID!) {\n promotion(id: $id) {\n \n id\n name\n description\n couponCode\n enabled\n startsAt\n endsAt\n usageLimit\n perCustomerUsageLimit\n createdAt\n updatedAt\n\n translations { id languageCode name description }\n conditions { code args { name value } }\n actions { code args { name value } }\n customFields { combineWithB2b combineWithOtherPromotions priority managedBy }\n }\n }\n";
|
|
570
|
+
export declare const DELETE_PROMOTION_MUTATION = "\n mutation DeleteStorePromotion($id: ID!) {\n deletePromotion(id: $id) {\n result\n message\n }\n }\n";
|
|
571
|
+
export declare const PROMOTION_CONDITION_DEFINITIONS_QUERY = "\n query PromotionConditionDefinitions {\n promotionConditions { \n code\n description\n args {\n name\n type\n list\n required\n defaultValue\n label\n description\n ui\n }\n }\n }\n";
|
|
572
|
+
export declare const PROMOTION_ACTION_DEFINITIONS_QUERY = "\n query PromotionActionDefinitions {\n promotionActions { \n code\n description\n args {\n name\n type\n list\n required\n defaultValue\n label\n description\n ui\n }\n }\n }\n";
|
|
400
573
|
/** The condition the dashboard and the admin app put on every promotion they save. */
|
|
401
574
|
export declare const STACKING_GUARD_CONDITION = "promotion_stacking_guard";
|
|
402
575
|
export declare const APPLY_COUPON_CODE_TO_ORDER_MUTATION = "\n mutation ApplyCouponCodeToOrder($orderId: ID!, $couponCode: String!, $idempotencyKey: String) {\n applyCouponCodeToOrder(\n orderId: $orderId\n couponCode: $couponCode\n idempotencyKey: $idempotencyKey\n ) {\n \n id\n code\n state\n currencyCode\n couponCodes\n subTotal\n subTotalWithTax\n shipping\n shippingWithTax\n total\n totalWithTax\n discounts { promotionId adjustmentSource type description amount amountWithTax }\n promotions { id name }\n lines {\n id\n quantity\n productVariant { id sku name }\n unitPrice\n unitPriceWithTax\n linePrice\n linePriceWithTax\n discountedLinePrice\n discountedLinePriceWithTax\n proratedLinePrice\n proratedLinePriceWithTax\n discounts { promotionId adjustmentSource type description amount amountWithTax }\n }\n surcharges { id description sku price priceWithTax }\n packages { promotionId label price priceWithTax lineIds quantity }\n\n }\n }\n";
|
package/dist/pricing/index.js
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import { createPage, errorFromErrorResult, isErrorResult, NotFoundError, ValidationError, } from '@sixtyninecommerce/core';
|
|
1
|
+
import { ConflictError, createPage, errorFromErrorResult, isErrorResult, NotFoundError, UpstreamError, ValidationError, } from '@sixtyninecommerce/core';
|
|
2
|
+
import { fieldOf, vendureListPage, } from '../catalog/types.js';
|
|
3
|
+
import { createPricingBulkCouponsModule } from './bulk-coupons.js';
|
|
4
|
+
import { createPricingPriceListsModule } from './price-lists.js';
|
|
5
|
+
import { createPricingVouchersModule } from './vouchers.js';
|
|
2
6
|
/**
|
|
3
7
|
* The targeting conditions (incentives sprint 2), encoded as the engine stores
|
|
4
8
|
* them — every argument a string, lists JSON-encoded. Their argument names and
|
|
@@ -141,6 +145,14 @@ export const promotionActions = {
|
|
|
141
145
|
return { code: 'mix_and_match', arguments: [] };
|
|
142
146
|
},
|
|
143
147
|
};
|
|
148
|
+
export const PROMOTION_SORT_FIELDS = [
|
|
149
|
+
'name',
|
|
150
|
+
'couponCode',
|
|
151
|
+
'startsAt',
|
|
152
|
+
'endsAt',
|
|
153
|
+
'createdAt',
|
|
154
|
+
'updatedAt',
|
|
155
|
+
];
|
|
144
156
|
const DISCOUNT_FIELDS = 'promotionId adjustmentSource type description amount amountWithTax';
|
|
145
157
|
/** An order's pricing readout; the manual pricing doors (`orders.setLinePrices`, …) answer it too. */
|
|
146
158
|
export const ORDER_DISCOUNTS_FIELDS = /* GraphQL */ `
|
|
@@ -222,8 +234,144 @@ export const UPDATE_PROMOTION_MUTATION = /* GraphQL */ `
|
|
|
222
234
|
}
|
|
223
235
|
}
|
|
224
236
|
`;
|
|
237
|
+
const PROMOTION_ROW_FIELDS = /* GraphQL */ `
|
|
238
|
+
id
|
|
239
|
+
name
|
|
240
|
+
description
|
|
241
|
+
couponCode
|
|
242
|
+
enabled
|
|
243
|
+
startsAt
|
|
244
|
+
endsAt
|
|
245
|
+
usageLimit
|
|
246
|
+
perCustomerUsageLimit
|
|
247
|
+
createdAt
|
|
248
|
+
updatedAt
|
|
249
|
+
`;
|
|
250
|
+
export const PROMOTIONS_QUERY = /* GraphQL */ `
|
|
251
|
+
query StorePromotions($options: PromotionListOptions) {
|
|
252
|
+
promotions(options: $options) {
|
|
253
|
+
items {
|
|
254
|
+
${PROMOTION_ROW_FIELDS}
|
|
255
|
+
customFields { combineWithB2b combineWithOtherPromotions priority }
|
|
256
|
+
}
|
|
257
|
+
totalItems
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
`;
|
|
261
|
+
export const PROMOTION_QUERY = /* GraphQL */ `
|
|
262
|
+
query StorePromotion($id: ID!) {
|
|
263
|
+
promotion(id: $id) {
|
|
264
|
+
${PROMOTION_ROW_FIELDS}
|
|
265
|
+
translations { id languageCode name description }
|
|
266
|
+
conditions { code args { name value } }
|
|
267
|
+
actions { code args { name value } }
|
|
268
|
+
customFields { combineWithB2b combineWithOtherPromotions priority managedBy }
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
`;
|
|
272
|
+
export const DELETE_PROMOTION_MUTATION = /* GraphQL */ `
|
|
273
|
+
mutation DeleteStorePromotion($id: ID!) {
|
|
274
|
+
deletePromotion(id: $id) {
|
|
275
|
+
result
|
|
276
|
+
message
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
`;
|
|
280
|
+
const DEFINITION_FIELDS = /* GraphQL */ `
|
|
281
|
+
code
|
|
282
|
+
description
|
|
283
|
+
args {
|
|
284
|
+
name
|
|
285
|
+
type
|
|
286
|
+
list
|
|
287
|
+
required
|
|
288
|
+
defaultValue
|
|
289
|
+
label
|
|
290
|
+
description
|
|
291
|
+
ui
|
|
292
|
+
}
|
|
293
|
+
`;
|
|
294
|
+
export const PROMOTION_CONDITION_DEFINITIONS_QUERY = /* GraphQL */ `
|
|
295
|
+
query PromotionConditionDefinitions {
|
|
296
|
+
promotionConditions { ${DEFINITION_FIELDS} }
|
|
297
|
+
}
|
|
298
|
+
`;
|
|
299
|
+
export const PROMOTION_ACTION_DEFINITIONS_QUERY = /* GraphQL */ `
|
|
300
|
+
query PromotionActionDefinitions {
|
|
301
|
+
promotionActions { ${DEFINITION_FIELDS} }
|
|
302
|
+
}
|
|
303
|
+
`;
|
|
225
304
|
/** The condition the dashboard and the admin app put on every promotion they save. */
|
|
226
305
|
export const STACKING_GUARD_CONDITION = 'promotion_stacking_guard';
|
|
306
|
+
/**
|
|
307
|
+
* The price-list order-rule condition and action (`vendure-plugin-price-list`'s
|
|
308
|
+
* `order-rule-promotion.ts`): only the store's auto-managed promotion carries them, and the engine
|
|
309
|
+
* refuses them on any other (`PROMOTION_CONDITION_INVALID`), so they are never offered.
|
|
310
|
+
*/
|
|
311
|
+
const ORDER_RULE_OPERATION = 'price_list_order_rules';
|
|
312
|
+
/** Registered conditions a caller never sets itself (see `conditionDefinitions`). */
|
|
313
|
+
const NOT_OFFERED_CONDITIONS = new Set([
|
|
314
|
+
STACKING_GUARD_CONDITION,
|
|
315
|
+
ORDER_RULE_OPERATION,
|
|
316
|
+
]);
|
|
317
|
+
/** Registered actions a caller never sets itself (see `actionDefinitions`). */
|
|
318
|
+
const NOT_OFFERED_ACTIONS = new Set([ORDER_RULE_OPERATION]);
|
|
319
|
+
/**
|
|
320
|
+
* Every list read asks only for promotions no platform service manages: the store's order-rule
|
|
321
|
+
* promotion (`customFields.managedBy`) is never a row, on any page or search.
|
|
322
|
+
*/
|
|
323
|
+
const MERCHANT_PROMOTIONS = { managedBy: { isNull: true } };
|
|
324
|
+
function invalidPromotionList(code, message) {
|
|
325
|
+
return new ValidationError({ code, message, status: 400, service: 'vendure' });
|
|
326
|
+
}
|
|
327
|
+
/** `promotions(options)`'s variables for one page, the filters and the sort checked first. */
|
|
328
|
+
function promotionListVariables(options) {
|
|
329
|
+
const filter = { ...MERCHANT_PROMOTIONS };
|
|
330
|
+
const term = options?.term;
|
|
331
|
+
if (term !== undefined) {
|
|
332
|
+
if (typeof term !== 'string') {
|
|
333
|
+
throw invalidPromotionList('INVALID_PROMOTION_FILTER', 'term must be a string.');
|
|
334
|
+
}
|
|
335
|
+
const trimmed = term.trim();
|
|
336
|
+
if (trimmed !== '') {
|
|
337
|
+
filter._or = [{ name: { contains: trimmed } }, { couponCode: { contains: trimmed } }];
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
const enabled = options?.enabled;
|
|
341
|
+
if (enabled !== undefined) {
|
|
342
|
+
if (typeof enabled !== 'boolean') {
|
|
343
|
+
throw invalidPromotionList('INVALID_PROMOTION_FILTER', 'enabled must be true or false.');
|
|
344
|
+
}
|
|
345
|
+
filter.enabled = { eq: enabled };
|
|
346
|
+
}
|
|
347
|
+
const sort = options?.sort;
|
|
348
|
+
if (sort !== undefined &&
|
|
349
|
+
(!PROMOTION_SORT_FIELDS.includes(sort.field) ||
|
|
350
|
+
(sort.direction !== 'ASC' && sort.direction !== 'DESC'))) {
|
|
351
|
+
throw invalidPromotionList('INVALID_PROMOTION_SORT', `sort must name one of ${PROMOTION_SORT_FIELDS.join(', ')} and a direction ASC or DESC.`);
|
|
352
|
+
}
|
|
353
|
+
return (skip, take) => ({
|
|
354
|
+
options: {
|
|
355
|
+
skip,
|
|
356
|
+
take,
|
|
357
|
+
filter,
|
|
358
|
+
...(sort === undefined ? {} : { sort: { [sort.field]: sort.direction } }),
|
|
359
|
+
},
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
/** A definitions list read by name: anything but a list is refused, never answered empty. */
|
|
363
|
+
async function definitionsOf(transport, document, field, hidden, options) {
|
|
364
|
+
const definitions = await fieldOf(transport, document, field, {}, options);
|
|
365
|
+
if (!Array.isArray(definitions)) {
|
|
366
|
+
throw new UpstreamError({
|
|
367
|
+
code: 'UNEXPECTED_RESPONSE',
|
|
368
|
+
message: `The engine answered "${field}" without a list.`,
|
|
369
|
+
status: 502,
|
|
370
|
+
service: 'vendure',
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
return definitions.filter((definition) => !hidden.has(definition.code));
|
|
374
|
+
}
|
|
227
375
|
function withStackingGuard(conditions) {
|
|
228
376
|
return conditions.some((condition) => condition.code === STACKING_GUARD_CONDITION)
|
|
229
377
|
? conditions
|
|
@@ -279,6 +427,30 @@ function idVariable(value) {
|
|
|
279
427
|
export function createPricingModule(transport) {
|
|
280
428
|
return {
|
|
281
429
|
promotions: {
|
|
430
|
+
// Async, so a refused option rejects the promise like every refusal, never throws.
|
|
431
|
+
async list(options) {
|
|
432
|
+
return vendureListPage(transport, PROMOTIONS_QUERY, 'promotions', promotionListVariables(options), options);
|
|
433
|
+
},
|
|
434
|
+
get(id, options) {
|
|
435
|
+
return fieldOf(transport, PROMOTION_QUERY, 'promotion', { id }, options);
|
|
436
|
+
},
|
|
437
|
+
async delete(id, options) {
|
|
438
|
+
const answer = await fieldOf(transport, DELETE_PROMOTION_MUTATION, 'deletePromotion', { id }, options);
|
|
439
|
+
if (answer.result !== 'DELETED') {
|
|
440
|
+
throw new ConflictError({
|
|
441
|
+
code: 'PROMOTION_NOT_DELETED',
|
|
442
|
+
message: answer.message || `The engine kept promotion ${id}.`,
|
|
443
|
+
status: 409,
|
|
444
|
+
service: 'vendure',
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
},
|
|
448
|
+
conditionDefinitions(options) {
|
|
449
|
+
return definitionsOf(transport, PROMOTION_CONDITION_DEFINITIONS_QUERY, 'promotionConditions', NOT_OFFERED_CONDITIONS, options);
|
|
450
|
+
},
|
|
451
|
+
actionDefinitions(options) {
|
|
452
|
+
return definitionsOf(transport, PROMOTION_ACTION_DEFINITIONS_QUERY, 'promotionActions', NOT_OFFERED_ACTIONS, options);
|
|
453
|
+
},
|
|
282
454
|
async active(filter, options) {
|
|
283
455
|
const data = await transport.graphql({
|
|
284
456
|
api: 'admin',
|
|
@@ -317,7 +489,10 @@ export function createPricingModule(transport) {
|
|
|
317
489
|
return data.updatePromotion;
|
|
318
490
|
},
|
|
319
491
|
},
|
|
492
|
+
vouchers: createPricingVouchersModule(transport),
|
|
493
|
+
priceLists: createPricingPriceListsModule(transport),
|
|
320
494
|
coupons: {
|
|
495
|
+
bulk: createPricingBulkCouponsModule(transport),
|
|
321
496
|
async apply(orderId, couponCode, options) {
|
|
322
497
|
const data = await transport.graphql({
|
|
323
498
|
api: 'admin',
|