@sixtyninecommerce/admin 0.11.0 → 0.12.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 +1501 -23
- package/dist/auth/index.d.ts +7 -1
- package/dist/auth/index.js +8 -1
- package/dist/catalog/documents.d.ts +142 -0
- package/dist/catalog/documents.js +114 -0
- package/dist/catalog/index.d.ts +48 -7
- package/dist/catalog/index.js +6 -1
- package/dist/catalog/metadata.d.ts +244 -0
- package/dist/catalog/metadata.js +220 -0
- package/dist/catalog/properties.d.ts +38 -0
- package/dist/catalog/properties.js +52 -1
- package/dist/catalog/recommendations.d.ts +33 -6
- package/dist/catalog/recommendations.js +94 -2
- package/dist/catalog/reviews.d.ts +17 -4
- package/dist/catalog/reviews.js +7 -0
- package/dist/catalog/variants.d.ts +60 -0
- package/dist/catalog/variants.js +39 -0
- package/dist/catalog/visibility.d.ts +18 -2
- package/dist/client.d.ts +29 -3
- package/dist/client.js +19 -8
- package/dist/content/assets.d.ts +3 -4
- package/dist/content/forms.d.ts +332 -1
- package/dist/content/forms.js +140 -4
- package/dist/content/items.d.ts +31 -8
- package/dist/content/items.js +1 -1
- package/dist/content/menus.d.ts +254 -0
- package/dist/content/menus.js +70 -0
- package/dist/content/strings.d.ts +137 -0
- package/dist/content/strings.js +82 -0
- package/dist/customers/delivery-terms.d.ts +44 -0
- package/dist/customers/delivery-terms.js +32 -0
- package/dist/customers/index.d.ts +15 -0
- package/dist/customers/index.js +4 -0
- package/dist/documents/emails.d.ts +150 -0
- package/dist/documents/emails.js +220 -0
- package/dist/documents/index.d.ts +13 -0
- package/dist/documents/index.js +2 -0
- package/dist/fulfillments/index.d.ts +119 -1
- package/dist/fulfillments/index.js +124 -4
- package/dist/index.d.ts +43 -23
- package/dist/index.js +11 -5
- package/dist/integrations/exact-online-types.d.ts +542 -0
- package/dist/integrations/exact-online.d.ts +541 -5
- package/dist/integrations/exact-online.js +714 -1
- package/dist/integrations/index.d.ts +23 -8
- package/dist/integrations/index.js +9 -4
- package/dist/integrations/pipeline-discoveries.d.ts +65 -0
- package/dist/integrations/pipeline-discoveries.js +65 -0
- package/dist/integrations/pipeline-runs.d.ts +119 -0
- package/dist/integrations/pipeline-runs.js +87 -0
- package/dist/integrations/pipelines.d.ts +73 -2
- package/dist/integrations/pipelines.js +36 -1
- package/dist/integrations/price-import.d.ts +223 -0
- package/dist/integrations/price-import.js +124 -0
- package/dist/integrations/types.d.ts +221 -3
- package/dist/integrations/types.js +4 -3
- package/dist/meta/index.d.ts +10 -0
- package/dist/metafields/index.d.ts +8 -1
- package/dist/metafields/index.js +10 -0
- package/dist/orders/cancel-with-money.d.ts +10 -0
- package/dist/orders/cancel-with-money.js +2 -0
- package/dist/orders/commit-edit.d.ts +16 -0
- package/dist/orders/commit-edit.js +14 -1
- package/dist/orders/deposit-policy.d.ts +3 -1
- package/dist/orders/index.d.ts +22 -11
- package/dist/orders/index.js +5 -2
- package/dist/orders/list.d.ts +26 -5
- package/dist/orders/list.js +123 -13
- package/dist/orders/manual-discounts.d.ts +13 -5
- package/dist/orders/money-view.d.ts +149 -0
- package/dist/orders/money-view.js +99 -0
- package/dist/orders/plan-edit.d.ts +34 -2
- package/dist/orders/plan-edit.js +110 -12
- package/dist/orders/surcharges.d.ts +12 -0
- package/dist/orders/surcharges.js +34 -9
- package/dist/payments/account-credit.d.ts +17 -1
- package/dist/payments/account-credit.js +25 -2
- package/dist/payments/credit-noted-fields.d.ts +8 -1
- package/dist/payments/credit-noted-fields.js +34 -2
- package/dist/payments/customer-consent.d.ts +30 -0
- package/dist/payments/customer-consent.js +49 -0
- package/dist/payments/index.d.ts +89 -14
- package/dist/payments/index.js +22 -2
- package/dist/payments/requests.d.ts +6 -3
- package/dist/payments/requests.js +1 -0
- package/dist/pickups/index.d.ts +5 -3
- package/dist/pickups/index.js +5 -2
- package/dist/platform/email-gateways.d.ts +165 -0
- package/dist/platform/email-gateways.js +78 -0
- package/dist/platform/tax.d.ts +11 -3
- package/dist/platform/tax.js +30 -0
- package/dist/pos/exchanges.d.ts +6 -1
- package/dist/pos/index.d.ts +229 -10
- package/dist/pos/index.js +113 -4
- package/dist/pos/offline-sales.d.ts +44 -3
- package/dist/pos/offline-sales.js +57 -3
- package/dist/pos/returns.d.ts +28 -1
- package/dist/pos/returns.js +36 -6
- package/dist/pricing/price-lists.d.ts +3 -1
- package/dist/purchasing/alerts.d.ts +19 -4
- package/dist/purchasing/alerts.js +29 -3
- package/dist/purchasing/backorders.d.ts +61 -0
- package/dist/purchasing/backorders.js +92 -0
- package/dist/purchasing/index.d.ts +21 -3
- package/dist/purchasing/index.js +8 -0
- package/dist/purchasing/links.d.ts +263 -0
- package/dist/purchasing/links.js +192 -0
- package/dist/purchasing/purchase-orders.d.ts +4 -1
- package/dist/purchasing/receipts.d.ts +396 -0
- package/dist/purchasing/receipts.js +287 -0
- package/dist/purchasing/returns.d.ts +273 -0
- package/dist/purchasing/returns.js +229 -0
- package/dist/quotes/index.d.ts +20 -3
- package/dist/returns/index.d.ts +62 -1
- package/dist/returns/index.js +61 -0
- package/dist/seo/config.d.ts +128 -0
- package/dist/seo/config.js +95 -0
- package/dist/seo/redirects.d.ts +125 -0
- package/dist/seo/redirects.js +60 -1
- package/dist/seo/settings.d.ts +147 -0
- package/dist/seo/settings.js +209 -0
- package/dist/shipping/index.d.ts +6 -0
- package/dist/shipping/index.js +2 -0
- package/dist/shipping/methods.d.ts +8 -1
- package/dist/shipping/myparcel.d.ts +415 -1
- package/dist/shipping/myparcel.js +291 -3
- package/dist/shipping/rate-tables.d.ts +149 -4
- package/dist/shipping/rate-tables.js +229 -23
- package/dist/shipping/ship-to-countries.d.ts +75 -0
- package/dist/shipping/ship-to-countries.js +47 -0
- package/dist/stock/by-location.d.ts +86 -0
- package/dist/stock/by-location.js +94 -0
- package/dist/stock/index.d.ts +8 -1
- package/dist/stock/index.js +4 -0
- package/dist/stock/settings.d.ts +106 -0
- package/dist/stock/settings.js +103 -0
- package/dist/stock/transfers.d.ts +171 -10
- package/dist/stock/transfers.js +82 -4
- package/dist/stored-value/index.d.ts +98 -7
- package/dist/stored-value/index.js +71 -4
- package/dist/tax/display-policy.d.ts +105 -0
- package/dist/tax/display-policy.js +84 -0
- package/dist/tax/index.d.ts +3 -0
- package/dist/tax/index.js +2 -0
- package/dist/tenant/email-templates.d.ts +222 -1
- package/dist/tenant/email-templates.js +227 -10
- package/package.json +2 -2
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `admin.documents.emails` — the store's email delivery log, its counts, a retry of one delivery,
|
|
3
|
+
* and a test send of a template (headless spec §9.2 `documents`, "email sends"; W10-103).
|
|
4
|
+
*
|
|
5
|
+
* Every call needs `UpdateSettings` on the active store. A delivery's recipients, subject, error
|
|
6
|
+
* and metadata are customer data: below `customerData: full` (an app installation) they read
|
|
7
|
+
* `''`/`null` and the row carries `redacted: true`.
|
|
8
|
+
*/
|
|
9
|
+
import { type Page, type Transport } from '@sixtyninecommerce/core';
|
|
10
|
+
import type { Call, ListOptions } from '../types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Where a delivery stands. `skipped`: the store's `sender: none` for the event (the platform sent
|
|
13
|
+
* nothing, on purpose). `suppressed_sandbox`: a sandbox store withheld the customer's copy. The
|
|
14
|
+
* engine may add others; a reader keeps a default branch.
|
|
15
|
+
*/
|
|
16
|
+
export type EmailDeliveryStatus = 'sent' | 'failed' | 'blocked' | 'pending' | 'skipped' | 'suppressed_sandbox' | (string & {});
|
|
17
|
+
/** One email the store sent, or tried to. */
|
|
18
|
+
export interface EmailDelivery {
|
|
19
|
+
id: string;
|
|
20
|
+
/** The template it was rendered from (`order_confirmation`, …). */
|
|
21
|
+
templateType: string;
|
|
22
|
+
/** The notification event that sent it (`order_placed`, …). */
|
|
23
|
+
notificationEvent: string;
|
|
24
|
+
/** Comma-separated addresses. */
|
|
25
|
+
recipientTo: string;
|
|
26
|
+
recipientCc: string | null;
|
|
27
|
+
recipientBcc: string | null;
|
|
28
|
+
subject: string;
|
|
29
|
+
gatewayId: string | null;
|
|
30
|
+
status: EmailDeliveryStatus;
|
|
31
|
+
/** 1 for the first send; each retry adds one. */
|
|
32
|
+
attempt: number;
|
|
33
|
+
/** The mail provider's message id, when it took the email. */
|
|
34
|
+
messageId: string | null;
|
|
35
|
+
/** Why the last attempt failed, as the provider or the mail server said it. */
|
|
36
|
+
error: string | null;
|
|
37
|
+
durationMs: number | null;
|
|
38
|
+
/** The ids the email was rendered from (`orderId`, `invoiceId`, …) and other send facts. */
|
|
39
|
+
metadata: Record<string, unknown> | null;
|
|
40
|
+
/** ISO-8601 UTC. */
|
|
41
|
+
createdAt: string;
|
|
42
|
+
/**
|
|
43
|
+
* Set when the caller's customer-data level withheld part of the row (an app installation
|
|
44
|
+
* below `customerData: full`): the recipients, subject, error and metadata then read `''` or
|
|
45
|
+
* `null`, meaning "not granted", never "none on record".
|
|
46
|
+
*/
|
|
47
|
+
redacted?: true;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Which deliveries a list or a count covers. The two instants need an explicit offset (`Z` or
|
|
51
|
+
* `±HH:mm`) and are refused before the request leaves without one (`INVALID_DATETIME`): a store's
|
|
52
|
+
* day is not the caller's. To cover the store's days, send the first instant of the first day as
|
|
53
|
+
* `createdFrom` and the first instant of the day AFTER the last one as `createdBefore`
|
|
54
|
+
* ({@link EmailDeliveriesModule.list}).
|
|
55
|
+
*/
|
|
56
|
+
export interface EmailDeliveryFilter {
|
|
57
|
+
status?: EmailDeliveryStatus;
|
|
58
|
+
templateType?: string;
|
|
59
|
+
/** Created at or after this instant. */
|
|
60
|
+
createdFrom?: string;
|
|
61
|
+
/** Created strictly before this instant. */
|
|
62
|
+
createdBefore?: string;
|
|
63
|
+
}
|
|
64
|
+
/** How many of the store's deliveries are in each state, over a filter. */
|
|
65
|
+
export interface EmailDeliveryStats {
|
|
66
|
+
sent: number;
|
|
67
|
+
failed: number;
|
|
68
|
+
/** Never sent: every recipient is on the mail provider's suppression list. */
|
|
69
|
+
blocked: number;
|
|
70
|
+
pending: number;
|
|
71
|
+
}
|
|
72
|
+
export interface SendTestEmailInput {
|
|
73
|
+
/** A template type the platform renders (`admin.tenant.emailTemplates.catalog()`). */
|
|
74
|
+
templateType: string;
|
|
75
|
+
/** One email address. */
|
|
76
|
+
recipientEmail: string;
|
|
77
|
+
}
|
|
78
|
+
export interface EmailDeliveriesModule {
|
|
79
|
+
/**
|
|
80
|
+
* The store's deliveries, newest first, one page at a time (`limit` 1–100, 50 when omitted).
|
|
81
|
+
*
|
|
82
|
+
* **Store days.** The page that shows "from 24 to 25 October" in Europe/Amsterdam sends
|
|
83
|
+
* `createdFrom: '2026-10-24T00:00:00+02:00'` and `createdBefore: '2026-10-26T00:00:00+01:00'`:
|
|
84
|
+
* 25 October 2026 is 25 hours long there (the clocks go back), and the end is exclusive, so
|
|
85
|
+
* the whole last day is in and nothing of the next.
|
|
86
|
+
*
|
|
87
|
+
* **Coded refusals:** `INVALID_DATETIME` → `ValidationError` (400), an instant without an
|
|
88
|
+
* offset, before the request leaves; `EMAIL_DELIVERY_FILTER_INVALID` → `ValidationError`
|
|
89
|
+
* (400), a `limit` outside 1–100 or a range that ends before it starts.
|
|
90
|
+
*
|
|
91
|
+
* Rows carry `redacted: true` below `customerData: full` (see {@link EmailDelivery}).
|
|
92
|
+
*
|
|
93
|
+
* @effect read
|
|
94
|
+
* @permission UpdateSettings
|
|
95
|
+
*/
|
|
96
|
+
list(filter?: EmailDeliveryFilter, options?: ListOptions): Promise<Page<EmailDelivery>>;
|
|
97
|
+
/**
|
|
98
|
+
* How many deliveries are `sent`, `failed`, `blocked` and `pending`, over the same filter as
|
|
99
|
+
* {@link list} without its `status` (a count by status). Without a filter: the store's whole
|
|
100
|
+
* log. On an engine from before this release (no filter argument) a filtered count is made
|
|
101
|
+
* from the list's totals, one read per status.
|
|
102
|
+
*
|
|
103
|
+
* @effect read
|
|
104
|
+
* @permission UpdateSettings
|
|
105
|
+
*/
|
|
106
|
+
stats(filter?: Omit<EmailDeliveryFilter, 'status'>, options?: Call): Promise<EmailDeliveryStats>;
|
|
107
|
+
/**
|
|
108
|
+
* Send a `failed` or `blocked` delivery again, now, and answer the row with the new outcome:
|
|
109
|
+
* `status` is `sent`, `failed` again (with its `error`), `blocked` (the address is still on the
|
|
110
|
+
* provider's suppression list) or `suppressed_sandbox`. It resolves either way; read `status`.
|
|
111
|
+
* Synchronous: the email has been handed to the provider (or not) when it resolves.
|
|
112
|
+
*
|
|
113
|
+
* This sends the email to the CUSTOMER (or whoever it was addressed to) once more. Never call
|
|
114
|
+
* it in a loop or on a timer without a person deciding to.
|
|
115
|
+
*
|
|
116
|
+
* **Coded refusals** (nothing is sent): `EMAIL_DELIVERY_NOT_FOUND` → `NotFoundError` (404), no
|
|
117
|
+
* such delivery in this store; `EMAIL_DELIVERY_NOT_RETRYABLE` → `BusinessRuleError` (422), the
|
|
118
|
+
* delivery is not `failed` or `blocked`, it is a gift card's email (its code is not kept), or
|
|
119
|
+
* another retry of it started first.
|
|
120
|
+
*
|
|
121
|
+
* @effect irreversible
|
|
122
|
+
* @permission UpdateSettings
|
|
123
|
+
*/
|
|
124
|
+
retry(id: string, options?: Call): Promise<EmailDelivery>;
|
|
125
|
+
}
|
|
126
|
+
export interface DocumentEmailsModule {
|
|
127
|
+
deliveries: EmailDeliveriesModule;
|
|
128
|
+
/**
|
|
129
|
+
* Render `templateType` with sample data and send it, now, through the store's own email
|
|
130
|
+
* gateway, to `recipientEmail`. It is real mail. The send writes no delivery row.
|
|
131
|
+
*
|
|
132
|
+
* **Coded refusals:** `INVALID_TEST_EMAIL_RECIPIENT` and `INVALID_TEST_EMAIL_TEMPLATE` →
|
|
133
|
+
* `ValidationError` (400), before anything is sent; `TEST_EMAIL_SEND_FAILED` →
|
|
134
|
+
* `BusinessRuleError` (422), the gateway did not take it (the message names the SMTP step or
|
|
135
|
+
* the provider's code, never the server's own words).
|
|
136
|
+
*
|
|
137
|
+
* @effect irreversible
|
|
138
|
+
* @permission UpdateSettings
|
|
139
|
+
*/
|
|
140
|
+
sendTest(input: SendTestEmailInput, options?: Call): Promise<void>;
|
|
141
|
+
}
|
|
142
|
+
export declare const EMAIL_DELIVERIES_QUERY = "\n query AdminEmailDeliveries($options: EmailDeliveryLogListOptions) {\n emailDeliveryLogs(options: $options) {\n items { \n id\n templateType\n notificationEvent\n recipientTo\n recipientCc\n recipientBcc\n subject\n gatewayId\n status\n attempt\n messageId\n error\n durationMs\n metadata\n createdAt\n }\n totalItems\n }\n }\n";
|
|
143
|
+
export declare const EMAIL_DELIVERY_STATS_QUERY = "\n query AdminEmailDeliveryStats($options: EmailDeliveryStatsOptions) {\n emailDeliveryStats(options: $options) {\n sent\n failed\n blocked\n pending\n }\n }\n";
|
|
144
|
+
/** The store's whole log, without the filter argument an older engine does not know. */
|
|
145
|
+
export declare const EMAIL_DELIVERY_STATS_ALL_QUERY = "\n query AdminEmailDeliveryStatsAll {\n emailDeliveryStats {\n sent\n failed\n blocked\n pending\n }\n }\n";
|
|
146
|
+
/** How many deliveries match: the older engine's way to count over a filter. */
|
|
147
|
+
export declare const EMAIL_DELIVERY_COUNT_QUERY = "\n query AdminEmailDeliveryCount($options: EmailDeliveryLogListOptions) {\n emailDeliveryLogs(options: $options) {\n totalItems\n }\n }\n";
|
|
148
|
+
export declare const RETRY_EMAIL_DELIVERY_MUTATION = "\n mutation AdminRetryEmailDelivery($id: ID!) {\n retryEmailDelivery(id: $id) { \n id\n templateType\n notificationEvent\n recipientTo\n recipientCc\n recipientBcc\n subject\n gatewayId\n status\n attempt\n messageId\n error\n durationMs\n metadata\n createdAt\n }\n }\n";
|
|
149
|
+
export declare const SEND_TEST_EMAIL_MUTATION = "\n mutation AdminSendTestEmail($templateType: String!, $recipientEmail: String!) {\n sendTestEmail(templateType: $templateType, recipientEmail: $recipientEmail)\n }\n";
|
|
150
|
+
export declare function createDocumentEmailsModule(transport: Transport): DocumentEmailsModule;
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `admin.documents.emails` — the store's email delivery log, its counts, a retry of one delivery,
|
|
3
|
+
* and a test send of a template (headless spec §9.2 `documents`, "email sends"; W10-103).
|
|
4
|
+
*
|
|
5
|
+
* Every call needs `UpdateSettings` on the active store. A delivery's recipients, subject, error
|
|
6
|
+
* and metadata are customer data: below `customerData: full` (an app installation) they read
|
|
7
|
+
* `''`/`null` and the row carries `redacted: true`.
|
|
8
|
+
*/
|
|
9
|
+
import { pageFromVendureList, readOffsetCursor, ValidationError, } from '@sixtyninecommerce/core';
|
|
10
|
+
import { assertInstant } from '../catalog/types.js';
|
|
11
|
+
import { customerDataField } from '../customers/wire.js';
|
|
12
|
+
const DELIVERY_FIELDS = /* GraphQL */ `
|
|
13
|
+
id
|
|
14
|
+
templateType
|
|
15
|
+
notificationEvent
|
|
16
|
+
recipientTo
|
|
17
|
+
recipientCc
|
|
18
|
+
recipientBcc
|
|
19
|
+
subject
|
|
20
|
+
gatewayId
|
|
21
|
+
status
|
|
22
|
+
attempt
|
|
23
|
+
messageId
|
|
24
|
+
error
|
|
25
|
+
durationMs
|
|
26
|
+
metadata
|
|
27
|
+
createdAt
|
|
28
|
+
`;
|
|
29
|
+
export const EMAIL_DELIVERIES_QUERY = /* GraphQL */ `
|
|
30
|
+
query AdminEmailDeliveries($options: EmailDeliveryLogListOptions) {
|
|
31
|
+
emailDeliveryLogs(options: $options) {
|
|
32
|
+
items { ${DELIVERY_FIELDS} }
|
|
33
|
+
totalItems
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
`;
|
|
37
|
+
export const EMAIL_DELIVERY_STATS_QUERY = /* GraphQL */ `
|
|
38
|
+
query AdminEmailDeliveryStats($options: EmailDeliveryStatsOptions) {
|
|
39
|
+
emailDeliveryStats(options: $options) {
|
|
40
|
+
sent
|
|
41
|
+
failed
|
|
42
|
+
blocked
|
|
43
|
+
pending
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
`;
|
|
47
|
+
/** The store's whole log, without the filter argument an older engine does not know. */
|
|
48
|
+
export const EMAIL_DELIVERY_STATS_ALL_QUERY = /* GraphQL */ `
|
|
49
|
+
query AdminEmailDeliveryStatsAll {
|
|
50
|
+
emailDeliveryStats {
|
|
51
|
+
sent
|
|
52
|
+
failed
|
|
53
|
+
blocked
|
|
54
|
+
pending
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
`;
|
|
58
|
+
/** How many deliveries match: the older engine's way to count over a filter. */
|
|
59
|
+
export const EMAIL_DELIVERY_COUNT_QUERY = /* GraphQL */ `
|
|
60
|
+
query AdminEmailDeliveryCount($options: EmailDeliveryLogListOptions) {
|
|
61
|
+
emailDeliveryLogs(options: $options) {
|
|
62
|
+
totalItems
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
`;
|
|
66
|
+
export const RETRY_EMAIL_DELIVERY_MUTATION = /* GraphQL */ `
|
|
67
|
+
mutation AdminRetryEmailDelivery($id: ID!) {
|
|
68
|
+
retryEmailDelivery(id: $id) { ${DELIVERY_FIELDS} }
|
|
69
|
+
}
|
|
70
|
+
`;
|
|
71
|
+
export const SEND_TEST_EMAIL_MUTATION = /* GraphQL */ `
|
|
72
|
+
mutation AdminSendTestEmail($templateType: String!, $recipientEmail: String!) {
|
|
73
|
+
sendTestEmail(templateType: $templateType, recipientEmail: $recipientEmail)
|
|
74
|
+
}
|
|
75
|
+
`;
|
|
76
|
+
/** The engine's default page; the SDK states it so the cursor arithmetic knows the size. */
|
|
77
|
+
const DELIVERIES_PAGE_SIZE = 50;
|
|
78
|
+
function toDelivery(row) {
|
|
79
|
+
return {
|
|
80
|
+
id: String(row.id),
|
|
81
|
+
templateType: row.templateType,
|
|
82
|
+
notificationEvent: row.notificationEvent,
|
|
83
|
+
recipientTo: row.recipientTo,
|
|
84
|
+
recipientCc: row.recipientCc ?? null,
|
|
85
|
+
recipientBcc: row.recipientBcc ?? null,
|
|
86
|
+
subject: row.subject,
|
|
87
|
+
gatewayId: row.gatewayId ?? null,
|
|
88
|
+
status: row.status,
|
|
89
|
+
attempt: row.attempt,
|
|
90
|
+
messageId: row.messageId ?? null,
|
|
91
|
+
error: row.error ?? null,
|
|
92
|
+
durationMs: row.durationMs ?? null,
|
|
93
|
+
metadata: row.metadata ?? null,
|
|
94
|
+
createdAt: row.createdAt,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/** The engine's filter input: only the keys the caller set, so an older engine still answers. */
|
|
98
|
+
function wireFilter(filter) {
|
|
99
|
+
if (filter === undefined)
|
|
100
|
+
return {};
|
|
101
|
+
if (filter === null || typeof filter !== 'object' || Array.isArray(filter)) {
|
|
102
|
+
throw new ValidationError({
|
|
103
|
+
code: 'EMAIL_DELIVERY_FILTER_INVALID',
|
|
104
|
+
message: 'The delivery filter must be an object.',
|
|
105
|
+
status: 400,
|
|
106
|
+
service: 'vendure',
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
assertInstant('createdFrom', filter.createdFrom);
|
|
110
|
+
assertInstant('createdBefore', filter.createdBefore);
|
|
111
|
+
return {
|
|
112
|
+
...(filter.status ? { status: filter.status } : {}),
|
|
113
|
+
...(filter.templateType ? { templateType: filter.templateType } : {}),
|
|
114
|
+
...(filter.createdFrom ? { dateFrom: filter.createdFrom } : {}),
|
|
115
|
+
...(filter.createdBefore ? { dateBefore: filter.createdBefore } : {}),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* The engine refused the document over a field or argument it does not know: an engine from
|
|
120
|
+
* before this release (no `dateBefore`, no `emailDeliveryStats(options:)`). The dashboard can be
|
|
121
|
+
* live before vendure-server (`.claude/rules/backend.md`, additive rule), so the module falls
|
|
122
|
+
* back to the older spelling instead of failing. Matched on the names this module added, so a
|
|
123
|
+
* real refusal is never retried.
|
|
124
|
+
*/
|
|
125
|
+
function isOlderEngineRejection(error) {
|
|
126
|
+
if (!(error instanceof ValidationError) || error.service !== 'vendure')
|
|
127
|
+
return false;
|
|
128
|
+
// Apollo answers a document that fails validation (an unknown type or argument: the stats
|
|
129
|
+
// filter) with HTTP 400, which the transport reports as BAD_REQUEST without the engine's
|
|
130
|
+
// words; an unknown input field (dateBefore) is a variable coercion error at HTTP 200 and
|
|
131
|
+
// keeps them. Only ever asked about the documents this module added the names to.
|
|
132
|
+
return (error.code === 'BAD_REQUEST' ||
|
|
133
|
+
error.code === 'GRAPHQL_VALIDATION_FAILED' ||
|
|
134
|
+
/dateBefore|EmailDeliveryStatsOptions|Unknown argument "options"/.test(error.message));
|
|
135
|
+
}
|
|
136
|
+
/** The old inclusive spelling of an exclusive end: one millisecond before it. */
|
|
137
|
+
function legacyFilter(filter) {
|
|
138
|
+
const { dateBefore, ...rest } = filter;
|
|
139
|
+
if (typeof dateBefore !== 'string')
|
|
140
|
+
return rest;
|
|
141
|
+
return { ...rest, dateTo: new Date(Date.parse(dateBefore) - 1).toISOString() };
|
|
142
|
+
}
|
|
143
|
+
const COUNTED_STATUSES = ['sent', 'failed', 'blocked', 'pending'];
|
|
144
|
+
export function createDocumentEmailsModule(transport) {
|
|
145
|
+
/** Latched once the engine proved it predates `dateBefore` (one refused request per client). */
|
|
146
|
+
let olderEngine = false;
|
|
147
|
+
const listPage = async (skip, take, filter, options) => {
|
|
148
|
+
const read = (wire) => customerDataField(transport, EMAIL_DELIVERIES_QUERY, 'emailDeliveryLogs', { options: { ...wire, take, skip } }, options);
|
|
149
|
+
let answer;
|
|
150
|
+
if (olderEngine || !('dateBefore' in filter)) {
|
|
151
|
+
answer = await read(olderEngine ? legacyFilter(filter) : filter);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
try {
|
|
155
|
+
answer = await read(filter);
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
if (!isOlderEngineRejection(error))
|
|
159
|
+
throw error;
|
|
160
|
+
olderEngine = true;
|
|
161
|
+
answer = await read(legacyFilter(filter));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
const { value, mark } = answer;
|
|
165
|
+
const items = value.items.map((row) => mark(toDelivery(row)));
|
|
166
|
+
// Each following page re-sends the same filter and per-call options.
|
|
167
|
+
return pageFromVendureList({ items, totalItems: value.totalItems }, skip, take, (cursor) => listPage(readOffsetCursor(cursor), take, filter, options));
|
|
168
|
+
};
|
|
169
|
+
return {
|
|
170
|
+
deliveries: {
|
|
171
|
+
async list(filter, options) {
|
|
172
|
+
const wire = wireFilter(filter);
|
|
173
|
+
const take = options?.limit ?? DELIVERIES_PAGE_SIZE;
|
|
174
|
+
const skip = options?.after === undefined ? 0 : readOffsetCursor(options.after);
|
|
175
|
+
return listPage(skip, take, wire, options);
|
|
176
|
+
},
|
|
177
|
+
async stats(filter, options) {
|
|
178
|
+
const { status: _status, ...counted } = wireFilter(filter);
|
|
179
|
+
if (Object.keys(counted).length === 0) {
|
|
180
|
+
const data = await transport.graphql({ api: 'admin', query: EMAIL_DELIVERY_STATS_ALL_QUERY }, options);
|
|
181
|
+
return data.emailDeliveryStats;
|
|
182
|
+
}
|
|
183
|
+
if (!olderEngine) {
|
|
184
|
+
try {
|
|
185
|
+
const data = await transport.graphql({ api: 'admin', query: EMAIL_DELIVERY_STATS_QUERY, variables: { options: counted } }, options);
|
|
186
|
+
return data.emailDeliveryStats;
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
if (!isOlderEngineRejection(error))
|
|
190
|
+
throw error;
|
|
191
|
+
olderEngine = true;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
// An older engine counts only the whole log: count each status over the filter through
|
|
195
|
+
// the list's totals instead (one row read per status).
|
|
196
|
+
const totals = await Promise.all(COUNTED_STATUSES.map(async (status) => {
|
|
197
|
+
const data = await transport.graphql({
|
|
198
|
+
api: 'admin',
|
|
199
|
+
query: EMAIL_DELIVERY_COUNT_QUERY,
|
|
200
|
+
variables: { options: { ...legacyFilter(counted), status, take: 1, skip: 0 } },
|
|
201
|
+
}, options);
|
|
202
|
+
return data.emailDeliveryLogs.totalItems;
|
|
203
|
+
}));
|
|
204
|
+
const [sent = 0, failed = 0, blocked = 0, pending = 0] = totals;
|
|
205
|
+
return { sent, failed, blocked, pending };
|
|
206
|
+
},
|
|
207
|
+
async retry(id, options) {
|
|
208
|
+
const { value, mark } = await customerDataField(transport, RETRY_EMAIL_DELIVERY_MUTATION, 'retryEmailDelivery', { id }, options);
|
|
209
|
+
return mark(toDelivery(value));
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
async sendTest(input, options) {
|
|
213
|
+
await transport.graphql({
|
|
214
|
+
api: 'admin',
|
|
215
|
+
query: SEND_TEST_EMAIL_MUTATION,
|
|
216
|
+
variables: { templateType: input.templateType, recipientEmail: input.recipientEmail },
|
|
217
|
+
}, options);
|
|
218
|
+
},
|
|
219
|
+
};
|
|
220
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type Page, type Transport } from '@sixtyninecommerce/core';
|
|
2
2
|
import type { Call, ListOptions } from '../types.js';
|
|
3
3
|
import { type ArDocumentsModule } from './ar.js';
|
|
4
|
+
import { type DocumentEmailsModule } from './emails.js';
|
|
4
5
|
import { decodePdf } from './pdf.js';
|
|
5
6
|
export { decodePdf };
|
|
6
7
|
/**
|
|
@@ -402,6 +403,16 @@ export interface InvoiceCorrectionInput {
|
|
|
402
403
|
refundPaymentId?: string;
|
|
403
404
|
/** RETAIL only: move the credited amount to the customer's account instead (`accountCredit`). */
|
|
404
405
|
creditToAccount?: boolean;
|
|
406
|
+
/**
|
|
407
|
+
* `commitCorrection` with `creditToAccount` in a store whose book is store credit (the plan's
|
|
408
|
+
* `accountCredit.book` `STORE_CREDIT`): whether the customer expressly agreed to store credit
|
|
409
|
+
* instead of a refund to their payment (EU consumer law, CRD art. 13(1)), as staff recorded it.
|
|
410
|
+
* The move records it on its ledger entries (`StoredValueEntry.customerAgreed`); never a
|
|
411
|
+
* condition, nothing is refused for it. The plan ignores it and its `planHash` never sees it, so
|
|
412
|
+
* leave it out of `planCorrection` (an engine before the field, incentives sprint 8 PR 6a,
|
|
413
|
+
* refuses any call that gives it) and add it to the commit's input.
|
|
414
|
+
*/
|
|
415
|
+
customerAgreed?: boolean;
|
|
405
416
|
/**
|
|
406
417
|
* Details wrong only: the order's payment term in days. The corrected invoice is reissued
|
|
407
418
|
* under it and the order keeps it (its `paymentTermsDays`; its payment condition is cleared).
|
|
@@ -1591,6 +1602,8 @@ export interface DocumentsModule {
|
|
|
1591
1602
|
extensions: DocumentExtensionsModule;
|
|
1592
1603
|
/** The accounts-receivable ledger's documents: AR invoices, statements and credit notes. */
|
|
1593
1604
|
ar: ArDocumentsModule;
|
|
1605
|
+
/** The store's email delivery log (counts, a retry) and a template's test send. */
|
|
1606
|
+
emails: DocumentEmailsModule;
|
|
1594
1607
|
}
|
|
1595
1608
|
export declare const GENERATE_INVOICE_MUTATION = "\n mutation GenerateInvoice(\n $orderId: ID!\n $invoicedOn: String!\n $languageCode: String\n $note: String\n $extensions: [DocumentExtensionInput!]\n ) {\n generateInvoice(\n orderId: $orderId\n invoicedOn: $invoicedOn\n languageCode: $languageCode\n note: $note\n extensions: $extensions\n ) { \n id\n invoiceNumber\n invoicedOn\n orderId\n languageCode\n storageKey\n totalWithTax\n currencyCode\n note\n voidedOn\n reversedByCreditNoteId\n supersededByInvoiceId\n reissueOfInvoiceId\n kind\n supplementsInvoiceId\n lines { \n description\n sku\n orderLineId\n quantity\n unitPriceNet\n unitPriceWithTax\n taxRate\n lineTotalNet\n lineTotalWithTax\n unitPriceBasis\n }\n numberingProvider\n amountPaid\n amountDue\n createdAt\n }\n }\n";
|
|
1596
1609
|
export declare const GENERATE_PACKING_SLIP_MUTATION = "\n mutation GeneratePackingSlip(\n $fulfillmentId: ID!\n $languageCode: String\n $extensions: [DocumentExtensionInput!]\n ) {\n generatePackingSlip(\n fulfillmentId: $fulfillmentId\n languageCode: $languageCode\n extensions: $extensions\n ) { \n id\n packingSlipNumber\n fulfillmentId\n languageCode\n storageKey\n createdAt\n }\n }\n";
|
package/dist/documents/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createPage, idempotencyKey as mintIdempotencyKey, pageFromVendureList, readOffsetCursor, ValidationError, } from '@sixtyninecommerce/core';
|
|
2
2
|
import { storeCreditAware } from '../payments/store-credit-fields.js';
|
|
3
3
|
import { createArDocumentsModule } from './ar.js';
|
|
4
|
+
import { createDocumentEmailsModule } from './emails.js';
|
|
4
5
|
import { decodePdf } from './pdf.js';
|
|
5
6
|
// Also what `documents.ar.pdf` decodes with (headless W10-30).
|
|
6
7
|
export { decodePdf };
|
|
@@ -903,6 +904,7 @@ export function createDocumentsModule(transport) {
|
|
|
903
904
|
},
|
|
904
905
|
},
|
|
905
906
|
ar: createArDocumentsModule(transport),
|
|
907
|
+
emails: createDocumentEmailsModule(transport),
|
|
906
908
|
extensions: {
|
|
907
909
|
async list(options) {
|
|
908
910
|
const data = await transport.graphql({ api: 'admin', query: DOCUMENT_EXTENSIONS_QUERY }, options);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Transport } from '@sixtyninecommerce/core';
|
|
1
|
+
import { type PlatformError, type Transport } from '@sixtyninecommerce/core';
|
|
2
2
|
import type { OrderOverpaymentChoice, OverpaymentOption } from '../orders/surcharges.js';
|
|
3
3
|
import type { Call } from '../types.js';
|
|
4
4
|
import { type FulfillmentCreateMethods } from './create.js';
|
|
@@ -182,6 +182,15 @@ export interface FulfillmentCancelPreview {
|
|
|
182
182
|
export interface FulfillmentCancelChoice {
|
|
183
183
|
orderId: string;
|
|
184
184
|
choice: OrderOverpaymentChoice;
|
|
185
|
+
/**
|
|
186
|
+
* With `ACCOUNT_CREDIT` in a store whose book is store credit (`cancelPreview`'s
|
|
187
|
+
* `accountCredit.book` `STORE_CREDIT`): whether THIS order's customer expressly agreed to store
|
|
188
|
+
* credit instead of a refund to their payment (EU consumer law, CRD art. 13(1)), as staff
|
|
189
|
+
* recorded it. The settlement's move records it on its ledger entries
|
|
190
|
+
* (`StoredValueEntry.customerAgreed`); never a condition, nothing is refused for it. Sent only
|
|
191
|
+
* when given; an engine before the field (incentives sprint 8 PR 6a) refuses a call that gives it.
|
|
192
|
+
*/
|
|
193
|
+
customerAgreed?: boolean;
|
|
185
194
|
}
|
|
186
195
|
/** What `cancel` sends besides the fulfillment. */
|
|
187
196
|
export interface CancelFulfillmentInput {
|
|
@@ -265,6 +274,35 @@ export interface OrderFulfillmentCoverage {
|
|
|
265
274
|
}
|
|
266
275
|
/** The longest override reason the engine stores. */
|
|
267
276
|
export declare const FULFILLMENT_COVERAGE_REASON_MAX_LENGTH = 500;
|
|
277
|
+
/** A fulfillment as `transition` leaves it. */
|
|
278
|
+
export interface FulfillmentStateChange {
|
|
279
|
+
id: string;
|
|
280
|
+
/** The state it is in now (`Shipped`, `Delivered`, …). */
|
|
281
|
+
state: string;
|
|
282
|
+
/** The states it may move to next, as the store's fulfillment process allows. */
|
|
283
|
+
nextStates: string[];
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* The facts a refused `transition` carries on `PlatformError.extensions`, beside its code:
|
|
287
|
+
* the move that was asked for and the refusing step's own words.
|
|
288
|
+
*/
|
|
289
|
+
export interface FulfillmentTransitionRefusalFacts {
|
|
290
|
+
/** Core's code for every refused move: `FULFILLMENT_STATE_TRANSITION_ERROR`. */
|
|
291
|
+
errorCode: string;
|
|
292
|
+
fromState: string;
|
|
293
|
+
toState: string;
|
|
294
|
+
/** The refusing step's text, `[CODE]` prefix included when it had one. */
|
|
295
|
+
transitionError: string;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* What re-sending a fulfillment's label to the store's 3PL came to (`resendLabelHandoff`):
|
|
299
|
+
* - `QUEUED`: the email with the label is queued for the 3PL recipient;
|
|
300
|
+
* - `NOT_READY`: the fulfillment has no ready MyParcel label yet, so nothing was sent;
|
|
301
|
+
* - `DISABLED`: the store has the label hand-off notification switched off;
|
|
302
|
+
* - `NO_RECIPIENT`: it is on, but names no recipient;
|
|
303
|
+
* - `UNAVAILABLE`: the platform's email delivery is not installed.
|
|
304
|
+
*/
|
|
305
|
+
export type LabelHandoffOutcome = 'QUEUED' | 'DISABLED' | 'NO_RECIPIENT' | 'NOT_READY' | 'UNAVAILABLE';
|
|
268
306
|
/**
|
|
269
307
|
* Fulfillment parcels (multi-parcel shipments). Each method is its own request
|
|
270
308
|
* on purpose: a caller deployed ahead of an engine without these fields sees
|
|
@@ -412,6 +450,66 @@ export interface FulfillmentsModule extends FulfillmentCreateMethods {
|
|
|
412
450
|
allowUncovered(orderId: string, reason: string, options?: Call & {
|
|
413
451
|
idempotencyKey?: string;
|
|
414
452
|
}): Promise<FulfillmentCoverageOverride>;
|
|
453
|
+
/**
|
|
454
|
+
* Move a fulfillment to one of its `nextStates` (the order page's "Mark as Shipped" and "Mark as
|
|
455
|
+
* Delivered"). Needs `UpdateOrder`. The move runs the store's own fulfillment process, so the
|
|
456
|
+
* order's state follows and whatever the store does on a shipped or delivered fulfillment (its
|
|
457
|
+
* events, its notifications: the customer gets the shipped e-mail) happens; the process has no
|
|
458
|
+
* way back to an earlier state. Shipping an order's last open lines moves the ORDER to
|
|
459
|
+
* `Shipped`, which on a store that pushes orders to its ERP when they ship (Exact Online's
|
|
460
|
+
* "fulfilled" auto-push) sends the order there, where it cannot be taken back.
|
|
461
|
+
*
|
|
462
|
+
* A move into `Cancelled` is a cancel: it ends the fulfillment for good and has its carrier let
|
|
463
|
+
* go of the shipment, and the delivery charge it added comes off what each of its orders bills.
|
|
464
|
+
* It is refused, before the carrier is told, while the customer has PAID such a charge
|
|
465
|
+
* (`FULFILLMENT_CANCEL_OVERPAYMENT_CHOICE_REQUIRED`): {@link FulfillmentsModule.cancel} takes the
|
|
466
|
+
* choice of how that money goes back. An unpaid charge simply leaves the bill.
|
|
467
|
+
*
|
|
468
|
+
* Tagged `money`, its strongest effect: a cancel changes what a placed order bills.
|
|
469
|
+
*
|
|
470
|
+
* Refused, with nothing moved:
|
|
471
|
+
* - a step of the store's process that refuses the move answers ITS OWN code, which the engine
|
|
472
|
+
* prefixes to its text as `[CODE]`, with the text after it as the message, classed as the
|
|
473
|
+
* warehouse API classes the same code: `ORDER_NOT_COVERED` (the store requires full payment
|
|
474
|
+
* and an order is not paid in full: `coverage` reads what it owes, `allowUncovered` records
|
|
475
|
+
* an override), `ORDER_ON_HOLD` (release the order's fulfilment hold first),
|
|
476
|
+
* `BOOKING_REQUIRED`, `PARCELS_REQUIRED`, `CONSOLIDATION_ADDRESS_DIVERGED`, …;
|
|
477
|
+
* - any other refusal of the process, an edge it does not have included, is
|
|
478
|
+
* `FULFILLMENT_STATE_TRANSITION_ERROR` (`BusinessRuleError`, 422) with the refusing step's
|
|
479
|
+
* text as the message;
|
|
480
|
+
* - both carry {@link FulfillmentTransitionRefusalFacts} on `extensions`;
|
|
481
|
+
* - another store's or a missing fulfillment is `ENTITY_NOT_FOUND` (`NotFoundError`); a
|
|
482
|
+
* credential restricted to stock locations (an API token or app installation with
|
|
483
|
+
* `locationIds`) moves only a fulfillment that ships from one of them
|
|
484
|
+
* (`LOCATION_OUT_OF_SCOPE`, 422);
|
|
485
|
+
* - a blank id or state is refused before any request (`FULFILLMENT_TRANSITION_INVALID`,
|
|
486
|
+
* `ValidationError`).
|
|
487
|
+
*
|
|
488
|
+
* Takes no idempotency key: repeating a move that went through asks for an edge the process no
|
|
489
|
+
* longer has, and is refused as above, never moved twice.
|
|
490
|
+
*
|
|
491
|
+
* @effect money
|
|
492
|
+
* @permission UpdateOrder
|
|
493
|
+
*/
|
|
494
|
+
transition(fulfillmentId: string, state: string, options?: Call): Promise<FulfillmentStateChange>;
|
|
495
|
+
/**
|
|
496
|
+
* E-mail the fulfillment's ready MyParcel label again to the store's 3PL recipient (the
|
|
497
|
+
* `fulfillment_label_handoff` notification), whatever the store's automatic hand-off setting.
|
|
498
|
+
* Answers what came of it ({@link LabelHandoffOutcome}): only `QUEUED` sent anything; the
|
|
499
|
+
* others say why nothing was sent. Every outcome leaves an audit row. Needs `UpdateOrder`.
|
|
500
|
+
*
|
|
501
|
+
* Takes no idempotency key: a repeat sends the e-mail again.
|
|
502
|
+
*
|
|
503
|
+
* Refused: another store's or a missing fulfillment is `ENTITY_NOT_FOUND` (`NotFoundError`); a
|
|
504
|
+
* store without the MyParcel plugin `PLUGIN_ACCESS_DENIED` (`PermissionDeniedError`, 403) for
|
|
505
|
+
* an ordinary caller; a credential restricted to other stock locations `LOCATION_OUT_OF_SCOPE`
|
|
506
|
+
* (422). A blank id is refused before any request (`MYPARCEL_LABEL_INPUT_INVALID`,
|
|
507
|
+
* `ValidationError`).
|
|
508
|
+
*
|
|
509
|
+
* @effect irreversible
|
|
510
|
+
* @permission UpdateOrder
|
|
511
|
+
*/
|
|
512
|
+
resendLabelHandoff(fulfillmentId: string, options?: Call): Promise<LabelHandoffOutcome>;
|
|
415
513
|
/**
|
|
416
514
|
* The store's fulfilment payment policy (`fulfillmentPaymentPolicy`): whether a fulfilment of
|
|
417
515
|
* an order not paid in full is refused `ORDER_NOT_COVERED`, and which payment methods are
|
|
@@ -431,6 +529,12 @@ export interface FulfillmentsModule extends FulfillmentCreateMethods {
|
|
|
431
529
|
export declare const FULFILLMENT_CANCEL_PREVIEW_QUERY = "\n query FulfillmentCancelPreview($fulfillmentId: ID!) {\n fulfillmentCancelPreview(fulfillmentId: $fulfillmentId) {\n fulfillmentId\n overpayments {\n orderId\n orderCode\n amount\n currencyCode\n refund { \n available\n code\n message\n book\n }\n accountCredit { \n available\n code\n message\n book\n }\n }\n }\n }\n";
|
|
432
530
|
/** `$overpayment` and `$idempotencyKey` are optional and left out of the variables when not given. */
|
|
433
531
|
export declare const CANCEL_FULFILLMENT_MUTATION = "\n mutation CancelFulfillment(\n $fulfillmentId: ID!\n $overpayment: [FulfillmentCancelOverpaymentInput!]\n $idempotencyKey: String\n ) {\n cancelFulfillment(\n fulfillmentId: $fulfillmentId\n overpayment: $overpayment\n idempotencyKey: $idempotencyKey\n ) {\n fulfillment {\n id\n state\n }\n settlements {\n orderId\n orderCode\n amount\n currencyCode\n choice\n book\n }\n }\n }\n";
|
|
532
|
+
/**
|
|
533
|
+
* The refusal member is selected for its facts: `message` is core's per-code template ("Cannot
|
|
534
|
+
* transition Fulfillment from X to Y"), and the refusing step's reason is `transitionError` alone.
|
|
535
|
+
*/
|
|
536
|
+
export declare const TRANSITION_FULFILLMENT_MUTATION = "\n mutation TransitionFulfillment($id: ID!, $state: String!) {\n transitionFulfillmentToState(id: $id, state: $state) {\n __typename\n ... on Fulfillment {\n id\n state\n nextStates\n }\n ... on FulfillmentStateTransitionError {\n errorCode\n message\n fromState\n toState\n transitionError\n }\n }\n }\n";
|
|
537
|
+
export declare const RESEND_FULFILLMENT_LABEL_HANDOFF_MUTATION = "\n mutation ResendFulfillmentLabelHandoff($fulfillmentId: ID!) {\n resendFulfillmentLabelHandoff(fulfillmentId: $fulfillmentId)\n }\n";
|
|
434
538
|
/** Its own document: on an engine without the query this call alone fails validation. */
|
|
435
539
|
export declare const ORDER_FULFILLMENT_COVERAGE_QUERY = "\n query OrderFulfillmentCoverage($orderId: ID!) {\n orderFulfillmentCoverage(orderId: $orderId) {\n orderId\n orderCode\n currencyCode\n policyActive\n covered\n outstanding\n exempt\n exemptReason\n allowed\n override { \n id\n orderId\n reason\n actorKind\n actorId\n outstandingAtGrant\n currencyCode\n createdAt\n active\n }\n }\n }\n";
|
|
436
540
|
/** `$idempotencyKey` is optional and left out of the variables when not given. */
|
|
@@ -468,4 +572,18 @@ export declare const MYPARCEL_LABEL_TIMEOUT_MS = 55000;
|
|
|
468
572
|
export declare function toUnretractedShipments(raw: readonly MyparcelUnretractedShipment[] | null | undefined): MyparcelUnretractedShipment[];
|
|
469
573
|
/** The bytes of a base64 label document (`atob`: no Node `Buffer`, it ships to browsers). */
|
|
470
574
|
export declare function decodeBase64(base64: string): Uint8Array;
|
|
575
|
+
interface RawTransitionRefusal {
|
|
576
|
+
errorCode: string;
|
|
577
|
+
message: string;
|
|
578
|
+
fromState?: string | null;
|
|
579
|
+
toState?: string | null;
|
|
580
|
+
transitionError?: string | null;
|
|
581
|
+
}
|
|
582
|
+
/**
|
|
583
|
+
* A refused move as the coded error it is. Core carries a step's refusal only as text, so the
|
|
584
|
+
* step's own code is read off its `[CODE]` prefix and classed through the GraphQL dialect, as the
|
|
585
|
+
* warehouse API's refusals of the same codes are (`warehouseRefusalError`): one code, one class,
|
|
586
|
+
* whichever door answered it.
|
|
587
|
+
*/
|
|
588
|
+
export declare function fulfillmentTransitionRefusal(result: RawTransitionRefusal): PlatformError;
|
|
471
589
|
export declare function createFulfillmentsModule(transport: Transport): FulfillmentsModule;
|