@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/dist/index.js
CHANGED
|
@@ -8,7 +8,8 @@ import auth from "basic-auth";
|
|
|
8
8
|
import bodyParser from "body-parser";
|
|
9
9
|
import { randomBytes } from "node:crypto";
|
|
10
10
|
import { isDeepStrictEqual } from "node:util";
|
|
11
|
-
import { Decimal } from "decimal.js
|
|
11
|
+
import { Decimal } from "decimal.js";
|
|
12
|
+
import { Decimal as Decimal$1 } from "decimal.js/decimal";
|
|
12
13
|
import assert from "node:assert";
|
|
13
14
|
import { z } from "zod";
|
|
14
15
|
import { fromZodError } from "zod-validation-error";
|
|
@@ -521,70 +522,6 @@ var ProductTailoringUpdateHandler = class extends AbstractUpdateHandler {
|
|
|
521
522
|
}
|
|
522
523
|
};
|
|
523
524
|
|
|
524
|
-
//#endregion
|
|
525
|
-
//#region src/shipping.ts
|
|
526
|
-
const markMatchingShippingRate = (cart, shippingRate) => {
|
|
527
|
-
const isMatching = shippingRate.price.currencyCode === cart.totalPrice.currencyCode;
|
|
528
|
-
return {
|
|
529
|
-
...shippingRate,
|
|
530
|
-
tiers: markMatchingShippingRatePriceTiers(cart, shippingRate.tiers),
|
|
531
|
-
isMatching
|
|
532
|
-
};
|
|
533
|
-
};
|
|
534
|
-
const markMatchingShippingRatePriceTiers = (cart, tiers) => {
|
|
535
|
-
if (tiers.length === 0) return [];
|
|
536
|
-
if (new Set(tiers.map((tier) => tier.type)).size > 1) throw new Error("Can't handle multiple types of tiers");
|
|
537
|
-
const tierType = tiers[0].type;
|
|
538
|
-
switch (tierType) {
|
|
539
|
-
case "CartValue": return markMatchingCartValueTiers(cart, tiers);
|
|
540
|
-
default: throw new Error(`Unsupported tier type: ${tierType}`);
|
|
541
|
-
}
|
|
542
|
-
};
|
|
543
|
-
const markMatchingCartValueTiers = (cart, tiers) => {
|
|
544
|
-
const sortedTiers = [...tiers].sort((a, b) => b.minimumCentAmount - a.minimumCentAmount);
|
|
545
|
-
const result = {};
|
|
546
|
-
let hasMatchingTier = false;
|
|
547
|
-
for (const tier of sortedTiers) {
|
|
548
|
-
const isMatching = !hasMatchingTier && cart.totalPrice.currencyCode === tier.price.currencyCode && cart.totalPrice.centAmount >= tier.minimumCentAmount;
|
|
549
|
-
if (isMatching) hasMatchingTier = true;
|
|
550
|
-
result[tier.minimumCentAmount] = {
|
|
551
|
-
...tier,
|
|
552
|
-
isMatching
|
|
553
|
-
};
|
|
554
|
-
}
|
|
555
|
-
return tiers.map((tier) => result[tier.minimumCentAmount]);
|
|
556
|
-
};
|
|
557
|
-
const getShippingMethodsMatchingCart = (context, storage, cart, params = {}) => {
|
|
558
|
-
if (!cart.shippingAddress?.country) throw new CommercetoolsError({
|
|
559
|
-
code: "InvalidOperation",
|
|
560
|
-
message: `The cart with ID '${cart.id}' does not have a shipping address set.`
|
|
561
|
-
});
|
|
562
|
-
const zones = storage.query(context.projectKey, "zone", {
|
|
563
|
-
where: [`locations(country="${cart.shippingAddress.country}"))`],
|
|
564
|
-
limit: 100
|
|
565
|
-
});
|
|
566
|
-
const zoneIds = zones.results.map((zone) => zone.id);
|
|
567
|
-
const shippingMethods = storage.query(context.projectKey, "shipping-method", {
|
|
568
|
-
where: ["zoneRates(zone(id in (:zoneIds)))", `zoneRates(shippingRates(price(currencyCode="${cart.totalPrice.currencyCode}")))`],
|
|
569
|
-
"var.zoneIds": zoneIds,
|
|
570
|
-
expand: params.expand
|
|
571
|
-
});
|
|
572
|
-
const results = shippingMethods.results.map((shippingMethod) => {
|
|
573
|
-
const rates = shippingMethod.zoneRates.map((zoneRate) => ({
|
|
574
|
-
zone: zoneRate.zone,
|
|
575
|
-
shippingRates: zoneRate.shippingRates.map((rate) => markMatchingShippingRate(cart, rate)).filter((rate) => rate.isMatching)
|
|
576
|
-
})).filter((zoneRate) => zoneRate.shippingRates.length > 0);
|
|
577
|
-
return {
|
|
578
|
-
...shippingMethod,
|
|
579
|
-
zoneRates: rates
|
|
580
|
-
};
|
|
581
|
-
}).filter((shippingMethod) => shippingMethod.zoneRates.length > 0);
|
|
582
|
-
return {
|
|
583
|
-
...shippingMethods,
|
|
584
|
-
results
|
|
585
|
-
};
|
|
586
|
-
};
|
|
587
|
-
|
|
588
525
|
//#endregion
|
|
589
526
|
//#region src/repositories/helpers.ts
|
|
590
527
|
const createAddress = (base, projectKey, storage) => {
|
|
@@ -618,9 +555,9 @@ const createPrice = (draft) => ({
|
|
|
618
555
|
*/
|
|
619
556
|
const roundDecimal = (decimal, roundingMode) => {
|
|
620
557
|
switch (roundingMode) {
|
|
621
|
-
case "HalfEven": return decimal.toDecimalPlaces(0, Decimal.ROUND_HALF_EVEN);
|
|
622
|
-
case "HalfUp": return decimal.toDecimalPlaces(0, Decimal.ROUND_HALF_UP);
|
|
623
|
-
case "HalfDown": return decimal.toDecimalPlaces(0, Decimal.ROUND_HALF_DOWN);
|
|
558
|
+
case "HalfEven": return decimal.toDecimalPlaces(0, Decimal$1.ROUND_HALF_EVEN);
|
|
559
|
+
case "HalfUp": return decimal.toDecimalPlaces(0, Decimal$1.ROUND_HALF_UP);
|
|
560
|
+
case "HalfDown": return decimal.toDecimalPlaces(0, Decimal$1.ROUND_HALF_DOWN);
|
|
624
561
|
default: throw new Error(`Unknown rounding mode: ${roundingMode}`);
|
|
625
562
|
}
|
|
626
563
|
};
|
|
@@ -749,6 +686,133 @@ const getBusinessUnitKeyReference = (id, projectKey, storage) => {
|
|
|
749
686
|
};
|
|
750
687
|
};
|
|
751
688
|
|
|
689
|
+
//#endregion
|
|
690
|
+
//#region src/shipping.ts
|
|
691
|
+
const markMatchingShippingRate = (cart, shippingRate) => {
|
|
692
|
+
const isMatching = shippingRate.price.currencyCode === cart.totalPrice.currencyCode;
|
|
693
|
+
return {
|
|
694
|
+
...shippingRate,
|
|
695
|
+
tiers: markMatchingShippingRatePriceTiers(cart, shippingRate.tiers),
|
|
696
|
+
isMatching
|
|
697
|
+
};
|
|
698
|
+
};
|
|
699
|
+
const markMatchingShippingRatePriceTiers = (cart, tiers) => {
|
|
700
|
+
if (tiers.length === 0) return [];
|
|
701
|
+
if (new Set(tiers.map((tier) => tier.type)).size > 1) throw new Error("Can't handle multiple types of tiers");
|
|
702
|
+
const tierType = tiers[0].type;
|
|
703
|
+
switch (tierType) {
|
|
704
|
+
case "CartValue": return markMatchingCartValueTiers(cart, tiers);
|
|
705
|
+
default: throw new Error(`Unsupported tier type: ${tierType}`);
|
|
706
|
+
}
|
|
707
|
+
};
|
|
708
|
+
const markMatchingCartValueTiers = (cart, tiers) => {
|
|
709
|
+
const sortedTiers = [...tiers].sort((a, b) => b.minimumCentAmount - a.minimumCentAmount);
|
|
710
|
+
const result = {};
|
|
711
|
+
let hasMatchingTier = false;
|
|
712
|
+
for (const tier of sortedTiers) {
|
|
713
|
+
const isMatching = !hasMatchingTier && cart.totalPrice.currencyCode === tier.price.currencyCode && cart.totalPrice.centAmount >= tier.minimumCentAmount;
|
|
714
|
+
if (isMatching) hasMatchingTier = true;
|
|
715
|
+
result[tier.minimumCentAmount] = {
|
|
716
|
+
...tier,
|
|
717
|
+
isMatching
|
|
718
|
+
};
|
|
719
|
+
}
|
|
720
|
+
return tiers.map((tier) => result[tier.minimumCentAmount]);
|
|
721
|
+
};
|
|
722
|
+
const getShippingMethodsMatchingCart = (context, storage, cart, params = {}) => {
|
|
723
|
+
if (!cart.shippingAddress?.country) throw new CommercetoolsError({
|
|
724
|
+
code: "InvalidOperation",
|
|
725
|
+
message: `The cart with ID '${cart.id}' does not have a shipping address set.`
|
|
726
|
+
});
|
|
727
|
+
const zones = storage.query(context.projectKey, "zone", {
|
|
728
|
+
where: [`locations(country="${cart.shippingAddress.country}"))`],
|
|
729
|
+
limit: 100
|
|
730
|
+
});
|
|
731
|
+
const zoneIds = zones.results.map((zone) => zone.id);
|
|
732
|
+
const shippingMethods = storage.query(context.projectKey, "shipping-method", {
|
|
733
|
+
where: ["zoneRates(zone(id in (:zoneIds)))", `zoneRates(shippingRates(price(currencyCode="${cart.totalPrice.currencyCode}")))`],
|
|
734
|
+
"var.zoneIds": zoneIds,
|
|
735
|
+
expand: params.expand
|
|
736
|
+
});
|
|
737
|
+
const results = shippingMethods.results.map((shippingMethod) => {
|
|
738
|
+
const rates = shippingMethod.zoneRates.map((zoneRate) => ({
|
|
739
|
+
zone: zoneRate.zone,
|
|
740
|
+
shippingRates: zoneRate.shippingRates.map((rate) => markMatchingShippingRate(cart, rate)).filter((rate) => rate.isMatching)
|
|
741
|
+
})).filter((zoneRate) => zoneRate.shippingRates.length > 0);
|
|
742
|
+
return {
|
|
743
|
+
...shippingMethod,
|
|
744
|
+
zoneRates: rates
|
|
745
|
+
};
|
|
746
|
+
}).filter((shippingMethod) => shippingMethod.zoneRates.length > 0);
|
|
747
|
+
return {
|
|
748
|
+
...shippingMethods,
|
|
749
|
+
results
|
|
750
|
+
};
|
|
751
|
+
};
|
|
752
|
+
/**
|
|
753
|
+
* Creates shipping info from a shipping method, handling all tax calculations and pricing logic.
|
|
754
|
+
*/
|
|
755
|
+
const createShippingInfoFromMethod = (context, storage, resource, method) => {
|
|
756
|
+
const country = resource.shippingAddress.country;
|
|
757
|
+
const zoneRate = method.zoneRates.find((rate) => rate.zone.obj?.locations.some((loc) => loc.country === country));
|
|
758
|
+
if (!zoneRate) throw new Error("Zone rate not found");
|
|
759
|
+
const shippingRate = zoneRate.shippingRates[0];
|
|
760
|
+
if (!shippingRate) throw new Error("Shipping rate not found");
|
|
761
|
+
const taxCategory = storage.getByResourceIdentifier(context.projectKey, method.taxCategory);
|
|
762
|
+
const taxRate = taxCategory.rates.find((rate) => rate.country === country);
|
|
763
|
+
if (!taxRate) throw new CommercetoolsError({
|
|
764
|
+
code: "MissingTaxRateForCountry",
|
|
765
|
+
message: `Tax category '${taxCategory.id}' is missing a tax rate for country '${country}'.`,
|
|
766
|
+
taxCategoryId: taxCategory.id
|
|
767
|
+
});
|
|
768
|
+
const shippingRateTier = shippingRate.tiers.find((tier) => tier.isMatching);
|
|
769
|
+
if (shippingRateTier && shippingRateTier.type !== "CartValue") throw new Error("Non-CartValue shipping rate tier is not supported");
|
|
770
|
+
let shippingPrice = shippingRateTier ? createCentPrecisionMoney(shippingRateTier.price) : shippingRate.price;
|
|
771
|
+
if (shippingRate.freeAbove && shippingRate.freeAbove.currencyCode === resource.totalPrice.currencyCode && resource.totalPrice.centAmount >= shippingRate.freeAbove.centAmount) shippingPrice = {
|
|
772
|
+
...shippingPrice,
|
|
773
|
+
centAmount: 0
|
|
774
|
+
};
|
|
775
|
+
const totalGross = taxRate.includedInPrice ? shippingPrice : {
|
|
776
|
+
...shippingPrice,
|
|
777
|
+
centAmount: roundDecimal(new Decimal(shippingPrice.centAmount).mul(1 + taxRate.amount), resource.taxRoundingMode || "HalfEven").toNumber()
|
|
778
|
+
};
|
|
779
|
+
const totalNet = taxRate.includedInPrice ? {
|
|
780
|
+
...shippingPrice,
|
|
781
|
+
centAmount: roundDecimal(new Decimal(shippingPrice.centAmount).div(1 + taxRate.amount), resource.taxRoundingMode || "HalfEven").toNumber()
|
|
782
|
+
} : shippingPrice;
|
|
783
|
+
const taxPortions = [{
|
|
784
|
+
name: taxRate.name,
|
|
785
|
+
rate: taxRate.amount,
|
|
786
|
+
amount: {
|
|
787
|
+
...shippingPrice,
|
|
788
|
+
centAmount: totalGross.centAmount - totalNet.centAmount
|
|
789
|
+
}
|
|
790
|
+
}];
|
|
791
|
+
const totalTax = {
|
|
792
|
+
...shippingPrice,
|
|
793
|
+
centAmount: taxPortions.reduce((acc, portion) => acc + portion.amount.centAmount, 0)
|
|
794
|
+
};
|
|
795
|
+
const taxedPrice = {
|
|
796
|
+
totalNet,
|
|
797
|
+
totalGross,
|
|
798
|
+
taxPortions,
|
|
799
|
+
totalTax
|
|
800
|
+
};
|
|
801
|
+
return {
|
|
802
|
+
shippingMethod: {
|
|
803
|
+
typeId: "shipping-method",
|
|
804
|
+
id: method.id
|
|
805
|
+
},
|
|
806
|
+
shippingMethodName: method.name,
|
|
807
|
+
price: shippingPrice,
|
|
808
|
+
shippingRate,
|
|
809
|
+
taxedPrice,
|
|
810
|
+
taxRate,
|
|
811
|
+
taxCategory: method.taxCategory,
|
|
812
|
+
shippingMethodState: "MatchesCart"
|
|
813
|
+
};
|
|
814
|
+
};
|
|
815
|
+
|
|
752
816
|
//#endregion
|
|
753
817
|
//#region src/repositories/cart/helpers.ts
|
|
754
818
|
const selectPrice = ({ prices, currency, country }) => {
|
|
@@ -1136,6 +1200,34 @@ var CartUpdateHandler = class extends AbstractUpdateHandler {
|
|
|
1136
1200
|
id: v4()
|
|
1137
1201
|
}));
|
|
1138
1202
|
}
|
|
1203
|
+
setLineItemCustomField(context, resource, { lineItemId, lineItemKey, name, value, action }) {
|
|
1204
|
+
const lineItem = resource.lineItems.find((x) => lineItemId && x.id === lineItemId || lineItemKey && x.key === lineItemKey);
|
|
1205
|
+
if (!lineItem) throw new CommercetoolsError({
|
|
1206
|
+
code: "General",
|
|
1207
|
+
message: lineItemKey ? `A line item with key '${lineItemKey}' not found.` : `A line item with ID '${lineItemId}' not found.`
|
|
1208
|
+
});
|
|
1209
|
+
if (!lineItem.custom) throw new Error("Resource has no custom field");
|
|
1210
|
+
lineItem.custom.fields[name] = value;
|
|
1211
|
+
}
|
|
1212
|
+
setLineItemCustomType(context, resource, { lineItemId, lineItemKey, type, fields }) {
|
|
1213
|
+
const lineItem = resource.lineItems.find((x) => lineItemId && x.id === lineItemId || lineItemKey && x.key === lineItemKey);
|
|
1214
|
+
if (!lineItem) throw new CommercetoolsError({
|
|
1215
|
+
code: "General",
|
|
1216
|
+
message: lineItemKey ? `A line item with key '${lineItemKey}' not found.` : `A line item with ID '${lineItemId}' not found.`
|
|
1217
|
+
});
|
|
1218
|
+
if (!type) lineItem.custom = void 0;
|
|
1219
|
+
else {
|
|
1220
|
+
const resolvedType = this._storage.getByResourceIdentifier(context.projectKey, type);
|
|
1221
|
+
if (!resolvedType) throw new Error(`Type ${type} not found`);
|
|
1222
|
+
lineItem.custom = {
|
|
1223
|
+
type: {
|
|
1224
|
+
typeId: "type",
|
|
1225
|
+
id: resolvedType.id
|
|
1226
|
+
},
|
|
1227
|
+
fields: fields || {}
|
|
1228
|
+
};
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1139
1231
|
setLineItemShippingDetails(context, resource, { action, shippingDetails, lineItemId, lineItemKey }) {
|
|
1140
1232
|
const lineItem = resource.lineItems.find((x) => lineItemId && x.id === lineItemId || lineItemKey && x.key === lineItemKey);
|
|
1141
1233
|
if (!lineItem) throw new CommercetoolsError({
|
|
@@ -1327,11 +1419,6 @@ var CartRepository = class extends AbstractResourceRepository {
|
|
|
1327
1419
|
};
|
|
1328
1420
|
createShippingInfo(context, resource, shippingMethodRef) {
|
|
1329
1421
|
if (resource.taxMode === "External") throw new Error("External tax rate is not supported");
|
|
1330
|
-
const country = resource.shippingAddress?.country;
|
|
1331
|
-
if (!country) throw new CommercetoolsError({
|
|
1332
|
-
code: "InvalidOperation",
|
|
1333
|
-
message: `The cart with ID '${resource.id}' does not have a shipping address set.`
|
|
1334
|
-
});
|
|
1335
1422
|
this._storage.getByResourceIdentifier(context.projectKey, shippingMethodRef);
|
|
1336
1423
|
const shippingMethods = getShippingMethodsMatchingCart(context, this._storage, resource, { expand: ["zoneRates[*].zone"] });
|
|
1337
1424
|
const method = shippingMethods.results.find((candidate) => shippingMethodRef.id ? candidate.id === shippingMethodRef.id : candidate.key === shippingMethodRef.key);
|
|
@@ -1339,63 +1426,7 @@ var CartRepository = class extends AbstractResourceRepository {
|
|
|
1339
1426
|
code: "ShippingMethodDoesNotMatchCart",
|
|
1340
1427
|
message: `The shipping method with ${shippingMethodRef.id ? `ID '${shippingMethodRef.id}'` : `key '${shippingMethodRef.key}'`} is not allowed for the cart with ID '${resource.id}'.`
|
|
1341
1428
|
});
|
|
1342
|
-
|
|
1343
|
-
const taxRate = taxCategory.rates.find((rate) => rate.country === country);
|
|
1344
|
-
if (!taxRate) throw new CommercetoolsError({
|
|
1345
|
-
code: "MissingTaxRateForCountry",
|
|
1346
|
-
message: `Tax category '${taxCategory.id}' is missing a tax rate for country '${country}'.`,
|
|
1347
|
-
taxCategoryId: taxCategory.id
|
|
1348
|
-
});
|
|
1349
|
-
const zoneRate = method.zoneRates.find((rate) => rate.zone.obj?.locations.some((loc) => loc.country === country));
|
|
1350
|
-
if (!zoneRate) throw new Error("Zone rate not found");
|
|
1351
|
-
const shippingRate = zoneRate.shippingRates[0];
|
|
1352
|
-
if (!shippingRate) throw new Error("Shipping rate not found");
|
|
1353
|
-
const shippingRateTier = shippingRate.tiers.find((tier) => tier.isMatching);
|
|
1354
|
-
if (shippingRateTier && shippingRateTier.type !== "CartValue") throw new Error("Non-CartValue shipping rate tier is not supported");
|
|
1355
|
-
let shippingPrice = shippingRateTier ? createCentPrecisionMoney(shippingRateTier.price) : shippingRate.price;
|
|
1356
|
-
if (shippingRate.freeAbove && shippingRate.freeAbove.currencyCode === resource.totalPrice.currencyCode && resource.totalPrice.centAmount >= shippingRate.freeAbove.centAmount) shippingPrice = {
|
|
1357
|
-
...shippingPrice,
|
|
1358
|
-
centAmount: 0
|
|
1359
|
-
};
|
|
1360
|
-
const totalGross = taxRate.includedInPrice ? shippingPrice : {
|
|
1361
|
-
...shippingPrice,
|
|
1362
|
-
centAmount: roundDecimal(new Decimal(shippingPrice.centAmount).mul(1 + taxRate.amount), resource.taxRoundingMode).toNumber()
|
|
1363
|
-
};
|
|
1364
|
-
const totalNet = taxRate.includedInPrice ? {
|
|
1365
|
-
...shippingPrice,
|
|
1366
|
-
centAmount: roundDecimal(new Decimal(shippingPrice.centAmount).div(1 + taxRate.amount), resource.taxRoundingMode).toNumber()
|
|
1367
|
-
} : shippingPrice;
|
|
1368
|
-
const taxPortions = [{
|
|
1369
|
-
name: taxRate.name,
|
|
1370
|
-
rate: taxRate.amount,
|
|
1371
|
-
amount: {
|
|
1372
|
-
...shippingPrice,
|
|
1373
|
-
centAmount: totalGross.centAmount - totalNet.centAmount
|
|
1374
|
-
}
|
|
1375
|
-
}];
|
|
1376
|
-
const totalTax = {
|
|
1377
|
-
...shippingPrice,
|
|
1378
|
-
centAmount: taxPortions.reduce((acc, portion) => acc + portion.amount.centAmount, 0)
|
|
1379
|
-
};
|
|
1380
|
-
const taxedPrice = {
|
|
1381
|
-
totalNet,
|
|
1382
|
-
totalGross,
|
|
1383
|
-
taxPortions,
|
|
1384
|
-
totalTax
|
|
1385
|
-
};
|
|
1386
|
-
return {
|
|
1387
|
-
shippingMethod: {
|
|
1388
|
-
typeId: "shipping-method",
|
|
1389
|
-
id: method.id
|
|
1390
|
-
},
|
|
1391
|
-
shippingMethodName: method.name,
|
|
1392
|
-
price: shippingPrice,
|
|
1393
|
-
shippingRate,
|
|
1394
|
-
taxedPrice,
|
|
1395
|
-
taxRate,
|
|
1396
|
-
taxCategory: method.taxCategory,
|
|
1397
|
-
shippingMethodState: "MatchesCart"
|
|
1398
|
-
};
|
|
1429
|
+
return createShippingInfoFromMethod(context, this._storage, resource, method);
|
|
1399
1430
|
}
|
|
1400
1431
|
};
|
|
1401
1432
|
|
|
@@ -1478,6 +1509,34 @@ var OrderUpdateHandler = class extends AbstractUpdateHandler {
|
|
|
1478
1509
|
if (!resource.shippingInfo) throw new Error("Resource has no shipping info");
|
|
1479
1510
|
for (const delivery of resource.shippingInfo.deliveries || []) if (delivery.id === deliveryId && delivery.custom?.fields) delivery.custom.fields[name] = value;
|
|
1480
1511
|
}
|
|
1512
|
+
setLineItemCustomField(context, resource, { lineItemId, lineItemKey, name, value, action }) {
|
|
1513
|
+
const lineItem = resource.lineItems.find((x) => lineItemId && x.id === lineItemId || lineItemKey && x.key === lineItemKey);
|
|
1514
|
+
if (!lineItem) throw new CommercetoolsError({
|
|
1515
|
+
code: "General",
|
|
1516
|
+
message: lineItemKey ? `A line item with key '${lineItemKey}' not found.` : `A line item with ID '${lineItemId}' not found.`
|
|
1517
|
+
});
|
|
1518
|
+
if (!lineItem.custom) throw new Error("Resource has no custom field");
|
|
1519
|
+
lineItem.custom.fields[name] = value;
|
|
1520
|
+
}
|
|
1521
|
+
setLineItemCustomType(context, resource, { lineItemId, lineItemKey, type, fields }) {
|
|
1522
|
+
const lineItem = resource.lineItems.find((x) => lineItemId && x.id === lineItemId || lineItemKey && x.key === lineItemKey);
|
|
1523
|
+
if (!lineItem) throw new CommercetoolsError({
|
|
1524
|
+
code: "General",
|
|
1525
|
+
message: lineItemKey ? `A line item with key '${lineItemKey}' not found.` : `A line item with ID '${lineItemId}' not found.`
|
|
1526
|
+
});
|
|
1527
|
+
if (!type) lineItem.custom = void 0;
|
|
1528
|
+
else {
|
|
1529
|
+
const resolvedType = this._storage.getByResourceIdentifier(context.projectKey, type);
|
|
1530
|
+
if (!resolvedType) throw new Error(`Type ${type} not found`);
|
|
1531
|
+
lineItem.custom = {
|
|
1532
|
+
type: {
|
|
1533
|
+
typeId: "type",
|
|
1534
|
+
id: resolvedType.id
|
|
1535
|
+
},
|
|
1536
|
+
fields: fields || {}
|
|
1537
|
+
};
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1481
1540
|
setLocale(context, resource, { locale }) {
|
|
1482
1541
|
resource.locale = locale;
|
|
1483
1542
|
}
|
|
@@ -1577,6 +1636,7 @@ var OrderRepository = class extends AbstractResourceRepository {
|
|
|
1577
1636
|
refusedGifts: [],
|
|
1578
1637
|
shipping: cart.shipping,
|
|
1579
1638
|
shippingAddress: cart.shippingAddress,
|
|
1639
|
+
shippingInfo: cart.shippingInfo,
|
|
1580
1640
|
shippingMode: cart.shippingMode,
|
|
1581
1641
|
syncInfo: [],
|
|
1582
1642
|
taxCalculationMode: cart.taxCalculationMode,
|
|
@@ -1610,12 +1670,28 @@ var OrderRepository = class extends AbstractResourceRepository {
|
|
|
1610
1670
|
refusedGifts: [],
|
|
1611
1671
|
shippingMode: "Single",
|
|
1612
1672
|
shipping: [],
|
|
1673
|
+
shippingInfo: void 0,
|
|
1613
1674
|
store: resolveStoreReference(draft.store, context.projectKey, this._storage),
|
|
1614
1675
|
syncInfo: [],
|
|
1615
1676
|
lineItems: draft.lineItems?.map((item) => this.lineItemFromImportDraft.bind(this)(context, item)) || [],
|
|
1616
1677
|
customLineItems: draft.customLineItems?.map((item) => this.customLineItemFromImportDraft.bind(this)(context, item)) || [],
|
|
1617
1678
|
totalPrice: createCentPrecisionMoney(draft.totalPrice)
|
|
1618
1679
|
};
|
|
1680
|
+
if (draft.shippingInfo?.shippingMethod) {
|
|
1681
|
+
const { ...shippingMethodRef } = draft.shippingInfo.shippingMethod;
|
|
1682
|
+
if (shippingMethodRef.key && !shippingMethodRef.id) {
|
|
1683
|
+
const shippingMethod = this._storage.getByResourceIdentifier(context.projectKey, shippingMethodRef);
|
|
1684
|
+
if (!shippingMethod) throw new CommercetoolsError({
|
|
1685
|
+
code: "General",
|
|
1686
|
+
message: `A shipping method with key '${shippingMethodRef.key}' does not exist.`
|
|
1687
|
+
});
|
|
1688
|
+
shippingMethodRef.id = shippingMethod.id;
|
|
1689
|
+
}
|
|
1690
|
+
resource.shippingInfo = this.createShippingInfo(context, resource, {
|
|
1691
|
+
typeId: "shipping-method",
|
|
1692
|
+
id: shippingMethodRef.id
|
|
1693
|
+
});
|
|
1694
|
+
}
|
|
1619
1695
|
return this.saveNew(context, resource);
|
|
1620
1696
|
}
|
|
1621
1697
|
lineItemFromImportDraft(context, draft) {
|
|
@@ -1655,7 +1731,8 @@ var OrderRepository = class extends AbstractResourceRepository {
|
|
|
1655
1731
|
variant: {
|
|
1656
1732
|
id: variant.id,
|
|
1657
1733
|
sku: variant.sku,
|
|
1658
|
-
price: createPrice(draft.price)
|
|
1734
|
+
price: createPrice(draft.price),
|
|
1735
|
+
attributes: variant.attributes
|
|
1659
1736
|
}
|
|
1660
1737
|
};
|
|
1661
1738
|
return lineItem;
|
|
@@ -1686,6 +1763,32 @@ var OrderRepository = class extends AbstractResourceRepository {
|
|
|
1686
1763
|
if (result.count > 1) throw new Error("Duplicate order numbers");
|
|
1687
1764
|
return;
|
|
1688
1765
|
}
|
|
1766
|
+
createShippingInfo(context, resource, shippingMethodRef) {
|
|
1767
|
+
const cartLikeForMatching = {
|
|
1768
|
+
...resource,
|
|
1769
|
+
cartState: "Active",
|
|
1770
|
+
inventoryMode: "None",
|
|
1771
|
+
itemShippingAddresses: [],
|
|
1772
|
+
priceRoundingMode: resource.taxRoundingMode || "HalfEven",
|
|
1773
|
+
taxMode: resource.taxMode || "Platform",
|
|
1774
|
+
taxCalculationMode: resource.taxCalculationMode || "LineItemLevel",
|
|
1775
|
+
taxRoundingMode: resource.taxRoundingMode || "HalfEven",
|
|
1776
|
+
discountCodes: resource.discountCodes || [],
|
|
1777
|
+
directDiscounts: resource.directDiscounts || [],
|
|
1778
|
+
shippingInfo: void 0
|
|
1779
|
+
};
|
|
1780
|
+
const shippingMethods = getShippingMethodsMatchingCart(context, this._storage, cartLikeForMatching, { expand: ["zoneRates[*].zone"] });
|
|
1781
|
+
const method = shippingMethods.results.find((candidate) => candidate.id === shippingMethodRef.id);
|
|
1782
|
+
if (!method) throw new CommercetoolsError({
|
|
1783
|
+
code: "ShippingMethodDoesNotMatchCart",
|
|
1784
|
+
message: `The shipping method with ID '${shippingMethodRef.id}' is not allowed for the order with ID '${resource.id}'.`
|
|
1785
|
+
});
|
|
1786
|
+
const baseShippingInfo = createShippingInfoFromMethod(context, this._storage, resource, method);
|
|
1787
|
+
return {
|
|
1788
|
+
...baseShippingInfo,
|
|
1789
|
+
deliveries: []
|
|
1790
|
+
};
|
|
1791
|
+
}
|
|
1689
1792
|
};
|
|
1690
1793
|
|
|
1691
1794
|
//#endregion
|