@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
|
@@ -36,6 +36,7 @@ import type {
|
|
|
36
36
|
ProductAddToCategoryAction,
|
|
37
37
|
ProductRemoveFromCategoryAction,
|
|
38
38
|
ProductTransitionStateAction,
|
|
39
|
+
ChannelReference,
|
|
39
40
|
} from '@commercetools/platform-sdk'
|
|
40
41
|
import { v4 as uuidv4 } from 'uuid'
|
|
41
42
|
import type { Writable } from '../types.js'
|
|
@@ -126,10 +127,10 @@ export class ProductRepository extends AbstractResourceRepository<'product'> {
|
|
|
126
127
|
slug: draft.slug,
|
|
127
128
|
description: draft.description,
|
|
128
129
|
categories: categoryReferences,
|
|
129
|
-
masterVariant: variantFromDraft(1, draft.masterVariant),
|
|
130
|
+
masterVariant: this.variantFromDraft(context, 1, draft.masterVariant),
|
|
130
131
|
variants:
|
|
131
132
|
draft.variants?.map((variant, index) =>
|
|
132
|
-
variantFromDraft(index + 2, variant)
|
|
133
|
+
this.variantFromDraft(context, index + 2, variant)
|
|
133
134
|
) ?? [],
|
|
134
135
|
metaTitle: draft.metaTitle,
|
|
135
136
|
metaDescription: draft.metaDescription,
|
|
@@ -156,6 +157,38 @@ export class ProductRepository extends AbstractResourceRepository<'product'> {
|
|
|
156
157
|
return resource
|
|
157
158
|
}
|
|
158
159
|
|
|
160
|
+
private variantFromDraft(
|
|
161
|
+
context: RepositoryContext,
|
|
162
|
+
variantId: number,
|
|
163
|
+
variant: ProductVariantDraft
|
|
164
|
+
): ProductVariant {
|
|
165
|
+
return {
|
|
166
|
+
id: variantId,
|
|
167
|
+
sku: variant?.sku,
|
|
168
|
+
key: variant?.key,
|
|
169
|
+
attributes: variant?.attributes ?? [],
|
|
170
|
+
prices: variant?.prices?.map((p) => this.priceFromDraft(context, p)),
|
|
171
|
+
assets: [],
|
|
172
|
+
images: [],
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
private priceFromDraft(context: RepositoryContext, draft: PriceDraft): Price {
|
|
177
|
+
return {
|
|
178
|
+
id: uuidv4(),
|
|
179
|
+
key: draft.key,
|
|
180
|
+
country: draft.country,
|
|
181
|
+
value: createTypedMoney(draft.value),
|
|
182
|
+
channel: draft.channel
|
|
183
|
+
? getReferenceFromResourceIdentifier<ChannelReference>(
|
|
184
|
+
draft.channel,
|
|
185
|
+
context.projectKey,
|
|
186
|
+
this._storage
|
|
187
|
+
)
|
|
188
|
+
: undefined,
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
159
192
|
actions: Partial<
|
|
160
193
|
Record<
|
|
161
194
|
ProductUpdateAction['action'],
|
|
@@ -528,7 +561,7 @@ export class ProductRepository extends AbstractResourceRepository<'product'> {
|
|
|
528
561
|
}
|
|
529
562
|
|
|
530
563
|
// Pre-creating the price object ensures consistency between staged and current versions
|
|
531
|
-
const priceToAdd = priceFromDraft(price)
|
|
564
|
+
const priceToAdd = this.priceFromDraft(context, price)
|
|
532
565
|
|
|
533
566
|
// If true, only the staged Attribute is set. If false, both current and
|
|
534
567
|
// staged Attribute is set. Default is true
|
|
@@ -754,7 +787,7 @@ export class ProductRepository extends AbstractResourceRepository<'product'> {
|
|
|
754
787
|
(max, element) => (element.id > max ? element.id : max),
|
|
755
788
|
0
|
|
756
789
|
)
|
|
757
|
-
const variant = variantFromDraft(maxId + 1, variantDraft)
|
|
790
|
+
const variant = this.variantFromDraft(context, maxId + 1, variantDraft)
|
|
758
791
|
dataStaged.variants.push(variant)
|
|
759
792
|
|
|
760
793
|
const onlyStaged = staged !== undefined ? staged : true
|
|
@@ -1071,23 +1104,3 @@ const getVariant = (
|
|
|
1071
1104
|
: -1,
|
|
1072
1105
|
}
|
|
1073
1106
|
}
|
|
1074
|
-
|
|
1075
|
-
const variantFromDraft = (
|
|
1076
|
-
variantId: number,
|
|
1077
|
-
variant: ProductVariantDraft
|
|
1078
|
-
): ProductVariant => ({
|
|
1079
|
-
id: variantId,
|
|
1080
|
-
sku: variant?.sku,
|
|
1081
|
-
key: variant?.key,
|
|
1082
|
-
attributes: variant?.attributes ?? [],
|
|
1083
|
-
prices: variant?.prices?.map(priceFromDraft),
|
|
1084
|
-
assets: [],
|
|
1085
|
-
images: [],
|
|
1086
|
-
})
|
|
1087
|
-
|
|
1088
|
-
const priceFromDraft = (draft: PriceDraft): Price => ({
|
|
1089
|
-
id: uuidv4(),
|
|
1090
|
-
key: draft.key,
|
|
1091
|
-
country: draft.country,
|
|
1092
|
-
value: createTypedMoney(draft.value),
|
|
1093
|
-
})
|
|
@@ -1,11 +1,18 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import {
|
|
2
|
+
ChannelReference,
|
|
3
|
+
ProductReference,
|
|
4
|
+
type Review,
|
|
5
|
+
type ReviewDraft,
|
|
6
|
+
type ReviewUpdateAction,
|
|
7
|
+
type StateReference,
|
|
5
8
|
} from '@commercetools/platform-sdk'
|
|
6
9
|
import { getBaseResourceProperties } from '../helpers.js'
|
|
7
10
|
import type { Writable } from '../types.js'
|
|
8
11
|
import { AbstractResourceRepository, RepositoryContext } from './abstract.js'
|
|
12
|
+
import {
|
|
13
|
+
createCustomFields,
|
|
14
|
+
getReferenceFromResourceIdentifier,
|
|
15
|
+
} from './helpers.js'
|
|
9
16
|
|
|
10
17
|
export class ReviewRepository extends AbstractResourceRepository<'review'> {
|
|
11
18
|
getTypeId() {
|
|
@@ -13,9 +20,34 @@ export class ReviewRepository extends AbstractResourceRepository<'review'> {
|
|
|
13
20
|
}
|
|
14
21
|
|
|
15
22
|
create(context: RepositoryContext, draft: ReviewDraft): Review {
|
|
23
|
+
if (!draft.target) throw new Error('Missing target')
|
|
16
24
|
const resource: Review = {
|
|
17
25
|
...getBaseResourceProperties(),
|
|
26
|
+
|
|
27
|
+
locale: draft.locale,
|
|
28
|
+
authorName: draft.authorName,
|
|
29
|
+
title: draft.title,
|
|
30
|
+
text: draft.text,
|
|
31
|
+
rating: draft.rating,
|
|
32
|
+
uniquenessValue: draft.uniquenessValue,
|
|
33
|
+
state: draft.state
|
|
34
|
+
? getReferenceFromResourceIdentifier<StateReference>(
|
|
35
|
+
draft.state,
|
|
36
|
+
context.projectKey,
|
|
37
|
+
this._storage
|
|
38
|
+
)
|
|
39
|
+
: undefined,
|
|
40
|
+
target: draft.target
|
|
41
|
+
? getReferenceFromResourceIdentifier<
|
|
42
|
+
ProductReference | ChannelReference
|
|
43
|
+
>(draft.target, context.projectKey, this._storage)
|
|
44
|
+
: undefined,
|
|
18
45
|
includedInStatistics: false,
|
|
46
|
+
custom: createCustomFields(
|
|
47
|
+
draft.custom,
|
|
48
|
+
context.projectKey,
|
|
49
|
+
this._storage
|
|
50
|
+
),
|
|
19
51
|
}
|
|
20
52
|
this.saveNew(context, resource)
|
|
21
53
|
return resource
|
|
@@ -1,34 +1,41 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
1
|
+
import {
|
|
2
|
+
InvalidOperationError,
|
|
3
|
+
type ShippingMethod,
|
|
4
|
+
type ShippingMethodAddShippingRateAction,
|
|
5
|
+
type ShippingMethodAddZoneAction,
|
|
6
|
+
type ShippingMethodChangeIsDefaultAction,
|
|
7
|
+
type ShippingMethodChangeNameAction,
|
|
8
|
+
type ShippingMethodDraft,
|
|
9
|
+
type ShippingMethodRemoveZoneAction,
|
|
10
|
+
type ShippingMethodSetCustomFieldAction,
|
|
11
|
+
type ShippingMethodSetCustomTypeAction,
|
|
12
|
+
type ShippingMethodSetDescriptionAction,
|
|
13
|
+
type ShippingMethodSetKeyAction,
|
|
14
|
+
type ShippingMethodSetLocalizedDescriptionAction,
|
|
15
|
+
type ShippingMethodSetLocalizedNameAction,
|
|
16
|
+
type ShippingMethodSetPredicateAction,
|
|
17
|
+
type ShippingMethodUpdateAction,
|
|
18
|
+
type ShippingRate,
|
|
19
|
+
type ShippingRateDraft,
|
|
20
|
+
type ZoneRate,
|
|
21
|
+
type ZoneRateDraft,
|
|
22
|
+
type ZoneReference,
|
|
22
23
|
} from '@commercetools/platform-sdk'
|
|
23
24
|
import deepEqual from 'deep-equal'
|
|
24
25
|
import { getBaseResourceProperties } from '../helpers.js'
|
|
25
26
|
import type { Writable } from '../types.js'
|
|
26
|
-
import {
|
|
27
|
+
import {
|
|
28
|
+
AbstractResourceRepository,
|
|
29
|
+
GetParams,
|
|
30
|
+
RepositoryContext,
|
|
31
|
+
} from './abstract.js'
|
|
27
32
|
import {
|
|
28
33
|
createCustomFields,
|
|
29
34
|
createTypedMoney,
|
|
30
35
|
getReferenceFromResourceIdentifier,
|
|
31
36
|
} from './helpers.js'
|
|
37
|
+
import { CommercetoolsError } from '../exceptions.js'
|
|
38
|
+
import { markMatchingShippingRate } from '../shippingCalculator.js'
|
|
32
39
|
|
|
33
40
|
export class ShippingMethodRepository extends AbstractResourceRepository<'shipping-method'> {
|
|
34
41
|
getTypeId() {
|
|
@@ -79,6 +86,75 @@ export class ShippingMethodRepository extends AbstractResourceRepository<'shippi
|
|
|
79
86
|
tiers: rate.tiers || [],
|
|
80
87
|
})
|
|
81
88
|
|
|
89
|
+
/*
|
|
90
|
+
* Retrieves all the ShippingMethods that can ship to the shipping address of
|
|
91
|
+
* the given Cart. Each ShippingMethod contains exactly one ShippingRate with
|
|
92
|
+
* the flag isMatching set to true. This ShippingRate is used when the
|
|
93
|
+
* ShippingMethod is added to the Cart.
|
|
94
|
+
*/
|
|
95
|
+
public matchingCart(
|
|
96
|
+
context: RepositoryContext,
|
|
97
|
+
cartId: string,
|
|
98
|
+
params: GetParams = {}
|
|
99
|
+
) {
|
|
100
|
+
const cart = this._storage.get(context.projectKey, 'cart', cartId)
|
|
101
|
+
if (!cart) {
|
|
102
|
+
return undefined
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (!cart.shippingAddress?.country) {
|
|
106
|
+
throw new CommercetoolsError<InvalidOperationError>({
|
|
107
|
+
code: 'InvalidOperation',
|
|
108
|
+
message: `The cart with ID '${cart.id}' does not have a shipping address set.`,
|
|
109
|
+
})
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Get all shipping methods that have a zone that matches the shipping address
|
|
113
|
+
const zones = this._storage.query<'zone'>(context.projectKey, 'zone', {
|
|
114
|
+
where: [`locations(country="${cart.shippingAddress.country}"))`],
|
|
115
|
+
limit: 100,
|
|
116
|
+
})
|
|
117
|
+
const zoneIds = zones.results.map((zone) => zone.id)
|
|
118
|
+
const shippingMethods = this.query(context, {
|
|
119
|
+
where: [
|
|
120
|
+
`zoneRates(zone(id in (:zoneIds)))`,
|
|
121
|
+
`zoneRates(shippingRates(price(currencyCode="${cart.totalPrice.currencyCode}")))`,
|
|
122
|
+
],
|
|
123
|
+
'var.zoneIds': zoneIds,
|
|
124
|
+
expand: params.expand,
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
// Make sure that each shipping method has exactly one shipping rate and
|
|
128
|
+
// that the shipping rate is marked as matching
|
|
129
|
+
const results = shippingMethods.results
|
|
130
|
+
.map((shippingMethod) => {
|
|
131
|
+
// Iterate through the zoneRates, process the shipping rates and filter
|
|
132
|
+
// out all zoneRates which have no matching shipping rates left
|
|
133
|
+
const rates = shippingMethod.zoneRates
|
|
134
|
+
.map((zoneRate) => ({
|
|
135
|
+
zone: zoneRate.zone,
|
|
136
|
+
|
|
137
|
+
// Iterate through the shippingRates and mark the matching ones
|
|
138
|
+
// then we filter out the non-matching ones
|
|
139
|
+
shippingRates: zoneRate.shippingRates
|
|
140
|
+
.map((rate) => markMatchingShippingRate(cart, rate))
|
|
141
|
+
.filter((rate) => rate.isMatching),
|
|
142
|
+
}))
|
|
143
|
+
.filter((zoneRate) => zoneRate.shippingRates.length > 0)
|
|
144
|
+
|
|
145
|
+
return {
|
|
146
|
+
...shippingMethod,
|
|
147
|
+
zoneRates: rates,
|
|
148
|
+
}
|
|
149
|
+
})
|
|
150
|
+
.filter((shippingMethod) => shippingMethod.zoneRates.length > 0)
|
|
151
|
+
|
|
152
|
+
return {
|
|
153
|
+
...shippingMethods,
|
|
154
|
+
results: results,
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
82
158
|
actions: Partial<
|
|
83
159
|
Record<
|
|
84
160
|
ShippingMethodUpdateAction['action'],
|
|
@@ -17,11 +17,30 @@ export class CustomObjectService extends AbstractService {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
extraRoutes(router: Router) {
|
|
20
|
+
router.get('/:container', this.getWithContainer.bind(this))
|
|
20
21
|
router.get('/:container/:key', this.getWithContainerAndKey.bind(this))
|
|
21
22
|
router.post('/:container/:key', this.createWithContainerAndKey.bind(this))
|
|
22
23
|
router.delete('/:container/:key', this.deleteWithContainerAndKey.bind(this))
|
|
23
24
|
}
|
|
24
25
|
|
|
26
|
+
getWithContainer(request: Request, response: Response) {
|
|
27
|
+
const limit = this._parseParam(request.query.limit)
|
|
28
|
+
const offset = this._parseParam(request.query.offset)
|
|
29
|
+
|
|
30
|
+
const result = this.repository.queryWithContainer(
|
|
31
|
+
getRepositoryContext(request),
|
|
32
|
+
request.params.container,
|
|
33
|
+
{
|
|
34
|
+
expand: this._parseParam(request.query.expand),
|
|
35
|
+
where: this._parseParam(request.query.where),
|
|
36
|
+
limit: limit !== undefined ? Number(limit) : undefined,
|
|
37
|
+
offset: offset !== undefined ? Number(offset) : undefined,
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
return response.status(200).send(result)
|
|
42
|
+
}
|
|
43
|
+
|
|
25
44
|
getWithContainerAndKey(request: Request, response: Response) {
|
|
26
45
|
const result = this.repository.getWithContainerAndKey(
|
|
27
46
|
getRepositoryContext(request),
|
package/src/services/index.ts
CHANGED
|
@@ -23,6 +23,7 @@ import { ProductProjectionService } from './product-projection.js'
|
|
|
23
23
|
import { ProductSelectionService } from './product-selection.js'
|
|
24
24
|
import { ProductTypeService } from './product-type.js'
|
|
25
25
|
import { ProductService } from './product.js'
|
|
26
|
+
import { ReviewService } from './reviews.js'
|
|
26
27
|
import { ShippingMethodService } from './shipping-method.js'
|
|
27
28
|
import { ShoppingListService } from './shopping-list.js'
|
|
28
29
|
import { StandAlonePriceService } from './standalone-price.js'
|
|
@@ -84,6 +85,7 @@ export const createServices = (router: any, repos: any) => ({
|
|
|
84
85
|
router,
|
|
85
86
|
repos['product-selection']
|
|
86
87
|
),
|
|
88
|
+
reviews: new ReviewService(router, repos['review']),
|
|
87
89
|
'shopping-list': new ShoppingListService(router, repos['shopping-list']),
|
|
88
90
|
state: new StateService(router, repos['state']),
|
|
89
91
|
store: new StoreService(router, repos['store']),
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Router } from 'express'
|
|
2
|
+
import AbstractService from './abstract.js'
|
|
3
|
+
import { ReviewRepository } from '../repositories/review.js'
|
|
4
|
+
|
|
5
|
+
export class ReviewService extends AbstractService {
|
|
6
|
+
public repository: ReviewRepository
|
|
7
|
+
|
|
8
|
+
constructor(parent: Router, repository: ReviewRepository) {
|
|
9
|
+
super(parent)
|
|
10
|
+
this.repository = repository
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
getBasePath() {
|
|
14
|
+
return 'reviews'
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -1,24 +1,48 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
Cart,
|
|
3
|
+
CartDraft,
|
|
2
4
|
ShippingMethodDraft,
|
|
3
5
|
TaxCategoryDraft,
|
|
6
|
+
ZoneDraft,
|
|
4
7
|
} from '@commercetools/platform-sdk'
|
|
5
8
|
import supertest from 'supertest'
|
|
6
9
|
import { afterEach, beforeEach, describe, expect, test } from 'vitest'
|
|
7
10
|
import { CommercetoolsMock } from '../index.js'
|
|
11
|
+
import { isType } from '../types.js'
|
|
8
12
|
|
|
9
13
|
const ctMock = new CommercetoolsMock()
|
|
10
14
|
|
|
11
15
|
describe('Shipping method', () => {
|
|
12
16
|
beforeEach(async () => {
|
|
13
|
-
|
|
14
|
-
name: 'foo',
|
|
15
|
-
key: 'standard',
|
|
16
|
-
rates: [],
|
|
17
|
-
}
|
|
18
|
-
const createResponse = await supertest(ctMock.app)
|
|
17
|
+
await supertest(ctMock.app)
|
|
19
18
|
.post('/dummy/tax-categories')
|
|
20
|
-
.send(
|
|
21
|
-
|
|
19
|
+
.send(
|
|
20
|
+
isType<TaxCategoryDraft>({
|
|
21
|
+
name: 'foo',
|
|
22
|
+
key: 'standard',
|
|
23
|
+
rates: [],
|
|
24
|
+
})
|
|
25
|
+
)
|
|
26
|
+
.then((res) => {
|
|
27
|
+
expect(res.status).toEqual(201)
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
await supertest(ctMock.app)
|
|
31
|
+
.post('/dummy/zones')
|
|
32
|
+
.send(
|
|
33
|
+
isType<ZoneDraft>({
|
|
34
|
+
name: 'The Netherlands',
|
|
35
|
+
key: 'NL',
|
|
36
|
+
locations: [
|
|
37
|
+
{
|
|
38
|
+
country: 'NL',
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
})
|
|
42
|
+
)
|
|
43
|
+
.then((res) => {
|
|
44
|
+
expect(res.status).toEqual(201)
|
|
45
|
+
})
|
|
22
46
|
})
|
|
23
47
|
|
|
24
48
|
afterEach(async () => {
|
|
@@ -75,28 +99,103 @@ describe('Shipping method', () => {
|
|
|
75
99
|
})
|
|
76
100
|
|
|
77
101
|
test('Get shipping methods matching cart', async () => {
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
102
|
+
const cart = await supertest(ctMock.app)
|
|
103
|
+
.post('/dummy/carts')
|
|
104
|
+
.send(
|
|
105
|
+
isType<CartDraft>({
|
|
106
|
+
currency: 'EUR',
|
|
107
|
+
shippingAddress: {
|
|
108
|
+
country: 'NL',
|
|
109
|
+
},
|
|
110
|
+
})
|
|
111
|
+
)
|
|
112
|
+
.then((res) => res.body as Cart)
|
|
113
|
+
|
|
114
|
+
await supertest(ctMock.app)
|
|
85
115
|
.post('/dummy/shipping-methods')
|
|
86
|
-
.send(
|
|
116
|
+
.send(
|
|
117
|
+
isType<ShippingMethodDraft>({
|
|
118
|
+
name: 'NL',
|
|
119
|
+
taxCategory: { typeId: 'tax-category', key: 'standard' },
|
|
120
|
+
isDefault: true,
|
|
121
|
+
zoneRates: [
|
|
122
|
+
{
|
|
123
|
+
zone: {
|
|
124
|
+
typeId: 'zone',
|
|
125
|
+
key: 'NL',
|
|
126
|
+
},
|
|
127
|
+
shippingRates: [
|
|
128
|
+
{
|
|
129
|
+
price: {
|
|
130
|
+
currencyCode: 'EUR',
|
|
131
|
+
centAmount: 495,
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
],
|
|
135
|
+
},
|
|
136
|
+
],
|
|
137
|
+
})
|
|
138
|
+
)
|
|
139
|
+
.then((res) => {
|
|
140
|
+
expect(res.status).toEqual(201)
|
|
141
|
+
})
|
|
87
142
|
|
|
88
|
-
|
|
143
|
+
await supertest(ctMock.app)
|
|
144
|
+
.post('/dummy/shipping-methods')
|
|
145
|
+
.send(
|
|
146
|
+
isType<ShippingMethodDraft>({
|
|
147
|
+
name: 'NL/GBP',
|
|
148
|
+
taxCategory: { typeId: 'tax-category', key: 'standard' },
|
|
149
|
+
isDefault: true,
|
|
150
|
+
zoneRates: [
|
|
151
|
+
{
|
|
152
|
+
zone: {
|
|
153
|
+
typeId: 'zone',
|
|
154
|
+
key: 'NL',
|
|
155
|
+
},
|
|
156
|
+
shippingRates: [
|
|
157
|
+
{
|
|
158
|
+
price: {
|
|
159
|
+
currencyCode: 'GBP',
|
|
160
|
+
centAmount: 495,
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
],
|
|
164
|
+
},
|
|
165
|
+
],
|
|
166
|
+
})
|
|
167
|
+
)
|
|
168
|
+
.then((res) => {
|
|
169
|
+
expect(res.status).toEqual(201)
|
|
170
|
+
})
|
|
89
171
|
|
|
90
172
|
const response = await supertest(ctMock.app).get(
|
|
91
|
-
`/dummy/shipping-methods/matching-cart?cartId
|
|
173
|
+
`/dummy/shipping-methods/matching-cart?cartId=${cart.id}`
|
|
92
174
|
)
|
|
93
175
|
|
|
94
|
-
expect(response.status).toBe(200)
|
|
95
|
-
expect(response.body).
|
|
176
|
+
expect(response.status, JSON.stringify(response.body)).toBe(200)
|
|
177
|
+
expect(response.body).toMatchObject({
|
|
96
178
|
count: 1,
|
|
97
179
|
limit: 20,
|
|
98
180
|
offset: 0,
|
|
99
|
-
results: [
|
|
181
|
+
results: [
|
|
182
|
+
{
|
|
183
|
+
name: 'NL',
|
|
184
|
+
zoneRates: [
|
|
185
|
+
{
|
|
186
|
+
shippingRates: [
|
|
187
|
+
{
|
|
188
|
+
isMatching: true,
|
|
189
|
+
price: {
|
|
190
|
+
currencyCode: 'EUR',
|
|
191
|
+
centAmount: 495,
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
],
|
|
195
|
+
},
|
|
196
|
+
],
|
|
197
|
+
},
|
|
198
|
+
],
|
|
100
199
|
total: 1,
|
|
101
200
|
})
|
|
102
201
|
})
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { Router } from 'express'
|
|
1
|
+
import { Request, Response, Router } from 'express'
|
|
2
2
|
import { ShippingMethodRepository } from '../repositories/shipping-method.js'
|
|
3
3
|
import AbstractService from './abstract.js'
|
|
4
|
+
import { getRepositoryContext } from '../repositories/helpers.js'
|
|
5
|
+
import { queryParamsValue } from '../helpers.js'
|
|
4
6
|
|
|
5
7
|
export class ShippingMethodService extends AbstractService {
|
|
6
8
|
public repository: ShippingMethodRepository
|
|
@@ -16,6 +18,21 @@ export class ShippingMethodService extends AbstractService {
|
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
extraRoutes(parent: Router) {
|
|
19
|
-
parent.get('/matching-cart', this.
|
|
21
|
+
parent.get('/matching-cart', this.matchingCart.bind(this))
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
matchingCart(request: Request, response: Response) {
|
|
25
|
+
const cartId = queryParamsValue(request.query.cartId)
|
|
26
|
+
if (!cartId) {
|
|
27
|
+
return response.status(400).send()
|
|
28
|
+
}
|
|
29
|
+
const result = this.repository.matchingCart(
|
|
30
|
+
getRepositoryContext(request),
|
|
31
|
+
cartId,
|
|
32
|
+
{
|
|
33
|
+
expand: this._parseParam(request.query.expand),
|
|
34
|
+
}
|
|
35
|
+
)
|
|
36
|
+
return response.status(200).send(result)
|
|
20
37
|
}
|
|
21
38
|
}
|