@labdigital/commercetools-mock 2.34.3 → 2.36.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 +305 -170
- 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 +301 -166
- 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/customer/index.ts +43 -9
- 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/services/customer.test.ts +45 -5
- package/src/services/index.ts +2 -0
- package/src/services/my-business-unit.ts +28 -0
- package/src/services/my-customer.test.ts +2 -0
- package/src/{shippingCalculator.test.ts → shipping.test.ts} +1 -1
- package/src/shipping.ts +147 -0
- package/src/types.ts +2 -1
- 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;
|
|
@@ -2849,10 +3021,8 @@ var CartRepository = class extends AbstractResourceRepository {
|
|
|
2849
3021
|
product.masterData.current.masterVariant,
|
|
2850
3022
|
...product.masterData.current.variants
|
|
2851
3023
|
].find((x) => {
|
|
2852
|
-
if (sku)
|
|
2853
|
-
|
|
2854
|
-
if (variantId)
|
|
2855
|
-
return x.id === variantId;
|
|
3024
|
+
if (sku) return x.sku === sku;
|
|
3025
|
+
if (variantId) return x.id === variantId;
|
|
2856
3026
|
return false;
|
|
2857
3027
|
});
|
|
2858
3028
|
if (!variant) {
|
|
@@ -3538,8 +3708,34 @@ var CustomerRepository = class extends AbstractResourceRepository {
|
|
|
3538
3708
|
...address,
|
|
3539
3709
|
id: generateRandomString(5)
|
|
3540
3710
|
})) ?? [];
|
|
3541
|
-
const
|
|
3542
|
-
|
|
3711
|
+
const lookupAdressId = (addresses2, addressId) => {
|
|
3712
|
+
if (addressId < addresses2.length) {
|
|
3713
|
+
const id = addresses2[addressId].id;
|
|
3714
|
+
if (!id) {
|
|
3715
|
+
throw new Error("Address ID is missing");
|
|
3716
|
+
}
|
|
3717
|
+
return id;
|
|
3718
|
+
}
|
|
3719
|
+
throw new CommercetoolsError({
|
|
3720
|
+
code: "InvalidInput",
|
|
3721
|
+
message: `Address with ID '${addressId}' not found.`,
|
|
3722
|
+
errors: [
|
|
3723
|
+
{
|
|
3724
|
+
code: "InvalidInput",
|
|
3725
|
+
message: `Address with ID '${addressId}' not found.`,
|
|
3726
|
+
field: "addressId"
|
|
3727
|
+
}
|
|
3728
|
+
]
|
|
3729
|
+
});
|
|
3730
|
+
};
|
|
3731
|
+
const defaultBillingAddressId = draft.defaultBillingAddress ? lookupAdressId(addresses, draft.defaultBillingAddress) : void 0;
|
|
3732
|
+
const defaultShippingAddressId = draft.defaultShippingAddress ? lookupAdressId(addresses, draft.defaultShippingAddress) : void 0;
|
|
3733
|
+
const shippingAddressIds = draft.shippingAddresses?.map(
|
|
3734
|
+
(addressId) => lookupAdressId(addresses, addressId)
|
|
3735
|
+
) ?? [];
|
|
3736
|
+
const billingAddressIds = draft.billingAddresses?.map(
|
|
3737
|
+
(addressId) => lookupAdressId(addresses, addressId)
|
|
3738
|
+
) ?? [];
|
|
3543
3739
|
const resource = {
|
|
3544
3740
|
...getBaseResourceProperties(),
|
|
3545
3741
|
key: draft.key,
|
|
@@ -3558,6 +3754,8 @@ var CustomerRepository = class extends AbstractResourceRepository {
|
|
|
3558
3754
|
externalId: draft.externalId,
|
|
3559
3755
|
defaultBillingAddressId,
|
|
3560
3756
|
defaultShippingAddressId,
|
|
3757
|
+
shippingAddressIds,
|
|
3758
|
+
billingAddressIds,
|
|
3561
3759
|
custom: createCustomFields(
|
|
3562
3760
|
draft.custom,
|
|
3563
3761
|
context.projectKey,
|
|
@@ -4110,8 +4308,7 @@ var OrderUpdateHandler = class extends AbstractUpdateHandler {
|
|
|
4110
4308
|
assert2(resource.shippingInfo, "shippingInfo is not defined");
|
|
4111
4309
|
if (Array.isArray(resource.shippingInfo.deliveries)) {
|
|
4112
4310
|
resource.shippingInfo.deliveries.map((delivery) => {
|
|
4113
|
-
if (delivery.id !== deliveryId)
|
|
4114
|
-
throw "No matching delivery id found";
|
|
4311
|
+
if (delivery.id !== deliveryId) throw "No matching delivery id found";
|
|
4115
4312
|
if (delivery.custom) {
|
|
4116
4313
|
const update = delivery.custom.fields;
|
|
4117
4314
|
update[name] = value;
|
|
@@ -4138,8 +4335,7 @@ var OrderUpdateHandler = class extends AbstractUpdateHandler {
|
|
|
4138
4335
|
);
|
|
4139
4336
|
}
|
|
4140
4337
|
setStore(context, resource, { store }) {
|
|
4141
|
-
if (!store)
|
|
4142
|
-
return;
|
|
4338
|
+
if (!store) return;
|
|
4143
4339
|
const resolvedType = this._storage.getByResourceIdentifier(
|
|
4144
4340
|
context.projectKey,
|
|
4145
4341
|
store
|
|
@@ -4170,8 +4366,7 @@ var OrderUpdateHandler = class extends AbstractUpdateHandler {
|
|
|
4170
4366
|
};
|
|
4171
4367
|
}
|
|
4172
4368
|
updateSyncInfo(context, resource, { channel, externalId, syncedAt }) {
|
|
4173
|
-
if (!channel)
|
|
4174
|
-
return;
|
|
4369
|
+
if (!channel) return;
|
|
4175
4370
|
const resolvedType = this._storage.getByResourceIdentifier(
|
|
4176
4371
|
context.projectKey,
|
|
4177
4372
|
channel
|
|
@@ -4761,8 +4956,7 @@ var generateMatchFunc2 = (filter) => {
|
|
|
4761
4956
|
throw new Error(`Syntax error while parsing '${filter}'.`);
|
|
4762
4957
|
}
|
|
4763
4958
|
return (obj) => {
|
|
4764
|
-
if (!result.children)
|
|
4765
|
-
return false;
|
|
4959
|
+
if (!result.children) return false;
|
|
4766
4960
|
return result.children.some((c) => c.match(obj));
|
|
4767
4961
|
};
|
|
4768
4962
|
};
|
|
@@ -5076,7 +5270,7 @@ var ProductSearch = class {
|
|
|
5076
5270
|
let resources = this._storage.all(projectKey, "product").map(
|
|
5077
5271
|
(r) => this.transform(r, params.productProjectionParameters?.staged ?? false)
|
|
5078
5272
|
).filter((p) => {
|
|
5079
|
-
if (!params.productProjectionParameters?.staged) {
|
|
5273
|
+
if (!(params.productProjectionParameters?.staged ?? false)) {
|
|
5080
5274
|
return p.published;
|
|
5081
5275
|
}
|
|
5082
5276
|
return true;
|
|
@@ -6073,7 +6267,7 @@ var ProductProjectionSearch = class {
|
|
|
6073
6267
|
}
|
|
6074
6268
|
search(projectKey, params) {
|
|
6075
6269
|
let resources = this._storage.all(projectKey, "product").map((r) => this.transform(r, params.staged ?? false)).filter((p) => {
|
|
6076
|
-
if (!params.staged) {
|
|
6270
|
+
if (!(params.staged ?? false)) {
|
|
6077
6271
|
return p.published;
|
|
6078
6272
|
}
|
|
6079
6273
|
return true;
|
|
@@ -6158,8 +6352,7 @@ var ProductProjectionSearch = class {
|
|
|
6158
6352
|
};
|
|
6159
6353
|
}
|
|
6160
6354
|
getFacets(params, products) {
|
|
6161
|
-
if (!params.facet)
|
|
6162
|
-
return {};
|
|
6355
|
+
if (!params.facet) return {};
|
|
6163
6356
|
const result = {};
|
|
6164
6357
|
const regexp = new RegExp(/ counting products$/);
|
|
6165
6358
|
for (let facet of params.facet) {
|
|
@@ -6338,7 +6531,7 @@ var ProductProjectionRepository = class extends AbstractResourceRepository {
|
|
|
6338
6531
|
}
|
|
6339
6532
|
query(context, params = {}) {
|
|
6340
6533
|
let resources = this._storage.all(context.projectKey, "product").map((r) => this._searchService.transform(r, params.staged ?? false)).filter((p) => {
|
|
6341
|
-
if (!params.staged) {
|
|
6534
|
+
if (!(params.staged ?? false)) {
|
|
6342
6535
|
return p.published;
|
|
6343
6536
|
}
|
|
6344
6537
|
return true;
|
|
@@ -6642,8 +6835,7 @@ var ReviewRepository = class extends AbstractResourceRepository {
|
|
|
6642
6835
|
super("review", storage);
|
|
6643
6836
|
}
|
|
6644
6837
|
create(context, draft) {
|
|
6645
|
-
if (!draft.target)
|
|
6646
|
-
throw new Error("Missing target");
|
|
6838
|
+
if (!draft.target) throw new Error("Missing target");
|
|
6647
6839
|
const resource = {
|
|
6648
6840
|
...getBaseResourceProperties(),
|
|
6649
6841
|
locale: draft.locale,
|
|
@@ -6669,48 +6861,6 @@ var ReviewRepository = class extends AbstractResourceRepository {
|
|
|
6669
6861
|
}
|
|
6670
6862
|
};
|
|
6671
6863
|
|
|
6672
|
-
// src/shippingCalculator.ts
|
|
6673
|
-
var markMatchingShippingRate = (cart, shippingRate) => {
|
|
6674
|
-
const isMatching = shippingRate.price.currencyCode === cart.totalPrice.currencyCode;
|
|
6675
|
-
return {
|
|
6676
|
-
...shippingRate,
|
|
6677
|
-
tiers: markMatchingShippingRatePriceTiers(cart, shippingRate.tiers),
|
|
6678
|
-
isMatching
|
|
6679
|
-
};
|
|
6680
|
-
};
|
|
6681
|
-
var markMatchingShippingRatePriceTiers = (cart, tiers) => {
|
|
6682
|
-
if (tiers.length === 0) {
|
|
6683
|
-
return [];
|
|
6684
|
-
}
|
|
6685
|
-
if (new Set(tiers.map((tier) => tier.type)).size > 1) {
|
|
6686
|
-
throw new Error("Can't handle multiple types of tiers");
|
|
6687
|
-
}
|
|
6688
|
-
const tierType = tiers[0].type;
|
|
6689
|
-
switch (tierType) {
|
|
6690
|
-
case "CartValue":
|
|
6691
|
-
return markMatchingCartValueTiers(cart, tiers);
|
|
6692
|
-
default:
|
|
6693
|
-
throw new Error(`Unsupported tier type: ${tierType}`);
|
|
6694
|
-
}
|
|
6695
|
-
};
|
|
6696
|
-
var markMatchingCartValueTiers = (cart, tiers) => {
|
|
6697
|
-
const sortedTiers = [...tiers].sort(
|
|
6698
|
-
(a, b) => b.minimumCentAmount - a.minimumCentAmount
|
|
6699
|
-
);
|
|
6700
|
-
const result = {};
|
|
6701
|
-
let hasMatchingTier = false;
|
|
6702
|
-
for (const tier of sortedTiers) {
|
|
6703
|
-
const isMatching = !hasMatchingTier && cart.totalPrice.currencyCode === tier.price.currencyCode && cart.totalPrice.centAmount >= tier.minimumCentAmount;
|
|
6704
|
-
if (isMatching)
|
|
6705
|
-
hasMatchingTier = true;
|
|
6706
|
-
result[tier.minimumCentAmount] = {
|
|
6707
|
-
...tier,
|
|
6708
|
-
isMatching
|
|
6709
|
-
};
|
|
6710
|
-
}
|
|
6711
|
-
return tiers.map((tier) => result[tier.minimumCentAmount]);
|
|
6712
|
-
};
|
|
6713
|
-
|
|
6714
6864
|
// src/repositories/shipping-method/actions.ts
|
|
6715
6865
|
import deepEqual3 from "deep-equal";
|
|
6716
6866
|
|
|
@@ -6854,41 +7004,7 @@ var ShippingMethodRepository = class extends AbstractResourceRepository {
|
|
|
6854
7004
|
if (!cart) {
|
|
6855
7005
|
return void 0;
|
|
6856
7006
|
}
|
|
6857
|
-
|
|
6858
|
-
throw new CommercetoolsError({
|
|
6859
|
-
code: "InvalidOperation",
|
|
6860
|
-
message: `The cart with ID '${cart.id}' does not have a shipping address set.`
|
|
6861
|
-
});
|
|
6862
|
-
}
|
|
6863
|
-
const zones = this._storage.query(context.projectKey, "zone", {
|
|
6864
|
-
where: [`locations(country="${cart.shippingAddress.country}"))`],
|
|
6865
|
-
limit: 100
|
|
6866
|
-
});
|
|
6867
|
-
const zoneIds = zones.results.map((zone) => zone.id);
|
|
6868
|
-
const shippingMethods = this.query(context, {
|
|
6869
|
-
"where": [
|
|
6870
|
-
`zoneRates(zone(id in (:zoneIds)))`,
|
|
6871
|
-
`zoneRates(shippingRates(price(currencyCode="${cart.totalPrice.currencyCode}")))`
|
|
6872
|
-
],
|
|
6873
|
-
"var.zoneIds": zoneIds,
|
|
6874
|
-
"expand": params.expand
|
|
6875
|
-
});
|
|
6876
|
-
const results = shippingMethods.results.map((shippingMethod) => {
|
|
6877
|
-
const rates = shippingMethod.zoneRates.map((zoneRate) => ({
|
|
6878
|
-
zone: zoneRate.zone,
|
|
6879
|
-
// Iterate through the shippingRates and mark the matching ones
|
|
6880
|
-
// then we filter out the non-matching ones
|
|
6881
|
-
shippingRates: zoneRate.shippingRates.map((rate) => markMatchingShippingRate(cart, rate)).filter((rate) => rate.isMatching)
|
|
6882
|
-
})).filter((zoneRate) => zoneRate.shippingRates.length > 0);
|
|
6883
|
-
return {
|
|
6884
|
-
...shippingMethod,
|
|
6885
|
-
zoneRates: rates
|
|
6886
|
-
};
|
|
6887
|
-
}).filter((shippingMethod) => shippingMethod.zoneRates.length > 0);
|
|
6888
|
-
return {
|
|
6889
|
-
...shippingMethods,
|
|
6890
|
-
results
|
|
6891
|
-
};
|
|
7007
|
+
return getShippingMethodsMatchingCart(context, this._storage, cart, params);
|
|
6892
7008
|
}
|
|
6893
7009
|
_transformZoneRateDraft(context, draft) {
|
|
6894
7010
|
return {
|
|
@@ -7328,8 +7444,7 @@ var StoreRepository = class extends AbstractResourceRepository {
|
|
|
7328
7444
|
}
|
|
7329
7445
|
};
|
|
7330
7446
|
var transformChannels = (context, storage, channels) => {
|
|
7331
|
-
if (!channels)
|
|
7332
|
-
return [];
|
|
7447
|
+
if (!channels) return [];
|
|
7333
7448
|
return channels.map(
|
|
7334
7449
|
(ref) => getReferenceFromResourceIdentifier(
|
|
7335
7450
|
ref,
|
|
@@ -7752,8 +7867,7 @@ var AbstractService = class {
|
|
|
7752
7867
|
expand: this._parseParam(request.query.expand)
|
|
7753
7868
|
}
|
|
7754
7869
|
);
|
|
7755
|
-
if (!result)
|
|
7756
|
-
return response.status(404).send();
|
|
7870
|
+
if (!result) return response.status(404).send();
|
|
7757
7871
|
return response.status(200).send(result);
|
|
7758
7872
|
}
|
|
7759
7873
|
deleteWithId(request, response) {
|
|
@@ -8136,9 +8250,9 @@ var InventoryEntryService = class extends AbstractService {
|
|
|
8136
8250
|
}
|
|
8137
8251
|
};
|
|
8138
8252
|
|
|
8139
|
-
// src/services/my-
|
|
8253
|
+
// src/services/my-business-unit.ts
|
|
8140
8254
|
import { Router as Router2 } from "express";
|
|
8141
|
-
var
|
|
8255
|
+
var MyBusinessUnitService = class extends AbstractService {
|
|
8142
8256
|
repository;
|
|
8143
8257
|
constructor(parent, repository) {
|
|
8144
8258
|
super(parent);
|
|
@@ -8151,6 +8265,26 @@ var MyCartService = class extends AbstractService {
|
|
|
8151
8265
|
const basePath = this.getBasePath();
|
|
8152
8266
|
const router = Router2({ mergeParams: true });
|
|
8153
8267
|
this.extraRoutes(router);
|
|
8268
|
+
router.get("/business-units/", this.get.bind(this));
|
|
8269
|
+
parent.use(`/${basePath}`, router);
|
|
8270
|
+
}
|
|
8271
|
+
};
|
|
8272
|
+
|
|
8273
|
+
// src/services/my-cart.ts
|
|
8274
|
+
import { Router as Router3 } from "express";
|
|
8275
|
+
var MyCartService = class extends AbstractService {
|
|
8276
|
+
repository;
|
|
8277
|
+
constructor(parent, repository) {
|
|
8278
|
+
super(parent);
|
|
8279
|
+
this.repository = repository;
|
|
8280
|
+
}
|
|
8281
|
+
getBasePath() {
|
|
8282
|
+
return "me";
|
|
8283
|
+
}
|
|
8284
|
+
registerRoutes(parent) {
|
|
8285
|
+
const basePath = this.getBasePath();
|
|
8286
|
+
const router = Router3({ mergeParams: true });
|
|
8287
|
+
this.extraRoutes(router);
|
|
8154
8288
|
router.get("/active-cart", this.activeCart.bind(this));
|
|
8155
8289
|
router.get("/carts/", this.get.bind(this));
|
|
8156
8290
|
router.get("/carts/:id", this.getWithId.bind(this));
|
|
@@ -8169,7 +8303,7 @@ var MyCartService = class extends AbstractService {
|
|
|
8169
8303
|
};
|
|
8170
8304
|
|
|
8171
8305
|
// src/services/my-customer.ts
|
|
8172
|
-
import { Router as
|
|
8306
|
+
import { Router as Router4 } from "express";
|
|
8173
8307
|
var MyCustomerService = class extends AbstractService {
|
|
8174
8308
|
repository;
|
|
8175
8309
|
constructor(parent, repository) {
|
|
@@ -8181,7 +8315,7 @@ var MyCustomerService = class extends AbstractService {
|
|
|
8181
8315
|
}
|
|
8182
8316
|
registerRoutes(parent) {
|
|
8183
8317
|
const basePath = this.getBasePath();
|
|
8184
|
-
const router =
|
|
8318
|
+
const router = Router4({ mergeParams: true });
|
|
8185
8319
|
this.extraRoutes(router);
|
|
8186
8320
|
router.get("", this.getMe.bind(this));
|
|
8187
8321
|
router.post("", this.updateMe.bind(this));
|
|
@@ -8277,7 +8411,7 @@ var MyCustomerService = class extends AbstractService {
|
|
|
8277
8411
|
};
|
|
8278
8412
|
|
|
8279
8413
|
// src/services/my-order.ts
|
|
8280
|
-
import { Router as
|
|
8414
|
+
import { Router as Router5 } from "express";
|
|
8281
8415
|
var MyOrderService = class extends AbstractService {
|
|
8282
8416
|
repository;
|
|
8283
8417
|
constructor(parent, repository) {
|
|
@@ -8289,7 +8423,7 @@ var MyOrderService = class extends AbstractService {
|
|
|
8289
8423
|
}
|
|
8290
8424
|
registerRoutes(parent) {
|
|
8291
8425
|
const basePath = this.getBasePath();
|
|
8292
|
-
const router =
|
|
8426
|
+
const router = Router5({ mergeParams: true });
|
|
8293
8427
|
this.extraRoutes(router);
|
|
8294
8428
|
router.get("/orders/", this.get.bind(this));
|
|
8295
8429
|
router.get("/orders/:id", this.getWithId.bind(this));
|
|
@@ -8651,6 +8785,7 @@ var createServices = (router, repos) => ({
|
|
|
8651
8785
|
"my-cart": new MyCartService(router, repos["my-cart"]),
|
|
8652
8786
|
"my-order": new MyOrderService(router, repos["my-order"]),
|
|
8653
8787
|
"my-customer": new MyCustomerService(router, repos["my-customer"]),
|
|
8788
|
+
"my-business-unit": new MyBusinessUnitService(router, repos["business-unit"]),
|
|
8654
8789
|
"my-payment": new MyPaymentService(router, repos["my-payment"]),
|
|
8655
8790
|
"my-shopping-list": new MyShoppingListService(
|
|
8656
8791
|
router,
|