@labdigital/commercetools-mock 2.34.2 → 2.35.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.cjs +250 -160
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -11
- package/dist/index.d.ts +11 -11
- package/dist/index.js +250 -160
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/src/product-projection-search.ts +1 -1
- package/src/product-search.ts +1 -1
- package/src/repositories/cart/actions.ts +160 -4
- package/src/repositories/cart/index.test.ts +151 -0
- package/src/repositories/cart/index.ts +15 -5
- package/src/repositories/helpers.ts +21 -0
- package/src/repositories/product-projection.ts +1 -1
- package/src/repositories/shipping-method/index.ts +2 -54
- package/src/services/cart.test.ts +417 -0
- package/src/{shippingCalculator.test.ts → shipping.test.ts} +1 -1
- package/src/shipping.ts +147 -0
- package/src/shippingCalculator.ts +0 -74
package/dist/index.js
CHANGED
|
@@ -146,8 +146,7 @@ var OAuth2Store = class {
|
|
|
146
146
|
};
|
|
147
147
|
}
|
|
148
148
|
validateToken(token) {
|
|
149
|
-
if (!this.validate)
|
|
150
|
-
return true;
|
|
149
|
+
if (!this.validate) return true;
|
|
151
150
|
const foundToken = this.tokens.find((t) => t.access_token === token);
|
|
152
151
|
if (foundToken) {
|
|
153
152
|
return true;
|
|
@@ -617,19 +616,16 @@ function toRegExp(str) {
|
|
|
617
616
|
return new RegExp(str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"));
|
|
618
617
|
}
|
|
619
618
|
function normalize(regex) {
|
|
620
|
-
if (typeof regex === "string")
|
|
621
|
-
regex = toRegExp(regex);
|
|
619
|
+
if (typeof regex === "string") regex = toRegExp(regex);
|
|
622
620
|
if (!regex.source.startsWith("^"))
|
|
623
621
|
return new RegExp(`^${regex.source}`, regex.flags);
|
|
624
|
-
else
|
|
625
|
-
return regex;
|
|
622
|
+
else return regex;
|
|
626
623
|
}
|
|
627
624
|
function first(arr, predicate) {
|
|
628
625
|
let i = 0;
|
|
629
626
|
for (const item of arr) {
|
|
630
627
|
const result = predicate(item, i++);
|
|
631
|
-
if (result)
|
|
632
|
-
return { item, result };
|
|
628
|
+
if (result) return { item, result };
|
|
633
629
|
}
|
|
634
630
|
}
|
|
635
631
|
var TokenTypes = class {
|
|
@@ -793,8 +789,7 @@ var Lexer = class {
|
|
|
793
789
|
*/
|
|
794
790
|
peek(position = this._state.position) {
|
|
795
791
|
const read = (i = position) => {
|
|
796
|
-
if (i >= this._state.source.length)
|
|
797
|
-
return EOF(this);
|
|
792
|
+
if (i >= this._state.source.length) return EOF(this);
|
|
798
793
|
const n = this._tokenTypes.peek(this._state.source, i);
|
|
799
794
|
if (!n || !n.result) {
|
|
800
795
|
throw new Error(
|
|
@@ -814,8 +809,7 @@ var Lexer = class {
|
|
|
814
809
|
) : null;
|
|
815
810
|
};
|
|
816
811
|
const t = read();
|
|
817
|
-
if (t)
|
|
818
|
-
return t;
|
|
812
|
+
if (t) return t;
|
|
819
813
|
let unexpected = this._state.source.substring(position, position + 1);
|
|
820
814
|
try {
|
|
821
815
|
this.peek(position + 1);
|
|
@@ -837,8 +831,7 @@ var Lexer = class {
|
|
|
837
831
|
*/
|
|
838
832
|
strpos(i) {
|
|
839
833
|
let lines = this._state.source.substring(0, i).split(/\r?\n/);
|
|
840
|
-
if (!Array.isArray(lines))
|
|
841
|
-
lines = [lines];
|
|
834
|
+
if (!Array.isArray(lines)) lines = [lines];
|
|
842
835
|
const line = lines.length;
|
|
843
836
|
const column = lines[lines.length - 1].length + 1;
|
|
844
837
|
return { line, column };
|
|
@@ -937,8 +930,7 @@ var Parser = class {
|
|
|
937
930
|
* @returns {number} The binding power of the specified token type
|
|
938
931
|
*/
|
|
939
932
|
bp(tokenOrType) {
|
|
940
|
-
if (tokenOrType == null)
|
|
941
|
-
return Number.NEGATIVE_INFINITY;
|
|
933
|
+
if (tokenOrType == null) return Number.NEGATIVE_INFINITY;
|
|
942
934
|
if (tokenOrType && typeof tokenOrType.isEof == "function" && tokenOrType.isEof())
|
|
943
935
|
return Number.NEGATIVE_INFINITY;
|
|
944
936
|
const type = this._type(tokenOrType);
|
|
@@ -983,27 +975,21 @@ var Parser = class {
|
|
|
983
975
|
parse(opts = { terminals: [0] }) {
|
|
984
976
|
const stop = opts.stop = opts.stop || createStop();
|
|
985
977
|
const check = () => {
|
|
986
|
-
if (stop.isStopped())
|
|
987
|
-
return false;
|
|
978
|
+
if (stop.isStopped()) return false;
|
|
988
979
|
const t = this.lexer.peek();
|
|
989
980
|
const bp = this.bp(t);
|
|
990
981
|
return opts.terminals.reduce((canContinue, rbpOrType) => {
|
|
991
|
-
if (!canContinue)
|
|
992
|
-
|
|
993
|
-
if (typeof rbpOrType == "
|
|
994
|
-
return rbpOrType < bp;
|
|
995
|
-
if (typeof rbpOrType == "string")
|
|
996
|
-
return t.type != rbpOrType;
|
|
982
|
+
if (!canContinue) return false;
|
|
983
|
+
if (typeof rbpOrType == "number") return rbpOrType < bp;
|
|
984
|
+
if (typeof rbpOrType == "string") return t.type != rbpOrType;
|
|
997
985
|
}, true);
|
|
998
986
|
};
|
|
999
987
|
const mkinfo = (token) => {
|
|
1000
988
|
const bp = this.bp(token);
|
|
1001
989
|
return { token, bp, stop, ctx: opts.ctx, options: opts };
|
|
1002
990
|
};
|
|
1003
|
-
if (!opts.terminals)
|
|
1004
|
-
|
|
1005
|
-
if (opts.terminals.length == 0)
|
|
1006
|
-
opts.terminals.push(0);
|
|
991
|
+
if (!opts.terminals) opts.terminals = [0];
|
|
992
|
+
if (opts.terminals.length == 0) opts.terminals.push(0);
|
|
1007
993
|
let left = this.nud(mkinfo(this.lexer.next()));
|
|
1008
994
|
while (check()) {
|
|
1009
995
|
const operator = this.lexer.next();
|
|
@@ -1343,8 +1329,7 @@ var generateMatchFunc = (predicate) => {
|
|
|
1343
1329
|
const expr = parser.parse({ terminals: [")"] });
|
|
1344
1330
|
return (obj, vars) => {
|
|
1345
1331
|
const value = resolveValue(obj, left);
|
|
1346
|
-
if (!value)
|
|
1347
|
-
return false;
|
|
1332
|
+
if (!value) return false;
|
|
1348
1333
|
const maxDistance = resolveSymbol(expr[2], vars);
|
|
1349
1334
|
const distance = haversineDistance(
|
|
1350
1335
|
{
|
|
@@ -1431,8 +1416,7 @@ var InMemoryStorage = class extends AbstractStorage {
|
|
|
1431
1416
|
getProject = (projectKey) => this.addProject(projectKey);
|
|
1432
1417
|
// Expand resolves a nested reference and injects the object in the given obj
|
|
1433
1418
|
expand = (projectKey, obj, clause) => {
|
|
1434
|
-
if (!clause)
|
|
1435
|
-
return obj;
|
|
1419
|
+
if (!clause) return obj;
|
|
1436
1420
|
const newObj = cloneObject(obj);
|
|
1437
1421
|
if (Array.isArray(clause)) {
|
|
1438
1422
|
for (const c of clause) {
|
|
@@ -1463,15 +1447,13 @@ var InMemoryStorage = class extends AbstractStorage {
|
|
|
1463
1447
|
this._resolveReference(projectKey, reference, params.rest);
|
|
1464
1448
|
} else if (params.index === "*") {
|
|
1465
1449
|
const reference = obj[params.element];
|
|
1466
|
-
if (reference === void 0 || !Array.isArray(reference))
|
|
1467
|
-
return;
|
|
1450
|
+
if (reference === void 0 || !Array.isArray(reference)) return;
|
|
1468
1451
|
for (const itemRef of reference) {
|
|
1469
1452
|
this._resolveReference(projectKey, itemRef, params.rest);
|
|
1470
1453
|
}
|
|
1471
1454
|
} else {
|
|
1472
1455
|
const reference = obj[params.element][params.index];
|
|
1473
|
-
if (reference === void 0)
|
|
1474
|
-
return;
|
|
1456
|
+
if (reference === void 0) return;
|
|
1475
1457
|
this._resolveReference(projectKey, reference, params.rest);
|
|
1476
1458
|
}
|
|
1477
1459
|
};
|
|
@@ -1682,8 +1664,7 @@ var InMemoryStorage = class extends AbstractStorage {
|
|
|
1682
1664
|
});
|
|
1683
1665
|
}
|
|
1684
1666
|
_resolveReference(projectKey, reference, expand) {
|
|
1685
|
-
if (reference === void 0)
|
|
1686
|
-
return;
|
|
1667
|
+
if (reference === void 0) return;
|
|
1687
1668
|
if (reference.typeId !== void 0 && (reference.id !== void 0 || reference.key !== void 0)) {
|
|
1688
1669
|
if (!reference.obj) {
|
|
1689
1670
|
reference.obj = this.getByResourceIdentifier(projectKey, {
|
|
@@ -1731,8 +1712,7 @@ import deepEqual from "deep-equal";
|
|
|
1731
1712
|
|
|
1732
1713
|
// src/repositories/errors.ts
|
|
1733
1714
|
var checkConcurrentModification = (currentVersion, expectedVersion, identifier) => {
|
|
1734
|
-
if (currentVersion === expectedVersion)
|
|
1735
|
-
return;
|
|
1715
|
+
if (currentVersion === expectedVersion) return;
|
|
1736
1716
|
console.error(
|
|
1737
1717
|
`Object ${identifier} has a different version than expected. Expected: ${expectedVersion} - Actual: ${currentVersion}.`
|
|
1738
1718
|
);
|
|
@@ -1905,10 +1885,10 @@ var ProductTailoringUpdateHandler = class extends AbstractUpdateHandler {
|
|
|
1905
1885
|
};
|
|
1906
1886
|
|
|
1907
1887
|
// src/repositories/helpers.ts
|
|
1888
|
+
import { Decimal } from "decimal.js/decimal";
|
|
1908
1889
|
import { v4 as uuidv44 } from "uuid";
|
|
1909
1890
|
var createAddress = (base, projectKey, storage) => {
|
|
1910
|
-
if (!base)
|
|
1911
|
-
return void 0;
|
|
1891
|
+
if (!base) return void 0;
|
|
1912
1892
|
if (!base?.country) {
|
|
1913
1893
|
throw new Error("Country is required");
|
|
1914
1894
|
}
|
|
@@ -1917,12 +1897,9 @@ var createAddress = (base, projectKey, storage) => {
|
|
|
1917
1897
|
};
|
|
1918
1898
|
};
|
|
1919
1899
|
var createCustomFields = (draft, projectKey, storage) => {
|
|
1920
|
-
if (!draft)
|
|
1921
|
-
|
|
1922
|
-
if (!draft.type)
|
|
1923
|
-
return void 0;
|
|
1924
|
-
if (!draft.type.typeId)
|
|
1925
|
-
return void 0;
|
|
1900
|
+
if (!draft) return void 0;
|
|
1901
|
+
if (!draft.type) return void 0;
|
|
1902
|
+
if (!draft.type.typeId) return void 0;
|
|
1926
1903
|
const typeResource = storage.getByResourceIdentifier(
|
|
1927
1904
|
projectKey,
|
|
1928
1905
|
draft.type
|
|
@@ -1944,6 +1921,18 @@ var createPrice = (draft) => ({
|
|
|
1944
1921
|
id: uuidv44(),
|
|
1945
1922
|
value: createTypedMoney(draft.value)
|
|
1946
1923
|
});
|
|
1924
|
+
var roundDecimal = (decimal, roundingMode) => {
|
|
1925
|
+
switch (roundingMode) {
|
|
1926
|
+
case "HalfEven":
|
|
1927
|
+
return decimal.toDecimalPlaces(0, Decimal.ROUND_HALF_EVEN);
|
|
1928
|
+
case "HalfUp":
|
|
1929
|
+
return decimal.toDecimalPlaces(0, Decimal.ROUND_HALF_UP);
|
|
1930
|
+
case "HalfDown":
|
|
1931
|
+
return decimal.toDecimalPlaces(0, Decimal.ROUND_HALF_DOWN);
|
|
1932
|
+
default:
|
|
1933
|
+
throw new Error(`Unknown rounding mode: ${roundingMode}`);
|
|
1934
|
+
}
|
|
1935
|
+
};
|
|
1947
1936
|
var createCentPrecisionMoney = (value) => {
|
|
1948
1937
|
let fractionDigits = 2;
|
|
1949
1938
|
switch (value.currencyCode.toUpperCase()) {
|
|
@@ -1993,8 +1982,7 @@ var createTypedMoney = (value) => {
|
|
|
1993
1982
|
return result;
|
|
1994
1983
|
};
|
|
1995
1984
|
var resolveStoreReference = (ref, projectKey, storage) => {
|
|
1996
|
-
if (!ref)
|
|
1997
|
-
return void 0;
|
|
1985
|
+
if (!ref) return void 0;
|
|
1998
1986
|
const resource = storage.getByResourceIdentifier(projectKey, ref);
|
|
1999
1987
|
if (!resource) {
|
|
2000
1988
|
throw new Error("No such store");
|
|
@@ -2062,8 +2050,7 @@ var getRepositoryContext = (request) => ({
|
|
|
2062
2050
|
storeKey: request.params.storeKey
|
|
2063
2051
|
});
|
|
2064
2052
|
var createAssociate = (a, projectKey, storage) => {
|
|
2065
|
-
if (!a)
|
|
2066
|
-
return void 0;
|
|
2053
|
+
if (!a) return void 0;
|
|
2067
2054
|
if (!a.associateRoleAssignments) {
|
|
2068
2055
|
throw new Error("AssociateRoleAssignments is required");
|
|
2069
2056
|
}
|
|
@@ -2369,8 +2356,95 @@ var BusinessUnitUpdateHandler = class extends AbstractUpdateHandler {
|
|
|
2369
2356
|
import { v4 as uuidv46 } from "uuid";
|
|
2370
2357
|
|
|
2371
2358
|
// src/repositories/cart/actions.ts
|
|
2359
|
+
import { Decimal as Decimal2 } from "decimal.js/decimal";
|
|
2372
2360
|
import { v4 as uuidv45 } from "uuid";
|
|
2373
2361
|
|
|
2362
|
+
// src/shipping.ts
|
|
2363
|
+
var markMatchingShippingRate = (cart, shippingRate) => {
|
|
2364
|
+
const isMatching = shippingRate.price.currencyCode === cart.totalPrice.currencyCode;
|
|
2365
|
+
return {
|
|
2366
|
+
...shippingRate,
|
|
2367
|
+
tiers: markMatchingShippingRatePriceTiers(cart, shippingRate.tiers),
|
|
2368
|
+
isMatching
|
|
2369
|
+
};
|
|
2370
|
+
};
|
|
2371
|
+
var markMatchingShippingRatePriceTiers = (cart, tiers) => {
|
|
2372
|
+
if (tiers.length === 0) {
|
|
2373
|
+
return [];
|
|
2374
|
+
}
|
|
2375
|
+
if (new Set(tiers.map((tier) => tier.type)).size > 1) {
|
|
2376
|
+
throw new Error("Can't handle multiple types of tiers");
|
|
2377
|
+
}
|
|
2378
|
+
const tierType = tiers[0].type;
|
|
2379
|
+
switch (tierType) {
|
|
2380
|
+
case "CartValue":
|
|
2381
|
+
return markMatchingCartValueTiers(cart, tiers);
|
|
2382
|
+
// case 'CartClassification':
|
|
2383
|
+
// return markMatchingCartClassificationTiers(cart, tiers)
|
|
2384
|
+
// case 'CartScore':
|
|
2385
|
+
// return markMatchingCartScoreTiers(cart, tiers)
|
|
2386
|
+
default:
|
|
2387
|
+
throw new Error(`Unsupported tier type: ${tierType}`);
|
|
2388
|
+
}
|
|
2389
|
+
};
|
|
2390
|
+
var markMatchingCartValueTiers = (cart, tiers) => {
|
|
2391
|
+
const sortedTiers = [...tiers].sort(
|
|
2392
|
+
(a, b) => b.minimumCentAmount - a.minimumCentAmount
|
|
2393
|
+
);
|
|
2394
|
+
const result = {};
|
|
2395
|
+
let hasMatchingTier = false;
|
|
2396
|
+
for (const tier of sortedTiers) {
|
|
2397
|
+
const isMatching = !hasMatchingTier && cart.totalPrice.currencyCode === tier.price.currencyCode && cart.totalPrice.centAmount >= tier.minimumCentAmount;
|
|
2398
|
+
if (isMatching) hasMatchingTier = true;
|
|
2399
|
+
result[tier.minimumCentAmount] = {
|
|
2400
|
+
...tier,
|
|
2401
|
+
isMatching
|
|
2402
|
+
};
|
|
2403
|
+
}
|
|
2404
|
+
return tiers.map((tier) => result[tier.minimumCentAmount]);
|
|
2405
|
+
};
|
|
2406
|
+
var getShippingMethodsMatchingCart = (context, storage, cart, params = {}) => {
|
|
2407
|
+
if (!cart.shippingAddress?.country) {
|
|
2408
|
+
throw new CommercetoolsError({
|
|
2409
|
+
code: "InvalidOperation",
|
|
2410
|
+
message: `The cart with ID '${cart.id}' does not have a shipping address set.`
|
|
2411
|
+
});
|
|
2412
|
+
}
|
|
2413
|
+
const zones = storage.query(context.projectKey, "zone", {
|
|
2414
|
+
where: [`locations(country="${cart.shippingAddress.country}"))`],
|
|
2415
|
+
limit: 100
|
|
2416
|
+
});
|
|
2417
|
+
const zoneIds = zones.results.map((zone) => zone.id);
|
|
2418
|
+
const shippingMethods = storage.query(
|
|
2419
|
+
context.projectKey,
|
|
2420
|
+
"shipping-method",
|
|
2421
|
+
{
|
|
2422
|
+
"where": [
|
|
2423
|
+
`zoneRates(zone(id in (:zoneIds)))`,
|
|
2424
|
+
`zoneRates(shippingRates(price(currencyCode="${cart.totalPrice.currencyCode}")))`
|
|
2425
|
+
],
|
|
2426
|
+
"var.zoneIds": zoneIds,
|
|
2427
|
+
"expand": params.expand
|
|
2428
|
+
}
|
|
2429
|
+
);
|
|
2430
|
+
const results = shippingMethods.results.map((shippingMethod) => {
|
|
2431
|
+
const rates = shippingMethod.zoneRates.map((zoneRate) => ({
|
|
2432
|
+
zone: zoneRate.zone,
|
|
2433
|
+
// Iterate through the shippingRates and mark the matching ones
|
|
2434
|
+
// then we filter out the non-matching ones
|
|
2435
|
+
shippingRates: zoneRate.shippingRates.map((rate) => markMatchingShippingRate(cart, rate)).filter((rate) => rate.isMatching)
|
|
2436
|
+
})).filter((zoneRate) => zoneRate.shippingRates.length > 0);
|
|
2437
|
+
return {
|
|
2438
|
+
...shippingMethod,
|
|
2439
|
+
zoneRates: rates
|
|
2440
|
+
};
|
|
2441
|
+
}).filter((shippingMethod) => shippingMethod.zoneRates.length > 0);
|
|
2442
|
+
return {
|
|
2443
|
+
...shippingMethods,
|
|
2444
|
+
results
|
|
2445
|
+
};
|
|
2446
|
+
};
|
|
2447
|
+
|
|
2374
2448
|
// src/repositories/cart/helpers.ts
|
|
2375
2449
|
var selectPrice = ({
|
|
2376
2450
|
prices,
|
|
@@ -2432,10 +2506,8 @@ var CartUpdateHandler = class extends AbstractUpdateHandler {
|
|
|
2432
2506
|
product.masterData.current.masterVariant,
|
|
2433
2507
|
...product.masterData.current.variants
|
|
2434
2508
|
].find((x) => {
|
|
2435
|
-
if (sku)
|
|
2436
|
-
|
|
2437
|
-
if (variantId)
|
|
2438
|
-
return x.id === variantId;
|
|
2509
|
+
if (sku) return x.sku === sku;
|
|
2510
|
+
if (variantId) return x.id === variantId;
|
|
2439
2511
|
return false;
|
|
2440
2512
|
});
|
|
2441
2513
|
if (!variant) {
|
|
@@ -2741,16 +2813,116 @@ var CartUpdateHandler = class extends AbstractUpdateHandler {
|
|
|
2741
2813
|
}
|
|
2742
2814
|
setShippingMethod(context, resource, { shippingMethod }) {
|
|
2743
2815
|
if (shippingMethod) {
|
|
2744
|
-
|
|
2816
|
+
if (resource.taxMode === "External") {
|
|
2817
|
+
throw new Error("External tax rate is not supported");
|
|
2818
|
+
}
|
|
2819
|
+
const country = resource.shippingAddress?.country;
|
|
2820
|
+
if (!country) {
|
|
2821
|
+
throw new CommercetoolsError({
|
|
2822
|
+
code: "InvalidOperation",
|
|
2823
|
+
message: `The cart with ID '${resource.id}' does not have a shipping address set.`
|
|
2824
|
+
});
|
|
2825
|
+
}
|
|
2826
|
+
this._storage.getByResourceIdentifier(
|
|
2745
2827
|
context.projectKey,
|
|
2746
2828
|
shippingMethod
|
|
2747
2829
|
);
|
|
2830
|
+
const shippingMethods = getShippingMethodsMatchingCart(
|
|
2831
|
+
context,
|
|
2832
|
+
this._storage,
|
|
2833
|
+
resource,
|
|
2834
|
+
{
|
|
2835
|
+
expand: ["zoneRates[*].zone"]
|
|
2836
|
+
}
|
|
2837
|
+
);
|
|
2838
|
+
const method = shippingMethods.results.find(
|
|
2839
|
+
(candidate) => shippingMethod.id ? candidate.id === shippingMethod.id : candidate.key === shippingMethod.key
|
|
2840
|
+
);
|
|
2841
|
+
if (!method) {
|
|
2842
|
+
throw new CommercetoolsError({
|
|
2843
|
+
code: "ShippingMethodDoesNotMatchCart",
|
|
2844
|
+
message: `The shipping method with ${shippingMethod.id ? `ID '${shippingMethod.id}'` : `key '${shippingMethod.key}'`} is not allowed for the cart with ID '${resource.id}'.`
|
|
2845
|
+
});
|
|
2846
|
+
}
|
|
2847
|
+
const taxCategory = this._storage.getByResourceIdentifier(
|
|
2848
|
+
context.projectKey,
|
|
2849
|
+
method.taxCategory
|
|
2850
|
+
);
|
|
2851
|
+
const taxRate = taxCategory.rates.find(
|
|
2852
|
+
(rate) => rate.country === country
|
|
2853
|
+
);
|
|
2854
|
+
if (!taxRate) {
|
|
2855
|
+
throw new CommercetoolsError({
|
|
2856
|
+
code: "MissingTaxRateForCountry",
|
|
2857
|
+
message: `Tax category '${taxCategory.id}' is missing a tax rate for country '${country}'.`,
|
|
2858
|
+
taxCategoryId: taxCategory.id
|
|
2859
|
+
});
|
|
2860
|
+
}
|
|
2861
|
+
const zoneRate = method.zoneRates.find(
|
|
2862
|
+
(rate) => rate.zone.obj.locations.some((loc) => loc.country === country)
|
|
2863
|
+
);
|
|
2864
|
+
if (!zoneRate) {
|
|
2865
|
+
throw new Error("Zone rate not found");
|
|
2866
|
+
}
|
|
2867
|
+
const shippingRate = zoneRate.shippingRates[0];
|
|
2868
|
+
if (!shippingRate) {
|
|
2869
|
+
throw new Error("Shipping rate not found");
|
|
2870
|
+
}
|
|
2871
|
+
const shippingRateTier = shippingRate.tiers.find(
|
|
2872
|
+
(tier) => tier.isMatching
|
|
2873
|
+
);
|
|
2874
|
+
if (shippingRateTier && shippingRateTier.type !== "CartValue") {
|
|
2875
|
+
throw new Error("Non-CartValue shipping rate tier is not supported");
|
|
2876
|
+
}
|
|
2877
|
+
const shippingPrice = shippingRateTier ? createCentPrecisionMoney(shippingRateTier.price) : shippingRate.price;
|
|
2878
|
+
const totalGross = taxRate.includedInPrice ? shippingPrice : {
|
|
2879
|
+
...shippingPrice,
|
|
2880
|
+
centAmount: roundDecimal(
|
|
2881
|
+
new Decimal2(shippingPrice.centAmount).mul(1 + taxRate.amount),
|
|
2882
|
+
resource.taxRoundingMode
|
|
2883
|
+
).toNumber()
|
|
2884
|
+
};
|
|
2885
|
+
const totalNet = taxRate.includedInPrice ? {
|
|
2886
|
+
...shippingPrice,
|
|
2887
|
+
centAmount: roundDecimal(
|
|
2888
|
+
new Decimal2(shippingPrice.centAmount).div(1 + taxRate.amount),
|
|
2889
|
+
resource.taxRoundingMode
|
|
2890
|
+
).toNumber()
|
|
2891
|
+
} : shippingPrice;
|
|
2892
|
+
const taxPortions = [
|
|
2893
|
+
{
|
|
2894
|
+
name: taxRate.name,
|
|
2895
|
+
rate: taxRate.amount,
|
|
2896
|
+
amount: {
|
|
2897
|
+
...shippingPrice,
|
|
2898
|
+
centAmount: totalGross.centAmount - totalNet.centAmount
|
|
2899
|
+
}
|
|
2900
|
+
}
|
|
2901
|
+
];
|
|
2902
|
+
const totalTax = {
|
|
2903
|
+
...shippingPrice,
|
|
2904
|
+
centAmount: taxPortions.reduce(
|
|
2905
|
+
(acc, portion) => acc + portion.amount.centAmount,
|
|
2906
|
+
0
|
|
2907
|
+
)
|
|
2908
|
+
};
|
|
2909
|
+
const taxedPrice = {
|
|
2910
|
+
totalNet,
|
|
2911
|
+
totalGross,
|
|
2912
|
+
taxPortions,
|
|
2913
|
+
totalTax
|
|
2914
|
+
};
|
|
2748
2915
|
resource.shippingInfo = {
|
|
2749
2916
|
shippingMethod: {
|
|
2750
2917
|
typeId: "shipping-method",
|
|
2751
2918
|
id: method.id
|
|
2752
2919
|
},
|
|
2753
|
-
shippingMethodName: method.name
|
|
2920
|
+
shippingMethodName: method.name,
|
|
2921
|
+
price: shippingPrice,
|
|
2922
|
+
shippingRate,
|
|
2923
|
+
taxedPrice,
|
|
2924
|
+
taxRate,
|
|
2925
|
+
taxCategory: method.taxCategory
|
|
2754
2926
|
};
|
|
2755
2927
|
} else {
|
|
2756
2928
|
resource.shippingInfo = void 0;
|
|
@@ -2775,8 +2947,11 @@ var CartRepository = class extends AbstractResourceRepository {
|
|
|
2775
2947
|
) ?? [];
|
|
2776
2948
|
const resource = {
|
|
2777
2949
|
...getBaseResourceProperties(),
|
|
2950
|
+
anonymousId: draft.anonymousId,
|
|
2951
|
+
billingAddress: draft.billingAddress ? createAddress(draft.billingAddress, context.projectKey, this._storage) : void 0,
|
|
2778
2952
|
cartState: "Active",
|
|
2779
2953
|
country: draft.country,
|
|
2954
|
+
customerEmail: draft.customerEmail,
|
|
2780
2955
|
customLineItems: [],
|
|
2781
2956
|
directDiscounts: [],
|
|
2782
2957
|
discountCodes: [],
|
|
@@ -2794,11 +2969,11 @@ var CartRepository = class extends AbstractResourceRepository {
|
|
|
2794
2969
|
fractionDigits: 0
|
|
2795
2970
|
},
|
|
2796
2971
|
shippingMode: "Single",
|
|
2797
|
-
shippingAddress: createAddress(
|
|
2972
|
+
shippingAddress: draft.shippingAddress ? createAddress(
|
|
2798
2973
|
draft.shippingAddress,
|
|
2799
2974
|
context.projectKey,
|
|
2800
2975
|
this._storage
|
|
2801
|
-
),
|
|
2976
|
+
) : void 0,
|
|
2802
2977
|
shipping: [],
|
|
2803
2978
|
origin: draft.origin ?? "Customer",
|
|
2804
2979
|
refusedGifts: [],
|
|
@@ -2809,6 +2984,7 @@ var CartRepository = class extends AbstractResourceRepository {
|
|
|
2809
2984
|
)
|
|
2810
2985
|
};
|
|
2811
2986
|
resource.totalPrice.centAmount = calculateCartTotalPrice(resource);
|
|
2987
|
+
resource.store = context.storeKey ? { typeId: "store", key: context.storeKey } : void 0;
|
|
2812
2988
|
return this.saveNew(context, resource);
|
|
2813
2989
|
}
|
|
2814
2990
|
getActiveCart(projectKey) {
|
|
@@ -2845,10 +3021,8 @@ var CartRepository = class extends AbstractResourceRepository {
|
|
|
2845
3021
|
product.masterData.current.masterVariant,
|
|
2846
3022
|
...product.masterData.current.variants
|
|
2847
3023
|
].find((x) => {
|
|
2848
|
-
if (sku)
|
|
2849
|
-
|
|
2850
|
-
if (variantId)
|
|
2851
|
-
return x.id === variantId;
|
|
3024
|
+
if (sku) return x.sku === sku;
|
|
3025
|
+
if (variantId) return x.id === variantId;
|
|
2852
3026
|
return false;
|
|
2853
3027
|
});
|
|
2854
3028
|
if (!variant) {
|
|
@@ -4106,8 +4280,7 @@ var OrderUpdateHandler = class extends AbstractUpdateHandler {
|
|
|
4106
4280
|
assert2(resource.shippingInfo, "shippingInfo is not defined");
|
|
4107
4281
|
if (Array.isArray(resource.shippingInfo.deliveries)) {
|
|
4108
4282
|
resource.shippingInfo.deliveries.map((delivery) => {
|
|
4109
|
-
if (delivery.id !== deliveryId)
|
|
4110
|
-
throw "No matching delivery id found";
|
|
4283
|
+
if (delivery.id !== deliveryId) throw "No matching delivery id found";
|
|
4111
4284
|
if (delivery.custom) {
|
|
4112
4285
|
const update = delivery.custom.fields;
|
|
4113
4286
|
update[name] = value;
|
|
@@ -4134,8 +4307,7 @@ var OrderUpdateHandler = class extends AbstractUpdateHandler {
|
|
|
4134
4307
|
);
|
|
4135
4308
|
}
|
|
4136
4309
|
setStore(context, resource, { store }) {
|
|
4137
|
-
if (!store)
|
|
4138
|
-
return;
|
|
4310
|
+
if (!store) return;
|
|
4139
4311
|
const resolvedType = this._storage.getByResourceIdentifier(
|
|
4140
4312
|
context.projectKey,
|
|
4141
4313
|
store
|
|
@@ -4166,8 +4338,7 @@ var OrderUpdateHandler = class extends AbstractUpdateHandler {
|
|
|
4166
4338
|
};
|
|
4167
4339
|
}
|
|
4168
4340
|
updateSyncInfo(context, resource, { channel, externalId, syncedAt }) {
|
|
4169
|
-
if (!channel)
|
|
4170
|
-
return;
|
|
4341
|
+
if (!channel) return;
|
|
4171
4342
|
const resolvedType = this._storage.getByResourceIdentifier(
|
|
4172
4343
|
context.projectKey,
|
|
4173
4344
|
channel
|
|
@@ -4757,8 +4928,7 @@ var generateMatchFunc2 = (filter) => {
|
|
|
4757
4928
|
throw new Error(`Syntax error while parsing '${filter}'.`);
|
|
4758
4929
|
}
|
|
4759
4930
|
return (obj) => {
|
|
4760
|
-
if (!result.children)
|
|
4761
|
-
return false;
|
|
4931
|
+
if (!result.children) return false;
|
|
4762
4932
|
return result.children.some((c) => c.match(obj));
|
|
4763
4933
|
};
|
|
4764
4934
|
};
|
|
@@ -5072,7 +5242,7 @@ var ProductSearch = class {
|
|
|
5072
5242
|
let resources = this._storage.all(projectKey, "product").map(
|
|
5073
5243
|
(r) => this.transform(r, params.productProjectionParameters?.staged ?? false)
|
|
5074
5244
|
).filter((p) => {
|
|
5075
|
-
if (!params.productProjectionParameters?.staged) {
|
|
5245
|
+
if (!(params.productProjectionParameters?.staged ?? false)) {
|
|
5076
5246
|
return p.published;
|
|
5077
5247
|
}
|
|
5078
5248
|
return true;
|
|
@@ -6069,7 +6239,7 @@ var ProductProjectionSearch = class {
|
|
|
6069
6239
|
}
|
|
6070
6240
|
search(projectKey, params) {
|
|
6071
6241
|
let resources = this._storage.all(projectKey, "product").map((r) => this.transform(r, params.staged ?? false)).filter((p) => {
|
|
6072
|
-
if (!params.staged) {
|
|
6242
|
+
if (!(params.staged ?? false)) {
|
|
6073
6243
|
return p.published;
|
|
6074
6244
|
}
|
|
6075
6245
|
return true;
|
|
@@ -6154,8 +6324,7 @@ var ProductProjectionSearch = class {
|
|
|
6154
6324
|
};
|
|
6155
6325
|
}
|
|
6156
6326
|
getFacets(params, products) {
|
|
6157
|
-
if (!params.facet)
|
|
6158
|
-
return {};
|
|
6327
|
+
if (!params.facet) return {};
|
|
6159
6328
|
const result = {};
|
|
6160
6329
|
const regexp = new RegExp(/ counting products$/);
|
|
6161
6330
|
for (let facet of params.facet) {
|
|
@@ -6334,7 +6503,7 @@ var ProductProjectionRepository = class extends AbstractResourceRepository {
|
|
|
6334
6503
|
}
|
|
6335
6504
|
query(context, params = {}) {
|
|
6336
6505
|
let resources = this._storage.all(context.projectKey, "product").map((r) => this._searchService.transform(r, params.staged ?? false)).filter((p) => {
|
|
6337
|
-
if (!params.staged) {
|
|
6506
|
+
if (!(params.staged ?? false)) {
|
|
6338
6507
|
return p.published;
|
|
6339
6508
|
}
|
|
6340
6509
|
return true;
|
|
@@ -6638,8 +6807,7 @@ var ReviewRepository = class extends AbstractResourceRepository {
|
|
|
6638
6807
|
super("review", storage);
|
|
6639
6808
|
}
|
|
6640
6809
|
create(context, draft) {
|
|
6641
|
-
if (!draft.target)
|
|
6642
|
-
throw new Error("Missing target");
|
|
6810
|
+
if (!draft.target) throw new Error("Missing target");
|
|
6643
6811
|
const resource = {
|
|
6644
6812
|
...getBaseResourceProperties(),
|
|
6645
6813
|
locale: draft.locale,
|
|
@@ -6665,48 +6833,6 @@ var ReviewRepository = class extends AbstractResourceRepository {
|
|
|
6665
6833
|
}
|
|
6666
6834
|
};
|
|
6667
6835
|
|
|
6668
|
-
// src/shippingCalculator.ts
|
|
6669
|
-
var markMatchingShippingRate = (cart, shippingRate) => {
|
|
6670
|
-
const isMatching = shippingRate.price.currencyCode === cart.totalPrice.currencyCode;
|
|
6671
|
-
return {
|
|
6672
|
-
...shippingRate,
|
|
6673
|
-
tiers: markMatchingShippingRatePriceTiers(cart, shippingRate.tiers),
|
|
6674
|
-
isMatching
|
|
6675
|
-
};
|
|
6676
|
-
};
|
|
6677
|
-
var markMatchingShippingRatePriceTiers = (cart, tiers) => {
|
|
6678
|
-
if (tiers.length === 0) {
|
|
6679
|
-
return [];
|
|
6680
|
-
}
|
|
6681
|
-
if (new Set(tiers.map((tier) => tier.type)).size > 1) {
|
|
6682
|
-
throw new Error("Can't handle multiple types of tiers");
|
|
6683
|
-
}
|
|
6684
|
-
const tierType = tiers[0].type;
|
|
6685
|
-
switch (tierType) {
|
|
6686
|
-
case "CartValue":
|
|
6687
|
-
return markMatchingCartValueTiers(cart, tiers);
|
|
6688
|
-
default:
|
|
6689
|
-
throw new Error(`Unsupported tier type: ${tierType}`);
|
|
6690
|
-
}
|
|
6691
|
-
};
|
|
6692
|
-
var markMatchingCartValueTiers = (cart, tiers) => {
|
|
6693
|
-
const sortedTiers = [...tiers].sort(
|
|
6694
|
-
(a, b) => b.minimumCentAmount - a.minimumCentAmount
|
|
6695
|
-
);
|
|
6696
|
-
const result = {};
|
|
6697
|
-
let hasMatchingTier = false;
|
|
6698
|
-
for (const tier of sortedTiers) {
|
|
6699
|
-
const isMatching = !hasMatchingTier && cart.totalPrice.currencyCode === tier.price.currencyCode && cart.totalPrice.centAmount >= tier.minimumCentAmount;
|
|
6700
|
-
if (isMatching)
|
|
6701
|
-
hasMatchingTier = true;
|
|
6702
|
-
result[tier.minimumCentAmount] = {
|
|
6703
|
-
...tier,
|
|
6704
|
-
isMatching
|
|
6705
|
-
};
|
|
6706
|
-
}
|
|
6707
|
-
return tiers.map((tier) => result[tier.minimumCentAmount]);
|
|
6708
|
-
};
|
|
6709
|
-
|
|
6710
6836
|
// src/repositories/shipping-method/actions.ts
|
|
6711
6837
|
import deepEqual3 from "deep-equal";
|
|
6712
6838
|
|
|
@@ -6850,41 +6976,7 @@ var ShippingMethodRepository = class extends AbstractResourceRepository {
|
|
|
6850
6976
|
if (!cart) {
|
|
6851
6977
|
return void 0;
|
|
6852
6978
|
}
|
|
6853
|
-
|
|
6854
|
-
throw new CommercetoolsError({
|
|
6855
|
-
code: "InvalidOperation",
|
|
6856
|
-
message: `The cart with ID '${cart.id}' does not have a shipping address set.`
|
|
6857
|
-
});
|
|
6858
|
-
}
|
|
6859
|
-
const zones = this._storage.query(context.projectKey, "zone", {
|
|
6860
|
-
where: [`locations(country="${cart.shippingAddress.country}"))`],
|
|
6861
|
-
limit: 100
|
|
6862
|
-
});
|
|
6863
|
-
const zoneIds = zones.results.map((zone) => zone.id);
|
|
6864
|
-
const shippingMethods = this.query(context, {
|
|
6865
|
-
"where": [
|
|
6866
|
-
`zoneRates(zone(id in (:zoneIds)))`,
|
|
6867
|
-
`zoneRates(shippingRates(price(currencyCode="${cart.totalPrice.currencyCode}")))`
|
|
6868
|
-
],
|
|
6869
|
-
"var.zoneIds": zoneIds,
|
|
6870
|
-
"expand": params.expand
|
|
6871
|
-
});
|
|
6872
|
-
const results = shippingMethods.results.map((shippingMethod) => {
|
|
6873
|
-
const rates = shippingMethod.zoneRates.map((zoneRate) => ({
|
|
6874
|
-
zone: zoneRate.zone,
|
|
6875
|
-
// Iterate through the shippingRates and mark the matching ones
|
|
6876
|
-
// then we filter out the non-matching ones
|
|
6877
|
-
shippingRates: zoneRate.shippingRates.map((rate) => markMatchingShippingRate(cart, rate)).filter((rate) => rate.isMatching)
|
|
6878
|
-
})).filter((zoneRate) => zoneRate.shippingRates.length > 0);
|
|
6879
|
-
return {
|
|
6880
|
-
...shippingMethod,
|
|
6881
|
-
zoneRates: rates
|
|
6882
|
-
};
|
|
6883
|
-
}).filter((shippingMethod) => shippingMethod.zoneRates.length > 0);
|
|
6884
|
-
return {
|
|
6885
|
-
...shippingMethods,
|
|
6886
|
-
results
|
|
6887
|
-
};
|
|
6979
|
+
return getShippingMethodsMatchingCart(context, this._storage, cart, params);
|
|
6888
6980
|
}
|
|
6889
6981
|
_transformZoneRateDraft(context, draft) {
|
|
6890
6982
|
return {
|
|
@@ -7324,8 +7416,7 @@ var StoreRepository = class extends AbstractResourceRepository {
|
|
|
7324
7416
|
}
|
|
7325
7417
|
};
|
|
7326
7418
|
var transformChannels = (context, storage, channels) => {
|
|
7327
|
-
if (!channels)
|
|
7328
|
-
return [];
|
|
7419
|
+
if (!channels) return [];
|
|
7329
7420
|
return channels.map(
|
|
7330
7421
|
(ref) => getReferenceFromResourceIdentifier(
|
|
7331
7422
|
ref,
|
|
@@ -7748,8 +7839,7 @@ var AbstractService = class {
|
|
|
7748
7839
|
expand: this._parseParam(request.query.expand)
|
|
7749
7840
|
}
|
|
7750
7841
|
);
|
|
7751
|
-
if (!result)
|
|
7752
|
-
return response.status(404).send();
|
|
7842
|
+
if (!result) return response.status(404).send();
|
|
7753
7843
|
return response.status(200).send(result);
|
|
7754
7844
|
}
|
|
7755
7845
|
deleteWithId(request, response) {
|