@labdigital/commercetools-mock 2.7.0 → 2.9.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 +362 -77
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +36 -2
- package/dist/index.d.ts +36 -2
- package/dist/index.js +362 -77
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/ctMock.ts +4 -0
- package/src/lib/predicateParser.test.ts +96 -11
- package/src/lib/predicateParser.ts +43 -12
- package/src/oauth/server.ts +11 -1
- package/src/priceSelector.ts +10 -5
- package/src/repositories/abstract.ts +5 -4
- package/src/repositories/cart.ts +77 -33
- package/src/repositories/custom-object.ts +18 -0
- package/src/repositories/customer.ts +1 -0
- package/src/repositories/helpers.ts +1 -1
- package/src/repositories/order.ts +45 -3
- package/src/repositories/product-projection.ts +15 -0
- package/src/repositories/product-selection.ts +0 -1
- package/src/repositories/product.ts +37 -24
- package/src/repositories/review.ts +36 -4
- package/src/repositories/shipping-method.ts +98 -22
- package/src/services/custom-object.ts +19 -0
- package/src/services/index.ts +2 -0
- package/src/services/product-selection.test.ts +0 -1
- package/src/services/reviews.ts +16 -0
- package/src/services/shipping-method.test.ts +120 -21
- package/src/services/shipping-method.ts +19 -2
- package/src/shippingCalculator.test.ts +280 -0
- package/src/shippingCalculator.ts +74 -0
- package/src/storage/abstract.ts +1 -1
- package/src/storage/in-memory.ts +91 -65
- package/src/types.ts +2 -0
package/dist/index.js
CHANGED
|
@@ -683,7 +683,7 @@ var resolveValue = (obj, val) => {
|
|
|
683
683
|
if (Array.isArray(obj)) {
|
|
684
684
|
return Object.values(obj).filter((v) => val.value in v).map((v) => v[val.value]);
|
|
685
685
|
}
|
|
686
|
-
|
|
686
|
+
return void 0;
|
|
687
687
|
}
|
|
688
688
|
return obj[val.value];
|
|
689
689
|
};
|
|
@@ -763,22 +763,43 @@ var generateMatchFunc = (predicate) => {
|
|
|
763
763
|
const expr = parser.parse();
|
|
764
764
|
lexer.expect(")");
|
|
765
765
|
return (obj, vars) => {
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
766
|
+
if (Array.isArray(obj)) {
|
|
767
|
+
return obj.some((item) => {
|
|
768
|
+
const value = resolveValue(item, left);
|
|
769
|
+
if (value) {
|
|
770
|
+
return expr(value, vars);
|
|
771
|
+
}
|
|
772
|
+
return false;
|
|
773
|
+
});
|
|
774
|
+
} else {
|
|
775
|
+
const value = resolveValue(obj, left);
|
|
776
|
+
if (value) {
|
|
777
|
+
return expr(value, vars);
|
|
778
|
+
}
|
|
779
|
+
return false;
|
|
769
780
|
}
|
|
770
|
-
return false;
|
|
771
781
|
};
|
|
772
782
|
}).bp(")", 0).led("=", 20, ({ left, bp }) => {
|
|
773
783
|
const expr = parser.parse({ terminals: [bp - 1] });
|
|
774
784
|
validateSymbol(expr);
|
|
775
785
|
return (obj, vars) => {
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
786
|
+
if (Array.isArray(obj)) {
|
|
787
|
+
return obj.some((item) => {
|
|
788
|
+
const value = resolveValue(item, left);
|
|
789
|
+
const other = resolveSymbol(expr, vars);
|
|
790
|
+
if (Array.isArray(value)) {
|
|
791
|
+
return !!value.some((elem) => elem === other);
|
|
792
|
+
}
|
|
793
|
+
return value === other;
|
|
794
|
+
});
|
|
795
|
+
} else {
|
|
796
|
+
const resolvedValue = resolveValue(obj, left);
|
|
797
|
+
const resolvedSymbol = resolveSymbol(expr, vars);
|
|
798
|
+
if (Array.isArray(resolvedValue)) {
|
|
799
|
+
return !!resolvedValue.some((elem) => elem === resolvedSymbol);
|
|
800
|
+
}
|
|
801
|
+
return resolvedValue === resolvedSymbol;
|
|
780
802
|
}
|
|
781
|
-
return resolvedValue === resolvedSymbol;
|
|
782
803
|
};
|
|
783
804
|
}).led("!=", 20, ({ left, bp }) => {
|
|
784
805
|
const expr = parser.parse({ terminals: [bp - 1] });
|
|
@@ -846,10 +867,11 @@ var generateMatchFunc = (predicate) => {
|
|
|
846
867
|
if (!Array.isArray(symbols)) {
|
|
847
868
|
symbols = [expr];
|
|
848
869
|
}
|
|
849
|
-
const inValues = symbols.
|
|
870
|
+
const inValues = symbols.flatMap(
|
|
850
871
|
(item) => resolveSymbol(item, vars)
|
|
851
872
|
);
|
|
852
|
-
|
|
873
|
+
const value = resolveValue(obj, left);
|
|
874
|
+
return inValues.includes(value);
|
|
853
875
|
};
|
|
854
876
|
}).led("MATCHES_IGNORE_CASE", 20, ({ left, bp }) => {
|
|
855
877
|
const expr = parser.parse({ terminals: [bp - 1] });
|
|
@@ -1027,9 +1049,12 @@ var InMemoryStorage = class extends AbstractStorage {
|
|
|
1027
1049
|
}
|
|
1028
1050
|
let resources = this.all(projectKey, typeId);
|
|
1029
1051
|
if (params.where) {
|
|
1052
|
+
const vars = Object.fromEntries(
|
|
1053
|
+
Object.entries(params).filter(([key]) => key.startsWith("var.")).map(([key, value]) => [key.slice(4), value])
|
|
1054
|
+
);
|
|
1030
1055
|
try {
|
|
1031
1056
|
const filterFunc = parseQueryExpression(params.where);
|
|
1032
|
-
resources = resources.filter((resource) => filterFunc(resource,
|
|
1057
|
+
resources = resources.filter((resource) => filterFunc(resource, vars));
|
|
1033
1058
|
} catch (err) {
|
|
1034
1059
|
throw new CommercetoolsError(
|
|
1035
1060
|
{
|
|
@@ -1096,28 +1121,34 @@ var InMemoryStorage = class extends AbstractStorage {
|
|
|
1096
1121
|
if (resource) {
|
|
1097
1122
|
return resource;
|
|
1098
1123
|
}
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1124
|
+
throw new CommercetoolsError({
|
|
1125
|
+
code: "ReferencedResourceNotFound",
|
|
1126
|
+
message: `The referenced object of type '${identifier.typeId}' with id '${identifier.id}' was not found. It either doesn't exist, or it can't be accessed from this endpoint (e.g., if the endpoint filters by store or customer account).`,
|
|
1127
|
+
typeId: identifier.typeId,
|
|
1128
|
+
id: identifier.id
|
|
1129
|
+
});
|
|
1103
1130
|
}
|
|
1104
1131
|
if (identifier.key) {
|
|
1105
|
-
const
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
return resource;
|
|
1113
|
-
}
|
|
1114
|
-
} else {
|
|
1115
|
-
throw new Error(
|
|
1116
|
-
`No storage found for resource type: ${identifier.typeId}`
|
|
1117
|
-
);
|
|
1132
|
+
const resource = this.getByKey(
|
|
1133
|
+
projectKey,
|
|
1134
|
+
identifier.typeId,
|
|
1135
|
+
identifier.key
|
|
1136
|
+
);
|
|
1137
|
+
if (resource) {
|
|
1138
|
+
return resource;
|
|
1118
1139
|
}
|
|
1140
|
+
throw new CommercetoolsError({
|
|
1141
|
+
code: "ReferencedResourceNotFound",
|
|
1142
|
+
message: `The referenced object of type '${identifier.typeId}' with key '${identifier.key}' was not found. It either doesn't exist, or it can't be accessed from this endpoint (e.g., if the endpoint filters by store or customer account).`,
|
|
1143
|
+
typeId: identifier.typeId,
|
|
1144
|
+
key: identifier.key
|
|
1145
|
+
});
|
|
1119
1146
|
}
|
|
1120
|
-
|
|
1147
|
+
throw new CommercetoolsError({
|
|
1148
|
+
code: "InvalidJsonInput",
|
|
1149
|
+
message: "Request body does not contain valid JSON.",
|
|
1150
|
+
detailedErrorMessage: "ResourceIdentifier requires an 'id' xor a 'key'"
|
|
1151
|
+
});
|
|
1121
1152
|
}
|
|
1122
1153
|
addProject = (projectKey) => {
|
|
1123
1154
|
if (!this.projects[projectKey]) {
|
|
@@ -1194,11 +1225,13 @@ var InMemoryStorage = class extends AbstractStorage {
|
|
|
1194
1225
|
if (reference === void 0)
|
|
1195
1226
|
return;
|
|
1196
1227
|
if (reference.typeId !== void 0 && (reference.id !== void 0 || reference.key !== void 0)) {
|
|
1197
|
-
reference.obj
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1228
|
+
if (!reference.obj) {
|
|
1229
|
+
reference.obj = this.getByResourceIdentifier(projectKey, {
|
|
1230
|
+
typeId: reference.typeId,
|
|
1231
|
+
id: reference.id,
|
|
1232
|
+
key: reference.key
|
|
1233
|
+
});
|
|
1234
|
+
}
|
|
1202
1235
|
if (expand) {
|
|
1203
1236
|
this._resolveResource(projectKey, reference.obj, expand);
|
|
1204
1237
|
}
|
|
@@ -1269,11 +1302,12 @@ var hashPassword = (clearPassword) => Buffer.from(clearPassword).toString("base6
|
|
|
1269
1302
|
|
|
1270
1303
|
// src/oauth/server.ts
|
|
1271
1304
|
var OAuth2Server = class {
|
|
1272
|
-
store;
|
|
1273
|
-
customerRepository;
|
|
1274
1305
|
constructor(options) {
|
|
1306
|
+
this.options = options;
|
|
1275
1307
|
this.store = new OAuth2Store(options.validate);
|
|
1276
1308
|
}
|
|
1309
|
+
store;
|
|
1310
|
+
customerRepository;
|
|
1277
1311
|
setCustomerRepository(repository) {
|
|
1278
1312
|
this.customerRepository = repository;
|
|
1279
1313
|
}
|
|
@@ -1297,6 +1331,11 @@ var OAuth2Server = class {
|
|
|
1297
1331
|
return router;
|
|
1298
1332
|
}
|
|
1299
1333
|
createMiddleware() {
|
|
1334
|
+
if (!this.options.validate) {
|
|
1335
|
+
return async (request, response, next) => {
|
|
1336
|
+
next();
|
|
1337
|
+
};
|
|
1338
|
+
}
|
|
1300
1339
|
return async (request, response, next) => {
|
|
1301
1340
|
const token = getBearerToken(request);
|
|
1302
1341
|
if (!token) {
|
|
@@ -1633,7 +1672,7 @@ var getReferenceFromResourceIdentifier = (resourceIdentifier, projectKey, storag
|
|
|
1633
1672
|
resourceIdentifier
|
|
1634
1673
|
);
|
|
1635
1674
|
if (!resource) {
|
|
1636
|
-
const errIdentifier = resourceIdentifier.key ? `key '${resourceIdentifier.key}'` : `identifier '${resourceIdentifier.
|
|
1675
|
+
const errIdentifier = resourceIdentifier.key ? `key '${resourceIdentifier.key}'` : `identifier '${resourceIdentifier.id}'`;
|
|
1637
1676
|
throw new CommercetoolsError(
|
|
1638
1677
|
{
|
|
1639
1678
|
code: "ReferencedResourceNotFound",
|
|
@@ -1834,10 +1873,7 @@ var AbstractResourceRepository = class extends AbstractRepository {
|
|
|
1834
1873
|
}
|
|
1835
1874
|
query(context, params = {}) {
|
|
1836
1875
|
const result = this._storage.query(context.projectKey, this.getTypeId(), {
|
|
1837
|
-
|
|
1838
|
-
where: params.where,
|
|
1839
|
-
offset: params.offset,
|
|
1840
|
-
limit: params.limit
|
|
1876
|
+
...params
|
|
1841
1877
|
});
|
|
1842
1878
|
result.results = result.results.map(this.postProcessResource);
|
|
1843
1879
|
return result;
|
|
@@ -2157,6 +2193,11 @@ var CartRepository = class extends AbstractResourceRepository {
|
|
|
2157
2193
|
fractionDigits: 0
|
|
2158
2194
|
},
|
|
2159
2195
|
shippingMode: "Single",
|
|
2196
|
+
shippingAddress: createAddress(
|
|
2197
|
+
draft.shippingAddress,
|
|
2198
|
+
context.projectKey,
|
|
2199
|
+
this._storage
|
|
2200
|
+
),
|
|
2160
2201
|
shipping: [],
|
|
2161
2202
|
origin: draft.origin ?? "Customer",
|
|
2162
2203
|
refusedGifts: [],
|
|
@@ -2358,9 +2399,6 @@ var CartRepository = class extends AbstractResourceRepository {
|
|
|
2358
2399
|
context.projectKey,
|
|
2359
2400
|
shippingMethod
|
|
2360
2401
|
);
|
|
2361
|
-
if (!method) {
|
|
2362
|
-
throw new Error(`Type ${shippingMethod} not found`);
|
|
2363
|
-
}
|
|
2364
2402
|
resource.shippingInfo = {
|
|
2365
2403
|
shippingMethod: {
|
|
2366
2404
|
typeId: "shipping-method",
|
|
@@ -2384,6 +2422,33 @@ var CartRepository = class extends AbstractResourceRepository {
|
|
|
2384
2422
|
}
|
|
2385
2423
|
resource.custom.fields[name] = value;
|
|
2386
2424
|
},
|
|
2425
|
+
setCustomShippingMethod: (context, resource, {
|
|
2426
|
+
shippingMethodName,
|
|
2427
|
+
shippingRate,
|
|
2428
|
+
taxCategory,
|
|
2429
|
+
externalTaxRate
|
|
2430
|
+
}) => {
|
|
2431
|
+
if (externalTaxRate) {
|
|
2432
|
+
throw new Error("External tax rate is not supported");
|
|
2433
|
+
}
|
|
2434
|
+
const tax = taxCategory ? this._storage.getByResourceIdentifier(
|
|
2435
|
+
context.projectKey,
|
|
2436
|
+
taxCategory
|
|
2437
|
+
) : void 0;
|
|
2438
|
+
resource.shippingInfo = {
|
|
2439
|
+
shippingMethodName,
|
|
2440
|
+
price: createCentPrecisionMoney(shippingRate.price),
|
|
2441
|
+
shippingRate: {
|
|
2442
|
+
price: createTypedMoney(shippingRate.price),
|
|
2443
|
+
tiers: []
|
|
2444
|
+
},
|
|
2445
|
+
taxCategory: tax ? {
|
|
2446
|
+
typeId: "tax-category",
|
|
2447
|
+
id: tax?.id
|
|
2448
|
+
} : void 0,
|
|
2449
|
+
shippingMethodState: "MatchesCart"
|
|
2450
|
+
};
|
|
2451
|
+
},
|
|
2387
2452
|
setCustomType: (context, resource, { type, fields }) => {
|
|
2388
2453
|
if (!type) {
|
|
2389
2454
|
resource.custom = void 0;
|
|
@@ -2935,6 +3000,16 @@ var CustomObjectRepository = class extends AbstractResourceRepository {
|
|
|
2935
3000
|
return resource;
|
|
2936
3001
|
}
|
|
2937
3002
|
}
|
|
3003
|
+
queryWithContainer(context, container, params = {}) {
|
|
3004
|
+
const whereClause = params.where || [];
|
|
3005
|
+
whereClause.push(`container="${container}"`);
|
|
3006
|
+
const result = this._storage.query(context.projectKey, this.getTypeId(), {
|
|
3007
|
+
...params,
|
|
3008
|
+
where: whereClause
|
|
3009
|
+
});
|
|
3010
|
+
result.results = result.results.map(this.postProcessResource);
|
|
3011
|
+
return result;
|
|
3012
|
+
}
|
|
2938
3013
|
getWithContainerAndKey(context, container, key) {
|
|
2939
3014
|
const items = this._storage.all(context.projectKey, this.getTypeId());
|
|
2940
3015
|
return items.find(
|
|
@@ -2973,7 +3048,8 @@ var CustomerRepository = class extends AbstractResourceRepository {
|
|
|
2973
3048
|
email: draft.email.toLowerCase(),
|
|
2974
3049
|
password: draft.password ? hashPassword(draft.password) : void 0,
|
|
2975
3050
|
isEmailVerified: draft.isEmailVerified || false,
|
|
2976
|
-
addresses: []
|
|
3051
|
+
addresses: [],
|
|
3052
|
+
customerNumber: draft.customerNumber
|
|
2977
3053
|
};
|
|
2978
3054
|
this.saveNew(context, resource);
|
|
2979
3055
|
return resource;
|
|
@@ -3479,10 +3555,11 @@ var OrderRepository = class extends AbstractResourceRepository {
|
|
|
3479
3555
|
name: draft.name,
|
|
3480
3556
|
quantity: draft.quantity ?? 0,
|
|
3481
3557
|
perMethodTaxRate: [],
|
|
3482
|
-
priceMode: draft.priceMode,
|
|
3558
|
+
priceMode: draft.priceMode ?? "Standard",
|
|
3483
3559
|
slug: draft.slug,
|
|
3484
3560
|
state: [],
|
|
3485
|
-
totalPrice: createCentPrecisionMoney(draft.money)
|
|
3561
|
+
totalPrice: createCentPrecisionMoney(draft.money),
|
|
3562
|
+
taxedPricePortions: []
|
|
3486
3563
|
};
|
|
3487
3564
|
return lineItem;
|
|
3488
3565
|
}
|
|
@@ -3518,6 +3595,37 @@ var OrderRepository = class extends AbstractResourceRepository {
|
|
|
3518
3595
|
id: payment.id
|
|
3519
3596
|
});
|
|
3520
3597
|
},
|
|
3598
|
+
addReturnInfo: (context, resource, info) => {
|
|
3599
|
+
if (!resource.returnInfo) {
|
|
3600
|
+
resource.returnInfo = [];
|
|
3601
|
+
}
|
|
3602
|
+
const resolved = {
|
|
3603
|
+
items: info.items.map((item) => {
|
|
3604
|
+
const common = {
|
|
3605
|
+
...getBaseResourceProperties(),
|
|
3606
|
+
quantity: item.quantity,
|
|
3607
|
+
paymentState: "Initial",
|
|
3608
|
+
shipmentState: "Initial",
|
|
3609
|
+
comment: item.comment
|
|
3610
|
+
};
|
|
3611
|
+
if (item.customLineItemId) {
|
|
3612
|
+
return {
|
|
3613
|
+
...common,
|
|
3614
|
+
type: "CustomLineItemReturnItem",
|
|
3615
|
+
customLineItemId: item.customLineItemId
|
|
3616
|
+
};
|
|
3617
|
+
}
|
|
3618
|
+
return {
|
|
3619
|
+
...common,
|
|
3620
|
+
type: "LineItemReturnItem",
|
|
3621
|
+
lineItemId: item.customLineItemId || item.lineItemId
|
|
3622
|
+
};
|
|
3623
|
+
}),
|
|
3624
|
+
returnTrackingId: info.returnTrackingId,
|
|
3625
|
+
returnDate: info.returnDate
|
|
3626
|
+
};
|
|
3627
|
+
resource.returnInfo.push(resolved);
|
|
3628
|
+
},
|
|
3521
3629
|
changeOrderState: (context, resource, { orderState }) => {
|
|
3522
3630
|
resource.orderState = orderState;
|
|
3523
3631
|
},
|
|
@@ -3828,9 +3936,9 @@ var ProductRepository = class extends AbstractResourceRepository {
|
|
|
3828
3936
|
slug: draft.slug,
|
|
3829
3937
|
description: draft.description,
|
|
3830
3938
|
categories: categoryReferences,
|
|
3831
|
-
masterVariant: variantFromDraft(1, draft.masterVariant),
|
|
3939
|
+
masterVariant: this.variantFromDraft(context, 1, draft.masterVariant),
|
|
3832
3940
|
variants: draft.variants?.map(
|
|
3833
|
-
(variant, index) => variantFromDraft(index + 2, variant)
|
|
3941
|
+
(variant, index) => this.variantFromDraft(context, index + 2, variant)
|
|
3834
3942
|
) ?? [],
|
|
3835
3943
|
metaTitle: draft.metaTitle,
|
|
3836
3944
|
metaDescription: draft.metaDescription,
|
|
@@ -3853,6 +3961,30 @@ var ProductRepository = class extends AbstractResourceRepository {
|
|
|
3853
3961
|
this.saveNew(context, resource);
|
|
3854
3962
|
return resource;
|
|
3855
3963
|
}
|
|
3964
|
+
variantFromDraft(context, variantId, variant) {
|
|
3965
|
+
return {
|
|
3966
|
+
id: variantId,
|
|
3967
|
+
sku: variant?.sku,
|
|
3968
|
+
key: variant?.key,
|
|
3969
|
+
attributes: variant?.attributes ?? [],
|
|
3970
|
+
prices: variant?.prices?.map((p) => this.priceFromDraft(context, p)),
|
|
3971
|
+
assets: [],
|
|
3972
|
+
images: []
|
|
3973
|
+
};
|
|
3974
|
+
}
|
|
3975
|
+
priceFromDraft(context, draft) {
|
|
3976
|
+
return {
|
|
3977
|
+
id: uuidv46(),
|
|
3978
|
+
key: draft.key,
|
|
3979
|
+
country: draft.country,
|
|
3980
|
+
value: createTypedMoney(draft.value),
|
|
3981
|
+
channel: draft.channel ? getReferenceFromResourceIdentifier(
|
|
3982
|
+
draft.channel,
|
|
3983
|
+
context.projectKey,
|
|
3984
|
+
this._storage
|
|
3985
|
+
) : void 0
|
|
3986
|
+
};
|
|
3987
|
+
}
|
|
3856
3988
|
actions = {
|
|
3857
3989
|
publish: (context, resource, { scope }) => {
|
|
3858
3990
|
resource.masterData.current = resource.masterData.staged;
|
|
@@ -4097,7 +4229,7 @@ var ProductRepository = class extends AbstractResourceRepository {
|
|
|
4097
4229
|
data.variants[variantIndex] = variant;
|
|
4098
4230
|
}
|
|
4099
4231
|
};
|
|
4100
|
-
const priceToAdd = priceFromDraft(price);
|
|
4232
|
+
const priceToAdd = this.priceFromDraft(context, price);
|
|
4101
4233
|
const onlyStaged = staged !== void 0 ? staged : true;
|
|
4102
4234
|
addVariantPrice(resource.masterData.staged, priceToAdd);
|
|
4103
4235
|
if (!onlyStaged) {
|
|
@@ -4254,7 +4386,7 @@ var ProductRepository = class extends AbstractResourceRepository {
|
|
|
4254
4386
|
(max, element) => element.id > max ? element.id : max,
|
|
4255
4387
|
0
|
|
4256
4388
|
);
|
|
4257
|
-
const variant = variantFromDraft(maxId + 1, variantDraft);
|
|
4389
|
+
const variant = this.variantFromDraft(context, maxId + 1, variantDraft);
|
|
4258
4390
|
dataStaged.variants.push(variant);
|
|
4259
4391
|
const onlyStaged = staged !== void 0 ? staged : true;
|
|
4260
4392
|
if (!onlyStaged) {
|
|
@@ -4492,21 +4624,6 @@ var getVariant = (productData, variantId, sku) => {
|
|
|
4492
4624
|
variantIndex: !isMasterVariant && foundVariant ? productData.variants.indexOf(foundVariant) : -1
|
|
4493
4625
|
};
|
|
4494
4626
|
};
|
|
4495
|
-
var variantFromDraft = (variantId, variant) => ({
|
|
4496
|
-
id: variantId,
|
|
4497
|
-
sku: variant?.sku,
|
|
4498
|
-
key: variant?.key,
|
|
4499
|
-
attributes: variant?.attributes ?? [],
|
|
4500
|
-
prices: variant?.prices?.map(priceFromDraft),
|
|
4501
|
-
assets: [],
|
|
4502
|
-
images: []
|
|
4503
|
-
});
|
|
4504
|
-
var priceFromDraft = (draft) => ({
|
|
4505
|
-
id: uuidv46(),
|
|
4506
|
-
key: draft.key,
|
|
4507
|
-
country: draft.country,
|
|
4508
|
-
value: createTypedMoney(draft.value)
|
|
4509
|
-
});
|
|
4510
4627
|
|
|
4511
4628
|
// src/repositories/product-discount.ts
|
|
4512
4629
|
var ProductDiscountRepository = class extends AbstractResourceRepository {
|
|
@@ -4778,7 +4895,7 @@ var getVariants = (p) => [
|
|
|
4778
4895
|
];
|
|
4779
4896
|
|
|
4780
4897
|
// src/priceSelector.ts
|
|
4781
|
-
var applyPriceSelector = (products, selector) => {
|
|
4898
|
+
var applyPriceSelector = (products, selector, noScopedPrice = false) => {
|
|
4782
4899
|
validatePriceSelector(selector);
|
|
4783
4900
|
for (const product of products) {
|
|
4784
4901
|
const variants = [
|
|
@@ -4789,11 +4906,14 @@ var applyPriceSelector = (products, selector) => {
|
|
|
4789
4906
|
const scopedPrices = variant.prices?.filter((p) => priceSelectorFilter(p, selector)) ?? [];
|
|
4790
4907
|
if (scopedPrices.length > 0) {
|
|
4791
4908
|
const price = scopedPrices[0];
|
|
4792
|
-
variant.
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4909
|
+
variant.price = scopedPrices[0];
|
|
4910
|
+
if (!noScopedPrice) {
|
|
4911
|
+
variant.scopedPriceDiscounted = false;
|
|
4912
|
+
variant.scopedPrice = {
|
|
4913
|
+
...price,
|
|
4914
|
+
currentValue: price.value
|
|
4915
|
+
};
|
|
4916
|
+
}
|
|
4797
4917
|
}
|
|
4798
4918
|
}
|
|
4799
4919
|
}
|
|
@@ -5128,6 +5248,16 @@ var ProductProjectionRepository = class extends AbstractResourceRepository {
|
|
|
5128
5248
|
);
|
|
5129
5249
|
}
|
|
5130
5250
|
}
|
|
5251
|
+
applyPriceSelector(
|
|
5252
|
+
resources,
|
|
5253
|
+
{
|
|
5254
|
+
country: params.priceCountry,
|
|
5255
|
+
channel: params.priceChannel,
|
|
5256
|
+
customerGroup: params.priceCustomerGroup,
|
|
5257
|
+
currency: params.priceCurrency
|
|
5258
|
+
},
|
|
5259
|
+
true
|
|
5260
|
+
);
|
|
5131
5261
|
if (params.expand !== void 0) {
|
|
5132
5262
|
resources = resources.map(
|
|
5133
5263
|
(resource) => this._storage.expand(context.projectKey, resource, params.expand)
|
|
@@ -5162,7 +5292,6 @@ var ProductSelectionRepository = class extends AbstractResourceRepository {
|
|
|
5162
5292
|
productCount: 0,
|
|
5163
5293
|
key: draft.key,
|
|
5164
5294
|
name: draft.name,
|
|
5165
|
-
type: "individual",
|
|
5166
5295
|
mode: "Individual"
|
|
5167
5296
|
};
|
|
5168
5297
|
this.saveNew(context, resource);
|
|
@@ -5378,9 +5507,28 @@ var ReviewRepository = class extends AbstractResourceRepository {
|
|
|
5378
5507
|
return "review";
|
|
5379
5508
|
}
|
|
5380
5509
|
create(context, draft) {
|
|
5510
|
+
if (!draft.target)
|
|
5511
|
+
throw new Error("Missing target");
|
|
5381
5512
|
const resource = {
|
|
5382
5513
|
...getBaseResourceProperties(),
|
|
5383
|
-
|
|
5514
|
+
locale: draft.locale,
|
|
5515
|
+
authorName: draft.authorName,
|
|
5516
|
+
title: draft.title,
|
|
5517
|
+
text: draft.text,
|
|
5518
|
+
rating: draft.rating,
|
|
5519
|
+
uniquenessValue: draft.uniquenessValue,
|
|
5520
|
+
state: draft.state ? getReferenceFromResourceIdentifier(
|
|
5521
|
+
draft.state,
|
|
5522
|
+
context.projectKey,
|
|
5523
|
+
this._storage
|
|
5524
|
+
) : void 0,
|
|
5525
|
+
target: draft.target ? getReferenceFromResourceIdentifier(draft.target, context.projectKey, this._storage) : void 0,
|
|
5526
|
+
includedInStatistics: false,
|
|
5527
|
+
custom: createCustomFields(
|
|
5528
|
+
draft.custom,
|
|
5529
|
+
context.projectKey,
|
|
5530
|
+
this._storage
|
|
5531
|
+
)
|
|
5384
5532
|
};
|
|
5385
5533
|
this.saveNew(context, resource);
|
|
5386
5534
|
return resource;
|
|
@@ -5390,6 +5538,50 @@ var ReviewRepository = class extends AbstractResourceRepository {
|
|
|
5390
5538
|
|
|
5391
5539
|
// src/repositories/shipping-method.ts
|
|
5392
5540
|
import deepEqual3 from "deep-equal";
|
|
5541
|
+
|
|
5542
|
+
// src/shippingCalculator.ts
|
|
5543
|
+
var markMatchingShippingRate = (cart, shippingRate) => {
|
|
5544
|
+
const isMatching = shippingRate.price.currencyCode === cart.totalPrice.currencyCode;
|
|
5545
|
+
return {
|
|
5546
|
+
...shippingRate,
|
|
5547
|
+
tiers: markMatchingShippingRatePriceTiers(cart, shippingRate.tiers),
|
|
5548
|
+
isMatching
|
|
5549
|
+
};
|
|
5550
|
+
};
|
|
5551
|
+
var markMatchingShippingRatePriceTiers = (cart, tiers) => {
|
|
5552
|
+
if (tiers.length === 0) {
|
|
5553
|
+
return [];
|
|
5554
|
+
}
|
|
5555
|
+
if (new Set(tiers.map((tier) => tier.type)).size > 1) {
|
|
5556
|
+
throw new Error("Can't handle multiple types of tiers");
|
|
5557
|
+
}
|
|
5558
|
+
const tierType = tiers[0].type;
|
|
5559
|
+
switch (tierType) {
|
|
5560
|
+
case "CartValue":
|
|
5561
|
+
return markMatchingCartValueTiers(cart, tiers);
|
|
5562
|
+
default:
|
|
5563
|
+
throw new Error(`Unsupported tier type: ${tierType}`);
|
|
5564
|
+
}
|
|
5565
|
+
};
|
|
5566
|
+
var markMatchingCartValueTiers = (cart, tiers) => {
|
|
5567
|
+
const sortedTiers = [...tiers].sort(
|
|
5568
|
+
(a, b) => b.minimumCentAmount - a.minimumCentAmount
|
|
5569
|
+
);
|
|
5570
|
+
const result = {};
|
|
5571
|
+
let hasMatchingTier = false;
|
|
5572
|
+
for (const tier of sortedTiers) {
|
|
5573
|
+
const isMatching = !hasMatchingTier && cart.totalPrice.currencyCode === tier.price.currencyCode && cart.totalPrice.centAmount >= tier.minimumCentAmount;
|
|
5574
|
+
if (isMatching)
|
|
5575
|
+
hasMatchingTier = true;
|
|
5576
|
+
result[tier.minimumCentAmount] = {
|
|
5577
|
+
...tier,
|
|
5578
|
+
isMatching
|
|
5579
|
+
};
|
|
5580
|
+
}
|
|
5581
|
+
return tiers.map((tier) => result[tier.minimumCentAmount]);
|
|
5582
|
+
};
|
|
5583
|
+
|
|
5584
|
+
// src/repositories/shipping-method.ts
|
|
5393
5585
|
var ShippingMethodRepository = class extends AbstractResourceRepository {
|
|
5394
5586
|
getTypeId() {
|
|
5395
5587
|
return "shipping-method";
|
|
@@ -5429,6 +5621,53 @@ var ShippingMethodRepository = class extends AbstractResourceRepository {
|
|
|
5429
5621
|
freeAbove: rate.freeAbove && createTypedMoney(rate.freeAbove),
|
|
5430
5622
|
tiers: rate.tiers || []
|
|
5431
5623
|
});
|
|
5624
|
+
/*
|
|
5625
|
+
* Retrieves all the ShippingMethods that can ship to the shipping address of
|
|
5626
|
+
* the given Cart. Each ShippingMethod contains exactly one ShippingRate with
|
|
5627
|
+
* the flag isMatching set to true. This ShippingRate is used when the
|
|
5628
|
+
* ShippingMethod is added to the Cart.
|
|
5629
|
+
*/
|
|
5630
|
+
matchingCart(context, cartId, params = {}) {
|
|
5631
|
+
const cart = this._storage.get(context.projectKey, "cart", cartId);
|
|
5632
|
+
if (!cart) {
|
|
5633
|
+
return void 0;
|
|
5634
|
+
}
|
|
5635
|
+
if (!cart.shippingAddress?.country) {
|
|
5636
|
+
throw new CommercetoolsError({
|
|
5637
|
+
code: "InvalidOperation",
|
|
5638
|
+
message: `The cart with ID '${cart.id}' does not have a shipping address set.`
|
|
5639
|
+
});
|
|
5640
|
+
}
|
|
5641
|
+
const zones = this._storage.query(context.projectKey, "zone", {
|
|
5642
|
+
where: [`locations(country="${cart.shippingAddress.country}"))`],
|
|
5643
|
+
limit: 100
|
|
5644
|
+
});
|
|
5645
|
+
const zoneIds = zones.results.map((zone) => zone.id);
|
|
5646
|
+
const shippingMethods = this.query(context, {
|
|
5647
|
+
where: [
|
|
5648
|
+
`zoneRates(zone(id in (:zoneIds)))`,
|
|
5649
|
+
`zoneRates(shippingRates(price(currencyCode="${cart.totalPrice.currencyCode}")))`
|
|
5650
|
+
],
|
|
5651
|
+
"var.zoneIds": zoneIds,
|
|
5652
|
+
expand: params.expand
|
|
5653
|
+
});
|
|
5654
|
+
const results = shippingMethods.results.map((shippingMethod) => {
|
|
5655
|
+
const rates = shippingMethod.zoneRates.map((zoneRate) => ({
|
|
5656
|
+
zone: zoneRate.zone,
|
|
5657
|
+
// Iterate through the shippingRates and mark the matching ones
|
|
5658
|
+
// then we filter out the non-matching ones
|
|
5659
|
+
shippingRates: zoneRate.shippingRates.map((rate) => markMatchingShippingRate(cart, rate)).filter((rate) => rate.isMatching)
|
|
5660
|
+
})).filter((zoneRate) => zoneRate.shippingRates.length > 0);
|
|
5661
|
+
return {
|
|
5662
|
+
...shippingMethod,
|
|
5663
|
+
zoneRates: rates
|
|
5664
|
+
};
|
|
5665
|
+
}).filter((shippingMethod) => shippingMethod.zoneRates.length > 0);
|
|
5666
|
+
return {
|
|
5667
|
+
...shippingMethods,
|
|
5668
|
+
results
|
|
5669
|
+
};
|
|
5670
|
+
}
|
|
5432
5671
|
actions = {
|
|
5433
5672
|
addShippingRate: (_context, resource, { shippingRate, zone }) => {
|
|
5434
5673
|
const rate = this._transformShippingRate(shippingRate);
|
|
@@ -6282,10 +6521,26 @@ var CustomObjectService = class extends AbstractService {
|
|
|
6282
6521
|
return "custom-objects";
|
|
6283
6522
|
}
|
|
6284
6523
|
extraRoutes(router) {
|
|
6524
|
+
router.get("/:container", this.getWithContainer.bind(this));
|
|
6285
6525
|
router.get("/:container/:key", this.getWithContainerAndKey.bind(this));
|
|
6286
6526
|
router.post("/:container/:key", this.createWithContainerAndKey.bind(this));
|
|
6287
6527
|
router.delete("/:container/:key", this.deleteWithContainerAndKey.bind(this));
|
|
6288
6528
|
}
|
|
6529
|
+
getWithContainer(request, response) {
|
|
6530
|
+
const limit = this._parseParam(request.query.limit);
|
|
6531
|
+
const offset = this._parseParam(request.query.offset);
|
|
6532
|
+
const result = this.repository.queryWithContainer(
|
|
6533
|
+
getRepositoryContext(request),
|
|
6534
|
+
request.params.container,
|
|
6535
|
+
{
|
|
6536
|
+
expand: this._parseParam(request.query.expand),
|
|
6537
|
+
where: this._parseParam(request.query.where),
|
|
6538
|
+
limit: limit !== void 0 ? Number(limit) : void 0,
|
|
6539
|
+
offset: offset !== void 0 ? Number(offset) : void 0
|
|
6540
|
+
}
|
|
6541
|
+
);
|
|
6542
|
+
return response.status(200).send(result);
|
|
6543
|
+
}
|
|
6289
6544
|
getWithContainerAndKey(request, response) {
|
|
6290
6545
|
const result = this.repository.getWithContainerAndKey(
|
|
6291
6546
|
getRepositoryContext(request),
|
|
@@ -6700,6 +6955,18 @@ var ProductService = class extends AbstractService {
|
|
|
6700
6955
|
}
|
|
6701
6956
|
};
|
|
6702
6957
|
|
|
6958
|
+
// src/services/reviews.ts
|
|
6959
|
+
var ReviewService = class extends AbstractService {
|
|
6960
|
+
repository;
|
|
6961
|
+
constructor(parent, repository) {
|
|
6962
|
+
super(parent);
|
|
6963
|
+
this.repository = repository;
|
|
6964
|
+
}
|
|
6965
|
+
getBasePath() {
|
|
6966
|
+
return "reviews";
|
|
6967
|
+
}
|
|
6968
|
+
};
|
|
6969
|
+
|
|
6703
6970
|
// src/services/shipping-method.ts
|
|
6704
6971
|
var ShippingMethodService = class extends AbstractService {
|
|
6705
6972
|
repository;
|
|
@@ -6712,7 +6979,21 @@ var ShippingMethodService = class extends AbstractService {
|
|
|
6712
6979
|
return "shipping-methods";
|
|
6713
6980
|
}
|
|
6714
6981
|
extraRoutes(parent) {
|
|
6715
|
-
parent.get("/matching-cart", this.
|
|
6982
|
+
parent.get("/matching-cart", this.matchingCart.bind(this));
|
|
6983
|
+
}
|
|
6984
|
+
matchingCart(request, response) {
|
|
6985
|
+
const cartId = queryParamsValue(request.query.cartId);
|
|
6986
|
+
if (!cartId) {
|
|
6987
|
+
return response.status(400).send();
|
|
6988
|
+
}
|
|
6989
|
+
const result = this.repository.matchingCart(
|
|
6990
|
+
getRepositoryContext(request),
|
|
6991
|
+
cartId,
|
|
6992
|
+
{
|
|
6993
|
+
expand: this._parseParam(request.query.expand)
|
|
6994
|
+
}
|
|
6995
|
+
);
|
|
6996
|
+
return response.status(200).send(result);
|
|
6716
6997
|
}
|
|
6717
6998
|
};
|
|
6718
6999
|
|
|
@@ -6864,6 +7145,7 @@ var createServices = (router, repos) => ({
|
|
|
6864
7145
|
router,
|
|
6865
7146
|
repos["product-selection"]
|
|
6866
7147
|
),
|
|
7148
|
+
reviews: new ReviewService(router, repos["review"]),
|
|
6867
7149
|
"shopping-list": new ShoppingListService(router, repos["shopping-list"]),
|
|
6868
7150
|
state: new StateService(router, repos["state"]),
|
|
6869
7151
|
store: new StoreService(router, repos["store"]),
|
|
@@ -7053,6 +7335,9 @@ var CommercetoolsMock = class {
|
|
|
7053
7335
|
})
|
|
7054
7336
|
);
|
|
7055
7337
|
}
|
|
7338
|
+
mswServer() {
|
|
7339
|
+
return this._mswServer;
|
|
7340
|
+
}
|
|
7056
7341
|
startServer() {
|
|
7057
7342
|
if (_globalListeners.length > 0) {
|
|
7058
7343
|
if (this._mswServer !== void 0) {
|