@sixtyninecommerce/admin 0.11.0 → 0.13.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.
Files changed (153) hide show
  1. package/README.md +1509 -28
  2. package/dist/auth/index.d.ts +7 -1
  3. package/dist/auth/index.js +8 -1
  4. package/dist/catalog/documents.d.ts +142 -0
  5. package/dist/catalog/documents.js +114 -0
  6. package/dist/catalog/index.d.ts +48 -7
  7. package/dist/catalog/index.js +6 -1
  8. package/dist/catalog/metadata.d.ts +244 -0
  9. package/dist/catalog/metadata.js +220 -0
  10. package/dist/catalog/properties.d.ts +38 -0
  11. package/dist/catalog/properties.js +52 -1
  12. package/dist/catalog/recommendations.d.ts +33 -6
  13. package/dist/catalog/recommendations.js +94 -2
  14. package/dist/catalog/reviews.d.ts +17 -4
  15. package/dist/catalog/reviews.js +7 -0
  16. package/dist/catalog/variants.d.ts +60 -0
  17. package/dist/catalog/variants.js +39 -0
  18. package/dist/catalog/visibility.d.ts +18 -2
  19. package/dist/client.d.ts +29 -3
  20. package/dist/client.js +19 -8
  21. package/dist/content/assets.d.ts +3 -4
  22. package/dist/content/forms.d.ts +332 -1
  23. package/dist/content/forms.js +140 -4
  24. package/dist/content/items.d.ts +31 -8
  25. package/dist/content/items.js +1 -1
  26. package/dist/content/menus.d.ts +254 -0
  27. package/dist/content/menus.js +70 -0
  28. package/dist/content/strings.d.ts +137 -0
  29. package/dist/content/strings.js +82 -0
  30. package/dist/customers/delivery-terms.d.ts +44 -0
  31. package/dist/customers/delivery-terms.js +32 -0
  32. package/dist/customers/groups.d.ts +16 -5
  33. package/dist/customers/groups.js +6 -2
  34. package/dist/customers/index.d.ts +15 -0
  35. package/dist/customers/index.js +4 -0
  36. package/dist/documents/emails.d.ts +154 -0
  37. package/dist/documents/emails.js +220 -0
  38. package/dist/documents/index.d.ts +13 -0
  39. package/dist/documents/index.js +2 -0
  40. package/dist/fulfillments/create.d.ts +1 -1
  41. package/dist/fulfillments/create.js +5 -2
  42. package/dist/fulfillments/index.d.ts +119 -1
  43. package/dist/fulfillments/index.js +124 -4
  44. package/dist/fulfillments/warehouse.d.ts +29 -17
  45. package/dist/fulfillments/warehouse.js +32 -1
  46. package/dist/index.d.ts +43 -23
  47. package/dist/index.js +11 -5
  48. package/dist/integrations/exact-online-types.d.ts +542 -0
  49. package/dist/integrations/exact-online.d.ts +541 -5
  50. package/dist/integrations/exact-online.js +714 -1
  51. package/dist/integrations/index.d.ts +23 -8
  52. package/dist/integrations/index.js +9 -4
  53. package/dist/integrations/pipeline-discoveries.d.ts +65 -0
  54. package/dist/integrations/pipeline-discoveries.js +65 -0
  55. package/dist/integrations/pipeline-runs.d.ts +119 -0
  56. package/dist/integrations/pipeline-runs.js +87 -0
  57. package/dist/integrations/pipelines.d.ts +73 -2
  58. package/dist/integrations/pipelines.js +36 -1
  59. package/dist/integrations/price-import.d.ts +223 -0
  60. package/dist/integrations/price-import.js +124 -0
  61. package/dist/integrations/types.d.ts +221 -3
  62. package/dist/integrations/types.js +4 -3
  63. package/dist/meta/index.d.ts +10 -0
  64. package/dist/metafields/index.d.ts +8 -1
  65. package/dist/metafields/index.js +10 -0
  66. package/dist/orders/cancel-with-money.d.ts +10 -0
  67. package/dist/orders/cancel-with-money.js +2 -0
  68. package/dist/orders/commit-edit.d.ts +16 -0
  69. package/dist/orders/commit-edit.js +14 -1
  70. package/dist/orders/deposit-policy.d.ts +3 -1
  71. package/dist/orders/index.d.ts +22 -11
  72. package/dist/orders/index.js +5 -2
  73. package/dist/orders/list.d.ts +26 -5
  74. package/dist/orders/list.js +123 -13
  75. package/dist/orders/manual-discounts.d.ts +13 -5
  76. package/dist/orders/money-view.d.ts +149 -0
  77. package/dist/orders/money-view.js +99 -0
  78. package/dist/orders/plan-edit.d.ts +34 -2
  79. package/dist/orders/plan-edit.js +110 -12
  80. package/dist/orders/surcharges.d.ts +12 -0
  81. package/dist/orders/surcharges.js +34 -9
  82. package/dist/payments/account-credit.d.ts +17 -1
  83. package/dist/payments/account-credit.js +25 -2
  84. package/dist/payments/credit-noted-fields.d.ts +8 -1
  85. package/dist/payments/credit-noted-fields.js +34 -2
  86. package/dist/payments/customer-consent.d.ts +30 -0
  87. package/dist/payments/customer-consent.js +49 -0
  88. package/dist/payments/index.d.ts +89 -14
  89. package/dist/payments/index.js +22 -2
  90. package/dist/payments/requests.d.ts +6 -3
  91. package/dist/payments/requests.js +1 -0
  92. package/dist/pickups/index.d.ts +5 -3
  93. package/dist/pickups/index.js +5 -2
  94. package/dist/platform/email-gateways.d.ts +165 -0
  95. package/dist/platform/email-gateways.js +78 -0
  96. package/dist/platform/tax.d.ts +11 -3
  97. package/dist/platform/tax.js +30 -0
  98. package/dist/pos/exchanges.d.ts +6 -1
  99. package/dist/pos/index.d.ts +229 -10
  100. package/dist/pos/index.js +113 -4
  101. package/dist/pos/offline-sales.d.ts +44 -3
  102. package/dist/pos/offline-sales.js +57 -3
  103. package/dist/pos/returns.d.ts +28 -1
  104. package/dist/pos/returns.js +36 -6
  105. package/dist/pricing/price-lists.d.ts +3 -1
  106. package/dist/purchasing/alerts.d.ts +19 -4
  107. package/dist/purchasing/alerts.js +29 -3
  108. package/dist/purchasing/backorders.d.ts +61 -0
  109. package/dist/purchasing/backorders.js +92 -0
  110. package/dist/purchasing/index.d.ts +21 -3
  111. package/dist/purchasing/index.js +8 -0
  112. package/dist/purchasing/links.d.ts +263 -0
  113. package/dist/purchasing/links.js +192 -0
  114. package/dist/purchasing/purchase-orders.d.ts +4 -1
  115. package/dist/purchasing/receipts.d.ts +396 -0
  116. package/dist/purchasing/receipts.js +287 -0
  117. package/dist/purchasing/returns.d.ts +273 -0
  118. package/dist/purchasing/returns.js +229 -0
  119. package/dist/quotes/index.d.ts +20 -3
  120. package/dist/returns/index.d.ts +62 -1
  121. package/dist/returns/index.js +61 -0
  122. package/dist/seo/config.d.ts +128 -0
  123. package/dist/seo/config.js +95 -0
  124. package/dist/seo/redirects.d.ts +125 -0
  125. package/dist/seo/redirects.js +60 -1
  126. package/dist/seo/settings.d.ts +147 -0
  127. package/dist/seo/settings.js +209 -0
  128. package/dist/shipping/index.d.ts +6 -0
  129. package/dist/shipping/index.js +2 -0
  130. package/dist/shipping/methods.d.ts +8 -1
  131. package/dist/shipping/myparcel.d.ts +415 -1
  132. package/dist/shipping/myparcel.js +291 -3
  133. package/dist/shipping/rate-tables.d.ts +149 -4
  134. package/dist/shipping/rate-tables.js +229 -23
  135. package/dist/shipping/ship-to-countries.d.ts +75 -0
  136. package/dist/shipping/ship-to-countries.js +47 -0
  137. package/dist/stock/by-location.d.ts +86 -0
  138. package/dist/stock/by-location.js +94 -0
  139. package/dist/stock/index.d.ts +8 -1
  140. package/dist/stock/index.js +4 -0
  141. package/dist/stock/settings.d.ts +106 -0
  142. package/dist/stock/settings.js +103 -0
  143. package/dist/stock/transfers.d.ts +171 -10
  144. package/dist/stock/transfers.js +82 -4
  145. package/dist/stored-value/index.d.ts +98 -7
  146. package/dist/stored-value/index.js +71 -4
  147. package/dist/tax/display-policy.d.ts +105 -0
  148. package/dist/tax/display-policy.js +84 -0
  149. package/dist/tax/index.d.ts +3 -0
  150. package/dist/tax/index.js +2 -0
  151. package/dist/tenant/email-templates.d.ts +222 -1
  152. package/dist/tenant/email-templates.js +227 -10
  153. package/package.json +2 -2
@@ -0,0 +1,106 @@
1
+ import { type Transport } from '@sixtyninecommerce/core';
2
+ import type { Call } from '../types.js';
3
+ /** The store's default for ordering beyond saleable stock: never, up to stock on order, any quantity. */
4
+ export type StockBackorderPolicy = 'deny' | 'incoming' | 'unlimited';
5
+ /**
6
+ * How the storefront warehouse selection reads: `ALL` (no selection, every warehouse), `SUBSET`
7
+ * (only the listed ones), or `MALFORMED` (the stored value cannot be read; the engine sells from
8
+ * every warehouse and logs it, and saving a selection replaces it).
9
+ */
10
+ export type StorefrontStockLocationSelectionMode = 'ALL' | 'SUBSET' | 'MALFORMED';
11
+ export interface StorefrontStockLocations {
12
+ mode: StorefrontStockLocationSelectionMode;
13
+ /** The selected stock location ids, trimmed and de-duplicated (`SUBSET` only); else empty. */
14
+ locationIds: string[];
15
+ /** Why the stored value cannot be read (`MALFORMED` only); else null. */
16
+ reason: string | null;
17
+ }
18
+ /** A store's stock settings as the engine reads them. */
19
+ export interface StockSettings {
20
+ /** The channel the settings are stored on. */
21
+ channelId: string;
22
+ /**
23
+ * The store's own "track inventory" value; `null` = the store inherits
24
+ * {@link defaultTrackInventory}. It decides availability for this store's customers: a variant
25
+ * set to inherit tracks by it (a variant's own `TRUE`/`FALSE` wins), and an untracked variant
26
+ * is always available (saleable stock, add to cart, checkout, the storefront `stockLevel`,
27
+ * search, the till, feeds).
28
+ */
29
+ trackInventory: boolean | null;
30
+ /**
31
+ * The store's own out-of-stock threshold; `null` = the store inherits
32
+ * {@link defaultOutOfStockThreshold}. A variant on the global threshold (its own threshold
33
+ * wins otherwise, and a warehouse's own threshold wins at that warehouse) is unavailable once
34
+ * its stock on hand less allocations falls to it.
35
+ */
36
+ outOfStockThreshold: number | null;
37
+ /** The platform default a store that inherits tracks by. */
38
+ defaultTrackInventory: boolean;
39
+ /** The platform default threshold a store that inherits uses. */
40
+ defaultOutOfStockThreshold: number;
41
+ /** Whether the Shop API exposes operational stock numbers (on hand, allocated, saleable). */
42
+ exposeStockToStorefront: boolean;
43
+ /** Which warehouses back the storefront's saleable stock and its orders' reservations. */
44
+ storefrontStockLocations: StorefrontStockLocations;
45
+ /** The store's backorder default; a variant may override it. Unreadable reads `deny`. */
46
+ backorderPolicy: StockBackorderPolicy;
47
+ }
48
+ /** A change to the stock settings. An omitted field keeps the stored value. */
49
+ export interface StockSettingsPatch {
50
+ /**
51
+ * `null` = inherit the platform default. Changes which of this store's variants are available
52
+ * (see {@link StockSettings.trackInventory}).
53
+ */
54
+ trackInventory?: boolean | null;
55
+ /** `null` = inherit the platform default (see {@link StockSettings.outOfStockThreshold}). */
56
+ outOfStockThreshold?: number | null;
57
+ exposeStockToStorefront?: boolean;
58
+ /** Stock location ids of the store; `[]` clears the selection (every warehouse). */
59
+ storefrontStockLocationIds?: string[];
60
+ backorderPolicy?: StockBackorderPolicy;
61
+ }
62
+ /**
63
+ * The ACTIVE store's stock settings (`admin.stock.settings`). Reading needs any administrator
64
+ * permission on the store; writing needs `UpdateChannel` (the settings are stored on the channel
65
+ * and written through core `updateChannel`).
66
+ *
67
+ * The engine owns every rule: how a stored value reads is never worked out in the client. Ask
68
+ * {@link preview} for a change that is not saved.
69
+ */
70
+ export interface StockSettingsModule {
71
+ /**
72
+ * The settings as the engine reads them. An unreadable warehouse selection is `MALFORMED`, an
73
+ * unreadable backorder policy is `deny`, an unreadable exposure flag is off.
74
+ *
75
+ * @effect read
76
+ */
77
+ get(options?: Call): Promise<StockSettings>;
78
+ /**
79
+ * How the settings WOULD read with `patch` applied, without saving anything.
80
+ *
81
+ * Refused `CHANNEL_SETTINGS_INVALID` (`ValidationError`, one `details[]` entry per field, named
82
+ * like `customFields.backorderPolicy`) for a change the save would refuse: a `null` track
83
+ * inventory, threshold, exposure flag or policy, a policy that is not exactly one of the values,
84
+ * a blank warehouse id, or more than 500 warehouses. A malformed warehouse id is refused
85
+ * `ENTITY_NOT_FOUND` (`NotFoundError`).
86
+ *
87
+ * @effect read
88
+ */
89
+ preview(patch: StockSettingsPatch, options?: Call): Promise<StockSettings>;
90
+ /**
91
+ * Save `patch`, and answer the settings as the engine now reads them. Only the fields named are
92
+ * written; the warehouse list is stored as the engine reads it (trimmed, de-duplicated, `[]` as
93
+ * no selection).
94
+ *
95
+ * Refused, before anything is written, as {@link preview} refuses. Refused by the save itself:
96
+ * `FORBIDDEN` without `UpdateChannel`. A warehouse id that is not a stock location of the store
97
+ * is stored and ignored by the engine (it never widens the store's warehouses).
98
+ *
99
+ * @effect write
100
+ */
101
+ set(patch: StockSettingsPatch, options?: Call): Promise<StockSettings>;
102
+ }
103
+ export declare const STOCK_SETTINGS_QUERY = "\n query StockSettings {\n stockSettings { \n channelId\n trackInventory\n outOfStockThreshold\n defaultTrackInventory\n defaultOutOfStockThreshold\n exposeStockToStorefront\n storefrontStockLocations {\n mode\n locationIds\n reason\n }\n backorderPolicy\n }\n }\n";
104
+ export declare const PREVIEW_STOCK_SETTINGS_QUERY = "\n query PreviewStockSettings($input: StockSettingsInput!) {\n previewStockSettings(input: $input) { \n channelId\n trackInventory\n outOfStockThreshold\n defaultTrackInventory\n defaultOutOfStockThreshold\n exposeStockToStorefront\n storefrontStockLocations {\n mode\n locationIds\n reason\n }\n backorderPolicy\n }\n }\n";
105
+ export declare const SET_STOCK_SETTINGS_MUTATION = "\n mutation SetStockSettings($input: UpdateChannelInput!) {\n updateChannel(input: $input) {\n ... on Channel { id }\n ... on ErrorResult { errorCode message }\n }\n }\n";
106
+ export declare function createStockSettingsModule(transport: Transport): StockSettingsModule;
@@ -0,0 +1,103 @@
1
+ import { errorFromErrorResult, isErrorResult, } from '@sixtyninecommerce/core';
2
+ const VIEW_FIELDS = /* GraphQL */ `
3
+ channelId
4
+ trackInventory
5
+ outOfStockThreshold
6
+ defaultTrackInventory
7
+ defaultOutOfStockThreshold
8
+ exposeStockToStorefront
9
+ storefrontStockLocations {
10
+ mode
11
+ locationIds
12
+ reason
13
+ }
14
+ backorderPolicy
15
+ `;
16
+ export const STOCK_SETTINGS_QUERY = /* GraphQL */ `
17
+ query StockSettings {
18
+ stockSettings { ${VIEW_FIELDS} }
19
+ }
20
+ `;
21
+ export const PREVIEW_STOCK_SETTINGS_QUERY = /* GraphQL */ `
22
+ query PreviewStockSettings($input: StockSettingsInput!) {
23
+ previewStockSettings(input: $input) { ${VIEW_FIELDS} }
24
+ }
25
+ `;
26
+ export const SET_STOCK_SETTINGS_MUTATION = /* GraphQL */ `
27
+ mutation SetStockSettings($input: UpdateChannelInput!) {
28
+ updateChannel(input: $input) {
29
+ ... on Channel { id }
30
+ ... on ErrorResult { errorCode message }
31
+ }
32
+ }
33
+ `;
34
+ /** Exactly the fields the patch names: an omitted one keeps the stored value. */
35
+ function inputOf(patch) {
36
+ const input = {};
37
+ if (patch.trackInventory !== undefined)
38
+ input.trackInventory = patch.trackInventory;
39
+ if (patch.outOfStockThreshold !== undefined)
40
+ input.outOfStockThreshold = patch.outOfStockThreshold;
41
+ if (patch.exposeStockToStorefront !== undefined) {
42
+ input.exposeStockToStorefront = patch.exposeStockToStorefront;
43
+ }
44
+ if (patch.storefrontStockLocationIds !== undefined) {
45
+ input.storefrontStockLocationIds = [...patch.storefrontStockLocationIds];
46
+ }
47
+ if (patch.backorderPolicy !== undefined)
48
+ input.backorderPolicy = patch.backorderPolicy;
49
+ return input;
50
+ }
51
+ export function createStockSettingsModule(transport) {
52
+ const get = async (options) => {
53
+ const data = await transport.graphql({ api: 'admin', query: STOCK_SETTINGS_QUERY }, options);
54
+ return data.stockSettings;
55
+ };
56
+ const preview = async (patch, options) => {
57
+ const data = await transport.graphql({
58
+ api: 'admin',
59
+ query: PREVIEW_STOCK_SETTINGS_QUERY,
60
+ variables: { input: inputOf(patch) },
61
+ }, options);
62
+ return data.previewStockSettings;
63
+ };
64
+ return {
65
+ get,
66
+ preview,
67
+ async set(patch, options) {
68
+ // The engine judges the change first (its refusal is the save's) and answers the channel id
69
+ // and the warehouse list as it reads it, so the client keeps no copy of either rule.
70
+ const judged = await preview(patch, options);
71
+ const input = inputOf(patch);
72
+ const customFields = {};
73
+ if ('exposeStockToStorefront' in input) {
74
+ customFields.exposeStockToStorefront = input.exposeStockToStorefront;
75
+ }
76
+ if ('backorderPolicy' in input)
77
+ customFields.backorderPolicy = input.backorderPolicy;
78
+ if ('storefrontStockLocationIds' in input) {
79
+ const selection = judged.storefrontStockLocations;
80
+ // `null` is the column's "no selection", and the only value that clears a stored list.
81
+ customFields.storefrontStockLocationIds =
82
+ selection.mode === 'SUBSET' ? JSON.stringify(selection.locationIds) : null;
83
+ }
84
+ const data = await transport.graphql({
85
+ api: 'admin',
86
+ query: SET_STOCK_SETTINGS_MUTATION,
87
+ variables: {
88
+ input: {
89
+ id: judged.channelId,
90
+ ...('trackInventory' in input ? { trackInventory: input.trackInventory } : {}),
91
+ ...('outOfStockThreshold' in input
92
+ ? { outOfStockThreshold: input.outOfStockThreshold }
93
+ : {}),
94
+ ...(Object.keys(customFields).length > 0 ? { customFields } : {}),
95
+ },
96
+ },
97
+ }, options);
98
+ if (isErrorResult(data.updateChannel))
99
+ throw errorFromErrorResult(data.updateChannel);
100
+ return get(options);
101
+ },
102
+ };
103
+ }
@@ -5,6 +5,32 @@ import type { Call, ListOptions } from '../types.js';
5
5
  export type StockTransferState = 'draft' | 'in_transit' | 'received' | 'cancelled';
6
6
  /** A `transfer` moves stock between two locations; a `consumption` uses it up at one. */
7
7
  export type StockTransferKind = 'transfer' | 'consumption';
8
+ /**
9
+ * Why the engine would refuse a cancel or a return of a transfer now.
10
+ *
11
+ * - `STATE`: the state has no way to it (a cancel of a received transfer or a posted consumption).
12
+ * - `CANCELLED`: the transfer is cancelled.
13
+ * - `PARTIALLY_RECEIVED`: a cancel once any unit was received; `close` it instead.
14
+ * - `DRAFT_NOT_SHIPPED`: a return of a draft: nothing has moved yet.
15
+ * - `NOT_YET_RECEIVED`: a return of a transfer in transit that has received nothing yet.
16
+ * - `NOTHING_RECEIVED`: a return of a received transfer that received nothing.
17
+ * - `ALL_ON_RETURNS`: every received unit is already on a return; cancelling one frees its units.
18
+ * - `CONSUMPTION`, `IS_RETURN`, `NO_DESTINATION`: a return of a consumption, of a return, or
19
+ * of a transfer with no destination.
20
+ *
21
+ * Codes may be added; treat an unknown one as a refusal.
22
+ */
23
+ export type StockTransferActionRefusalCode = 'STATE' | 'CANCELLED' | 'PARTIALLY_RECEIVED' | 'DRAFT_NOT_SHIPPED' | 'NOT_YET_RECEIVED' | 'NOTHING_RECEIVED' | 'ALL_ON_RETURNS' | 'CONSUMPTION' | 'IS_RETURN' | 'NO_DESTINATION';
24
+ /**
25
+ * Whether an action on a transfer is available now, as the engine judges it, and why not.
26
+ * Advice only: the write judges again (with the caller's permission and locations), so a
27
+ * transfer that changed meanwhile is still refused.
28
+ */
29
+ export interface StockTransferActionAvailability {
30
+ available: boolean;
31
+ /** Null exactly when `available`. */
32
+ reasonCode: StockTransferActionRefusalCode | null;
33
+ }
8
34
  /**
9
35
  * What `search` matches in `list`: the transfer code only (`code`, the engine's default), or the
10
36
  * code or the label (`all`).
@@ -330,6 +356,12 @@ export interface StockTransferReturns {
330
356
  * return, or a transfer with nothing received.
331
357
  */
332
358
  returnableLines: StockTransferReturnableLine[];
359
+ /**
360
+ * Whether `createReturn` can make a return of it now, and why not (the engine's own rule).
361
+ * Null from an engine before the field: it says nothing either way, and `createReturn` still
362
+ * judges.
363
+ */
364
+ returnAvailability: StockTransferActionAvailability | null;
333
365
  }
334
366
  /**
335
367
  * The administrator who acted on a transfer. Usually a member of staff; an app installation or
@@ -368,6 +400,11 @@ export interface StockTransferCancellation {
368
400
  hendriksExport: {
369
401
  bluJayOrderNumber: string | null;
370
402
  } | null;
403
+ /**
404
+ * Whether `cancel` would accept it now, and why not (the engine's own rule). Null from an
405
+ * engine before the field: it says nothing either way, and `cancel` still judges.
406
+ */
407
+ cancelAvailability: StockTransferActionAvailability | null;
371
408
  }
372
409
  /** One MyParcel parcel of a stock transfer: its own shipment, label and barcode. */
373
410
  export interface StockTransferParcel {
@@ -430,6 +467,62 @@ export interface StockTransferLabel {
430
467
  filename: string;
431
468
  bytes: Uint8Array;
432
469
  }
470
+ /**
471
+ * The format of a store's transfer codes: `{prefix}{year}-{number}{suffix}`, e.g. `ST-2026-0001`
472
+ * (the defaults, until the store first sets its own).
473
+ */
474
+ export interface StockTransferNumberingConfig {
475
+ prefix: string;
476
+ suffix: string;
477
+ /** How many digits the number is padded to, 3 to 8. */
478
+ digits: number;
479
+ /**
480
+ * `none`, `short` (`26`) or `full` (`2026`). A row written before the engine checked it may
481
+ * hold another value, which prints like `none`.
482
+ */
483
+ yearFormat: string;
484
+ /**
485
+ * Stored for the shared numbering contract only: the counter restarts each UTC year whenever
486
+ * the code shows the year, and never when it does not, whatever this says.
487
+ */
488
+ yearReset: boolean;
489
+ }
490
+ /** A patch: a field left out keeps its value. */
491
+ export interface UpdateStockTransferNumberingConfigInput {
492
+ prefix?: string;
493
+ suffix?: string;
494
+ /** Clamped to 3..8. */
495
+ digits?: number;
496
+ /**
497
+ * `none`, `short` or `full`. Any other CHANGE is refused `NUMBERING_YEAR_FORMAT_INVALID`
498
+ * (→ `ValidationError`) and saves nothing; sending the stored value back always passes.
499
+ */
500
+ yearFormat?: string;
501
+ yearReset?: boolean;
502
+ }
503
+ /** `admin.stock.transfers.numbering`: the format the store's transfer codes take. */
504
+ export interface StockTransferNumberingModule {
505
+ /**
506
+ * The format the store's NEXT transfer code takes. A store in an organization that shares its
507
+ * numbering formats (`settings.numbering_formats`) reads the organization's format; the counter
508
+ * is always the store's own. Needs `ReadStockLocation`.
509
+ *
510
+ * @effect read
511
+ * @permission ReadStockLocation
512
+ */
513
+ get(options?: Call): Promise<StockTransferNumberingConfig>;
514
+ /**
515
+ * Change the format of the store's OWN row; codes already issued keep theirs, and the counter
516
+ * never changes. Answers that row, which is not what `get` reads while the store inherits the
517
+ * organization's format: read `get` again for the format in use. A store that inherits it is
518
+ * refused `ORGANIZATION_SETTINGS_INHERITED` until it overrides the group, and one whose
519
+ * organization locks the group `MANAGED_BY_ORGANIZATION`. Needs `UpdateStockLocation`.
520
+ *
521
+ * @effect write
522
+ * @permission UpdateStockLocation
523
+ */
524
+ set(input: UpdateStockTransferNumberingConfigInput, options?: Call): Promise<StockTransferNumberingConfig>;
525
+ }
433
526
  /**
434
527
  * Stock transfers (the engine's stock-transfer module, wrapped): a draft is
435
528
  * created, shipped (debiting the source), received line by line (crediting the
@@ -570,7 +663,8 @@ export interface StockTransfersModule {
570
663
  * source). An in-transit MyParcel shipment's parcels are voided at MyParcel
571
664
  * inside the call, so it is allowed up to 120s. A cancelled transfer is
572
665
  * final: cancelling it again is refused (`ValidationError`) and restores
573
- * nothing twice. An in-transit cancel is refused `FIELD_GROUP_LOCKED`
666
+ * nothing twice. Whether it would be accepted now, and why not, is
667
+ * `cancellation(id).cancelAvailability`. An in-transit cancel is refused `FIELD_GROUP_LOCKED`
574
668
  * (`BusinessRuleError`) while an app or API key owns the store's Stock.
575
669
  *
576
670
  * @effect destructive
@@ -592,9 +686,14 @@ export interface StockTransfersModule {
592
686
  createReturn(id: string, input: CreateStockTransferReturnInput, options?: Call): Promise<StockTransferDetail>;
593
687
  /**
594
688
  * How transfer `id` is linked to returns — the transfer it returns from, its
595
- * own returns, and what a new return may still take per variant — or null
596
- * when this store has no such transfer. Its own request, never part of
597
- * `get`. Needs `ReadStockLocation`.
689
+ * own returns, what a new return may still take per variant, and whether
690
+ * `createReturn` can make one now (`returnAvailability`, the engine's own
691
+ * rule: `createReturn` judges again, per line) — or null when this store has
692
+ * no such transfer. Its own request, never part of `get`. Needs
693
+ * `ReadStockLocation`.
694
+ *
695
+ * @effect read
696
+ * @permission ReadStockLocation
598
697
  */
599
698
  returns(id: string, options?: Call): Promise<StockTransferReturns | null>;
600
699
  /**
@@ -607,10 +706,14 @@ export interface StockTransfersModule {
607
706
  /**
608
707
  * Who cancelled transfer `id`, why, and the Hendriks export a cancel leaves
609
708
  * to be retracted by hand — or null when this store has no such transfer.
610
- * Read it before `cancel` to warn about the export, and after to show who
611
- * did it. Its own request, never part of `get`: a caller deployed ahead of
612
- * an engine that does not record the canceller sees only this call refused.
613
- * Needs `ReadStockLocation`.
709
+ * Read it before `cancel` to warn about the export and to know whether the
710
+ * cancel is offered (`cancelAvailability`, the engine's own rule: `cancel`
711
+ * judges again, with the caller's permission and locations), and after to
712
+ * show who did it. Its own request, never part of `get`: a caller deployed
713
+ * ahead of the engine sees only this call refused. Needs `ReadStockLocation`.
714
+ *
715
+ * @effect read
716
+ * @permission ReadStockLocation
614
717
  */
615
718
  cancellation(id: string, options?: Call): Promise<StockTransferCancellation | null>;
616
719
  /**
@@ -660,6 +763,59 @@ export interface StockTransfersModule {
660
763
  * default timeout does not cover.
661
764
  */
662
765
  myparcelLabel(id: string, format: StockTransferLabelFormat, options?: Call): Promise<StockTransferLabel>;
766
+ /**
767
+ * Void an in-transit shipment back to an editable draft, to correct a wrong handler or carrier
768
+ * and ship again. It undoes `ship`: the units go back to the source, every MyParcel parcel is
769
+ * voided at MyParcel inside the call, and the handler, its arguments, the carrier, tracking
770
+ * code, ETA, parcels and transfer note are cleared (the delivery address stays, for the
771
+ * re-ship). Answers the draft.
772
+ *
773
+ * MyParcel deletes only a concept: a parcel it keeps (a registered label) is named on
774
+ * `parcels(id).lastError`, recorded in `unretractedShipments` and never adopted by a re-ship.
775
+ * A Hendriks export, or any other handler's shipment, is NOT withdrawn: it is voided here only,
776
+ * and must be retracted at the 3PL by hand.
777
+ *
778
+ * Refused (`ValidationError`) for a transfer not in transit, so a repeat restores nothing
779
+ * twice, and once any unit was received or lost (close or cancel it instead). Refused
780
+ * `FIELD_GROUP_LOCKED` (`BusinessRuleError`) while an app or API key owns the store's Stock. A
781
+ * restricted credential must hold the source. The MyParcel calls make it allowed up to 120s;
782
+ * a `REQUEST_TIMEOUT` does not mean it failed, so `get` the transfer before trying again.
783
+ *
784
+ * @effect destructive
785
+ * @permission AdjustStock
786
+ */
787
+ removeShipment(id: string, options?: Call): Promise<StockTransferDetail>;
788
+ /**
789
+ * Upload the Hendriks (BluJay) export again for an in-transit transfer shipped with Hendriks
790
+ * whose export did not land at ship time (`hendriksRemotePath` still null). It reuses the
791
+ * transfer's BluJay order number and moves no stock. Answers the transfer with its
792
+ * `hendriksRemotePath`; an upload that fails is thrown, in the engine's words.
793
+ *
794
+ * Refused (`ValidationError`) for a transfer not shipped with Hendriks, not in transit, or
795
+ * already exported: a second retry waits for the first under the transfer's lock and is then
796
+ * refused, so one transfer never sends Hendriks two orders. A store without the Hendriks plugin
797
+ * is refused (`ValidationError`) too; one whose Hendriks set-up is missing or switched off is
798
+ * refused with no code yet, so that arrives as a `GRAPHQL_ERROR` (status 500) in the engine's
799
+ * words, and nothing is uploaded. A restricted credential must hold the source. The
800
+ * upload makes it allowed up to 120s; a `REQUEST_TIMEOUT` does not mean it failed, so `get` the
801
+ * transfer and look at `hendriksRemotePath` before trying again.
802
+ *
803
+ * @effect irreversible
804
+ * @permission AdjustStock
805
+ */
806
+ retryHendriksExport(id: string, options?: Call): Promise<StockTransferDetail>;
807
+ /**
808
+ * Generate the transfer's note (a consumption's: its consumption note) again and store it;
809
+ * answers the transfer with the new `pdfStorageKey`. Refused (`ValidationError`) for a draft.
810
+ * A store without document storage set up answers the transfer unchanged. A restricted
811
+ * credential must hold either end.
812
+ *
813
+ * @effect write
814
+ * @permission AdjustStock
815
+ */
816
+ regeneratePdf(id: string, options?: Call): Promise<StockTransferDetail>;
817
+ /** The format of the store's transfer codes. */
818
+ numbering: StockTransferNumberingModule;
663
819
  }
664
820
  export declare const STOCK_TRANSFERS_QUERY = "\n query StockTransfers($options: StockTransferListOptions) {\n stockTransfers(options: $options) { items { \n id\n code\n kind\n state\n sourceLocation { id name }\n destinationLocation { id name }\n label\n note\n carrier\n trackingCode\n estimatedArrivalAt\n shippedAt\n receivedAt\n cancelledAt\n cancelReason\n deliveryAddress {\n contactName\n company\n streetLine1\n streetLine2\n city\n province\n postalCode\n countryCode\n phoneNumber\n }\n createdAt\n updatedAt\n initiatedBy { id firstName lastName }\n items {\n id\n productVariant { id name sku }\n quantity\n receivedQuantity\n lostQuantity\n outstandingQuantity\n }\n totalLines\n totalQuantity\n totalReceivedQuantity\n totalLostQuantity\n } totalItems }\n }\n";
665
821
  export declare const STOCK_TRANSFER_QUERY = "\n query StockTransfer($id: ID!) { stockTransfer(id: $id) { \n id\n code\n kind\n state\n sourceLocation { id name }\n destinationLocation { id name customFields { address } }\n label\n note\n carrier\n trackingCode\n estimatedArrivalAt\n shippedAt\n receivedAt\n cancelledAt\n cancelReason\n deliveryAddress {\n contactName\n company\n streetLine1\n streetLine2\n city\n province\n postalCode\n countryCode\n phoneNumber\n }\n createdAt\n updatedAt\n initiatedBy { id firstName lastName }\n shippedBy { id firstName lastName }\n receivedBy { id firstName lastName }\n consumptionTotalValue\n consumptionHasUnpricedLines\n pdfStorageKey\n fulfillmentHandlerCode\n handlerArgs\n myparcelShipmentId\n myparcelBarcode\n hendriksRemotePath\n items {\n id\n productVariant { id name sku }\n quantity\n receivedQuantity\n lostQuantity\n outstandingQuantity\n unitCost\n }\n totalLines\n totalQuantity\n totalReceivedQuantity\n totalLostQuantity\n } }\n";
@@ -677,7 +833,12 @@ export declare const CLOSE_STOCK_TRANSFER_MUTATION = "\n mutation CloseStockTra
677
833
  export declare const CLOSE_STOCK_TRANSFER_WITH_SHORTFALL_MUTATION = "\n mutation CloseStockTransferWithShortfall(\n $id: ID!\n $acceptShortfallAsLost: Boolean\n $shortfall: [StockTransferShortfallLineInput!]!\n ) {\n closeStockTransfer(\n id: $id\n acceptShortfallAsLost: $acceptShortfallAsLost\n shortfall: $shortfall\n ) { \n id\n code\n kind\n state\n sourceLocation { id name }\n destinationLocation { id name customFields { address } }\n label\n note\n carrier\n trackingCode\n estimatedArrivalAt\n shippedAt\n receivedAt\n cancelledAt\n cancelReason\n deliveryAddress {\n contactName\n company\n streetLine1\n streetLine2\n city\n province\n postalCode\n countryCode\n phoneNumber\n }\n createdAt\n updatedAt\n initiatedBy { id firstName lastName }\n shippedBy { id firstName lastName }\n receivedBy { id firstName lastName }\n consumptionTotalValue\n consumptionHasUnpricedLines\n pdfStorageKey\n fulfillmentHandlerCode\n handlerArgs\n myparcelShipmentId\n myparcelBarcode\n hendriksRemotePath\n items {\n id\n productVariant { id name sku }\n quantity\n receivedQuantity\n lostQuantity\n outstandingQuantity\n unitCost\n }\n totalLines\n totalQuantity\n totalReceivedQuantity\n totalLostQuantity\n }\n }\n";
678
834
  export declare const CANCEL_STOCK_TRANSFER_MUTATION = "\n mutation CancelStockTransfer($id: ID!, $reason: String) {\n cancelStockTransfer(id: $id, reason: $reason) { \n id\n code\n kind\n state\n sourceLocation { id name }\n destinationLocation { id name customFields { address } }\n label\n note\n carrier\n trackingCode\n estimatedArrivalAt\n shippedAt\n receivedAt\n cancelledAt\n cancelReason\n deliveryAddress {\n contactName\n company\n streetLine1\n streetLine2\n city\n province\n postalCode\n countryCode\n phoneNumber\n }\n createdAt\n updatedAt\n initiatedBy { id firstName lastName }\n shippedBy { id firstName lastName }\n receivedBy { id firstName lastName }\n consumptionTotalValue\n consumptionHasUnpricedLines\n pdfStorageKey\n fulfillmentHandlerCode\n handlerArgs\n myparcelShipmentId\n myparcelBarcode\n hendriksRemotePath\n items {\n id\n productVariant { id name sku }\n quantity\n receivedQuantity\n lostQuantity\n outstandingQuantity\n unitCost\n }\n totalLines\n totalQuantity\n totalReceivedQuantity\n totalLostQuantity\n }\n }\n";
679
835
  export declare const CREATE_STOCK_TRANSFER_RETURN_MUTATION = "\n mutation CreateStockTransferReturn($id: ID!, $input: CreateStockTransferReturnInput!) {\n createStockTransferReturn(id: $id, input: $input) { \n id\n code\n kind\n state\n sourceLocation { id name }\n destinationLocation { id name customFields { address } }\n label\n note\n carrier\n trackingCode\n estimatedArrivalAt\n shippedAt\n receivedAt\n cancelledAt\n cancelReason\n deliveryAddress {\n contactName\n company\n streetLine1\n streetLine2\n city\n province\n postalCode\n countryCode\n phoneNumber\n }\n createdAt\n updatedAt\n initiatedBy { id firstName lastName }\n shippedBy { id firstName lastName }\n receivedBy { id firstName lastName }\n consumptionTotalValue\n consumptionHasUnpricedLines\n pdfStorageKey\n fulfillmentHandlerCode\n handlerArgs\n myparcelShipmentId\n myparcelBarcode\n hendriksRemotePath\n items {\n id\n productVariant { id name sku }\n quantity\n receivedQuantity\n lostQuantity\n outstandingQuantity\n unitCost\n }\n totalLines\n totalQuantity\n totalReceivedQuantity\n totalLostQuantity\n }\n }\n";
680
- export declare const STOCK_TRANSFER_RETURNS_QUERY = "\n query StockTransferReturns($id: ID!) {\n stockTransfer(id: $id) {\n returnOfTransferId\n returnOf { \n id\n code\n state\n label\n sourceLocation { id name }\n destinationLocation { id name }\n createdAt\n totalQuantity\n }\n returns { \n id\n code\n state\n label\n sourceLocation { id name }\n destinationLocation { id name }\n createdAt\n totalQuantity\n }\n returnableLines {\n productVariantId\n productVariant { name sku }\n receivedQuantity\n returnedQuantity\n returnableQuantity\n }\n }\n }\n";
836
+ export declare const REMOVE_STOCK_TRANSFER_SHIPMENT_MUTATION = "\n mutation RemoveStockTransferShipment($id: ID!) {\n removeStockTransferShipment(id: $id) { \n id\n code\n kind\n state\n sourceLocation { id name }\n destinationLocation { id name customFields { address } }\n label\n note\n carrier\n trackingCode\n estimatedArrivalAt\n shippedAt\n receivedAt\n cancelledAt\n cancelReason\n deliveryAddress {\n contactName\n company\n streetLine1\n streetLine2\n city\n province\n postalCode\n countryCode\n phoneNumber\n }\n createdAt\n updatedAt\n initiatedBy { id firstName lastName }\n shippedBy { id firstName lastName }\n receivedBy { id firstName lastName }\n consumptionTotalValue\n consumptionHasUnpricedLines\n pdfStorageKey\n fulfillmentHandlerCode\n handlerArgs\n myparcelShipmentId\n myparcelBarcode\n hendriksRemotePath\n items {\n id\n productVariant { id name sku }\n quantity\n receivedQuantity\n lostQuantity\n outstandingQuantity\n unitCost\n }\n totalLines\n totalQuantity\n totalReceivedQuantity\n totalLostQuantity\n }\n }\n";
837
+ export declare const RETRY_STOCK_TRANSFER_HENDRIKS_EXPORT_MUTATION = "\n mutation RetryStockTransferHendriksExport($id: ID!) {\n retryStockTransferHendriksExport(id: $id) { \n id\n code\n kind\n state\n sourceLocation { id name }\n destinationLocation { id name customFields { address } }\n label\n note\n carrier\n trackingCode\n estimatedArrivalAt\n shippedAt\n receivedAt\n cancelledAt\n cancelReason\n deliveryAddress {\n contactName\n company\n streetLine1\n streetLine2\n city\n province\n postalCode\n countryCode\n phoneNumber\n }\n createdAt\n updatedAt\n initiatedBy { id firstName lastName }\n shippedBy { id firstName lastName }\n receivedBy { id firstName lastName }\n consumptionTotalValue\n consumptionHasUnpricedLines\n pdfStorageKey\n fulfillmentHandlerCode\n handlerArgs\n myparcelShipmentId\n myparcelBarcode\n hendriksRemotePath\n items {\n id\n productVariant { id name sku }\n quantity\n receivedQuantity\n lostQuantity\n outstandingQuantity\n unitCost\n }\n totalLines\n totalQuantity\n totalReceivedQuantity\n totalLostQuantity\n }\n }\n";
838
+ export declare const REGENERATE_STOCK_TRANSFER_PDF_MUTATION = "\n mutation RegenerateStockTransferPdf($id: ID!) {\n regenerateStockTransferPdf(id: $id) { \n id\n code\n kind\n state\n sourceLocation { id name }\n destinationLocation { id name customFields { address } }\n label\n note\n carrier\n trackingCode\n estimatedArrivalAt\n shippedAt\n receivedAt\n cancelledAt\n cancelReason\n deliveryAddress {\n contactName\n company\n streetLine1\n streetLine2\n city\n province\n postalCode\n countryCode\n phoneNumber\n }\n createdAt\n updatedAt\n initiatedBy { id firstName lastName }\n shippedBy { id firstName lastName }\n receivedBy { id firstName lastName }\n consumptionTotalValue\n consumptionHasUnpricedLines\n pdfStorageKey\n fulfillmentHandlerCode\n handlerArgs\n myparcelShipmentId\n myparcelBarcode\n hendriksRemotePath\n items {\n id\n productVariant { id name sku }\n quantity\n receivedQuantity\n lostQuantity\n outstandingQuantity\n unitCost\n }\n totalLines\n totalQuantity\n totalReceivedQuantity\n totalLostQuantity\n }\n }\n";
839
+ export declare const STOCK_TRANSFER_NUMBERING_QUERY = "\n query StockTransferNumberingConfig {\n stockTransferNumberingConfig { \n prefix\n suffix\n digits\n yearFormat\n yearReset\n }\n }\n";
840
+ export declare const UPDATE_STOCK_TRANSFER_NUMBERING_MUTATION = "\n mutation UpdateStockTransferNumberingConfig($input: UpdateStockTransferNumberingConfigInput!) {\n updateStockTransferNumberingConfig(input: $input) { \n prefix\n suffix\n digits\n yearFormat\n yearReset\n }\n }\n";
841
+ export declare const STOCK_TRANSFER_RETURNS_QUERY = "\n query StockTransferReturns($id: ID!) {\n stockTransfer(id: $id) {\n returnOfTransferId\n returnOf { \n id\n code\n state\n label\n sourceLocation { id name }\n destinationLocation { id name }\n createdAt\n totalQuantity\n }\n returns { \n id\n code\n state\n label\n sourceLocation { id name }\n destinationLocation { id name }\n createdAt\n totalQuantity\n }\n returnableLines {\n productVariantId\n productVariant { name sku }\n receivedQuantity\n returnedQuantity\n returnableQuantity\n }\n returnAvailability { available reasonCode }\n }\n }\n";
681
842
  /** The per-line settlement fields, in a document of their own like the return fields. */
682
843
  export declare const STOCK_TRANSFER_SHORTFALL_QUERY = "\n query StockTransferShortfall($id: ID!) {\n stockTransfer(id: $id) {\n id\n state\n items {\n id\n productVariant { id sku }\n quantity\n receivedQuantity\n lostQuantity\n returnedToSourceQuantity\n outstandingQuantity\n }\n totalLostQuantity\n totalReturnedToSourceQuantity\n }\n }\n";
683
844
  /**
@@ -685,7 +846,7 @@ export declare const STOCK_TRANSFER_SHORTFALL_QUERY = "\n query StockTransferSh
685
846
  * parcel fields: `cancelledBy` is newer than the transfer module, and
686
847
  * `get`/`list`/`cancel` keep working against an engine without it.
687
848
  */
688
- export declare const STOCK_TRANSFER_CANCELLATION_QUERY = "\n query StockTransferCancellation($id: ID!) {\n stockTransfer(id: $id) {\n id\n state\n cancelledAt\n cancelReason\n cancelledBy { id firstName lastName }\n fulfillmentHandlerCode\n hendriksRemotePath\n hendriksBluJayOrderNumber\n }\n }\n";
849
+ export declare const STOCK_TRANSFER_CANCELLATION_QUERY = "\n query StockTransferCancellation($id: ID!) {\n stockTransfer(id: $id) {\n id\n state\n cancelledAt\n cancelReason\n cancelledBy { id firstName lastName }\n fulfillmentHandlerCode\n hendriksRemotePath\n hendriksBluJayOrderNumber\n cancelAvailability { available reasonCode }\n }\n }\n";
689
850
  export declare const STOCK_TRANSFER_PARCELS_QUERY = "\n query StockTransferParcels($id: ID!) { stockTransfer(id: $id) { \n id\n state\n fulfillmentHandlerCode\n parcelCount\n myparcelParcels { ordinal shipmentId barcode labelReady lastError }\n trackingCodes\n myparcelBarcode\n myparcelLastError\n myparcelUnretractedShipments { \n shipmentId\n reference\n verdict\n status\n statusName\n billable\n hidden\n reason\n cause\n firstRecordedAt\n lastCheckedAt\n resolvedAt\n }\n } }\n";
690
851
  export declare const RETRY_STOCK_TRANSFER_MYPARCEL_SHIPMENTS_MUTATION = "\n mutation RetryStockTransferMyparcelShipments($id: ID!) {\n retryStockTransferMyparcelShipments(id: $id) { \n id\n state\n fulfillmentHandlerCode\n parcelCount\n myparcelParcels { ordinal shipmentId barcode labelReady lastError }\n trackingCodes\n myparcelBarcode\n myparcelLastError\n myparcelUnretractedShipments { \n shipmentId\n reference\n verdict\n status\n statusName\n billable\n hidden\n reason\n cause\n firstRecordedAt\n lastCheckedAt\n resolvedAt\n }\n }\n }\n";
691
852
  export declare const LABEL_STOCK_TRANSFER_MYPARCEL_PARCELS_MUTATION = "\n mutation LabelStockTransferMyparcelParcels($id: ID!) {\n labelStockTransferMyparcelParcels(id: $id) { \n id\n state\n fulfillmentHandlerCode\n parcelCount\n myparcelParcels { ordinal shipmentId barcode labelReady lastError }\n trackingCodes\n myparcelBarcode\n myparcelLastError\n myparcelUnretractedShipments { \n shipmentId\n reference\n verdict\n status\n statusName\n billable\n hidden\n reason\n cause\n firstRecordedAt\n lastCheckedAt\n resolvedAt\n }\n }\n }\n";
@@ -1,5 +1,6 @@
1
1
  import { pageFromVendureList, readOffsetCursor, } from '@sixtyninecommerce/core';
2
2
  import { decodeBase64, MYPARCEL_LABEL_TIMEOUT_MS, toUnretractedShipments, UNRETRACTED_SHIPMENT_FIELDS, } from '../fulfillments/index.js';
3
+ import { isUnknownFieldRejection } from '../payments/store-credit-fields.js';
3
4
  const TRANSFER_FIELDS = /* GraphQL */ `
4
5
  id
5
6
  code
@@ -167,6 +168,38 @@ export const CREATE_STOCK_TRANSFER_RETURN_MUTATION = /* GraphQL */ `
167
168
  createStockTransferReturn(id: $id, input: $input) { ${TRANSFER_DETAIL_FIELDS} }
168
169
  }
169
170
  `;
171
+ export const REMOVE_STOCK_TRANSFER_SHIPMENT_MUTATION = /* GraphQL */ `
172
+ mutation RemoveStockTransferShipment($id: ID!) {
173
+ removeStockTransferShipment(id: $id) { ${TRANSFER_DETAIL_FIELDS} }
174
+ }
175
+ `;
176
+ export const RETRY_STOCK_TRANSFER_HENDRIKS_EXPORT_MUTATION = /* GraphQL */ `
177
+ mutation RetryStockTransferHendriksExport($id: ID!) {
178
+ retryStockTransferHendriksExport(id: $id) { ${TRANSFER_DETAIL_FIELDS} }
179
+ }
180
+ `;
181
+ export const REGENERATE_STOCK_TRANSFER_PDF_MUTATION = /* GraphQL */ `
182
+ mutation RegenerateStockTransferPdf($id: ID!) {
183
+ regenerateStockTransferPdf(id: $id) { ${TRANSFER_DETAIL_FIELDS} }
184
+ }
185
+ `;
186
+ const NUMBERING_FIELDS = /* GraphQL */ `
187
+ prefix
188
+ suffix
189
+ digits
190
+ yearFormat
191
+ yearReset
192
+ `;
193
+ export const STOCK_TRANSFER_NUMBERING_QUERY = /* GraphQL */ `
194
+ query StockTransferNumberingConfig {
195
+ stockTransferNumberingConfig { ${NUMBERING_FIELDS} }
196
+ }
197
+ `;
198
+ export const UPDATE_STOCK_TRANSFER_NUMBERING_MUTATION = /* GraphQL */ `
199
+ mutation UpdateStockTransferNumberingConfig($input: UpdateStockTransferNumberingConfigInput!) {
200
+ updateStockTransferNumberingConfig(input: $input) { ${NUMBERING_FIELDS} }
201
+ }
202
+ `;
170
203
  /**
171
204
  * The return fields, in a document of their own like the parcel fields below:
172
205
  * `get`/`list` keep working against an engine without them.
@@ -194,9 +227,19 @@ export const STOCK_TRANSFER_RETURNS_QUERY = /* GraphQL */ `
194
227
  returnedQuantity
195
228
  returnableQuantity
196
229
  }
230
+ returnAvailability { available reasonCode }
197
231
  }
198
232
  }
199
233
  `;
234
+ /**
235
+ * The availability verdicts (W10-71) are newer than the documents that carry them: an engine
236
+ * before them refuses the whole document, so the read is sent once more without them and
237
+ * answers the verdict as null.
238
+ */
239
+ const AVAILABILITY_SELECTION = /\s*(?:cancelAvailability|returnAvailability) \{ available reasonCode \}/g;
240
+ function withoutAvailability(document) {
241
+ return document.replace(AVAILABILITY_SELECTION, '');
242
+ }
200
243
  /** The per-line settlement fields, in a document of their own like the return fields. */
201
244
  export const STOCK_TRANSFER_SHORTFALL_QUERY = /* GraphQL */ `
202
245
  query StockTransferShortfall($id: ID!) {
@@ -247,6 +290,7 @@ export const STOCK_TRANSFER_CANCELLATION_QUERY = /* GraphQL */ `
247
290
  fulfillmentHandlerCode
248
291
  hendriksRemotePath
249
292
  hendriksBluJayOrderNumber
293
+ cancelAvailability { available reasonCode }
250
294
  }
251
295
  }
252
296
  `;
@@ -293,9 +337,10 @@ const MYPARCEL_HANDLER_CODE = 'myparcel';
293
337
  /**
294
338
  * A MyParcel ship and its retry book every parcel at MyParcel before they
295
339
  * answer (per parcel an adopt-by-reference lookup of up to 3 × 10s plus two
296
- * capped waits, and a 30s POST), and a cancel voids every parcel there. The
340
+ * capped waits, and a 30s POST), a cancel or a shipment removal voids every
341
+ * parcel there, and a Hendriks ship or export retry uploads its export. The
297
342
  * default 15s aborted calls the engine went on to finish, so the caller saw a
298
- * failure for a ship, booking or cancel that succeeded.
343
+ * failure for a ship, booking, cancel or removal that succeeded.
299
344
  */
300
345
  const CARRIER_CALL_TIMEOUT_MS = 120_000;
301
346
  /**
@@ -346,6 +391,7 @@ function toCancellation(raw) {
346
391
  cancelReason: raw.cancelReason,
347
392
  cancelledBy: raw.cancelledBy,
348
393
  hendriksExport: exported ? { bluJayOrderNumber: raw.hendriksBluJayOrderNumber } : null,
394
+ cancelAvailability: raw.cancelAvailability ?? null,
349
395
  };
350
396
  }
351
397
  function toTransfer(raw) {
@@ -433,8 +479,20 @@ function toReturns(raw) {
433
479
  variantName: productVariant.name,
434
480
  ...quantities,
435
481
  })),
482
+ returnAvailability: raw.returnAvailability ?? null,
436
483
  };
437
484
  }
485
+ /** Read the document, and once more without the availability verdicts when the engine does not know them. */
486
+ async function readWithoutAvailabilityOnOlderEngine(transport, query, id, options) {
487
+ try {
488
+ return await transport.graphql({ api: 'admin', query, variables: { id } }, options);
489
+ }
490
+ catch (error) {
491
+ if (!isUnknownFieldRejection(error))
492
+ throw error;
493
+ return transport.graphql({ api: 'admin', query: withoutAvailability(query), variables: { id } }, options);
494
+ }
495
+ }
438
496
  const toLines = (lines) => lines.map((line) => ({ productVariantId: line.variantId, quantity: line.quantity }));
439
497
  const DEFAULT_PAGE_SIZE = 25;
440
498
  export function createStockTransfersModule(transport) {
@@ -520,7 +578,7 @@ export function createStockTransfersModule(transport) {
520
578
  return one('createStockTransferReturn', CREATE_STOCK_TRANSFER_RETURN_MUTATION, { id, input: { ...rest, lines: toLines(lines) } }, options);
521
579
  },
522
580
  async returns(id, options) {
523
- const data = await transport.graphql({ api: 'admin', query: STOCK_TRANSFER_RETURNS_QUERY, variables: { id } }, options);
581
+ const data = await readWithoutAvailabilityOnOlderEngine(transport, STOCK_TRANSFER_RETURNS_QUERY, id, options);
524
582
  return data.stockTransfer === null ? null : toReturns(data.stockTransfer);
525
583
  },
526
584
  async shortfall(id, options) {
@@ -528,7 +586,7 @@ export function createStockTransfersModule(transport) {
528
586
  return data.stockTransfer === null ? null : toShortfall(data.stockTransfer);
529
587
  },
530
588
  async cancellation(id, options) {
531
- const data = await transport.graphql({ api: 'admin', query: STOCK_TRANSFER_CANCELLATION_QUERY, variables: { id } }, options);
589
+ const data = await readWithoutAvailabilityOnOlderEngine(transport, STOCK_TRANSFER_CANCELLATION_QUERY, id, options);
532
590
  return data.stockTransfer === null ? null : toCancellation(data.stockTransfer);
533
591
  },
534
592
  async parcels(id, options) {
@@ -560,5 +618,25 @@ export function createStockTransfersModule(transport) {
560
618
  const { base64, ...document } = data.getMyparcelStockTransferLabel;
561
619
  return { ...document, bytes: decodeBase64(base64) };
562
620
  },
621
+ removeShipment(id, options) {
622
+ return one('removeStockTransferShipment', REMOVE_STOCK_TRANSFER_SHIPMENT_MUTATION, { id }, { timeoutMs: CARRIER_CALL_TIMEOUT_MS, ...options });
623
+ },
624
+ retryHendriksExport(id, options) {
625
+ // The ship's budget: the same upload runs inside the call.
626
+ return one('retryStockTransferHendriksExport', RETRY_STOCK_TRANSFER_HENDRIKS_EXPORT_MUTATION, { id }, { timeoutMs: CARRIER_CALL_TIMEOUT_MS, ...options });
627
+ },
628
+ regeneratePdf(id, options) {
629
+ return one('regenerateStockTransferPdf', REGENERATE_STOCK_TRANSFER_PDF_MUTATION, { id }, options);
630
+ },
631
+ numbering: {
632
+ async get(options) {
633
+ const data = await transport.graphql({ api: 'admin', query: STOCK_TRANSFER_NUMBERING_QUERY }, options);
634
+ return data.stockTransferNumberingConfig;
635
+ },
636
+ async set(input, options) {
637
+ const data = await transport.graphql({ api: 'admin', query: UPDATE_STOCK_TRANSFER_NUMBERING_MUTATION, variables: { input } }, options);
638
+ return data.updateStockTransferNumberingConfig;
639
+ },
640
+ },
563
641
  };
564
642
  }