Skip to content

Commit bd7421b

Browse files
Implement missing fields for prices: customerGroup, validFrom, validUntil, discounted, tiers, custom
Co-authored-by: mvantellingen <[email protected]>
1 parent 69e1f20 commit bd7421b

File tree

2 files changed

+324
-0
lines changed

2 files changed

+324
-0
lines changed
Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,292 @@
1+
import type {
2+
CustomerGroupResourceIdentifier,
3+
DiscountedPriceDraft,
4+
PriceDraft,
5+
PriceTierDraft,
6+
ProductDiscountReference,
7+
} from "@commercetools/platform-sdk";
8+
import { describe, expect, test } from "vitest";
9+
import { getBaseResourceProperties } from "~src/helpers";
10+
import { InMemoryStorage } from "~src/storage";
11+
import type { RepositoryContext } from "../abstract";
12+
import { priceFromDraft } from "./helpers";
13+
14+
describe("priceFromDraft", () => {
15+
const context: RepositoryContext = {
16+
projectKey: "test-project",
17+
};
18+
const storage = new InMemoryStorage();
19+
20+
test("should handle basic price draft without optional fields", () => {
21+
const draft: PriceDraft = {
22+
value: {
23+
currencyCode: "EUR",
24+
centAmount: 1000,
25+
},
26+
country: "NL",
27+
};
28+
29+
const result = priceFromDraft(context, storage, draft);
30+
31+
expect(result).toMatchObject({
32+
id: expect.any(String),
33+
country: "NL",
34+
value: {
35+
type: "centPrecision",
36+
currencyCode: "EUR",
37+
centAmount: 1000,
38+
fractionDigits: 2,
39+
},
40+
});
41+
expect(result.key).toBeUndefined();
42+
expect(result.channel).toBeUndefined();
43+
expect(result.customerGroup).toBeUndefined();
44+
});
45+
46+
test("should handle customerGroup field when provided", () => {
47+
// First create a customer group in storage
48+
const customerGroup = {
49+
...getBaseResourceProperties(),
50+
id: "customer-group-id",
51+
key: "customer-group-key",
52+
name: "Test Customer Group",
53+
groupName: "Test Group",
54+
};
55+
storage.add("test-project", "customer-group", customerGroup);
56+
57+
const customerGroupResourceIdentifier: CustomerGroupResourceIdentifier = {
58+
typeId: "customer-group",
59+
id: "customer-group-id",
60+
};
61+
62+
const draft: PriceDraft = {
63+
value: {
64+
currencyCode: "EUR",
65+
centAmount: 1000,
66+
},
67+
country: "NL",
68+
customerGroup: customerGroupResourceIdentifier,
69+
};
70+
71+
const result = priceFromDraft(context, storage, draft);
72+
73+
expect(result).toMatchObject({
74+
id: expect.any(String),
75+
country: "NL",
76+
value: {
77+
type: "centPrecision",
78+
currencyCode: "EUR",
79+
centAmount: 1000,
80+
fractionDigits: 2,
81+
},
82+
customerGroup: {
83+
typeId: "customer-group",
84+
id: "customer-group-id",
85+
},
86+
});
87+
});
88+
89+
test("should handle validFrom and validUntil fields when provided", () => {
90+
const draft: PriceDraft = {
91+
value: {
92+
currencyCode: "EUR",
93+
centAmount: 1000,
94+
},
95+
country: "NL",
96+
validFrom: "2023-01-01T00:00:00.000Z",
97+
validUntil: "2023-12-31T23:59:59.999Z",
98+
};
99+
100+
const result = priceFromDraft(context, storage, draft);
101+
102+
expect(result).toMatchObject({
103+
id: expect.any(String),
104+
country: "NL",
105+
value: {
106+
type: "centPrecision",
107+
currencyCode: "EUR",
108+
centAmount: 1000,
109+
fractionDigits: 2,
110+
},
111+
validFrom: "2023-01-01T00:00:00.000Z",
112+
validUntil: "2023-12-31T23:59:59.999Z",
113+
});
114+
});
115+
116+
test("should handle tiers field when provided", () => {
117+
const tierDrafts: PriceTierDraft[] = [
118+
{
119+
minimumQuantity: 5,
120+
value: {
121+
currencyCode: "EUR",
122+
centAmount: 900,
123+
},
124+
},
125+
{
126+
minimumQuantity: 10,
127+
value: {
128+
currencyCode: "EUR",
129+
centAmount: 800,
130+
},
131+
},
132+
];
133+
134+
const draft: PriceDraft = {
135+
value: {
136+
currencyCode: "EUR",
137+
centAmount: 1000,
138+
},
139+
country: "NL",
140+
tiers: tierDrafts,
141+
};
142+
143+
const result = priceFromDraft(context, storage, draft);
144+
145+
expect(result).toMatchObject({
146+
id: expect.any(String),
147+
country: "NL",
148+
value: {
149+
type: "centPrecision",
150+
currencyCode: "EUR",
151+
centAmount: 1000,
152+
fractionDigits: 2,
153+
},
154+
tiers: [
155+
{
156+
minimumQuantity: 5,
157+
value: {
158+
type: "centPrecision",
159+
currencyCode: "EUR",
160+
centAmount: 900,
161+
fractionDigits: 2,
162+
},
163+
},
164+
{
165+
minimumQuantity: 10,
166+
value: {
167+
type: "centPrecision",
168+
currencyCode: "EUR",
169+
centAmount: 800,
170+
fractionDigits: 2,
171+
},
172+
},
173+
],
174+
});
175+
});
176+
177+
test("should handle discounted field when provided", () => {
178+
// First create a product discount in storage
179+
const productDiscount = {
180+
...getBaseResourceProperties(),
181+
id: "product-discount-id",
182+
name: { en: "Test Discount" },
183+
description: { en: "Test Discount Description" },
184+
value: {
185+
type: "relative" as const,
186+
permyriad: 2000, // 20% discount
187+
},
188+
predicate: "1=1",
189+
sortOrder: "0.1",
190+
isActive: true,
191+
references: [],
192+
};
193+
storage.add("test-project", "product-discount", productDiscount);
194+
195+
const discountedDraft: DiscountedPriceDraft = {
196+
value: {
197+
currencyCode: "EUR",
198+
centAmount: 800,
199+
},
200+
discount: {
201+
typeId: "product-discount",
202+
id: "product-discount-id",
203+
},
204+
};
205+
206+
const draft: PriceDraft = {
207+
value: {
208+
currencyCode: "EUR",
209+
centAmount: 1000,
210+
},
211+
country: "NL",
212+
discounted: discountedDraft,
213+
};
214+
215+
const result = priceFromDraft(context, storage, draft);
216+
217+
expect(result).toMatchObject({
218+
id: expect.any(String),
219+
country: "NL",
220+
value: {
221+
type: "centPrecision",
222+
currencyCode: "EUR",
223+
centAmount: 1000,
224+
fractionDigits: 2,
225+
},
226+
discounted: {
227+
value: {
228+
type: "centPrecision",
229+
currencyCode: "EUR",
230+
centAmount: 800,
231+
fractionDigits: 2,
232+
},
233+
discount: {
234+
typeId: "product-discount",
235+
id: "product-discount-id",
236+
},
237+
},
238+
});
239+
});
240+
241+
test("should handle custom field when provided", () => {
242+
// First create a type in storage for custom fields
243+
const customType = {
244+
...getBaseResourceProperties(),
245+
id: "custom-type-id",
246+
key: "custom-type-key",
247+
name: { en: "Custom Type" },
248+
resourceTypeIds: ["price"],
249+
fieldDefinitions: [],
250+
};
251+
storage.add("test-project", "type", customType);
252+
253+
const draft: PriceDraft = {
254+
value: {
255+
currencyCode: "EUR",
256+
centAmount: 1000,
257+
},
258+
country: "NL",
259+
custom: {
260+
type: {
261+
typeId: "type",
262+
id: "custom-type-id",
263+
},
264+
fields: {
265+
customField: "customValue",
266+
},
267+
},
268+
};
269+
270+
const result = priceFromDraft(context, storage, draft);
271+
272+
expect(result).toMatchObject({
273+
id: expect.any(String),
274+
country: "NL",
275+
value: {
276+
type: "centPrecision",
277+
currencyCode: "EUR",
278+
centAmount: 1000,
279+
fractionDigits: 2,
280+
},
281+
custom: {
282+
type: {
283+
typeId: "type",
284+
id: "custom-type-id",
285+
},
286+
fields: {
287+
customField: "customValue",
288+
},
289+
},
290+
});
291+
});
292+
});

src/repositories/product/helpers.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,16 @@ import type {
33
Asset,
44
AssetDraft,
55
ChannelReference,
6+
CustomerGroupReference,
7+
DiscountedPrice,
8+
DiscountedPriceDraft,
69
Price,
710
PriceDraft,
11+
PriceTier,
12+
PriceTierDraft,
813
Product,
914
ProductData,
15+
ProductDiscountReference,
1016
ProductVariant,
1117
ProductVariantDraft,
1218
} from "@commercetools/platform-sdk";
@@ -113,4 +119,30 @@ export const priceFromDraft = (
113119
storage,
114120
)
115121
: undefined,
122+
customerGroup: draft.customerGroup
123+
? getReferenceFromResourceIdentifier<CustomerGroupReference>(
124+
draft.customerGroup,
125+
context.projectKey,
126+
storage,
127+
)
128+
: undefined,
129+
validFrom: draft.validFrom,
130+
validUntil: draft.validUntil,
131+
discounted: draft.discounted
132+
? {
133+
value: createTypedMoney(draft.discounted.value),
134+
discount: getReferenceFromResourceIdentifier<ProductDiscountReference>(
135+
draft.discounted.discount,
136+
context.projectKey,
137+
storage,
138+
),
139+
}
140+
: undefined,
141+
tiers: draft.tiers?.map(
142+
(tier: PriceTierDraft): PriceTier => ({
143+
minimumQuantity: tier.minimumQuantity,
144+
value: createTypedMoney(tier.value),
145+
}),
146+
),
147+
custom: createCustomFields(draft.custom, context.projectKey, storage),
116148
});

0 commit comments

Comments
 (0)