@jsdev_ninja/core 0.12.7 → 0.12.8
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/core.cjs.js +1 -1
- package/dist/core.cjs.js.map +1 -1
- package/dist/core.es.js +1001 -853
- package/dist/core.es.js.map +1 -1
- package/dist/core.umd.js +1 -1
- package/dist/core.umd.js.map +1 -1
- package/dist/entities/Discount/__tests__/engine.test.d.ts +2 -0
- package/dist/entities/Discount/__tests__/engine.test.d.ts.map +1 -0
- package/dist/entities/Discount/__tests__/engine.test.js +298 -0
- package/dist/entities/Discount/__tests__/factory.test.d.ts +2 -0
- package/dist/entities/Discount/__tests__/factory.test.d.ts.map +1 -0
- package/dist/entities/Discount/__tests__/factory.test.js +75 -0
- package/dist/entities/Discount/__tests__/integration.test.d.ts +2 -0
- package/dist/entities/Discount/__tests__/integration.test.d.ts.map +1 -0
- package/dist/entities/Discount/__tests__/integration.test.js +115 -0
- package/dist/entities/Discount/__tests__/simple.test.d.ts +2 -0
- package/dist/entities/Discount/__tests__/simple.test.d.ts.map +1 -0
- package/dist/entities/Discount/__tests__/simple.test.js +186 -0
- package/dist/entities/Discount/__tests__/utils.test.d.ts +2 -0
- package/dist/entities/Discount/__tests__/utils.test.d.ts.map +1 -0
- package/dist/entities/Discount/__tests__/utils.test.js +55 -0
- package/dist/entities/Discount/engine.d.ts +29 -0
- package/dist/entities/Discount/engine.d.ts.map +1 -0
- package/dist/entities/Discount/engine.js +80 -0
- package/dist/entities/Discount/factory.d.ts +10 -0
- package/dist/entities/Discount/factory.d.ts.map +1 -0
- package/dist/entities/Discount/factory.js +18 -0
- package/dist/entities/Discount/index.d.ts +9 -0
- package/dist/entities/Discount/index.d.ts.map +1 -0
- package/dist/entities/Discount/index.js +8 -0
- package/dist/entities/Discount/strategies/BundleStrategy.d.ts +12 -0
- package/dist/entities/Discount/strategies/BundleStrategy.d.ts.map +1 -0
- package/dist/entities/Discount/strategies/BundleStrategy.js +80 -0
- package/dist/entities/Discount/strategies/__tests__/BundleStrategy.test.d.ts +2 -0
- package/dist/entities/Discount/strategies/__tests__/BundleStrategy.test.d.ts.map +1 -0
- package/dist/entities/Discount/strategies/__tests__/BundleStrategy.test.js +265 -0
- package/dist/entities/Discount/strategy.d.ts +6 -0
- package/dist/entities/Discount/strategy.d.ts.map +1 -0
- package/dist/entities/Discount/strategy.js +1 -0
- package/dist/entities/Discount/types.d.ts +148 -0
- package/dist/entities/Discount/types.d.ts.map +1 -0
- package/dist/entities/Discount/types.js +27 -0
- package/dist/entities/Discount/utils.d.ts +29 -0
- package/dist/entities/Discount/utils.d.ts.map +1 -0
- package/dist/entities/Discount/utils.js +39 -0
- package/dist/tsconfig.app.tsbuildinfo +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +16 -60
- package/lib/entities/Discount/strategies/__tests__/BundleStrategy.test.ts +12 -7
- package/lib/utils/index.ts +19 -80
- package/package.json +1 -1
- package/dist/entities/Discount.d.ts +0 -71
- package/dist/entities/Discount.d.ts.map +0 -1
- package/dist/entities/Discount.js +0 -20
- package/lib/entities/Discount.ts +0 -23
|
@@ -56,16 +56,19 @@ describe("BundleDiscountStrategy", () => {
|
|
|
56
56
|
expect(strategy.canApply(discount, mockContext)).toBe(true);
|
|
57
57
|
});
|
|
58
58
|
|
|
59
|
-
it("should return
|
|
59
|
+
it("should return true for bundle variant type", () => {
|
|
60
60
|
const discount = {
|
|
61
61
|
...mockDiscount,
|
|
62
62
|
variant: {
|
|
63
|
-
variantType: "
|
|
64
|
-
|
|
63
|
+
variantType: "bundle" as const,
|
|
64
|
+
productsId: ["product1", "product2"],
|
|
65
|
+
requiredQuantity: 3,
|
|
66
|
+
bundlePrice: 25,
|
|
65
67
|
},
|
|
66
68
|
};
|
|
67
69
|
|
|
68
|
-
|
|
70
|
+
// This should work since it's a bundle type and we have 3 items total
|
|
71
|
+
expect(strategy.canApply(discount, mockContext)).toBe(true);
|
|
69
72
|
});
|
|
70
73
|
|
|
71
74
|
it("should return false when not enough items", () => {
|
|
@@ -223,12 +226,14 @@ describe("BundleDiscountStrategy", () => {
|
|
|
223
226
|
expect(result.affectedItems[0].discountAmount).toBe(10);
|
|
224
227
|
});
|
|
225
228
|
|
|
226
|
-
it("should return not applicable for
|
|
229
|
+
it("should return not applicable for invalid bundle", () => {
|
|
227
230
|
const discount = {
|
|
228
231
|
...mockDiscount,
|
|
229
232
|
variant: {
|
|
230
|
-
variantType: "
|
|
231
|
-
|
|
233
|
+
variantType: "bundle" as const,
|
|
234
|
+
productsId: ["product1"],
|
|
235
|
+
requiredQuantity: 10, // Too many required
|
|
236
|
+
bundlePrice: 25,
|
|
232
237
|
},
|
|
233
238
|
};
|
|
234
239
|
|
package/lib/utils/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { TCart, TDiscount, TProduct, TStore } from "../entities";
|
|
2
|
+
import { DiscountEngine } from "../entities/Discount/engine";
|
|
2
3
|
|
|
3
4
|
const CONFIG = {
|
|
4
5
|
VAT: 18,
|
|
@@ -26,10 +27,6 @@ function getPriceAfterDiscount(product: TProduct) {
|
|
|
26
27
|
return product.price;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
// mark product that used in discount
|
|
30
|
-
// get final price for product and discount id
|
|
31
|
-
// filter better discount
|
|
32
|
-
|
|
33
30
|
// main
|
|
34
31
|
export function getCartCost({
|
|
35
32
|
cart,
|
|
@@ -41,89 +38,31 @@ export function getCartCost({
|
|
|
41
38
|
store: TStore;
|
|
42
39
|
}) {
|
|
43
40
|
const { isVatIncludedInPrice } = store;
|
|
44
|
-
|
|
41
|
+
|
|
42
|
+
// Convert cart items to the format expected by the discount engine
|
|
43
|
+
const cartForEngine = cart.map(item => ({
|
|
44
|
+
amount: item.amount,
|
|
45
|
+
product: {
|
|
46
|
+
id: item.product.id,
|
|
47
|
+
price: item.product.price,
|
|
48
|
+
},
|
|
49
|
+
}));
|
|
50
|
+
|
|
51
|
+
// Apply discounts using the new discount engine
|
|
52
|
+
const discountResult = DiscountEngine.calculateDiscounts(cartForEngine, discounts);
|
|
53
|
+
|
|
54
|
+
// Map the results back to the original format with additional product info
|
|
55
|
+
const result = cart.map((item, index) => {
|
|
56
|
+
const engineItem = discountResult.items[index];
|
|
45
57
|
return {
|
|
46
58
|
amount: item.amount,
|
|
47
59
|
product: { ...item.product },
|
|
48
60
|
originalPrice: item.product.price,
|
|
49
|
-
finalPrice: getPriceAfterDiscount(item.product),
|
|
50
|
-
finalDiscount: calculateDiscount(item.product),
|
|
61
|
+
finalPrice: engineItem ? engineItem.finalPrice : getPriceAfterDiscount(item.product),
|
|
62
|
+
finalDiscount: engineItem ? engineItem.finalDiscount : calculateDiscount(item.product),
|
|
51
63
|
};
|
|
52
64
|
});
|
|
53
65
|
|
|
54
|
-
// calculate delivery price before
|
|
55
|
-
// check if cart cost is greater than free delivery price
|
|
56
|
-
|
|
57
|
-
const activeDiscounts = discounts.filter((discount) => {
|
|
58
|
-
if (discount.variant.variantType === "bundle") {
|
|
59
|
-
const productsTotal =
|
|
60
|
-
cart?.reduce((total, item) => {
|
|
61
|
-
if (discount.variant.productsId.includes(item.product.id)) {
|
|
62
|
-
total += item.amount;
|
|
63
|
-
return total;
|
|
64
|
-
}
|
|
65
|
-
return total;
|
|
66
|
-
}, 0) ?? 0;
|
|
67
|
-
if (productsTotal >= discount.variant.requiredQuantity) {
|
|
68
|
-
// const times = Math.floor(productsTotal / discount.variant.requiredQuantity);
|
|
69
|
-
// console.log("yes", times, discount.variant.discountPrice);
|
|
70
|
-
return true;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
return false;
|
|
74
|
-
});
|
|
75
|
-
console.log("activeDiscounts", activeDiscounts);
|
|
76
|
-
|
|
77
|
-
activeDiscounts.forEach((discount) => {
|
|
78
|
-
if (discount.variant.variantType === "bundle") {
|
|
79
|
-
// get all products in cart
|
|
80
|
-
const products = cart.filter((item) =>
|
|
81
|
-
discount.variant.productsId.includes(item.product.id)
|
|
82
|
-
);
|
|
83
|
-
const productsTotal =
|
|
84
|
-
products?.reduce((total, item) => {
|
|
85
|
-
if (discount.variant.productsId.includes(item.product.id)) {
|
|
86
|
-
total += item.amount;
|
|
87
|
-
return total;
|
|
88
|
-
}
|
|
89
|
-
return total;
|
|
90
|
-
}, 0) ?? 0;
|
|
91
|
-
|
|
92
|
-
const times = Math.floor(productsTotal / discount.variant.requiredQuantity);
|
|
93
|
-
const price = getPriceAfterDiscount(products[0]?.product);
|
|
94
|
-
const _discount = calculateDiscount(products[0]?.product);
|
|
95
|
-
console.log("price", price, _discount);
|
|
96
|
-
const discountPrice =
|
|
97
|
-
Number(
|
|
98
|
-
(discount.variant.discountPrice / discount.variant.requiredQuantity).toFixed(2)
|
|
99
|
-
) * 1;
|
|
100
|
-
|
|
101
|
-
console.log("discountPrice", discountPrice);
|
|
102
|
-
const totalDiscount =
|
|
103
|
-
(price * discount.variant.requiredQuantity - discount.variant.discountPrice) * times;
|
|
104
|
-
|
|
105
|
-
const originalPrice = productsTotal * price;
|
|
106
|
-
const discountPriceFinal = originalPrice - totalDiscount;
|
|
107
|
-
|
|
108
|
-
const averagePrice = Number((discountPriceFinal / productsTotal).toFixed(2));
|
|
109
|
-
|
|
110
|
-
result = result.map((item) => {
|
|
111
|
-
if (discount.variant.productsId.includes(item.product.id)) {
|
|
112
|
-
return {
|
|
113
|
-
...item,
|
|
114
|
-
finalPrice: averagePrice,
|
|
115
|
-
originalPrice: item.product.price,
|
|
116
|
-
discountPrice: price,
|
|
117
|
-
finalDiscount: item.finalDiscount + (item.product.price - averagePrice),
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
return item;
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
// find average price
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
|
|
127
66
|
const cartDetails = result.reduce(
|
|
128
67
|
(acc, item) => {
|
|
129
68
|
const { product, amount, finalPrice, finalDiscount } = item;
|
package/package.json
CHANGED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
export declare const DiscountSchema: z.ZodObject<{
|
|
3
|
-
type: z.ZodLiteral<"Discount">;
|
|
4
|
-
storeId: z.ZodString;
|
|
5
|
-
companyId: z.ZodString;
|
|
6
|
-
id: z.ZodString;
|
|
7
|
-
name: z.ZodArray<z.ZodObject<{
|
|
8
|
-
lang: z.ZodEnum<["he"]>;
|
|
9
|
-
value: z.ZodString;
|
|
10
|
-
}, "strip", z.ZodTypeAny, {
|
|
11
|
-
value: string;
|
|
12
|
-
lang: "he";
|
|
13
|
-
}, {
|
|
14
|
-
value: string;
|
|
15
|
-
lang: "he";
|
|
16
|
-
}>, "many">;
|
|
17
|
-
active: z.ZodBoolean;
|
|
18
|
-
variant: z.ZodDiscriminatedUnion<"variantType", [z.ZodObject<{
|
|
19
|
-
variantType: z.ZodLiteral<"bundle">;
|
|
20
|
-
productsId: z.ZodArray<z.ZodString, "many">;
|
|
21
|
-
requiredQuantity: z.ZodNumber;
|
|
22
|
-
discountPrice: z.ZodNumber;
|
|
23
|
-
}, "strip", z.ZodTypeAny, {
|
|
24
|
-
variantType: "bundle";
|
|
25
|
-
productsId: string[];
|
|
26
|
-
requiredQuantity: number;
|
|
27
|
-
discountPrice: number;
|
|
28
|
-
}, {
|
|
29
|
-
variantType: "bundle";
|
|
30
|
-
productsId: string[];
|
|
31
|
-
requiredQuantity: number;
|
|
32
|
-
discountPrice: number;
|
|
33
|
-
}>]>;
|
|
34
|
-
images: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
35
|
-
}, "strip", z.ZodTypeAny, {
|
|
36
|
-
type: "Discount";
|
|
37
|
-
id: string;
|
|
38
|
-
companyId: string;
|
|
39
|
-
storeId: string;
|
|
40
|
-
name: {
|
|
41
|
-
value: string;
|
|
42
|
-
lang: "he";
|
|
43
|
-
}[];
|
|
44
|
-
active: boolean;
|
|
45
|
-
variant: {
|
|
46
|
-
variantType: "bundle";
|
|
47
|
-
productsId: string[];
|
|
48
|
-
requiredQuantity: number;
|
|
49
|
-
discountPrice: number;
|
|
50
|
-
};
|
|
51
|
-
images?: string[] | undefined;
|
|
52
|
-
}, {
|
|
53
|
-
type: "Discount";
|
|
54
|
-
id: string;
|
|
55
|
-
companyId: string;
|
|
56
|
-
storeId: string;
|
|
57
|
-
name: {
|
|
58
|
-
value: string;
|
|
59
|
-
lang: "he";
|
|
60
|
-
}[];
|
|
61
|
-
active: boolean;
|
|
62
|
-
variant: {
|
|
63
|
-
variantType: "bundle";
|
|
64
|
-
productsId: string[];
|
|
65
|
-
requiredQuantity: number;
|
|
66
|
-
discountPrice: number;
|
|
67
|
-
};
|
|
68
|
-
images?: string[] | undefined;
|
|
69
|
-
}>;
|
|
70
|
-
export type TDiscount = z.infer<typeof DiscountSchema>;
|
|
71
|
-
//# sourceMappingURL=Discount.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Discount.d.ts","sourceRoot":"","sources":["../../lib/entities/Discount.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgBzB,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC"}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import { LocaleSchema } from "./Locale";
|
|
3
|
-
const text = z.string().min(1);
|
|
4
|
-
export const DiscountSchema = z.object({
|
|
5
|
-
type: z.literal("Discount"),
|
|
6
|
-
storeId: text,
|
|
7
|
-
companyId: text,
|
|
8
|
-
id: text,
|
|
9
|
-
name: z.array(LocaleSchema),
|
|
10
|
-
active: z.boolean(),
|
|
11
|
-
variant: z.discriminatedUnion("variantType", [
|
|
12
|
-
z.object({
|
|
13
|
-
variantType: z.literal("bundle"),
|
|
14
|
-
productsId: z.array(z.string()).min(1),
|
|
15
|
-
requiredQuantity: z.number().positive(),
|
|
16
|
-
discountPrice: z.number().positive(),
|
|
17
|
-
}),
|
|
18
|
-
]),
|
|
19
|
-
images: z.array(z.string().nonempty()).optional(),
|
|
20
|
-
});
|
package/lib/entities/Discount.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import { LocaleSchema } from "./Locale";
|
|
3
|
-
|
|
4
|
-
const text = z.string().min(1);
|
|
5
|
-
|
|
6
|
-
export const DiscountSchema = z.object({
|
|
7
|
-
type: z.literal("Discount"),
|
|
8
|
-
storeId: text,
|
|
9
|
-
companyId: text,
|
|
10
|
-
id: text,
|
|
11
|
-
name: z.array(LocaleSchema),
|
|
12
|
-
active: z.boolean(),
|
|
13
|
-
variant: z.discriminatedUnion("variantType", [
|
|
14
|
-
z.object({
|
|
15
|
-
variantType: z.literal("bundle"),
|
|
16
|
-
productsId: z.array(z.string()).min(1),
|
|
17
|
-
requiredQuantity: z.number().positive(),
|
|
18
|
-
discountPrice: z.number().positive(),
|
|
19
|
-
}),
|
|
20
|
-
]),
|
|
21
|
-
images: z.array(z.string().nonempty()).optional(),
|
|
22
|
-
});
|
|
23
|
-
export type TDiscount = z.infer<typeof DiscountSchema>;
|