@labdigital/commercetools-mock 2.52.0 → 2.53.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/dist/index.d.ts +21 -21
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +31 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/lib/productSearchFilter.test.ts +77 -0
- package/src/product-search-availability.test.ts +242 -0
- package/src/product-search.ts +22 -4
- package/src/repositories/business-unit.test.ts +143 -0
- package/src/repositories/business-unit.ts +52 -0
package/package.json
CHANGED
|
@@ -346,4 +346,81 @@ describe("Product search filter", () => {
|
|
|
346
346
|
}).isMatch,
|
|
347
347
|
).toBeTruthy();
|
|
348
348
|
});
|
|
349
|
+
|
|
350
|
+
test("by availability.isOnStock", async () => {
|
|
351
|
+
const productWithAvailability: ProductProjection = {
|
|
352
|
+
...exampleProduct,
|
|
353
|
+
masterVariant: {
|
|
354
|
+
...exampleProduct.masterVariant,
|
|
355
|
+
availability: {
|
|
356
|
+
isOnStock: true,
|
|
357
|
+
availableQuantity: 10,
|
|
358
|
+
isOnStockForChannel: "test-channel",
|
|
359
|
+
} as any, // Cast to any since isOnStockForChannel is not in SDK type
|
|
360
|
+
},
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
// This should pass - current behavior
|
|
364
|
+
const result1 = match(
|
|
365
|
+
{
|
|
366
|
+
exact: {
|
|
367
|
+
field: "variants.availability.isOnStock",
|
|
368
|
+
value: true,
|
|
369
|
+
},
|
|
370
|
+
},
|
|
371
|
+
productWithAvailability,
|
|
372
|
+
);
|
|
373
|
+
|
|
374
|
+
expect(result1.isMatch).toBeTruthy();
|
|
375
|
+
|
|
376
|
+
const result2 = match(
|
|
377
|
+
{
|
|
378
|
+
exact: {
|
|
379
|
+
field: "variants.availability.isOnStock",
|
|
380
|
+
value: false,
|
|
381
|
+
},
|
|
382
|
+
},
|
|
383
|
+
productWithAvailability,
|
|
384
|
+
);
|
|
385
|
+
|
|
386
|
+
expect(result2.isMatch).toBeFalsy();
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
test("by availability.isOnStockForChannel", async () => {
|
|
390
|
+
const productWithAvailability: ProductProjection = {
|
|
391
|
+
...exampleProduct,
|
|
392
|
+
masterVariant: {
|
|
393
|
+
...exampleProduct.masterVariant,
|
|
394
|
+
availability: {
|
|
395
|
+
isOnStock: true,
|
|
396
|
+
availableQuantity: 10,
|
|
397
|
+
isOnStockForChannel: "test-channel",
|
|
398
|
+
} as any, // Cast to any since isOnStockForChannel is not in SDK type
|
|
399
|
+
},
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
expect(
|
|
403
|
+
match(
|
|
404
|
+
{
|
|
405
|
+
exact: {
|
|
406
|
+
field: "variants.availability.isOnStockForChannel",
|
|
407
|
+
value: "test-channel",
|
|
408
|
+
},
|
|
409
|
+
},
|
|
410
|
+
productWithAvailability,
|
|
411
|
+
).isMatch,
|
|
412
|
+
).toBeTruthy();
|
|
413
|
+
|
|
414
|
+
expect(
|
|
415
|
+
match(
|
|
416
|
+
{
|
|
417
|
+
exact: {
|
|
418
|
+
field: "variants.availability.isOnStockForChannel",
|
|
419
|
+
value: "other-channel",
|
|
420
|
+
},
|
|
421
|
+
},
|
|
422
|
+
productWithAvailability,
|
|
423
|
+
).isMatch,
|
|
424
|
+
).toBeFalsy();
|
|
425
|
+
});
|
|
349
426
|
});
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
InventoryEntryDraft,
|
|
3
|
+
ProductDraft,
|
|
4
|
+
ProductPagedSearchResponse,
|
|
5
|
+
ProductSearchRequest,
|
|
6
|
+
} from "@commercetools/platform-sdk";
|
|
7
|
+
import supertest from "supertest";
|
|
8
|
+
import { afterEach, beforeEach, describe, expect, test } from "vitest";
|
|
9
|
+
import { CommercetoolsMock } from "./index";
|
|
10
|
+
|
|
11
|
+
describe("Product Search - Availability Filtering", () => {
|
|
12
|
+
const ctMock = new CommercetoolsMock();
|
|
13
|
+
let productId: string;
|
|
14
|
+
|
|
15
|
+
beforeEach(async () => {
|
|
16
|
+
// Create a product type first
|
|
17
|
+
const productTypeDraft = {
|
|
18
|
+
name: "Test Product Type",
|
|
19
|
+
key: "test-type",
|
|
20
|
+
description: "Test Product Type",
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
await supertest(ctMock.app)
|
|
24
|
+
.post("/dummy/product-types")
|
|
25
|
+
.send(productTypeDraft);
|
|
26
|
+
|
|
27
|
+
// Create a test product
|
|
28
|
+
const productDraft: ProductDraft = {
|
|
29
|
+
name: { "en-US": "Test Product" },
|
|
30
|
+
productType: {
|
|
31
|
+
typeId: "product-type",
|
|
32
|
+
key: "test-type",
|
|
33
|
+
},
|
|
34
|
+
slug: { "en-US": "test-product" },
|
|
35
|
+
masterVariant: {
|
|
36
|
+
sku: "TEST-SKU-001",
|
|
37
|
+
},
|
|
38
|
+
variants: [
|
|
39
|
+
{
|
|
40
|
+
sku: "TEST-SKU-002",
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const productResponse = await supertest(ctMock.app)
|
|
46
|
+
.post("/dummy/products")
|
|
47
|
+
.send(productDraft);
|
|
48
|
+
|
|
49
|
+
productId = productResponse.body.id;
|
|
50
|
+
|
|
51
|
+
// Publish the product
|
|
52
|
+
await supertest(ctMock.app)
|
|
53
|
+
.post(`/dummy/products/${productId}`)
|
|
54
|
+
.send({
|
|
55
|
+
version: productResponse.body.version,
|
|
56
|
+
actions: [{ action: "publish" }],
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
afterEach(() => {
|
|
61
|
+
ctMock.clear();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
async function createInventoryEntry(
|
|
65
|
+
sku: string,
|
|
66
|
+
quantityOnStock: number,
|
|
67
|
+
channelId?: string,
|
|
68
|
+
) {
|
|
69
|
+
const inventoryEntry: InventoryEntryDraft = {
|
|
70
|
+
sku,
|
|
71
|
+
quantityOnStock,
|
|
72
|
+
...(channelId && {
|
|
73
|
+
supplyChannel: {
|
|
74
|
+
typeId: "channel",
|
|
75
|
+
id: channelId,
|
|
76
|
+
},
|
|
77
|
+
}),
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
await supertest(ctMock.app).post("/dummy/inventory").send(inventoryEntry);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function searchProducts(
|
|
84
|
+
query?: any,
|
|
85
|
+
): Promise<ProductPagedSearchResponse> {
|
|
86
|
+
const searchRequest: ProductSearchRequest = {
|
|
87
|
+
...(query && { query }),
|
|
88
|
+
productProjectionParameters: {
|
|
89
|
+
staged: false,
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const response = await supertest(ctMock.app)
|
|
94
|
+
.post("/dummy/products/search")
|
|
95
|
+
.send(searchRequest);
|
|
96
|
+
|
|
97
|
+
return response.body;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
test("should filter products by variants.availability.isOnStock = true", async () => {
|
|
101
|
+
// Create inventory with stock for one variant
|
|
102
|
+
await createInventoryEntry("TEST-SKU-001", 10);
|
|
103
|
+
|
|
104
|
+
const result = await searchProducts({
|
|
105
|
+
exact: {
|
|
106
|
+
field: "variants.availability.isOnStock",
|
|
107
|
+
value: true,
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
expect(result.results).toHaveLength(1);
|
|
112
|
+
expect(
|
|
113
|
+
result.results[0].productProjection?.masterVariant?.availability
|
|
114
|
+
?.isOnStock,
|
|
115
|
+
).toBe(true);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test("should filter products by variants.availability.isOnStock = false", async () => {
|
|
119
|
+
// Create inventory with zero stock
|
|
120
|
+
await createInventoryEntry("TEST-SKU-001", 0);
|
|
121
|
+
|
|
122
|
+
const result = await searchProducts({
|
|
123
|
+
exact: {
|
|
124
|
+
field: "variants.availability.isOnStock",
|
|
125
|
+
value: false,
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// Should find the product because it's not on stock
|
|
130
|
+
expect(result.results).toHaveLength(1);
|
|
131
|
+
expect(
|
|
132
|
+
result.results[0].productProjection?.masterVariant?.availability
|
|
133
|
+
?.isOnStock,
|
|
134
|
+
).toBe(false);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
test("should filter products by variants.availability.isOnStockForChannel", async () => {
|
|
138
|
+
const channelId = "test-channel-1";
|
|
139
|
+
|
|
140
|
+
// Create inventory for specific channel
|
|
141
|
+
await createInventoryEntry("TEST-SKU-001", 5, channelId);
|
|
142
|
+
|
|
143
|
+
const result = await searchProducts({
|
|
144
|
+
exact: {
|
|
145
|
+
field: "variants.availability.isOnStockForChannel",
|
|
146
|
+
value: channelId,
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
expect(result.results).toHaveLength(1);
|
|
151
|
+
expect(
|
|
152
|
+
(result.results[0].productProjection?.masterVariant?.availability as any)
|
|
153
|
+
?.isOnStockForChannel,
|
|
154
|
+
).toBe(channelId);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
test("should not find products when filtering by non-matching channel", async () => {
|
|
158
|
+
const channelId = "test-channel-1";
|
|
159
|
+
const otherChannelId = "test-channel-2";
|
|
160
|
+
|
|
161
|
+
// Create inventory for specific channel
|
|
162
|
+
await createInventoryEntry("TEST-SKU-001", 5, channelId);
|
|
163
|
+
|
|
164
|
+
const result = await searchProducts({
|
|
165
|
+
exact: {
|
|
166
|
+
field: "variants.availability.isOnStockForChannel",
|
|
167
|
+
value: otherChannelId,
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
expect(result.results).toHaveLength(0);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test("should handle products without inventory entries", async () => {
|
|
175
|
+
// Don't create any inventory entries
|
|
176
|
+
|
|
177
|
+
const result = await searchProducts({
|
|
178
|
+
exact: {
|
|
179
|
+
field: "variants.availability.isOnStock",
|
|
180
|
+
value: false,
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// Should find the product because it has no stock
|
|
185
|
+
expect(result.results).toHaveLength(1);
|
|
186
|
+
expect(
|
|
187
|
+
result.results[0].productProjection?.masterVariant?.availability
|
|
188
|
+
?.isOnStock,
|
|
189
|
+
).toBe(false);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
test("should work with OR queries for availability", async () => {
|
|
193
|
+
// Create inventory with stock
|
|
194
|
+
await createInventoryEntry("TEST-SKU-001", 10);
|
|
195
|
+
|
|
196
|
+
const result = await searchProducts({
|
|
197
|
+
or: [
|
|
198
|
+
{
|
|
199
|
+
exact: {
|
|
200
|
+
field: "variants.availability.isOnStock",
|
|
201
|
+
value: true,
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
exact: {
|
|
206
|
+
field: "variants.availability.isOnStock",
|
|
207
|
+
value: false,
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
],
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
// Should find the product regardless of stock status
|
|
214
|
+
expect(result.results).toHaveLength(1);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
test("should work with AND queries combining availability and other fields", async () => {
|
|
218
|
+
await createInventoryEntry("TEST-SKU-001", 10);
|
|
219
|
+
|
|
220
|
+
const result = await searchProducts({
|
|
221
|
+
and: [
|
|
222
|
+
{
|
|
223
|
+
exact: {
|
|
224
|
+
field: "variants.availability.isOnStock",
|
|
225
|
+
value: true,
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
exact: {
|
|
230
|
+
field: "variants.sku",
|
|
231
|
+
value: "TEST-SKU-001",
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
],
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
expect(result.results).toHaveLength(1);
|
|
238
|
+
expect(result.results[0].productProjection?.masterVariant?.sku).toBe(
|
|
239
|
+
"TEST-SKU-001",
|
|
240
|
+
);
|
|
241
|
+
});
|
|
242
|
+
});
|
package/src/product-search.ts
CHANGED
|
@@ -148,6 +148,23 @@ export class ProductSearch {
|
|
|
148
148
|
? product.masterData.current
|
|
149
149
|
: product.masterData.staged;
|
|
150
150
|
|
|
151
|
+
const getVariantAvailability = (sku?: string) => {
|
|
152
|
+
if (!sku) {
|
|
153
|
+
return {
|
|
154
|
+
isOnStock: false,
|
|
155
|
+
availableQuantity: 0,
|
|
156
|
+
isOnStockForChannel: undefined,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
return (
|
|
160
|
+
availabilityBySku.get(sku) || {
|
|
161
|
+
isOnStock: false,
|
|
162
|
+
availableQuantity: 0,
|
|
163
|
+
isOnStockForChannel: undefined,
|
|
164
|
+
}
|
|
165
|
+
);
|
|
166
|
+
};
|
|
167
|
+
|
|
151
168
|
return {
|
|
152
169
|
id: product.id,
|
|
153
170
|
createdAt: product.createdAt,
|
|
@@ -159,12 +176,13 @@ export class ProductSearch {
|
|
|
159
176
|
metaDescription: obj.metaDescription,
|
|
160
177
|
slug: obj.slug,
|
|
161
178
|
categories: obj.categories,
|
|
162
|
-
masterVariant:
|
|
179
|
+
masterVariant: {
|
|
180
|
+
...obj.masterVariant,
|
|
181
|
+
availability: getVariantAvailability(obj.masterVariant.sku),
|
|
182
|
+
},
|
|
163
183
|
variants: obj.variants.map((variant) => ({
|
|
164
184
|
...variant,
|
|
165
|
-
availability: variant.sku
|
|
166
|
-
? availabilityBySku.get(variant.sku)
|
|
167
|
-
: { isOnStock: false, availableQuantity: 0, isOnStockForChannel: [] },
|
|
185
|
+
availability: getVariantAvailability(variant.sku),
|
|
168
186
|
})),
|
|
169
187
|
productType: product.productType,
|
|
170
188
|
hasStagedChanges: product.masterData.hasStagedChanges,
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
BusinessUnitAddShippingAddressIdAction,
|
|
2
3
|
BusinessUnitChangeNameAction,
|
|
3
4
|
BusinessUnitChangeStatusAction,
|
|
5
|
+
BusinessUnitRemoveAddressAction,
|
|
4
6
|
BusinessUnitSetContactEmailAction,
|
|
7
|
+
BusinessUnitSetDefaultShippingAddressAction,
|
|
5
8
|
CompanyDraft,
|
|
6
9
|
DivisionDraft,
|
|
7
10
|
} from "@commercetools/platform-sdk";
|
|
@@ -250,6 +253,146 @@ describe("BusinessUnit Repository", () => {
|
|
|
250
253
|
expect(result.version).toBe(businessUnit.version + 1);
|
|
251
254
|
});
|
|
252
255
|
|
|
256
|
+
test("update business unit - setDefaultShippingAddress", () => {
|
|
257
|
+
const draft: CompanyDraft = {
|
|
258
|
+
key: "default-shipping-company",
|
|
259
|
+
unitType: "Company",
|
|
260
|
+
name: "Default Shipping Company",
|
|
261
|
+
addresses: [
|
|
262
|
+
{
|
|
263
|
+
country: "US",
|
|
264
|
+
city: "New York",
|
|
265
|
+
streetName: "5th Avenue",
|
|
266
|
+
streetNumber: "123",
|
|
267
|
+
postalCode: "10001",
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
country: "US",
|
|
271
|
+
city: "Boston",
|
|
272
|
+
streetName: "Boylston",
|
|
273
|
+
streetNumber: "456",
|
|
274
|
+
postalCode: "02116",
|
|
275
|
+
},
|
|
276
|
+
],
|
|
277
|
+
shippingAddresses: [0, 1],
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
const ctx = { projectKey: "dummy" };
|
|
281
|
+
const businessUnit = repository.create(ctx, draft);
|
|
282
|
+
const addressId = businessUnit.addresses[1].id;
|
|
283
|
+
|
|
284
|
+
const result = repository.processUpdateActions(
|
|
285
|
+
ctx,
|
|
286
|
+
businessUnit,
|
|
287
|
+
businessUnit.version,
|
|
288
|
+
[
|
|
289
|
+
{
|
|
290
|
+
action: "setDefaultShippingAddress",
|
|
291
|
+
addressId,
|
|
292
|
+
} as BusinessUnitSetDefaultShippingAddressAction,
|
|
293
|
+
],
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
expect(result.defaultShippingAddressId).toBe(addressId);
|
|
297
|
+
expect(result.version).toBe(businessUnit.version + 1);
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
test("update business unit - addShippingAddressId", () => {
|
|
301
|
+
const draft: CompanyDraft = {
|
|
302
|
+
key: "add-shipping-address-company",
|
|
303
|
+
unitType: "Company",
|
|
304
|
+
name: "Add Shipping Address Company",
|
|
305
|
+
addresses: [
|
|
306
|
+
{
|
|
307
|
+
country: "US",
|
|
308
|
+
city: "New York",
|
|
309
|
+
streetName: "5th Avenue",
|
|
310
|
+
streetNumber: "123",
|
|
311
|
+
postalCode: "10001",
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
country: "US",
|
|
315
|
+
city: "Boston",
|
|
316
|
+
streetName: "Boylston",
|
|
317
|
+
streetNumber: "456",
|
|
318
|
+
postalCode: "02116",
|
|
319
|
+
},
|
|
320
|
+
],
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
const ctx = { projectKey: "dummy" };
|
|
324
|
+
const businessUnit = repository.create(ctx, draft);
|
|
325
|
+
const addressId = businessUnit.addresses[1].id;
|
|
326
|
+
|
|
327
|
+
const result = repository.processUpdateActions(
|
|
328
|
+
ctx,
|
|
329
|
+
businessUnit,
|
|
330
|
+
businessUnit.version,
|
|
331
|
+
[
|
|
332
|
+
{
|
|
333
|
+
action: "addShippingAddressId",
|
|
334
|
+
addressId,
|
|
335
|
+
} as BusinessUnitAddShippingAddressIdAction,
|
|
336
|
+
],
|
|
337
|
+
);
|
|
338
|
+
|
|
339
|
+
expect(result.shippingAddressIds).toContain(addressId);
|
|
340
|
+
expect(result.version).toBe(businessUnit.version + 1);
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
test("update business unit - removeAddress", () => {
|
|
344
|
+
const draft: CompanyDraft = {
|
|
345
|
+
key: "remove-address-company",
|
|
346
|
+
unitType: "Company",
|
|
347
|
+
name: "Remove Address Company",
|
|
348
|
+
addresses: [
|
|
349
|
+
{
|
|
350
|
+
country: "US",
|
|
351
|
+
city: "New York",
|
|
352
|
+
streetName: "5th Avenue",
|
|
353
|
+
streetNumber: "123",
|
|
354
|
+
postalCode: "10001",
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
country: "US",
|
|
358
|
+
city: "Boston",
|
|
359
|
+
streetName: "Boylston",
|
|
360
|
+
streetNumber: "456",
|
|
361
|
+
postalCode: "02116",
|
|
362
|
+
},
|
|
363
|
+
],
|
|
364
|
+
billingAddresses: [0, 1],
|
|
365
|
+
shippingAddresses: [0, 1],
|
|
366
|
+
defaultBillingAddress: 0,
|
|
367
|
+
defaultShippingAddress: 1,
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
const ctx = { projectKey: "dummy" };
|
|
371
|
+
const businessUnit = repository.create(ctx, draft);
|
|
372
|
+
const addressIdToRemove = businessUnit.addresses[0].id;
|
|
373
|
+
const remainingAddressId = businessUnit.addresses[1].id;
|
|
374
|
+
|
|
375
|
+
const result = repository.processUpdateActions(
|
|
376
|
+
ctx,
|
|
377
|
+
businessUnit,
|
|
378
|
+
businessUnit.version,
|
|
379
|
+
[
|
|
380
|
+
{
|
|
381
|
+
action: "removeAddress",
|
|
382
|
+
addressId: addressIdToRemove,
|
|
383
|
+
} as BusinessUnitRemoveAddressAction,
|
|
384
|
+
],
|
|
385
|
+
);
|
|
386
|
+
|
|
387
|
+
expect(result.addresses).toHaveLength(1);
|
|
388
|
+
expect(result.addresses[0].id).toBe(remainingAddressId);
|
|
389
|
+
expect(result.billingAddressIds).toEqual([remainingAddressId]);
|
|
390
|
+
expect(result.shippingAddressIds).toEqual([remainingAddressId]);
|
|
391
|
+
expect(result.defaultBillingAddressId).toBeUndefined();
|
|
392
|
+
expect(result.defaultShippingAddressId).toBe(remainingAddressId);
|
|
393
|
+
expect(result.version).toBe(businessUnit.version + 1);
|
|
394
|
+
});
|
|
395
|
+
|
|
253
396
|
test("get and delete business unit", () => {
|
|
254
397
|
const draft: CompanyDraft = {
|
|
255
398
|
key: "delete-test",
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
BusinessUnitAddShippingAddressIdAction,
|
|
2
3
|
BusinessUnitChangeApprovalRuleModeAction,
|
|
3
4
|
BusinessUnitChangeAssociateModeAction,
|
|
4
5
|
BusinessUnitChangeStatusAction,
|
|
5
6
|
BusinessUnitSetCustomTypeAction,
|
|
7
|
+
BusinessUnitSetDefaultShippingAddressAction,
|
|
6
8
|
BusinessUnitUpdateAction,
|
|
7
9
|
CompanyDraft,
|
|
8
10
|
DivisionDraft,
|
|
@@ -17,6 +19,7 @@ import type {
|
|
|
17
19
|
BusinessUnitChangeNameAction,
|
|
18
20
|
BusinessUnitChangeParentUnitAction,
|
|
19
21
|
BusinessUnitDraft,
|
|
22
|
+
BusinessUnitRemoveAddressAction,
|
|
20
23
|
BusinessUnitSetAssociatesAction,
|
|
21
24
|
BusinessUnitSetContactEmailAction,
|
|
22
25
|
BusinessUnitSetStoreModeAction,
|
|
@@ -289,4 +292,53 @@ class BusinessUnitUpdateHandler
|
|
|
289
292
|
) {
|
|
290
293
|
resource.storeMode = storeMode;
|
|
291
294
|
}
|
|
295
|
+
|
|
296
|
+
setDefaultShippingAddress(
|
|
297
|
+
context: RepositoryContext,
|
|
298
|
+
resource: Writable<BusinessUnit>,
|
|
299
|
+
{ addressId }: BusinessUnitSetDefaultShippingAddressAction,
|
|
300
|
+
) {
|
|
301
|
+
resource.defaultShippingAddressId = addressId;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
addShippingAddressId(
|
|
305
|
+
context: RepositoryContext,
|
|
306
|
+
resource: Writable<BusinessUnit>,
|
|
307
|
+
{ addressId }: BusinessUnitAddShippingAddressIdAction,
|
|
308
|
+
) {
|
|
309
|
+
if (!resource.shippingAddressIds) {
|
|
310
|
+
resource.shippingAddressIds = [];
|
|
311
|
+
}
|
|
312
|
+
if (addressId) {
|
|
313
|
+
resource.shippingAddressIds.push(addressId);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
removeAddress(
|
|
318
|
+
context: RepositoryContext,
|
|
319
|
+
resource: Writable<BusinessUnit>,
|
|
320
|
+
{ addressId }: BusinessUnitRemoveAddressAction,
|
|
321
|
+
) {
|
|
322
|
+
resource.addresses = resource.addresses.filter(
|
|
323
|
+
(addr) => addr.id !== addressId,
|
|
324
|
+
);
|
|
325
|
+
|
|
326
|
+
if (resource.shippingAddressIds) {
|
|
327
|
+
resource.shippingAddressIds = resource.shippingAddressIds.filter(
|
|
328
|
+
(id) => id !== addressId,
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
if (resource.billingAddressIds) {
|
|
332
|
+
resource.billingAddressIds = resource.billingAddressIds.filter(
|
|
333
|
+
(id) => id !== addressId,
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
if (resource.defaultShippingAddressId === addressId) {
|
|
338
|
+
resource.defaultShippingAddressId = undefined;
|
|
339
|
+
}
|
|
340
|
+
if (resource.defaultBillingAddressId === addressId) {
|
|
341
|
+
resource.defaultBillingAddressId = undefined;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
292
344
|
}
|