@jsdev_ninja/core 0.13.27 → 0.13.28
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 +2 -0
- package/dist/core.cjs.js.map +1 -0
- package/dist/core.es.js +3614 -0
- package/dist/core.es.js.map +1 -0
- package/dist/core.umd.js +2 -0
- package/dist/core.umd.js.map +1 -0
- package/dist/lib/entities/Address.d.ts +28 -0
- package/dist/lib/entities/Address.d.ts.map +1 -0
- package/dist/lib/entities/Address.js +10 -0
- package/dist/lib/entities/Atoms.d.ts +16 -0
- package/dist/lib/entities/Atoms.d.ts.map +1 -0
- package/{lib/entities/Atoms.ts → dist/lib/entities/Atoms.js} +2 -6
- package/dist/lib/entities/Cart.d.ts +1278 -0
- package/dist/lib/entities/Cart.d.ts.map +1 -0
- package/dist/lib/entities/Cart.js +18 -0
- package/dist/lib/entities/Category.d.ts +103 -0
- package/dist/lib/entities/Category.d.ts.map +1 -0
- package/dist/lib/entities/Category.js +20 -0
- package/dist/lib/entities/Company.d.ts +16 -0
- package/dist/lib/entities/Company.d.ts.map +1 -0
- package/dist/lib/entities/Company.js +6 -0
- package/dist/lib/entities/DeliveryNote.d.ts +248 -0
- package/dist/lib/entities/DeliveryNote.d.ts.map +1 -0
- package/dist/lib/entities/DeliveryNote.js +61 -0
- package/dist/lib/entities/Discount/__tests__/engine.test.d.ts +2 -0
- package/dist/lib/entities/Discount/__tests__/engine.test.d.ts.map +1 -0
- package/dist/lib/entities/Discount/__tests__/engine.test.js +298 -0
- package/dist/lib/entities/Discount/__tests__/factory.test.d.ts +2 -0
- package/dist/lib/entities/Discount/__tests__/factory.test.d.ts.map +1 -0
- package/dist/lib/entities/Discount/__tests__/factory.test.js +75 -0
- package/dist/lib/entities/Discount/__tests__/integration.test.d.ts +2 -0
- package/dist/lib/entities/Discount/__tests__/integration.test.d.ts.map +1 -0
- package/dist/lib/entities/Discount/__tests__/integration.test.js +115 -0
- package/dist/lib/entities/Discount/__tests__/simple.test.d.ts +2 -0
- package/dist/lib/entities/Discount/__tests__/simple.test.d.ts.map +1 -0
- package/dist/lib/entities/Discount/__tests__/simple.test.js +186 -0
- package/dist/lib/entities/Discount/__tests__/utils.test.d.ts +2 -0
- package/dist/lib/entities/Discount/__tests__/utils.test.d.ts.map +1 -0
- package/dist/lib/entities/Discount/__tests__/utils.test.js +55 -0
- package/dist/lib/entities/Discount/engine.d.ts +29 -0
- package/dist/lib/entities/Discount/engine.d.ts.map +1 -0
- package/dist/lib/entities/Discount/engine.js +85 -0
- package/dist/lib/entities/Discount/factory.d.ts +10 -0
- package/dist/lib/entities/Discount/factory.d.ts.map +1 -0
- package/dist/lib/entities/Discount/factory.js +18 -0
- package/dist/lib/entities/Discount/index.d.ts +9 -0
- package/dist/lib/entities/Discount/index.d.ts.map +1 -0
- package/{lib/entities/Discount/index.ts → dist/lib/entities/Discount/index.js} +0 -2
- package/dist/lib/entities/Discount/strategies/BundleStrategy.d.ts +12 -0
- package/dist/lib/entities/Discount/strategies/BundleStrategy.d.ts.map +1 -0
- package/dist/lib/entities/Discount/strategies/BundleStrategy.js +78 -0
- package/dist/lib/entities/Discount/strategies/__tests__/BundleStrategy.test.d.ts +2 -0
- package/dist/lib/entities/Discount/strategies/__tests__/BundleStrategy.test.d.ts.map +1 -0
- package/dist/lib/entities/Discount/strategies/__tests__/BundleStrategy.test.js +265 -0
- package/dist/lib/entities/Discount/strategy.d.ts +6 -0
- package/dist/lib/entities/Discount/strategy.d.ts.map +1 -0
- package/dist/lib/entities/Discount/types.d.ts +148 -0
- package/dist/lib/entities/Discount/types.d.ts.map +1 -0
- package/dist/lib/entities/Discount/types.js +29 -0
- package/dist/lib/entities/Discount/utils.d.ts +29 -0
- package/dist/lib/entities/Discount/utils.d.ts.map +1 -0
- package/{lib/entities/Discount/utils.ts → dist/lib/entities/Discount/utils.js} +12 -15
- package/dist/lib/entities/FavoriteProduct.d.ts +25 -0
- package/dist/lib/entities/FavoriteProduct.d.ts.map +1 -0
- package/dist/lib/entities/FavoriteProduct.js +9 -0
- package/dist/lib/entities/Invoice.d.ts +210 -0
- package/dist/lib/entities/Invoice.d.ts.map +1 -0
- package/dist/lib/entities/Invoice.js +49 -0
- package/dist/lib/entities/Locale.d.ts +22 -0
- package/dist/lib/entities/Locale.d.ts.map +1 -0
- package/{lib/entities/Locale.ts → dist/lib/entities/Locale.js} +2 -4
- package/dist/lib/entities/Order.d.ts +1806 -0
- package/dist/lib/entities/Order.d.ts.map +1 -0
- package/dist/lib/entities/Order.js +62 -0
- package/dist/lib/entities/Organization.d.ts +100 -0
- package/dist/lib/entities/Organization.d.ts.map +1 -0
- package/dist/lib/entities/Organization.js +16 -0
- package/dist/lib/entities/Product.d.ts +694 -0
- package/dist/lib/entities/Product.d.ts.map +1 -0
- package/dist/lib/entities/Product.js +61 -0
- package/dist/lib/entities/Profile.d.ts +98 -0
- package/dist/lib/entities/Profile.d.ts.map +1 -0
- package/dist/lib/entities/Profile.js +50 -0
- package/dist/lib/entities/Store.d.ts +93 -0
- package/dist/lib/entities/Store.d.ts.map +1 -0
- package/dist/lib/entities/Store.js +20 -0
- package/dist/lib/entities/index.d.ts +15 -0
- package/dist/lib/entities/index.d.ts.map +1 -0
- package/dist/lib/firebase-api/app.d.ts +2 -0
- package/dist/lib/firebase-api/app.d.ts.map +1 -0
- package/dist/lib/firebase-api/app.js +16 -0
- package/dist/lib/firebase-api/index.d.ts +75 -0
- package/dist/lib/firebase-api/index.d.ts.map +1 -0
- package/dist/lib/firebase-api/index.js +33 -0
- package/dist/lib/index.d.ts +4 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/utils/index.d.ts +109 -0
- package/dist/lib/utils/index.d.ts.map +1 -0
- package/dist/lib/utils/index.js +95 -0
- package/dist/tsconfig.app.tsbuildinfo +1 -0
- package/dist/tsconfig.node.tsbuildinfo +1 -0
- package/dist/vite.config.d.ts +3 -0
- package/dist/vite.config.d.ts.map +1 -0
- package/dist/vite.config.js +25 -0
- package/package.json +8 -1
- package/eslint.config.js +0 -28
- package/index.html +0 -13
- package/lib/entities/Address.ts +0 -13
- package/lib/entities/Cart.ts +0 -24
- package/lib/entities/Category.ts +0 -35
- package/lib/entities/Company.ts +0 -9
- package/lib/entities/DeliveryNote.ts +0 -70
- package/lib/entities/Discount/__tests__/engine.test.ts +0 -337
- package/lib/entities/Discount/__tests__/factory.test.ts +0 -91
- package/lib/entities/Discount/__tests__/integration.test.ts +0 -132
- package/lib/entities/Discount/__tests__/simple.test.ts +0 -215
- package/lib/entities/Discount/__tests__/utils.test.ts +0 -69
- package/lib/entities/Discount/engine.ts +0 -138
- package/lib/entities/Discount/factory.ts +0 -25
- package/lib/entities/Discount/strategies/BundleStrategy.ts +0 -119
- package/lib/entities/Discount/strategies/__tests__/BundleStrategy.test.ts +0 -295
- package/lib/entities/Discount/strategy.ts +0 -6
- package/lib/entities/Discount/types.ts +0 -68
- package/lib/entities/FavoriteProduct.ts +0 -12
- package/lib/entities/Invoice.ts +0 -57
- package/lib/entities/Order.ts +0 -67
- package/lib/entities/Organization.ts +0 -23
- package/lib/entities/Product.ts +0 -68
- package/lib/entities/Profile.ts +0 -56
- package/lib/entities/Store.ts +0 -24
- package/lib/firebase-api/app.ts +0 -18
- package/lib/firebase-api/index.ts +0 -46
- package/lib/utils/index.ts +0 -127
- package/src/vite-env.d.ts +0 -1
- package/tsconfig.app.json +0 -20
- package/tsconfig.json +0 -7
- package/tsconfig.node.json +0 -26
- package/vite.config.ts +0 -27
- package/vitest.config.ts +0 -10
- /package/{src/main.tsx → dist/lib/entities/Discount/strategy.js} +0 -0
- /package/{lib/entities/index.ts → dist/lib/entities/index.js} +0 -0
- /package/{lib/index.tsx → dist/lib/index.js} +0 -0
|
@@ -1,295 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach } from "vitest";
|
|
2
|
-
import { BundleDiscountStrategy } from "../BundleStrategy";
|
|
3
|
-
import { TDiscount, DiscountContext } from "../../types";
|
|
4
|
-
|
|
5
|
-
describe("BundleDiscountStrategy", () => {
|
|
6
|
-
let strategy: BundleDiscountStrategy;
|
|
7
|
-
let mockContext: DiscountContext;
|
|
8
|
-
|
|
9
|
-
beforeEach(() => {
|
|
10
|
-
strategy = new BundleDiscountStrategy();
|
|
11
|
-
|
|
12
|
-
mockContext = {
|
|
13
|
-
cart: [
|
|
14
|
-
{
|
|
15
|
-
amount: 2,
|
|
16
|
-
product: {
|
|
17
|
-
id: "product1",
|
|
18
|
-
price: 10,
|
|
19
|
-
},
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
amount: 1,
|
|
23
|
-
product: {
|
|
24
|
-
id: "product2",
|
|
25
|
-
price: 15,
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
],
|
|
29
|
-
user: undefined,
|
|
30
|
-
appliedDiscounts: [],
|
|
31
|
-
};
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
describe("canApply", () => {
|
|
35
|
-
it("should return true for valid bundle discount", () => {
|
|
36
|
-
const discount: TDiscount = {
|
|
37
|
-
type: "Discount",
|
|
38
|
-
storeId: "store1",
|
|
39
|
-
companyId: "company1",
|
|
40
|
-
id: "bundle1",
|
|
41
|
-
name: [{ lang: "he", value: "Buy 3 for $25" }],
|
|
42
|
-
active: true,
|
|
43
|
-
startDate: Date.now() - 1000,
|
|
44
|
-
endDate: Date.now() + 1000,
|
|
45
|
-
variant: {
|
|
46
|
-
variantType: "bundle",
|
|
47
|
-
productsId: ["product1", "product2"],
|
|
48
|
-
requiredQuantity: 3,
|
|
49
|
-
bundlePrice: 25,
|
|
50
|
-
},
|
|
51
|
-
conditions: {
|
|
52
|
-
stackable: false,
|
|
53
|
-
},
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
expect(strategy.canApply(discount, mockContext)).toBe(true);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it("should return true for bundle variant type", () => {
|
|
60
|
-
const discount = {
|
|
61
|
-
...mockDiscount,
|
|
62
|
-
variant: {
|
|
63
|
-
variantType: "bundle" as const,
|
|
64
|
-
productsId: ["product1", "product2"],
|
|
65
|
-
requiredQuantity: 3,
|
|
66
|
-
bundlePrice: 25,
|
|
67
|
-
},
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
// This should work since it's a bundle type and we have 3 items total
|
|
71
|
-
expect(strategy.canApply(discount, mockContext)).toBe(true);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it("should return false when not enough items", () => {
|
|
75
|
-
const discount: TDiscount = {
|
|
76
|
-
type: "Discount",
|
|
77
|
-
storeId: "store1",
|
|
78
|
-
companyId: "company1",
|
|
79
|
-
id: "bundle1",
|
|
80
|
-
name: [{ lang: "he", value: "Buy 5 for $40" }],
|
|
81
|
-
active: true,
|
|
82
|
-
startDate: Date.now() - 1000,
|
|
83
|
-
endDate: Date.now() + 1000,
|
|
84
|
-
variant: {
|
|
85
|
-
variantType: "bundle",
|
|
86
|
-
productsId: ["product1", "product2"],
|
|
87
|
-
requiredQuantity: 5, // Need 5, but cart only has 3
|
|
88
|
-
bundlePrice: 40,
|
|
89
|
-
},
|
|
90
|
-
conditions: {
|
|
91
|
-
stackable: false,
|
|
92
|
-
},
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
expect(strategy.canApply(discount, mockContext)).toBe(false);
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it("should return false when discount is inactive", () => {
|
|
99
|
-
const discount: TDiscount = {
|
|
100
|
-
type: "Discount",
|
|
101
|
-
storeId: "store1",
|
|
102
|
-
companyId: "company1",
|
|
103
|
-
id: "bundle1",
|
|
104
|
-
name: [{ lang: "he", value: "Buy 3 for $25" }],
|
|
105
|
-
active: false, // Inactive
|
|
106
|
-
startDate: Date.now() - 1000,
|
|
107
|
-
endDate: Date.now() + 1000,
|
|
108
|
-
variant: {
|
|
109
|
-
variantType: "bundle",
|
|
110
|
-
productsId: ["product1", "product2"],
|
|
111
|
-
requiredQuantity: 3,
|
|
112
|
-
bundlePrice: 25,
|
|
113
|
-
},
|
|
114
|
-
conditions: {
|
|
115
|
-
stackable: false,
|
|
116
|
-
},
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
expect(strategy.canApply(discount, mockContext)).toBe(false);
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
it("should return false when discount is expired", () => {
|
|
123
|
-
const discount: TDiscount = {
|
|
124
|
-
type: "Discount",
|
|
125
|
-
storeId: "store1",
|
|
126
|
-
companyId: "company1",
|
|
127
|
-
id: "bundle1",
|
|
128
|
-
name: [{ lang: "he", value: "Buy 3 for $25" }],
|
|
129
|
-
active: true,
|
|
130
|
-
startDate: Date.now() - 2000,
|
|
131
|
-
endDate: Date.now() - 1000, // Expired
|
|
132
|
-
variant: {
|
|
133
|
-
variantType: "bundle",
|
|
134
|
-
productsId: ["product1", "product2"],
|
|
135
|
-
requiredQuantity: 3,
|
|
136
|
-
bundlePrice: 25,
|
|
137
|
-
},
|
|
138
|
-
conditions: {
|
|
139
|
-
stackable: false,
|
|
140
|
-
},
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
expect(strategy.canApply(discount, mockContext)).toBe(false);
|
|
144
|
-
});
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
describe("calculate", () => {
|
|
148
|
-
it("should calculate bundle discount correctly", () => {
|
|
149
|
-
const discount: TDiscount = {
|
|
150
|
-
type: "Discount",
|
|
151
|
-
storeId: "store1",
|
|
152
|
-
companyId: "company1",
|
|
153
|
-
id: "bundle1",
|
|
154
|
-
name: [{ lang: "he", value: "Buy 3 for $25" }],
|
|
155
|
-
active: true,
|
|
156
|
-
startDate: Date.now() - 1000,
|
|
157
|
-
endDate: Date.now() + 1000,
|
|
158
|
-
variant: {
|
|
159
|
-
variantType: "bundle",
|
|
160
|
-
productsId: ["product1", "product2"],
|
|
161
|
-
requiredQuantity: 3,
|
|
162
|
-
bundlePrice: 25,
|
|
163
|
-
},
|
|
164
|
-
conditions: {
|
|
165
|
-
stackable: false,
|
|
166
|
-
},
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
const result = strategy.calculate(discount, mockContext);
|
|
170
|
-
|
|
171
|
-
expect(result.applicable).toBe(true);
|
|
172
|
-
expect(result.discountAmount).toBe(10); // (2×10 + 1×15) - 25 = 35 - 25 = 10
|
|
173
|
-
expect(result.affectedItems).toHaveLength(2);
|
|
174
|
-
|
|
175
|
-
// Check product1 discount
|
|
176
|
-
const product1Item = result.affectedItems.find(item => item.productId === "product1");
|
|
177
|
-
expect(product1Item).toBeDefined();
|
|
178
|
-
expect(product1Item!.discountAmount).toBeCloseTo(5.71, 2); // Proportional to 20/35
|
|
179
|
-
|
|
180
|
-
// Check product2 discount
|
|
181
|
-
const product2Item = result.affectedItems.find(item => item.productId === "product2");
|
|
182
|
-
expect(product2Item).toBeDefined();
|
|
183
|
-
expect(product2Item!.discountAmount).toBeCloseTo(4.29, 2); // Proportional to 15/35
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
it("should handle multiple bundles", () => {
|
|
187
|
-
const contextWithMoreItems: DiscountContext = {
|
|
188
|
-
cart: [
|
|
189
|
-
{
|
|
190
|
-
amount: 6, // 6 items
|
|
191
|
-
product: {
|
|
192
|
-
id: "product1",
|
|
193
|
-
price: 10,
|
|
194
|
-
},
|
|
195
|
-
},
|
|
196
|
-
],
|
|
197
|
-
user: undefined,
|
|
198
|
-
appliedDiscounts: [],
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
const discount: TDiscount = {
|
|
202
|
-
type: "Discount",
|
|
203
|
-
storeId: "store1",
|
|
204
|
-
companyId: "company1",
|
|
205
|
-
id: "bundle1",
|
|
206
|
-
name: [{ lang: "he", value: "Buy 3 for $25" }],
|
|
207
|
-
active: true,
|
|
208
|
-
startDate: Date.now() - 1000,
|
|
209
|
-
endDate: Date.now() + 1000,
|
|
210
|
-
variant: {
|
|
211
|
-
variantType: "bundle",
|
|
212
|
-
productsId: ["product1"],
|
|
213
|
-
requiredQuantity: 3,
|
|
214
|
-
bundlePrice: 25,
|
|
215
|
-
},
|
|
216
|
-
conditions: {
|
|
217
|
-
stackable: false,
|
|
218
|
-
},
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
const result = strategy.calculate(discount, contextWithMoreItems);
|
|
222
|
-
|
|
223
|
-
expect(result.applicable).toBe(true);
|
|
224
|
-
expect(result.discountAmount).toBe(10); // (6×10) - (2×25) = 60 - 50 = 10
|
|
225
|
-
expect(result.affectedItems).toHaveLength(1);
|
|
226
|
-
expect(result.affectedItems[0].discountAmount).toBe(10);
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
it("should return not applicable for invalid bundle", () => {
|
|
230
|
-
const discount = {
|
|
231
|
-
...mockDiscount,
|
|
232
|
-
variant: {
|
|
233
|
-
variantType: "bundle" as const,
|
|
234
|
-
productsId: ["product1"],
|
|
235
|
-
requiredQuantity: 10, // Too many required
|
|
236
|
-
bundlePrice: 25,
|
|
237
|
-
},
|
|
238
|
-
};
|
|
239
|
-
|
|
240
|
-
const result = strategy.calculate(discount, mockContext);
|
|
241
|
-
|
|
242
|
-
expect(result.applicable).toBe(false);
|
|
243
|
-
expect(result.discountAmount).toBe(0);
|
|
244
|
-
expect(result.affectedItems).toHaveLength(0);
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
it("should return not applicable when not enough items", () => {
|
|
248
|
-
const discount: TDiscount = {
|
|
249
|
-
type: "Discount",
|
|
250
|
-
storeId: "store1",
|
|
251
|
-
companyId: "company1",
|
|
252
|
-
id: "bundle1",
|
|
253
|
-
name: [{ lang: "he", value: "Buy 5 for $40" }],
|
|
254
|
-
active: true,
|
|
255
|
-
startDate: Date.now() - 1000,
|
|
256
|
-
endDate: Date.now() + 1000,
|
|
257
|
-
variant: {
|
|
258
|
-
variantType: "bundle",
|
|
259
|
-
productsId: ["product1", "product2"],
|
|
260
|
-
requiredQuantity: 5,
|
|
261
|
-
bundlePrice: 40,
|
|
262
|
-
},
|
|
263
|
-
conditions: {
|
|
264
|
-
stackable: false,
|
|
265
|
-
},
|
|
266
|
-
};
|
|
267
|
-
|
|
268
|
-
const result = strategy.calculate(discount, mockContext);
|
|
269
|
-
|
|
270
|
-
expect(result.applicable).toBe(false);
|
|
271
|
-
expect(result.discountAmount).toBe(0);
|
|
272
|
-
expect(result.affectedItems).toHaveLength(0);
|
|
273
|
-
});
|
|
274
|
-
});
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
const mockDiscount: TDiscount = {
|
|
278
|
-
type: "Discount",
|
|
279
|
-
storeId: "store1",
|
|
280
|
-
companyId: "company1",
|
|
281
|
-
id: "bundle1",
|
|
282
|
-
name: [{ lang: "he", value: "Buy 3 for $25" }],
|
|
283
|
-
active: true,
|
|
284
|
-
startDate: Date.now() - 1000,
|
|
285
|
-
endDate: Date.now() + 1000,
|
|
286
|
-
variant: {
|
|
287
|
-
variantType: "bundle",
|
|
288
|
-
productsId: ["product1", "product2"],
|
|
289
|
-
requiredQuantity: 3,
|
|
290
|
-
bundlePrice: 25,
|
|
291
|
-
},
|
|
292
|
-
conditions: {
|
|
293
|
-
stackable: false,
|
|
294
|
-
},
|
|
295
|
-
};
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
|
|
3
|
-
// Simple discount conditions
|
|
4
|
-
export const DiscountConditionsSchema = z
|
|
5
|
-
.object({
|
|
6
|
-
minSpend: z.number().positive().optional(),
|
|
7
|
-
stackable: z.boolean().default(false),
|
|
8
|
-
})
|
|
9
|
-
.optional();
|
|
10
|
-
|
|
11
|
-
// Bundle discount - buy X items for Y price
|
|
12
|
-
export const DiscountVariantSchema = z.discriminatedUnion("variantType", [
|
|
13
|
-
z.object({
|
|
14
|
-
variantType: z.literal("bundle"),
|
|
15
|
-
productsId: z.array(z.string().nonempty()).min(1), // Which products are included
|
|
16
|
-
requiredQuantity: z.number().positive(), // How many items needed (e.g., 3)
|
|
17
|
-
bundlePrice: z.number().positive(), // Total price for the bundle (e.g., $25)
|
|
18
|
-
}),
|
|
19
|
-
]);
|
|
20
|
-
|
|
21
|
-
export const DiscountSchema = z.object({
|
|
22
|
-
type: z.literal("Discount"),
|
|
23
|
-
storeId: z.string().min(1),
|
|
24
|
-
companyId: z.string().min(1),
|
|
25
|
-
id: z.string().min(1),
|
|
26
|
-
name: z.array(z.object({ lang: z.enum(["he"]), value: z.string().nonempty() })),
|
|
27
|
-
active: z.boolean(),
|
|
28
|
-
startDate: z.number(),
|
|
29
|
-
endDate: z.number(),
|
|
30
|
-
variant: DiscountVariantSchema,
|
|
31
|
-
conditions: DiscountConditionsSchema,
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
export type TDiscount = z.infer<typeof DiscountSchema>;
|
|
35
|
-
export type DiscountVariant = z.infer<typeof DiscountVariantSchema>;
|
|
36
|
-
export type DiscountConditions = z.infer<typeof DiscountConditionsSchema>;
|
|
37
|
-
|
|
38
|
-
// Simple result types
|
|
39
|
-
export interface DiscountResult {
|
|
40
|
-
applicable: boolean;
|
|
41
|
-
discountAmount: number;
|
|
42
|
-
affectedItems: Array<{
|
|
43
|
-
productId: string;
|
|
44
|
-
quantity: number;
|
|
45
|
-
originalPrice: number;
|
|
46
|
-
discountedPrice: number;
|
|
47
|
-
discountAmount: number;
|
|
48
|
-
}>;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export interface AppliedDiscount {
|
|
52
|
-
discountId: string;
|
|
53
|
-
discountName: string;
|
|
54
|
-
discountAmount: number;
|
|
55
|
-
affectedItems: DiscountResult["affectedItems"];
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export interface DiscountContext {
|
|
59
|
-
cart: Array<{
|
|
60
|
-
amount: number;
|
|
61
|
-
product: {
|
|
62
|
-
id: string;
|
|
63
|
-
price: number;
|
|
64
|
-
};
|
|
65
|
-
}>;
|
|
66
|
-
user?: Record<string, unknown>;
|
|
67
|
-
appliedDiscounts: AppliedDiscount[];
|
|
68
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
|
|
3
|
-
export const FavoriteProductSchema = z.object({
|
|
4
|
-
type: z.literal("FavoriteProduct"),
|
|
5
|
-
id: z.string().uuid(),
|
|
6
|
-
companyId: z.string().uuid(),
|
|
7
|
-
storeId: z.string().uuid(),
|
|
8
|
-
userId: z.string().uuid(),
|
|
9
|
-
productId: z.string().uuid(),
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
export type TFavoriteProduct = z.infer<typeof FavoriteProductSchema>;
|
package/lib/entities/Invoice.ts
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import { CalculatedDataSchema } from "./DeliveryNote";
|
|
3
|
-
|
|
4
|
-
// Main Invoice schema
|
|
5
|
-
export const EzInvoiceSchema = z.object({
|
|
6
|
-
doc_uuid: z.string().uuid("Document UUID must be a valid UUID"),
|
|
7
|
-
pdf_link: z.string().url("PDF link must be a valid URL"),
|
|
8
|
-
pdf_link_copy: z.string().url("PDF copy link must be a valid URL"),
|
|
9
|
-
doc_number: z.string().min(1, "Document number is required"),
|
|
10
|
-
sent_mails: z.array(z.string().email("Each email must be valid")),
|
|
11
|
-
success: z.boolean(),
|
|
12
|
-
ua_uuid: z.string().uuid("UA UUID must be a valid UUID"),
|
|
13
|
-
calculatedData: CalculatedDataSchema,
|
|
14
|
-
warning: z.string().optional(),
|
|
15
|
-
date: z.number().optional(),
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
export const InvoiceSchema = z.object({
|
|
19
|
-
id: z.string().min(1, "ID is required"),
|
|
20
|
-
number: z.string().min(1, "Number is required"),
|
|
21
|
-
date: z.string().min(1, "Date is required"),
|
|
22
|
-
createdAt: z.number().min(1, "Created at is required"),
|
|
23
|
-
status: z.enum(["pending", "paid", "cancelled"]),
|
|
24
|
-
companyDetails: z
|
|
25
|
-
.object({
|
|
26
|
-
name: z.string().min(1, "Name is required").optional(),
|
|
27
|
-
address: z.string().min(1, "Address is required").optional(),
|
|
28
|
-
phone: z.string().min(1, "Phone is required").optional(),
|
|
29
|
-
email: z.string().email("Email must be valid").optional(),
|
|
30
|
-
})
|
|
31
|
-
.optional(),
|
|
32
|
-
clientDetails: z
|
|
33
|
-
.object({
|
|
34
|
-
name: z.string().min(1, "Name is required").optional(),
|
|
35
|
-
address: z.string().min(1, "Address is required").optional(),
|
|
36
|
-
phone: z.string().min(1, "Phone is required").optional(),
|
|
37
|
-
email: z.string().email("Email must be valid").optional(),
|
|
38
|
-
})
|
|
39
|
-
.optional(),
|
|
40
|
-
items: z
|
|
41
|
-
.array(
|
|
42
|
-
z.object({
|
|
43
|
-
name: z.string().min(1, "Name is required").optional(),
|
|
44
|
-
price: z.number().min(1, "Price is required").optional(),
|
|
45
|
-
quantity: z.number().min(1, "Quantity is required").optional(),
|
|
46
|
-
total: z.number().min(1, "Total is required").optional(),
|
|
47
|
-
})
|
|
48
|
-
)
|
|
49
|
-
.optional(),
|
|
50
|
-
total: z.number().min(1, "Total is required").optional(),
|
|
51
|
-
vat: z.number().min(1, "VAT is required").optional(),
|
|
52
|
-
link: z.string().url("Link must be a valid URL").optional(),
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
// Type inference
|
|
56
|
-
export type TInvoice = z.infer<typeof InvoiceSchema>;
|
|
57
|
-
export type TEzInvoice = z.infer<typeof EzInvoiceSchema>;
|
package/lib/entities/Order.ts
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import { ProfileSchema } from "./Profile";
|
|
3
|
-
import { notEmptyTextSchema } from "./Atoms";
|
|
4
|
-
import { CartItemProductSchema } from "./Cart";
|
|
5
|
-
import { DeliveryNoteSchema, EzDeliveryNoteSchema } from "./DeliveryNote";
|
|
6
|
-
import { BillingAccountSchema } from "./Organization";
|
|
7
|
-
import { EzInvoiceSchema, InvoiceSchema } from "./Invoice";
|
|
8
|
-
|
|
9
|
-
// pending - order created / by user
|
|
10
|
-
// processing order accepted by store by admin
|
|
11
|
-
// delivered - order delivered by admin
|
|
12
|
-
// canceled - order canceled by user/admin
|
|
13
|
-
// completed - order paid by admin
|
|
14
|
-
|
|
15
|
-
// type PaymentMethod = "credit_card" | "paypal" | "bank_transfer" | "cash_on_delivery";
|
|
16
|
-
|
|
17
|
-
export const OrderSchema = z.object({
|
|
18
|
-
type: z.literal("Order"),
|
|
19
|
-
createdBy: z.enum(["user", "admin"]).optional(),
|
|
20
|
-
id: notEmptyTextSchema,
|
|
21
|
-
companyId: notEmptyTextSchema,
|
|
22
|
-
storeId: notEmptyTextSchema,
|
|
23
|
-
userId: notEmptyTextSchema,
|
|
24
|
-
status: z.enum([
|
|
25
|
-
"draft", // before payment
|
|
26
|
-
"pending", // after payment
|
|
27
|
-
"processing", // after admin approve
|
|
28
|
-
"in_delivery", //
|
|
29
|
-
"delivered",
|
|
30
|
-
"cancelled",
|
|
31
|
-
"completed",
|
|
32
|
-
"refunded",
|
|
33
|
-
]),
|
|
34
|
-
paymentType: z.enum(["internal", "external"]).optional(),
|
|
35
|
-
paymentStatus: z.enum(["pending", "pending_j5", "external", "completed", "failed", "refunded"]), //todo check if hyp support partial refund
|
|
36
|
-
cart: z.object({
|
|
37
|
-
id: z.string(),
|
|
38
|
-
items: z.array(CartItemProductSchema),
|
|
39
|
-
cartDiscount: z.number(),
|
|
40
|
-
cartTotal: z.number(),
|
|
41
|
-
cartVat: z.number(),
|
|
42
|
-
deliveryPrice: z.number().optional(), // final delivery price for cart
|
|
43
|
-
}),
|
|
44
|
-
storeOptions: z
|
|
45
|
-
.object({
|
|
46
|
-
deliveryPrice: z.number().optional(),
|
|
47
|
-
freeDeliveryPrice: z.number().optional(),
|
|
48
|
-
isVatIncludedInPrice: z.boolean().optional(),
|
|
49
|
-
})
|
|
50
|
-
.optional(),
|
|
51
|
-
orderDeliveryPrice: z.number().optional(), // delivery price for order
|
|
52
|
-
originalAmount: z.number().positive().optional(), // what client pay
|
|
53
|
-
actualAmount: z.number().positive().optional(), // what store charge
|
|
54
|
-
date: z.number(),
|
|
55
|
-
deliveryDate: z.coerce.number(),
|
|
56
|
-
client: ProfileSchema.required({}),
|
|
57
|
-
nameOnInvoice: z.string().optional(),
|
|
58
|
-
clientComment: z.string().optional(),
|
|
59
|
-
organizationId: z.string().optional(),
|
|
60
|
-
billingAccount: BillingAccountSchema.optional(),
|
|
61
|
-
deliveryNote: DeliveryNoteSchema.optional(),
|
|
62
|
-
invoice: InvoiceSchema.optional(),
|
|
63
|
-
ezInvoice: EzInvoiceSchema.optional(),
|
|
64
|
-
ezDeliveryNote: EzDeliveryNoteSchema.optional(),
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
export type TOrder = z.infer<typeof OrderSchema>;
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
|
|
3
|
-
export const BillingAccountSchema = z.object({
|
|
4
|
-
number: z.string(),
|
|
5
|
-
name: z.string(),
|
|
6
|
-
id: z.string(),
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
// client organization for clients
|
|
10
|
-
export const OrganizationSchema = z.object({
|
|
11
|
-
id: z.string(),
|
|
12
|
-
name: z.string(),
|
|
13
|
-
discountPercentage: z.number().positive().min(0).max(100).optional(),
|
|
14
|
-
nameOnInvoice: z.string().optional(),
|
|
15
|
-
billingAccounts: z.array(BillingAccountSchema),
|
|
16
|
-
paymentType: z.enum(["default", "delayed"]),
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
export const NewOrganizationSchema = OrganizationSchema.omit({ id: true });
|
|
20
|
-
|
|
21
|
-
export type TBillingAccount = z.infer<typeof BillingAccountSchema>;
|
|
22
|
-
export type TNewOrganization = z.infer<typeof NewOrganizationSchema>;
|
|
23
|
-
export type TOrganization = z.infer<typeof OrganizationSchema>;
|
package/lib/entities/Product.ts
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import { LocaleSchema } from "./Locale";
|
|
3
|
-
import { CategorySchema } from "./Category";
|
|
4
|
-
|
|
5
|
-
const text = z.string().min(1);
|
|
6
|
-
|
|
7
|
-
export const ProductSchema = z.object({
|
|
8
|
-
type: z.literal("Product"),
|
|
9
|
-
storeId: text,
|
|
10
|
-
companyId: text,
|
|
11
|
-
id: text,
|
|
12
|
-
objectID: text,
|
|
13
|
-
sku: text,
|
|
14
|
-
name: z.array(LocaleSchema),
|
|
15
|
-
description: z.array(LocaleSchema),
|
|
16
|
-
isPublished: z.boolean(),
|
|
17
|
-
vat: z.boolean(),
|
|
18
|
-
priceType: z.object({
|
|
19
|
-
type: z.enum(["unit", "kg", "gram", "liter", "ml"]),
|
|
20
|
-
value: z.number(),
|
|
21
|
-
}),
|
|
22
|
-
price: z.number().positive(),
|
|
23
|
-
purchasePrice: z.number().optional(),
|
|
24
|
-
profitPercentage: z.number().optional(),
|
|
25
|
-
currency: z.literal("ILS"),
|
|
26
|
-
discount: z.object({
|
|
27
|
-
type: z.enum(["number", "percent", "none"]),
|
|
28
|
-
value: z.number(),
|
|
29
|
-
}),
|
|
30
|
-
isDiscountable: z.boolean({ description: "included in store discounts" }).optional(),
|
|
31
|
-
weight: z.object({
|
|
32
|
-
value: z.number(),
|
|
33
|
-
unit: z.enum(["kg", "gram", "none"]),
|
|
34
|
-
}),
|
|
35
|
-
volume: z.object({
|
|
36
|
-
value: z.number(),
|
|
37
|
-
unit: z.enum(["liter", "ml", "none"]),
|
|
38
|
-
}),
|
|
39
|
-
images: z.array(z.object({ url: z.string().url(), id: z.string() })),
|
|
40
|
-
manufacturer: z.string(),
|
|
41
|
-
brand: z.string(),
|
|
42
|
-
importer: z.string(),
|
|
43
|
-
supplier: z.string(),
|
|
44
|
-
ingredients: z.array(LocaleSchema),
|
|
45
|
-
created_at: z.number(),
|
|
46
|
-
updated_at: z.number(),
|
|
47
|
-
categoryIds: z.array(z.string().nonempty()),
|
|
48
|
-
|
|
49
|
-
// @deprecated
|
|
50
|
-
categoryList: z.array(CategorySchema).optional(),
|
|
51
|
-
// @deprecated
|
|
52
|
-
categories: z.object({
|
|
53
|
-
lvl0: z.array(z.string()),
|
|
54
|
-
lvl1: z.array(z.string()),
|
|
55
|
-
lvl2: z.array(z.string()),
|
|
56
|
-
lvl3: z.array(z.string()),
|
|
57
|
-
lvl4: z.array(z.string()),
|
|
58
|
-
}).optional(),
|
|
59
|
-
// @deprecated
|
|
60
|
-
categoryNames: z.array(z.string()).optional(),
|
|
61
|
-
});
|
|
62
|
-
export type TProduct = z.infer<typeof ProductSchema>;
|
|
63
|
-
|
|
64
|
-
export const NewProductSchema = ProductSchema.extend({
|
|
65
|
-
image: z.instanceof(File).optional(),
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
export type TNewProduct = z.infer<typeof NewProductSchema>;
|
package/lib/entities/Profile.ts
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import { AddressSchema } from "./Address";
|
|
3
|
-
import { notEmptyTextSchema } from "./Atoms";
|
|
4
|
-
|
|
5
|
-
export const ProfilePaymentTypeSchema = z.enum(["default", "delayed"], {
|
|
6
|
-
description: "delayed is J5 transaction",
|
|
7
|
-
});
|
|
8
|
-
export type TProfilePaymentType = z.infer<typeof ProfilePaymentTypeSchema>;
|
|
9
|
-
|
|
10
|
-
export const ProfileSchema = z.object({
|
|
11
|
-
type: z.literal("Profile"),
|
|
12
|
-
id: notEmptyTextSchema,
|
|
13
|
-
companyId: notEmptyTextSchema,
|
|
14
|
-
storeId: notEmptyTextSchema,
|
|
15
|
-
tenantId: notEmptyTextSchema,
|
|
16
|
-
clientType: z.enum(["user", "company"]),
|
|
17
|
-
companyName: z.string().optional(),
|
|
18
|
-
displayName: notEmptyTextSchema,
|
|
19
|
-
email: z.string().email(),
|
|
20
|
-
phoneNumber: z.string().optional(),
|
|
21
|
-
address: AddressSchema.optional(),
|
|
22
|
-
isAnonymous: z.boolean(),
|
|
23
|
-
createdDate: z.number(),
|
|
24
|
-
lastActivityDate: z.number(),
|
|
25
|
-
paymentType: ProfilePaymentTypeSchema,
|
|
26
|
-
organizationId: z.string().optional().nullable(),
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
export type TProfile = z.infer<typeof ProfileSchema>;
|
|
30
|
-
|
|
31
|
-
export function createEmptyProfile(): TProfile {
|
|
32
|
-
return {
|
|
33
|
-
type: "Profile",
|
|
34
|
-
id: "",
|
|
35
|
-
companyId: "",
|
|
36
|
-
storeId: "",
|
|
37
|
-
tenantId: "",
|
|
38
|
-
clientType: "user",
|
|
39
|
-
displayName: "",
|
|
40
|
-
email: "",
|
|
41
|
-
phoneNumber: "",
|
|
42
|
-
address: {
|
|
43
|
-
country: "",
|
|
44
|
-
city: "",
|
|
45
|
-
street: "",
|
|
46
|
-
streetNumber: "",
|
|
47
|
-
floor: "",
|
|
48
|
-
apartmentEnterNumber: "",
|
|
49
|
-
apartmentNumber: "",
|
|
50
|
-
},
|
|
51
|
-
createdDate: 0,
|
|
52
|
-
lastActivityDate: 0,
|
|
53
|
-
isAnonymous: true,
|
|
54
|
-
paymentType: ProfilePaymentTypeSchema.Values.default,
|
|
55
|
-
};
|
|
56
|
-
}
|
package/lib/entities/Store.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import { AddressSchema } from "./Address";
|
|
3
|
-
|
|
4
|
-
export const clientTypesSchema = z.enum(["individual", "company"]);
|
|
5
|
-
|
|
6
|
-
export const StoreSchema = z.object({
|
|
7
|
-
id: z.string(),
|
|
8
|
-
companyId: z.string(),
|
|
9
|
-
name: z.string(),
|
|
10
|
-
urls: z.array(z.string()),
|
|
11
|
-
logoUrl: z.string(),
|
|
12
|
-
tenantId: z.string(), // firebase auth tenantId
|
|
13
|
-
paymentType: z.enum(["external", "j5"]),
|
|
14
|
-
allowAnonymousClients: z.boolean(),
|
|
15
|
-
isVatIncludedInPrice: z.boolean(),
|
|
16
|
-
clientTypes: z.array(clientTypesSchema),
|
|
17
|
-
minimumOrder: z.number().optional(),
|
|
18
|
-
freeDeliveryPrice: z.number().optional(),
|
|
19
|
-
deliveryPrice: z.number().optional(),
|
|
20
|
-
address: AddressSchema.optional(),
|
|
21
|
-
companyNumber: z.string().optional(), // חפ של החברה
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
export type TStore = z.infer<typeof StoreSchema>;
|