@labdigital/commercetools-mock 2.58.0 → 2.59.1
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 +24 -23
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +234 -131
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/repositories/cart/actions.ts +78 -0
- package/src/repositories/cart/index.ts +11 -137
- package/src/repositories/order/actions.ts +81 -0
- package/src/repositories/order/index.test.ts +307 -0
- package/src/repositories/order/index.ts +98 -2
- package/src/services/cart.test.ts +170 -0
- package/src/services/order.test.ts +236 -1
- package/src/shipping.ts +157 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@labdigital/commercetools-mock",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.59.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Michael van Tellingen",
|
|
6
6
|
"type": "module",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"express": "5.1.0",
|
|
22
22
|
"light-my-request": "6.6.0",
|
|
23
23
|
"morgan": "1.10.0",
|
|
24
|
-
"msw": "2.
|
|
24
|
+
"msw": "2.8.4",
|
|
25
25
|
"uuid": "11.1.0",
|
|
26
26
|
"zod": "3.24.2",
|
|
27
27
|
"zod-validation-error": "3.4.0"
|
|
@@ -26,6 +26,8 @@ import type {
|
|
|
26
26
|
CartSetCustomTypeAction,
|
|
27
27
|
CartSetCustomerEmailAction,
|
|
28
28
|
CartSetDirectDiscountsAction,
|
|
29
|
+
CartSetLineItemCustomFieldAction,
|
|
30
|
+
CartSetLineItemCustomTypeAction,
|
|
29
31
|
CartSetLineItemShippingDetailsAction,
|
|
30
32
|
CartSetLocaleAction,
|
|
31
33
|
CartSetShippingAddressAction,
|
|
@@ -662,6 +664,82 @@ export class CartUpdateHandler
|
|
|
662
664
|
);
|
|
663
665
|
}
|
|
664
666
|
|
|
667
|
+
setLineItemCustomField(
|
|
668
|
+
context: RepositoryContext,
|
|
669
|
+
resource: Writable<Cart>,
|
|
670
|
+
{
|
|
671
|
+
lineItemId,
|
|
672
|
+
lineItemKey,
|
|
673
|
+
name,
|
|
674
|
+
value,
|
|
675
|
+
action,
|
|
676
|
+
}: CartSetLineItemCustomFieldAction,
|
|
677
|
+
) {
|
|
678
|
+
const lineItem = resource.lineItems.find(
|
|
679
|
+
(x) =>
|
|
680
|
+
(lineItemId && x.id === lineItemId) ||
|
|
681
|
+
(lineItemKey && x.key === lineItemKey),
|
|
682
|
+
);
|
|
683
|
+
|
|
684
|
+
if (!lineItem) {
|
|
685
|
+
// Check if line item is found
|
|
686
|
+
throw new CommercetoolsError<GeneralError>({
|
|
687
|
+
code: "General",
|
|
688
|
+
message: lineItemKey
|
|
689
|
+
? `A line item with key '${lineItemKey}' not found.`
|
|
690
|
+
: `A line item with ID '${lineItemId}' not found.`,
|
|
691
|
+
});
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
if (!lineItem.custom) {
|
|
695
|
+
throw new Error("Resource has no custom field");
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
lineItem.custom.fields[name] = value;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
setLineItemCustomType(
|
|
702
|
+
context: RepositoryContext,
|
|
703
|
+
resource: Writable<Cart>,
|
|
704
|
+
{ lineItemId, lineItemKey, type, fields }: CartSetLineItemCustomTypeAction,
|
|
705
|
+
) {
|
|
706
|
+
const lineItem = resource.lineItems.find(
|
|
707
|
+
(x) =>
|
|
708
|
+
(lineItemId && x.id === lineItemId) ||
|
|
709
|
+
(lineItemKey && x.key === lineItemKey),
|
|
710
|
+
);
|
|
711
|
+
|
|
712
|
+
if (!lineItem) {
|
|
713
|
+
// Check if line item is found
|
|
714
|
+
throw new CommercetoolsError<GeneralError>({
|
|
715
|
+
code: "General",
|
|
716
|
+
message: lineItemKey
|
|
717
|
+
? `A line item with key '${lineItemKey}' not found.`
|
|
718
|
+
: `A line item with ID '${lineItemId}' not found.`,
|
|
719
|
+
});
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
if (!type) {
|
|
723
|
+
lineItem.custom = undefined;
|
|
724
|
+
} else {
|
|
725
|
+
const resolvedType = this._storage.getByResourceIdentifier(
|
|
726
|
+
context.projectKey,
|
|
727
|
+
type,
|
|
728
|
+
);
|
|
729
|
+
if (!resolvedType) {
|
|
730
|
+
throw new Error(`Type ${type} not found`);
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
lineItem.custom = {
|
|
734
|
+
type: {
|
|
735
|
+
typeId: "type",
|
|
736
|
+
id: resolvedType.id,
|
|
737
|
+
},
|
|
738
|
+
fields: fields || {},
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
|
|
665
743
|
setLineItemShippingDetails(
|
|
666
744
|
context: RepositoryContext,
|
|
667
745
|
resource: Writable<Cart>,
|
|
@@ -23,19 +23,16 @@ import { v4 as uuidv4 } from "uuid";
|
|
|
23
23
|
import type { Config } from "~src/config";
|
|
24
24
|
import { CommercetoolsError } from "~src/exceptions";
|
|
25
25
|
import { getBaseResourceProperties } from "~src/helpers";
|
|
26
|
-
import {
|
|
26
|
+
import {
|
|
27
|
+
createShippingInfoFromMethod,
|
|
28
|
+
getShippingMethodsMatchingCart,
|
|
29
|
+
} from "~src/shipping";
|
|
27
30
|
import type { Writable } from "~src/types";
|
|
28
31
|
import {
|
|
29
32
|
AbstractResourceRepository,
|
|
30
33
|
type RepositoryContext,
|
|
31
34
|
} from "../abstract";
|
|
32
|
-
import {
|
|
33
|
-
createAddress,
|
|
34
|
-
createCentPrecisionMoney,
|
|
35
|
-
createCustomFields,
|
|
36
|
-
createTypedMoney,
|
|
37
|
-
roundDecimal,
|
|
38
|
-
} from "../helpers";
|
|
35
|
+
import { createAddress, createCustomFields } from "../helpers";
|
|
39
36
|
import { CartUpdateHandler } from "./actions";
|
|
40
37
|
import {
|
|
41
38
|
calculateCartTotalPrice,
|
|
@@ -284,15 +281,6 @@ export class CartRepository extends AbstractResourceRepository<"cart"> {
|
|
|
284
281
|
throw new Error("External tax rate is not supported");
|
|
285
282
|
}
|
|
286
283
|
|
|
287
|
-
const country = resource.shippingAddress?.country;
|
|
288
|
-
|
|
289
|
-
if (!country) {
|
|
290
|
-
throw new CommercetoolsError<InvalidOperationError>({
|
|
291
|
-
code: "InvalidOperation",
|
|
292
|
-
message: `The cart with ID '${resource.id}' does not have a shipping address set.`,
|
|
293
|
-
});
|
|
294
|
-
}
|
|
295
|
-
|
|
296
284
|
// Bit of a hack: calling this checks that the resource identifier is
|
|
297
285
|
// valid (i.e. id xor key) and that the shipping method exists.
|
|
298
286
|
this._storage.getByResourceIdentifier<"shipping-method">(
|
|
@@ -327,126 +315,12 @@ export class CartRepository extends AbstractResourceRepository<"cart"> {
|
|
|
327
315
|
});
|
|
328
316
|
}
|
|
329
317
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
const taxRate = taxCategory.rates.find((rate) => rate.country === country);
|
|
337
|
-
|
|
338
|
-
if (!taxRate) {
|
|
339
|
-
throw new CommercetoolsError<MissingTaxRateForCountryError>({
|
|
340
|
-
code: "MissingTaxRateForCountry",
|
|
341
|
-
message: `Tax category '${taxCategory.id}' is missing a tax rate for country '${country}'.`,
|
|
342
|
-
taxCategoryId: taxCategory.id,
|
|
343
|
-
});
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
// There should only be one zone rate matching the address, since
|
|
347
|
-
// Locations cannot be assigned to more than one zone.
|
|
348
|
-
// See https://docs.commercetools.com/api/projects/zones#location
|
|
349
|
-
const zoneRate = method.zoneRates.find((rate) =>
|
|
350
|
-
rate.zone.obj?.locations.some((loc) => loc.country === country),
|
|
318
|
+
// Use the shared shipping info creation logic
|
|
319
|
+
return createShippingInfoFromMethod(
|
|
320
|
+
context,
|
|
321
|
+
this._storage,
|
|
322
|
+
resource,
|
|
323
|
+
method,
|
|
351
324
|
);
|
|
352
|
-
|
|
353
|
-
if (!zoneRate) {
|
|
354
|
-
// This shouldn't happen because getShippingMethodsMatchingCart already
|
|
355
|
-
// filtered out shipping methods without any zones matching the address
|
|
356
|
-
throw new Error("Zone rate not found");
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
// Shipping rates are defined by currency, and getShippingMethodsMatchingCart
|
|
360
|
-
// also matches on currency, so there should only be one in the array.
|
|
361
|
-
// See https://docs.commercetools.com/api/projects/shippingMethods#zonerate
|
|
362
|
-
const shippingRate = zoneRate.shippingRates[0];
|
|
363
|
-
if (!shippingRate) {
|
|
364
|
-
// This shouldn't happen because getShippingMethodsMatchingCart already
|
|
365
|
-
// filtered out shipping methods without any matching rates
|
|
366
|
-
throw new Error("Shipping rate not found");
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
const shippingRateTier = shippingRate.tiers.find((tier) => tier.isMatching);
|
|
370
|
-
if (shippingRateTier && shippingRateTier.type !== "CartValue") {
|
|
371
|
-
throw new Error("Non-CartValue shipping rate tier is not supported");
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
let shippingPrice = shippingRateTier
|
|
375
|
-
? createCentPrecisionMoney(shippingRateTier.price)
|
|
376
|
-
: shippingRate.price;
|
|
377
|
-
|
|
378
|
-
// Handle freeAbove: if cart total is above the freeAbove threshold, shipping is free
|
|
379
|
-
if (
|
|
380
|
-
shippingRate.freeAbove &&
|
|
381
|
-
shippingRate.freeAbove.currencyCode ===
|
|
382
|
-
resource.totalPrice.currencyCode &&
|
|
383
|
-
resource.totalPrice.centAmount >= shippingRate.freeAbove.centAmount
|
|
384
|
-
) {
|
|
385
|
-
shippingPrice = {
|
|
386
|
-
...shippingPrice,
|
|
387
|
-
centAmount: 0,
|
|
388
|
-
};
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
// Calculate tax amounts
|
|
392
|
-
const totalGross: CentPrecisionMoney = taxRate.includedInPrice
|
|
393
|
-
? shippingPrice
|
|
394
|
-
: {
|
|
395
|
-
...shippingPrice,
|
|
396
|
-
centAmount: roundDecimal(
|
|
397
|
-
new Decimal(shippingPrice.centAmount).mul(1 + taxRate.amount),
|
|
398
|
-
resource.taxRoundingMode,
|
|
399
|
-
).toNumber(),
|
|
400
|
-
};
|
|
401
|
-
|
|
402
|
-
const totalNet: CentPrecisionMoney = taxRate.includedInPrice
|
|
403
|
-
? {
|
|
404
|
-
...shippingPrice,
|
|
405
|
-
centAmount: roundDecimal(
|
|
406
|
-
new Decimal(shippingPrice.centAmount).div(1 + taxRate.amount),
|
|
407
|
-
resource.taxRoundingMode,
|
|
408
|
-
).toNumber(),
|
|
409
|
-
}
|
|
410
|
-
: shippingPrice;
|
|
411
|
-
|
|
412
|
-
const taxPortions: TaxPortion[] = [
|
|
413
|
-
{
|
|
414
|
-
name: taxRate.name,
|
|
415
|
-
rate: taxRate.amount,
|
|
416
|
-
amount: {
|
|
417
|
-
...shippingPrice,
|
|
418
|
-
centAmount: totalGross.centAmount - totalNet.centAmount,
|
|
419
|
-
},
|
|
420
|
-
},
|
|
421
|
-
];
|
|
422
|
-
|
|
423
|
-
const totalTax: CentPrecisionMoney = {
|
|
424
|
-
...shippingPrice,
|
|
425
|
-
centAmount: taxPortions.reduce(
|
|
426
|
-
(acc, portion) => acc + portion.amount.centAmount,
|
|
427
|
-
0,
|
|
428
|
-
),
|
|
429
|
-
};
|
|
430
|
-
|
|
431
|
-
const taxedPrice: TaxedItemPrice = {
|
|
432
|
-
totalNet,
|
|
433
|
-
totalGross,
|
|
434
|
-
taxPortions,
|
|
435
|
-
totalTax,
|
|
436
|
-
};
|
|
437
|
-
|
|
438
|
-
return {
|
|
439
|
-
shippingMethod: {
|
|
440
|
-
typeId: "shipping-method" as const,
|
|
441
|
-
id: method.id,
|
|
442
|
-
},
|
|
443
|
-
shippingMethodName: method.name,
|
|
444
|
-
price: shippingPrice,
|
|
445
|
-
shippingRate,
|
|
446
|
-
taxedPrice,
|
|
447
|
-
taxRate,
|
|
448
|
-
taxCategory: method.taxCategory,
|
|
449
|
-
shippingMethodState: "MatchesCart",
|
|
450
|
-
};
|
|
451
325
|
}
|
|
452
326
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
CustomLineItemReturnItem,
|
|
3
|
+
GeneralError,
|
|
3
4
|
LineItemReturnItem,
|
|
4
5
|
Order,
|
|
5
6
|
OrderAddPaymentAction,
|
|
@@ -9,10 +10,13 @@ import type {
|
|
|
9
10
|
OrderChangeShipmentStateAction,
|
|
10
11
|
OrderSetBillingAddressAction,
|
|
11
12
|
OrderSetCustomFieldAction,
|
|
13
|
+
OrderSetCustomLineItemCustomTypeAction,
|
|
12
14
|
OrderSetCustomTypeAction,
|
|
13
15
|
OrderSetCustomerEmailAction,
|
|
14
16
|
OrderSetCustomerIdAction,
|
|
15
17
|
OrderSetDeliveryCustomFieldAction,
|
|
18
|
+
OrderSetLineItemCustomFieldAction,
|
|
19
|
+
OrderSetLineItemCustomTypeAction,
|
|
16
20
|
OrderSetLocaleAction,
|
|
17
21
|
OrderSetOrderNumberAction,
|
|
18
22
|
OrderSetParcelCustomFieldAction,
|
|
@@ -27,6 +31,7 @@ import type {
|
|
|
27
31
|
Store,
|
|
28
32
|
SyncInfo,
|
|
29
33
|
} from "@commercetools/platform-sdk";
|
|
34
|
+
import { CommercetoolsError } from "~src/exceptions";
|
|
30
35
|
import { getBaseResourceProperties } from "~src/helpers";
|
|
31
36
|
import type { Writable } from "~src/types";
|
|
32
37
|
import type { RepositoryContext, UpdateHandlerInterface } from "../abstract";
|
|
@@ -205,6 +210,82 @@ export class OrderUpdateHandler
|
|
|
205
210
|
}
|
|
206
211
|
}
|
|
207
212
|
|
|
213
|
+
setLineItemCustomField(
|
|
214
|
+
context: RepositoryContext,
|
|
215
|
+
resource: Order,
|
|
216
|
+
{
|
|
217
|
+
lineItemId,
|
|
218
|
+
lineItemKey,
|
|
219
|
+
name,
|
|
220
|
+
value,
|
|
221
|
+
action,
|
|
222
|
+
}: OrderSetLineItemCustomFieldAction,
|
|
223
|
+
) {
|
|
224
|
+
const lineItem = resource.lineItems.find(
|
|
225
|
+
(x) =>
|
|
226
|
+
(lineItemId && x.id === lineItemId) ||
|
|
227
|
+
(lineItemKey && x.key === lineItemKey),
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
if (!lineItem) {
|
|
231
|
+
// Check if line item is found
|
|
232
|
+
throw new CommercetoolsError<GeneralError>({
|
|
233
|
+
code: "General",
|
|
234
|
+
message: lineItemKey
|
|
235
|
+
? `A line item with key '${lineItemKey}' not found.`
|
|
236
|
+
: `A line item with ID '${lineItemId}' not found.`,
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (!lineItem.custom) {
|
|
241
|
+
throw new Error("Resource has no custom field");
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
lineItem.custom.fields[name] = value;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
setLineItemCustomType(
|
|
248
|
+
context: RepositoryContext,
|
|
249
|
+
resource: Writable<Order>,
|
|
250
|
+
{ lineItemId, lineItemKey, type, fields }: OrderSetLineItemCustomTypeAction,
|
|
251
|
+
) {
|
|
252
|
+
const lineItem = resource.lineItems.find(
|
|
253
|
+
(x) =>
|
|
254
|
+
(lineItemId && x.id === lineItemId) ||
|
|
255
|
+
(lineItemKey && x.key === lineItemKey),
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
if (!lineItem) {
|
|
259
|
+
// Check if line item is found
|
|
260
|
+
throw new CommercetoolsError<GeneralError>({
|
|
261
|
+
code: "General",
|
|
262
|
+
message: lineItemKey
|
|
263
|
+
? `A line item with key '${lineItemKey}' not found.`
|
|
264
|
+
: `A line item with ID '${lineItemId}' not found.`,
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (!type) {
|
|
269
|
+
lineItem.custom = undefined;
|
|
270
|
+
} else {
|
|
271
|
+
const resolvedType = this._storage.getByResourceIdentifier(
|
|
272
|
+
context.projectKey,
|
|
273
|
+
type,
|
|
274
|
+
);
|
|
275
|
+
if (!resolvedType) {
|
|
276
|
+
throw new Error(`Type ${type} not found`);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
lineItem.custom = {
|
|
280
|
+
type: {
|
|
281
|
+
typeId: "type",
|
|
282
|
+
id: resolvedType.id,
|
|
283
|
+
},
|
|
284
|
+
fields: fields || {},
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
208
289
|
setLocale(
|
|
209
290
|
context: RepositoryContext,
|
|
210
291
|
resource: Writable<Order>,
|
|
@@ -2,6 +2,7 @@ import { beforeEach } from "node:test";
|
|
|
2
2
|
import type {
|
|
3
3
|
Cart,
|
|
4
4
|
LineItem,
|
|
5
|
+
Order,
|
|
5
6
|
OrderImportDraft,
|
|
6
7
|
} from "@commercetools/platform-sdk";
|
|
7
8
|
import { describe, expect, test } from "vitest";
|
|
@@ -187,6 +188,8 @@ describe("Order repository", () => {
|
|
|
187
188
|
expect(result.taxRoundingMode).toEqual(cart.taxRoundingMode);
|
|
188
189
|
expect(result.totalPrice).toEqual(cart.totalPrice);
|
|
189
190
|
expect(result.store).toEqual(cart.store);
|
|
191
|
+
// Test that shippingInfo is copied from cart to order
|
|
192
|
+
expect(result.shippingInfo).toEqual(cart.shippingInfo);
|
|
190
193
|
});
|
|
191
194
|
|
|
192
195
|
test("create order in store", async () => {
|
|
@@ -510,4 +513,308 @@ describe("Order repository", () => {
|
|
|
510
513
|
repository.import('dummy', draft)
|
|
511
514
|
})
|
|
512
515
|
*/
|
|
516
|
+
|
|
517
|
+
describe("shippingInfo functionality", () => {
|
|
518
|
+
test("createShippingInfo creates basic shipping info", () => {
|
|
519
|
+
// Create a zone for Netherlands
|
|
520
|
+
const zone = {
|
|
521
|
+
...getBaseResourceProperties(),
|
|
522
|
+
id: "zone-nl",
|
|
523
|
+
name: "Netherlands Zone",
|
|
524
|
+
locations: [
|
|
525
|
+
{
|
|
526
|
+
country: "NL",
|
|
527
|
+
},
|
|
528
|
+
],
|
|
529
|
+
};
|
|
530
|
+
|
|
531
|
+
// Create a shipping method first
|
|
532
|
+
const shippingMethod = {
|
|
533
|
+
...getBaseResourceProperties(),
|
|
534
|
+
id: "shipping-method-123",
|
|
535
|
+
name: "Express Shipping",
|
|
536
|
+
active: true,
|
|
537
|
+
isDefault: false,
|
|
538
|
+
taxCategory: {
|
|
539
|
+
typeId: "tax-category" as const,
|
|
540
|
+
id: "tax-category-123",
|
|
541
|
+
},
|
|
542
|
+
zoneRates: [
|
|
543
|
+
{
|
|
544
|
+
zone: {
|
|
545
|
+
typeId: "zone" as const,
|
|
546
|
+
id: "zone-nl",
|
|
547
|
+
obj: zone,
|
|
548
|
+
},
|
|
549
|
+
shippingRates: [
|
|
550
|
+
{
|
|
551
|
+
price: {
|
|
552
|
+
type: "centPrecision" as const,
|
|
553
|
+
currencyCode: "EUR",
|
|
554
|
+
centAmount: 500,
|
|
555
|
+
fractionDigits: 2,
|
|
556
|
+
},
|
|
557
|
+
tiers: [],
|
|
558
|
+
},
|
|
559
|
+
],
|
|
560
|
+
},
|
|
561
|
+
],
|
|
562
|
+
};
|
|
563
|
+
|
|
564
|
+
const taxCategory = {
|
|
565
|
+
...getBaseResourceProperties(),
|
|
566
|
+
id: "tax-category-123",
|
|
567
|
+
name: "Standard Tax",
|
|
568
|
+
rates: [
|
|
569
|
+
{
|
|
570
|
+
name: "Standard VAT",
|
|
571
|
+
amount: 0.21,
|
|
572
|
+
country: "NL",
|
|
573
|
+
includedInPrice: true,
|
|
574
|
+
},
|
|
575
|
+
],
|
|
576
|
+
};
|
|
577
|
+
|
|
578
|
+
storage.add("dummy", "zone", zone);
|
|
579
|
+
storage.add("dummy", "shipping-method", shippingMethod);
|
|
580
|
+
storage.add("dummy", "tax-category", taxCategory);
|
|
581
|
+
|
|
582
|
+
const order: Order = {
|
|
583
|
+
...getBaseResourceProperties(),
|
|
584
|
+
orderNumber: "order-123",
|
|
585
|
+
orderState: "Open",
|
|
586
|
+
origin: "Customer",
|
|
587
|
+
customLineItems: [],
|
|
588
|
+
lineItems: [],
|
|
589
|
+
totalPrice: {
|
|
590
|
+
type: "centPrecision",
|
|
591
|
+
currencyCode: "EUR",
|
|
592
|
+
centAmount: 1000,
|
|
593
|
+
fractionDigits: 2,
|
|
594
|
+
},
|
|
595
|
+
lastMessageSequenceNumber: 0,
|
|
596
|
+
refusedGifts: [],
|
|
597
|
+
shipping: [],
|
|
598
|
+
shippingMode: "Single",
|
|
599
|
+
shippingAddress: {
|
|
600
|
+
id: "address-123",
|
|
601
|
+
country: "NL",
|
|
602
|
+
firstName: "John",
|
|
603
|
+
lastName: "Doe",
|
|
604
|
+
streetName: "Main Street",
|
|
605
|
+
streetNumber: "123",
|
|
606
|
+
postalCode: "1234AB",
|
|
607
|
+
city: "Amsterdam",
|
|
608
|
+
},
|
|
609
|
+
syncInfo: [],
|
|
610
|
+
taxCalculationMode: "UnitPriceLevel",
|
|
611
|
+
taxMode: "Platform",
|
|
612
|
+
taxRoundingMode: "HalfEven",
|
|
613
|
+
};
|
|
614
|
+
|
|
615
|
+
const ctx = { projectKey: "dummy" };
|
|
616
|
+
const result = repository.createShippingInfo(ctx, order, {
|
|
617
|
+
typeId: "shipping-method",
|
|
618
|
+
id: "shipping-method-123",
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
expect(result).toBeDefined();
|
|
622
|
+
expect(result.shippingMethod?.id).toBe("shipping-method-123");
|
|
623
|
+
expect(result.shippingMethodName).toBe("Express Shipping");
|
|
624
|
+
expect(result.price.currencyCode).toBe("EUR");
|
|
625
|
+
expect(result.price.centAmount).toBe(500);
|
|
626
|
+
expect(result.shippingMethodState).toBe("MatchesCart");
|
|
627
|
+
expect(result.deliveries).toEqual([]);
|
|
628
|
+
expect(result.taxCategory?.id).toBe("tax-category-123");
|
|
629
|
+
});
|
|
630
|
+
|
|
631
|
+
test("import order with shippingInfo", () => {
|
|
632
|
+
// Create required resources
|
|
633
|
+
const zone = {
|
|
634
|
+
...getBaseResourceProperties(),
|
|
635
|
+
id: "zone-de",
|
|
636
|
+
name: "Germany Zone",
|
|
637
|
+
locations: [
|
|
638
|
+
{
|
|
639
|
+
country: "DE",
|
|
640
|
+
},
|
|
641
|
+
],
|
|
642
|
+
};
|
|
643
|
+
|
|
644
|
+
const shippingMethod = {
|
|
645
|
+
...getBaseResourceProperties(),
|
|
646
|
+
id: "shipping-method-456",
|
|
647
|
+
name: "Standard Shipping",
|
|
648
|
+
active: true,
|
|
649
|
+
isDefault: false,
|
|
650
|
+
taxCategory: {
|
|
651
|
+
typeId: "tax-category" as const,
|
|
652
|
+
id: "tax-category-456",
|
|
653
|
+
},
|
|
654
|
+
zoneRates: [
|
|
655
|
+
{
|
|
656
|
+
zone: {
|
|
657
|
+
typeId: "zone" as const,
|
|
658
|
+
id: "zone-de",
|
|
659
|
+
obj: zone,
|
|
660
|
+
},
|
|
661
|
+
shippingRates: [
|
|
662
|
+
{
|
|
663
|
+
price: {
|
|
664
|
+
type: "centPrecision" as const,
|
|
665
|
+
currencyCode: "EUR",
|
|
666
|
+
centAmount: 500,
|
|
667
|
+
fractionDigits: 2,
|
|
668
|
+
},
|
|
669
|
+
tiers: [],
|
|
670
|
+
},
|
|
671
|
+
],
|
|
672
|
+
},
|
|
673
|
+
],
|
|
674
|
+
};
|
|
675
|
+
|
|
676
|
+
const taxCategory = {
|
|
677
|
+
...getBaseResourceProperties(),
|
|
678
|
+
id: "tax-category-456",
|
|
679
|
+
name: "Standard Tax",
|
|
680
|
+
rates: [
|
|
681
|
+
{
|
|
682
|
+
name: "Standard VAT",
|
|
683
|
+
amount: 0.19,
|
|
684
|
+
country: "DE",
|
|
685
|
+
includedInPrice: true,
|
|
686
|
+
},
|
|
687
|
+
],
|
|
688
|
+
};
|
|
689
|
+
|
|
690
|
+
storage.add("dummy", "zone", zone);
|
|
691
|
+
storage.add("dummy", "shipping-method", shippingMethod);
|
|
692
|
+
storage.add("dummy", "tax-category", taxCategory);
|
|
693
|
+
|
|
694
|
+
const draft: OrderImportDraft = {
|
|
695
|
+
orderNumber: "imported-order-123",
|
|
696
|
+
totalPrice: {
|
|
697
|
+
currencyCode: "EUR",
|
|
698
|
+
centAmount: 2000,
|
|
699
|
+
},
|
|
700
|
+
shippingAddress: {
|
|
701
|
+
country: "DE",
|
|
702
|
+
firstName: "Max",
|
|
703
|
+
lastName: "Mustermann",
|
|
704
|
+
streetName: "Hauptstraße",
|
|
705
|
+
streetNumber: "1",
|
|
706
|
+
postalCode: "10115",
|
|
707
|
+
city: "Berlin",
|
|
708
|
+
},
|
|
709
|
+
shippingInfo: {
|
|
710
|
+
shippingMethodName: "Standard Shipping",
|
|
711
|
+
price: {
|
|
712
|
+
currencyCode: "EUR",
|
|
713
|
+
centAmount: 500,
|
|
714
|
+
},
|
|
715
|
+
shippingRate: {
|
|
716
|
+
price: {
|
|
717
|
+
currencyCode: "EUR",
|
|
718
|
+
centAmount: 500,
|
|
719
|
+
},
|
|
720
|
+
tiers: [],
|
|
721
|
+
},
|
|
722
|
+
shippingMethod: {
|
|
723
|
+
typeId: "shipping-method",
|
|
724
|
+
id: "shipping-method-456",
|
|
725
|
+
},
|
|
726
|
+
taxCategory: {
|
|
727
|
+
typeId: "tax-category",
|
|
728
|
+
id: "tax-category-456",
|
|
729
|
+
},
|
|
730
|
+
taxRate: {
|
|
731
|
+
name: "Standard VAT",
|
|
732
|
+
amount: 0.19,
|
|
733
|
+
country: "DE",
|
|
734
|
+
includedInPrice: true,
|
|
735
|
+
},
|
|
736
|
+
shippingMethodState: "MatchesCart",
|
|
737
|
+
deliveries: [
|
|
738
|
+
{
|
|
739
|
+
key: "delivery-1",
|
|
740
|
+
items: [],
|
|
741
|
+
parcels: [
|
|
742
|
+
{
|
|
743
|
+
key: "parcel-1",
|
|
744
|
+
measurements: {
|
|
745
|
+
heightInMillimeter: 100,
|
|
746
|
+
lengthInMillimeter: 200,
|
|
747
|
+
widthInMillimeter: 150,
|
|
748
|
+
weightInGram: 500,
|
|
749
|
+
},
|
|
750
|
+
items: [],
|
|
751
|
+
},
|
|
752
|
+
],
|
|
753
|
+
},
|
|
754
|
+
],
|
|
755
|
+
},
|
|
756
|
+
};
|
|
757
|
+
|
|
758
|
+
const ctx = { projectKey: "dummy" };
|
|
759
|
+
const result = repository.import(ctx, draft);
|
|
760
|
+
|
|
761
|
+
expect(result.shippingInfo).toBeDefined();
|
|
762
|
+
expect(result.shippingInfo?.shippingMethodName).toBe("Standard Shipping");
|
|
763
|
+
expect(result.shippingInfo?.price.centAmount).toBe(500);
|
|
764
|
+
expect(result.shippingInfo?.shippingMethod?.id).toBe(
|
|
765
|
+
"shipping-method-456",
|
|
766
|
+
);
|
|
767
|
+
expect(result.shippingInfo?.taxCategory?.id).toBe("tax-category-456");
|
|
768
|
+
expect(result.shippingInfo?.taxRate?.amount).toBe(0.19);
|
|
769
|
+
// Note: deliveries from import drafts are not currently supported in native implementation
|
|
770
|
+
expect(result.shippingInfo?.deliveries).toEqual([]);
|
|
771
|
+
});
|
|
772
|
+
|
|
773
|
+
test("createShippingInfo throws error for non-existent shipping method", () => {
|
|
774
|
+
const order: Order = {
|
|
775
|
+
...getBaseResourceProperties(),
|
|
776
|
+
orderNumber: "order-456",
|
|
777
|
+
orderState: "Open",
|
|
778
|
+
origin: "Customer",
|
|
779
|
+
customLineItems: [],
|
|
780
|
+
lineItems: [],
|
|
781
|
+
totalPrice: {
|
|
782
|
+
type: "centPrecision",
|
|
783
|
+
currencyCode: "USD",
|
|
784
|
+
centAmount: 1500,
|
|
785
|
+
fractionDigits: 2,
|
|
786
|
+
},
|
|
787
|
+
lastMessageSequenceNumber: 0,
|
|
788
|
+
refusedGifts: [],
|
|
789
|
+
shipping: [],
|
|
790
|
+
shippingMode: "Single",
|
|
791
|
+
shippingAddress: {
|
|
792
|
+
id: "address-456",
|
|
793
|
+
country: "US",
|
|
794
|
+
firstName: "Jane",
|
|
795
|
+
lastName: "Smith",
|
|
796
|
+
streetName: "Broadway",
|
|
797
|
+
streetNumber: "456",
|
|
798
|
+
postalCode: "10001",
|
|
799
|
+
city: "New York",
|
|
800
|
+
state: "NY",
|
|
801
|
+
},
|
|
802
|
+
syncInfo: [],
|
|
803
|
+
taxCalculationMode: "UnitPriceLevel",
|
|
804
|
+
taxMode: "Platform",
|
|
805
|
+
taxRoundingMode: "HalfEven",
|
|
806
|
+
};
|
|
807
|
+
|
|
808
|
+
const ctx = { projectKey: "dummy" };
|
|
809
|
+
|
|
810
|
+
expect(() => {
|
|
811
|
+
repository.createShippingInfo(ctx, order, {
|
|
812
|
+
typeId: "shipping-method",
|
|
813
|
+
id: "non-existent-shipping-method",
|
|
814
|
+
});
|
|
815
|
+
}).toThrow(
|
|
816
|
+
/The shipping method with ID 'non-existent-shipping-method' is not allowed/,
|
|
817
|
+
);
|
|
818
|
+
});
|
|
819
|
+
});
|
|
513
820
|
});
|