@myparcel-dev/pdk-admin 2.0.1 → 2.1.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/CHANGELOG.md +10 -0
- package/package.json +2 -2
- package/src/actions/composables/queries/account/useOrderCapabilitiesQuery.spec.ts +56 -0
- package/src/actions/composables/queries/account/useOrderCapabilitiesQuery.ts +11 -8
- package/src/actions/composables/queries/account/useShipmentCapabilitiesQuery.spec.ts +64 -0
- package/src/actions/composables/queries/account/useShipmentCapabilitiesQuery.ts +8 -7
- package/src/forms/shipmentOptions/useCapabilitiesWatcher.spec.ts +1 -1
- package/src/forms/shipmentOptions/useCapabilitiesWatcher.ts +2 -1
- package/src/forms/shipmentOptions/wireProxyCapabilities.spec.ts +59 -7
- package/src/forms/shipmentOptions/wireProxyCapabilities.ts +31 -20
- package/src/types/sdk.types.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
<!-- MONOWEAVE:BELOW -->
|
|
4
4
|
|
|
5
|
+
## [2.1.0](https://github.com/myparcelnl/js-pdk/compare/@myparcel-dev/pdk-admin@2.0.1...@myparcel-dev/pdk-admin@2.1.0) "@myparcel-dev/pdk-admin" (2026-08-05)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* **admin:** send business/consumer flag when loading shipment options ([#359](https://github.com/myparcelnl/js-pdk/issues/359)) ([d1cb75a](https://github.com/myparcelnl/js-pdk/commit/d1cb75a3530df89e0b3b94407a567d7b6efb497e))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
5
15
|
## [2.0.1](https://github.com/myparcelnl/js-pdk/compare/@myparcel-dev/pdk-admin@2.0.0...@myparcel-dev/pdk-admin@2.0.1) "@myparcel-dev/pdk-admin" (2026-07-20)
|
|
6
16
|
|
|
7
17
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myparcel-dev/pdk-admin",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/myparcelnl/js-pdk.git",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@myparcel-dev/constants": "^2.9.0",
|
|
40
|
-
"@myparcel-dev/pdk-common": "^2.0
|
|
40
|
+
"@myparcel-dev/pdk-common": "^2.1.0",
|
|
41
41
|
"@myparcel-dev/sdk": "^5.1.0",
|
|
42
42
|
"@myparcel-dev/vue-form-builder": "1.0.0-beta.42.6",
|
|
43
43
|
"@tanstack/vue-query": "~4.43.0",
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import {ref} from 'vue';
|
|
2
|
+
import {describe, expect, it, vi} from 'vitest';
|
|
3
|
+
import {useOrderCapabilitiesQuery} from './useOrderCapabilitiesQuery';
|
|
4
|
+
|
|
5
|
+
type RequestBody = {recipient: {countryCode: string; isBusiness?: boolean}};
|
|
6
|
+
|
|
7
|
+
let capturedBody: RequestBody | undefined;
|
|
8
|
+
|
|
9
|
+
const proxyCapabilities = vi.fn((options: {body: RequestBody}) => {
|
|
10
|
+
capturedBody = options.body;
|
|
11
|
+
|
|
12
|
+
return Promise.resolve({results: []});
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
vi.mock('@tanstack/vue-query', () => ({
|
|
16
|
+
useQuery: (queryKey: unknown, queryFn: () => Promise<unknown>) => ({queryFn}),
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
vi.mock('../../../../sdk', () => ({
|
|
20
|
+
usePdkAdminApi: () => ({proxyCapabilities}),
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
vi.mock('../../../../services', () => ({
|
|
24
|
+
globalLogger: {error: vi.fn(), debug: vi.fn(), warn: vi.fn(), info: vi.fn()},
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
type QueryFnHolder = {queryFn: () => Promise<unknown>};
|
|
28
|
+
|
|
29
|
+
describe('useOrderCapabilitiesQuery', () => {
|
|
30
|
+
it('forwards the business flag on the recipient body', async () => {
|
|
31
|
+
capturedBody = undefined;
|
|
32
|
+
|
|
33
|
+
const query = useOrderCapabilitiesQuery(ref({cc: 'NL', isBusiness: true})) as unknown as QueryFnHolder;
|
|
34
|
+
await query.queryFn();
|
|
35
|
+
|
|
36
|
+
expect(capturedBody?.recipient).toEqual({countryCode: 'NL', isBusiness: true});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('sends an explicit consumer flag on the recipient body', async () => {
|
|
40
|
+
capturedBody = undefined;
|
|
41
|
+
|
|
42
|
+
const query = useOrderCapabilitiesQuery(ref({cc: 'NL', isBusiness: false})) as unknown as QueryFnHolder;
|
|
43
|
+
await query.queryFn();
|
|
44
|
+
|
|
45
|
+
expect(capturedBody?.recipient).toEqual({countryCode: 'NL', isBusiness: false});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('omits isBusiness when the flag is not provided', async () => {
|
|
49
|
+
capturedBody = undefined;
|
|
50
|
+
|
|
51
|
+
const query = useOrderCapabilitiesQuery(ref({cc: 'NL'})) as unknown as QueryFnHolder;
|
|
52
|
+
await query.queryFn();
|
|
53
|
+
|
|
54
|
+
expect(capturedBody?.recipient).toEqual({countryCode: 'NL'});
|
|
55
|
+
});
|
|
56
|
+
});
|
|
@@ -15,15 +15,18 @@ import {usePdkAdminApi} from '../../../../sdk';
|
|
|
15
15
|
export type OrderCapabilitiesInput = {
|
|
16
16
|
cc?: string;
|
|
17
17
|
weight?: number;
|
|
18
|
+
isBusiness?: boolean;
|
|
18
19
|
};
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
|
-
* Order-scoped capabilities query — fires the shared CapabilitiesAction with ONLY destination
|
|
22
|
-
* and
|
|
23
|
-
* the union of `packageTypes`, `deliveryTypes`, and `options` valid
|
|
22
|
+
* Order-scoped capabilities query — fires the shared CapabilitiesAction with ONLY destination,
|
|
23
|
+
* weight and the recipient business flag, no carrier/packageType/deliveryType filters. Returns
|
|
24
|
+
* one entry per carrier with the union of `packageTypes`, `deliveryTypes`, and `options` valid
|
|
25
|
+
* for the order context.
|
|
24
26
|
*
|
|
25
|
-
* Drives the carrier / packageType / deliveryType dropdowns. Refetches only on cc / weight
|
|
26
|
-
* changes so option toggles and dropdown picks don't trigger needless network
|
|
27
|
+
* Drives the carrier / packageType / deliveryType dropdowns. Refetches only on cc / weight /
|
|
28
|
+
* isBusiness changes so option toggles and dropdown picks don't trigger needless network
|
|
29
|
+
* round-trips.
|
|
27
30
|
*
|
|
28
31
|
* Errors are logged via `globalLogger.error` so we have a breadcrumb for support, but we
|
|
29
32
|
* deliberately don't surface a user-facing toast — an intermittent capabilities failure
|
|
@@ -38,7 +41,7 @@ export const useOrderCapabilitiesQuery = (
|
|
|
38
41
|
return useQuery(
|
|
39
42
|
queryKey,
|
|
40
43
|
async () => {
|
|
41
|
-
const {cc, weight} = input.value;
|
|
44
|
+
const {cc, weight, isBusiness} = input.value;
|
|
42
45
|
|
|
43
46
|
if (!cc) return [];
|
|
44
47
|
|
|
@@ -46,8 +49,8 @@ export const useOrderCapabilitiesQuery = (
|
|
|
46
49
|
const proxyCapabilities = pdk.proxyCapabilities as unknown as ProxyCapabilitiesCall;
|
|
47
50
|
|
|
48
51
|
const body: ProxyCapabilitiesBody = {
|
|
49
|
-
recipient: {countryCode: cc},
|
|
50
|
-
...(weight
|
|
52
|
+
recipient: {countryCode: cc, ...(isBusiness === undefined ? null : {isBusiness})},
|
|
53
|
+
...(weight === undefined ? null : {physicalProperties: {weight: {value: weight, unit: 'g'}}}),
|
|
51
54
|
};
|
|
52
55
|
|
|
53
56
|
const response = await proxyCapabilities({body, parameters: {filterSupported: true}});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import {ref} from 'vue';
|
|
2
|
+
import {describe, expect, it, vi} from 'vitest';
|
|
3
|
+
import {useShipmentCapabilitiesQuery} from './useShipmentCapabilitiesQuery';
|
|
4
|
+
|
|
5
|
+
type RequestBody = {recipient: {countryCode: string; isBusiness?: boolean}};
|
|
6
|
+
|
|
7
|
+
let capturedBody: RequestBody | undefined;
|
|
8
|
+
|
|
9
|
+
const proxyCapabilities = vi.fn((options: {body: RequestBody}) => {
|
|
10
|
+
capturedBody = options.body;
|
|
11
|
+
|
|
12
|
+
return Promise.resolve({results: []});
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
vi.mock('@tanstack/vue-query', () => ({
|
|
16
|
+
useQuery: (queryKey: unknown, queryFn: () => Promise<unknown>) => ({queryFn}),
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
vi.mock('../../../../sdk', () => ({
|
|
20
|
+
usePdkAdminApi: () => ({proxyCapabilities}),
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
vi.mock('../../../../services', () => ({
|
|
24
|
+
globalLogger: {error: vi.fn(), debug: vi.fn(), warn: vi.fn(), info: vi.fn()},
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
type QueryFnHolder = {queryFn: () => Promise<unknown>};
|
|
28
|
+
|
|
29
|
+
const fullSelection = (isBusiness?: boolean) => ({
|
|
30
|
+
cc: 'NL',
|
|
31
|
+
carrier: 'POSTNL',
|
|
32
|
+
packageType: 'PACKAGE',
|
|
33
|
+
deliveryType: 'STANDARD',
|
|
34
|
+
...(isBusiness === undefined ? null : {isBusiness}),
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
describe('useShipmentCapabilitiesQuery', () => {
|
|
38
|
+
it('forwards the business flag on the recipient body', async () => {
|
|
39
|
+
capturedBody = undefined;
|
|
40
|
+
|
|
41
|
+
const query = useShipmentCapabilitiesQuery(ref(fullSelection(true))) as unknown as QueryFnHolder;
|
|
42
|
+
await query.queryFn();
|
|
43
|
+
|
|
44
|
+
expect(capturedBody?.recipient).toEqual({countryCode: 'NL', isBusiness: true});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('sends an explicit consumer flag on the recipient body', async () => {
|
|
48
|
+
capturedBody = undefined;
|
|
49
|
+
|
|
50
|
+
const query = useShipmentCapabilitiesQuery(ref(fullSelection(false))) as unknown as QueryFnHolder;
|
|
51
|
+
await query.queryFn();
|
|
52
|
+
|
|
53
|
+
expect(capturedBody?.recipient).toEqual({countryCode: 'NL', isBusiness: false});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('omits isBusiness when the flag is not provided', async () => {
|
|
57
|
+
capturedBody = undefined;
|
|
58
|
+
|
|
59
|
+
const query = useShipmentCapabilitiesQuery(ref(fullSelection())) as unknown as QueryFnHolder;
|
|
60
|
+
await query.queryFn();
|
|
61
|
+
|
|
62
|
+
expect(capturedBody?.recipient).toEqual({countryCode: 'NL'});
|
|
63
|
+
});
|
|
64
|
+
});
|
|
@@ -22,6 +22,7 @@ import {usePdkAdminApi} from '../../../../sdk';
|
|
|
22
22
|
export type CapabilitiesSelection = {
|
|
23
23
|
cc?: string;
|
|
24
24
|
weight?: number;
|
|
25
|
+
isBusiness?: boolean;
|
|
25
26
|
carrier?: string;
|
|
26
27
|
packageType?: string;
|
|
27
28
|
deliveryType?: string;
|
|
@@ -29,10 +30,10 @@ export type CapabilitiesSelection = {
|
|
|
29
30
|
|
|
30
31
|
/**
|
|
31
32
|
* Shipment-scoped capabilities query — fires the shared CapabilitiesAction with the FULL
|
|
32
|
-
* selection (carrier + packageType + deliveryType + cc + weight) and returns the
|
|
33
|
-
* carrier entry (the one shipment configuration the user has chosen). Drives the option
|
|
34
|
-
* and acts as the invalid-combo signal: when `results` is empty, the chosen combination
|
|
35
|
-
* valid for the order context.
|
|
33
|
+
* selection (carrier + packageType + deliveryType + cc + weight + isBusiness) and returns the
|
|
34
|
+
* matching carrier entry (the one shipment configuration the user has chosen). Drives the option
|
|
35
|
+
* panel and acts as the invalid-combo signal: when `results` is empty, the chosen combination
|
|
36
|
+
* isn't valid for the order context.
|
|
36
37
|
*
|
|
37
38
|
* The selection ref is the only refetch trigger — no window-focus, mount, or reconnect refetches.
|
|
38
39
|
* Server-side option filtering is opted in via the `filterSupported` query parameter so admin sees
|
|
@@ -60,7 +61,7 @@ export const useShipmentCapabilitiesQuery = (
|
|
|
60
61
|
return useQuery(
|
|
61
62
|
queryKey,
|
|
62
63
|
async () => {
|
|
63
|
-
const {cc, weight, carrier, packageType, deliveryType} = selection.value;
|
|
64
|
+
const {cc, weight, isBusiness, carrier, packageType, deliveryType} = selection.value;
|
|
64
65
|
|
|
65
66
|
// The `enabled` gate guarantees these are all present when this runs; TypeScript can't
|
|
66
67
|
// see through the runtime check, so we narrow explicitly here.
|
|
@@ -70,10 +71,10 @@ export const useShipmentCapabilitiesQuery = (
|
|
|
70
71
|
const proxyCapabilities = pdk.proxyCapabilities as unknown as ProxyCapabilitiesCall;
|
|
71
72
|
|
|
72
73
|
const body: ProxyCapabilitiesBody = {
|
|
73
|
-
recipient: {countryCode: cc},
|
|
74
|
+
recipient: {countryCode: cc, ...(isBusiness === undefined ? null : {isBusiness})},
|
|
74
75
|
// PDK orders carry physical-properties weight in grams (see WeightServiceInterface::UNIT_GRAMS),
|
|
75
76
|
// and the SDK's PhysicalPropertiesWeightV2 expects a {value, unit} object — not a primitive.
|
|
76
|
-
...(weight
|
|
77
|
+
...(weight === undefined ? null : {physicalProperties: {weight: {value: weight, unit: 'g'}}}),
|
|
77
78
|
carrier,
|
|
78
79
|
packageType,
|
|
79
80
|
deliveryType,
|
|
@@ -4,7 +4,8 @@ import {type CapabilitiesSelection} from '../../actions/composables/queries/acco
|
|
|
4
4
|
|
|
5
5
|
const DEBOUNCE_MS = 100;
|
|
6
6
|
|
|
7
|
-
export type OrderInput = {cc?: string; weight?: number};
|
|
7
|
+
export type OrderInput = {cc?: string; weight?: number; isBusiness?: boolean};
|
|
8
|
+
|
|
8
9
|
export type FormInput = {carrier?: string; packageType?: string; deliveryType?: string};
|
|
9
10
|
|
|
10
11
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {describe, expect, it, vi, beforeEach} from 'vitest';
|
|
2
1
|
import {effectScope, nextTick, ref} from 'vue';
|
|
2
|
+
import {describe, expect, it, vi, beforeEach} from 'vitest';
|
|
3
3
|
import {BackendEndpoint, TriState} from '@myparcel-dev/pdk-common';
|
|
4
4
|
import {FIELD_CARRIER, FIELD_DELIVERY_TYPE, FIELD_MANUAL_WEIGHT, FIELD_PACKAGE_TYPE} from './field';
|
|
5
5
|
|
|
@@ -35,12 +35,12 @@ const buildForm = (initial: Record<string, unknown>) => {
|
|
|
35
35
|
});
|
|
36
36
|
|
|
37
37
|
return {
|
|
38
|
-
getValue: <T
|
|
38
|
+
getValue: <T>(name: string): T => fields.get(name)?.ref.value as T,
|
|
39
39
|
setExternally: (name: string, value: unknown) => {
|
|
40
40
|
const field = fields.get(name);
|
|
41
41
|
|
|
42
42
|
if (field) {
|
|
43
|
-
|
|
43
|
+
field.ref.value = value;
|
|
44
44
|
} else {
|
|
45
45
|
fields.set(name, {ref: ref(value)});
|
|
46
46
|
}
|
|
@@ -55,12 +55,14 @@ beforeEach(() => {
|
|
|
55
55
|
useShipmentCapabilitiesQueryMock.mockClear();
|
|
56
56
|
});
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
// `isBusiness` is omitted from the shipping address unless explicitly passed — production
|
|
59
|
+
// orders may not carry the flag at all, so the flag-absent shape is the representative default.
|
|
60
|
+
const orderShape = (cc = 'NL', initialWeight = 1500, isBusiness: boolean | undefined = undefined) =>
|
|
59
61
|
({
|
|
60
62
|
externalIdentifier: 'order-1',
|
|
61
|
-
shippingAddress: {cc},
|
|
63
|
+
shippingAddress: {cc, ...(isBusiness === undefined ? null : {isBusiness})},
|
|
62
64
|
physicalProperties: {initialWeight},
|
|
63
|
-
}
|
|
65
|
+
} as never);
|
|
64
66
|
|
|
65
67
|
describe('wireProxyCapabilities', () => {
|
|
66
68
|
it('treats TriState.Inherit (-1) as "no manual override" and falls back to initialWeight', async () => {
|
|
@@ -105,7 +107,9 @@ describe('wireProxyCapabilities', () => {
|
|
|
105
107
|
const orderInputRef = useOrderCapabilitiesQueryMock.mock.calls[0][0] as {value: {weight?: number}};
|
|
106
108
|
|
|
107
109
|
// Wait for the debounce (refDebounced default 100ms in this codebase).
|
|
108
|
-
await new Promise((resolve) =>
|
|
110
|
+
await new Promise((resolve) => {
|
|
111
|
+
setTimeout(resolve, 150);
|
|
112
|
+
});
|
|
109
113
|
await nextTick();
|
|
110
114
|
|
|
111
115
|
expect(orderInputRef.value.weight).toBe(4200);
|
|
@@ -113,6 +117,54 @@ describe('wireProxyCapabilities', () => {
|
|
|
113
117
|
scope.stop();
|
|
114
118
|
});
|
|
115
119
|
|
|
120
|
+
it('forwards the recipient business flag from the order shipping address to both queries', async () => {
|
|
121
|
+
const form = buildForm({
|
|
122
|
+
[FIELD_CARRIER]: 'POSTNL',
|
|
123
|
+
[FIELD_PACKAGE_TYPE]: 'PACKAGE',
|
|
124
|
+
[FIELD_DELIVERY_TYPE]: 'STANDARD',
|
|
125
|
+
[FIELD_MANUAL_WEIGHT]: TriState.Inherit,
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
const scope = effectScope();
|
|
129
|
+
const {wireProxyCapabilities} = await import('./wireProxyCapabilities');
|
|
130
|
+
|
|
131
|
+
scope.run(() => {
|
|
132
|
+
wireProxyCapabilities(form as never, orderShape('NL', 1500, true));
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
const orderInputRef = useOrderCapabilitiesQueryMock.mock.calls[0][0] as {value: {isBusiness?: boolean}};
|
|
136
|
+
const selectionRef = useShipmentCapabilitiesQueryMock.mock.calls[0][0] as {value: {isBusiness?: boolean}};
|
|
137
|
+
|
|
138
|
+
expect(orderInputRef.value.isBusiness).toBe(true);
|
|
139
|
+
expect(selectionRef.value.isBusiness).toBe(true);
|
|
140
|
+
|
|
141
|
+
scope.stop();
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('leaves isBusiness undefined for both queries when the order has no flag', async () => {
|
|
145
|
+
const form = buildForm({
|
|
146
|
+
[FIELD_CARRIER]: 'POSTNL',
|
|
147
|
+
[FIELD_PACKAGE_TYPE]: 'PACKAGE',
|
|
148
|
+
[FIELD_DELIVERY_TYPE]: 'STANDARD',
|
|
149
|
+
[FIELD_MANUAL_WEIGHT]: TriState.Inherit,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const scope = effectScope();
|
|
153
|
+
const {wireProxyCapabilities} = await import('./wireProxyCapabilities');
|
|
154
|
+
|
|
155
|
+
scope.run(() => {
|
|
156
|
+
wireProxyCapabilities(form as never, orderShape());
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
const orderInputRef = useOrderCapabilitiesQueryMock.mock.calls[0][0] as {value: {isBusiness?: boolean}};
|
|
160
|
+
const selectionRef = useShipmentCapabilitiesQueryMock.mock.calls[0][0] as {value: {isBusiness?: boolean}};
|
|
161
|
+
|
|
162
|
+
expect(orderInputRef.value.isBusiness).toBeUndefined();
|
|
163
|
+
expect(selectionRef.value.isBusiness).toBeUndefined();
|
|
164
|
+
|
|
165
|
+
scope.stop();
|
|
166
|
+
});
|
|
167
|
+
|
|
116
168
|
it('skips wiring and returns undefined when the order has no externalIdentifier (bulk path)', async () => {
|
|
117
169
|
const form = buildForm({});
|
|
118
170
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {computed, onScopeDispose, type Ref} from 'vue';
|
|
2
2
|
import {type FormInstance} from '@myparcel-dev/vue-form-builder';
|
|
3
3
|
import {BackendEndpoint, type Plugin} from '@myparcel-dev/pdk-common';
|
|
4
|
-
import {globalLogger} from '../../services';
|
|
5
4
|
import {useQueryStore} from '../../stores';
|
|
5
|
+
import {globalLogger} from '../../services';
|
|
6
6
|
import {
|
|
7
7
|
useShipmentCapabilitiesQuery,
|
|
8
8
|
type CapabilitiesSelection,
|
|
@@ -15,15 +15,38 @@ import {useCapabilitiesWatcher, type FormInput, type OrderInput} from './useCapa
|
|
|
15
15
|
import {FIELD_CARRIER, FIELD_DELIVERY_TYPE, FIELD_MANUAL_WEIGHT, FIELD_PACKAGE_TYPE} from './field';
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
18
|
+
* Resolve the order-scoped capabilities input from the form + order.
|
|
19
|
+
*
|
|
20
|
+
* Read weight through `form.getValue()` (which goes through `q(field.ref)` / `toValue`) rather
|
|
21
|
+
* than `form.values` so reactive deps are tracked when called inside a computed. Manual weight from
|
|
22
|
+
* `FIELD_MANUAL_WEIGHT` wins when set — it carries `TriState.Inherit` (-1) when unset, and only a
|
|
23
|
+
* positive number is a real override; otherwise fall back to the order's initial weight.
|
|
24
|
+
*
|
|
25
|
+
* `isBusiness` is the PDK-derived recipient flag (from the company name), forwarded as-is — no
|
|
26
|
+
* company or other PII is handled here.
|
|
27
|
+
*/
|
|
28
|
+
const resolveOrderInput = (form: FormInstance, order: Plugin.ModelContextOrderDataContext): OrderInput => {
|
|
29
|
+
const manualWeightRaw = form.getValue(FIELD_MANUAL_WEIGHT);
|
|
30
|
+
const manualWeight = typeof manualWeightRaw === 'number' && manualWeightRaw > 0 ? manualWeightRaw : undefined;
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
cc: order.shippingAddress?.cc,
|
|
34
|
+
weight: manualWeight ?? order.physicalProperties?.initialWeight,
|
|
35
|
+
isBusiness: order.shippingAddress?.isBusiness,
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Wire BOTH capabilities queries — order-scoped (cc + weight + isBusiness) and shipment-scoped
|
|
41
|
+
* (full selection) — into the shipment-options form for a single order, register them in the
|
|
42
|
+
* query store under composite-string modifiers (`${orderId}.order` and `${orderId}.shipment`),
|
|
43
|
+
* and tear them down when the form's scope disposes (modal close).
|
|
22
44
|
*
|
|
23
45
|
* The two queries serve different concerns:
|
|
24
46
|
*
|
|
25
47
|
* - **Order query** drives the carrier / packageType / deliveryType dropdowns from each
|
|
26
|
-
* carrier's flat union arrays. Refetches only when destination or
|
|
48
|
+
* carrier's flat union arrays. Refetches only when destination, weight or the recipient
|
|
49
|
+
* business flag change.
|
|
27
50
|
* - **Shipment query** drives per-option metadata (`isRequired`, `requires`, `excludes`,
|
|
28
51
|
* `insuredAmount`) for the chosen combination. Refetches when any axis of the selection
|
|
29
52
|
* changes; the empty-result case is the invalid-combo signal consumed by
|
|
@@ -51,20 +74,7 @@ export const wireProxyCapabilities = (
|
|
|
51
74
|
const orderModifier = `${orderId}.order`;
|
|
52
75
|
const shipmentModifier = `${orderId}.shipment`;
|
|
53
76
|
|
|
54
|
-
|
|
55
|
-
// than `form.values[name]` so reactive deps are tracked correctly inside computed/watchers.
|
|
56
|
-
const orderInput = computed<OrderInput>(() => {
|
|
57
|
-
// FIELD_MANUAL_WEIGHT carries `TriState.Inherit` (-1) when the user hasn't entered a manual
|
|
58
|
-
// override; only positive numbers represent an actual weight. Treat anything else as "unset"
|
|
59
|
-
// and fall back to the order's initial weight.
|
|
60
|
-
const manualWeightRaw = form.getValue(FIELD_MANUAL_WEIGHT);
|
|
61
|
-
const manualWeight = typeof manualWeightRaw === 'number' && manualWeightRaw > 0 ? manualWeightRaw : undefined;
|
|
62
|
-
|
|
63
|
-
return {
|
|
64
|
-
cc: order.shippingAddress?.cc,
|
|
65
|
-
weight: manualWeight ?? order.physicalProperties?.initialWeight,
|
|
66
|
-
};
|
|
67
|
-
});
|
|
77
|
+
const orderInput = computed<OrderInput>(() => resolveOrderInput(form, order));
|
|
68
78
|
|
|
69
79
|
const formInput = computed<FormInput>(() => ({
|
|
70
80
|
carrier: form.getValue<string | undefined>(FIELD_CARRIER),
|
|
@@ -77,6 +87,7 @@ export const wireProxyCapabilities = (
|
|
|
77
87
|
const orderInputForQuery = computed<OrderCapabilitiesInput>(() => ({
|
|
78
88
|
cc: selection.value.cc,
|
|
79
89
|
weight: selection.value.weight,
|
|
90
|
+
isBusiness: selection.value.isBusiness,
|
|
80
91
|
}));
|
|
81
92
|
|
|
82
93
|
const orderQuery = useOrderCapabilitiesQuery(orderInputForQuery);
|
package/src/types/sdk.types.ts
CHANGED
|
@@ -209,7 +209,7 @@ interface ProxyCapabilitiesDefinition extends PdkEndpointDefinition {
|
|
|
209
209
|
* SDK's `PhysicalPropertiesWeightV2` model defines it on the wire.
|
|
210
210
|
*/
|
|
211
211
|
body: {
|
|
212
|
-
recipient: {countryCode: string};
|
|
212
|
+
recipient: {countryCode: string; isBusiness?: boolean};
|
|
213
213
|
physicalProperties?: {
|
|
214
214
|
weight?: {value: number; unit: 'g' | 'kg'};
|
|
215
215
|
};
|