washday-sdk 0.0.1

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.
Files changed (36) hide show
  1. package/dist/enum/index.js +15 -0
  2. package/dist/index.js +28 -0
  3. package/dist/interfaces/Company.js +1 -0
  4. package/dist/interfaces/Customer.js +2 -0
  5. package/dist/interfaces/Order.js +2 -0
  6. package/dist/interfaces/Permission.js +2 -0
  7. package/dist/interfaces/Product.js +2 -0
  8. package/dist/interfaces/Section.js +2 -0
  9. package/dist/interfaces/Store.js +2 -0
  10. package/dist/interfaces/StoreImage.js +2 -0
  11. package/dist/interfaces/User.js +2 -0
  12. package/dist/utils/index.js +17 -0
  13. package/dist/utils/orders/calculateOrderTotal.js +33 -0
  14. package/dist/utils/orders/calculateTotalTaxesIncluded.js +65 -0
  15. package/dist/utils/orders/calculateTotalTaxesOverPrice.js +74 -0
  16. package/dist/utils/orders/helpers.js +64 -0
  17. package/dist/utils/orders/index.js +5 -0
  18. package/package.json +23 -0
  19. package/src/enum/index.ts +11 -0
  20. package/src/index.ts +5 -0
  21. package/src/interfaces/Company.ts +0 -0
  22. package/src/interfaces/Customer.ts +51 -0
  23. package/src/interfaces/Order.ts +85 -0
  24. package/src/interfaces/Permission.ts +24 -0
  25. package/src/interfaces/Product.ts +59 -0
  26. package/src/interfaces/Section.ts +14 -0
  27. package/src/interfaces/Store.ts +350 -0
  28. package/src/interfaces/StoreImage.ts +9 -0
  29. package/src/interfaces/User.ts +43 -0
  30. package/src/utils/index.ts +1 -0
  31. package/src/utils/orders/calculateOrderTotal.ts +60 -0
  32. package/src/utils/orders/calculateTotalTaxesIncluded.ts +75 -0
  33. package/src/utils/orders/calculateTotalTaxesOverPrice.ts +83 -0
  34. package/src/utils/orders/helpers.ts +73 -0
  35. package/src/utils/orders/index.ts +5 -0
  36. package/tsconfig.json +10 -0
@@ -0,0 +1,350 @@
1
+ import { IProduct } from "./Product"
2
+ import { ISection } from "./Section"
3
+ import { IStoreImage } from "./StoreImage"
4
+ import { IUser, IStaff } from "./User"
5
+ import { IOrder, IOrderPaymentLines } from "./Order"
6
+
7
+ export interface IStore {
8
+ name: string,
9
+ streetAddress?: string,
10
+ zipCode?: string,
11
+ administrator: IUser | string,
12
+ owner: IUser | string,
13
+ createdBy: IUser | string,
14
+ city: string,
15
+ state: string,
16
+ country: string,
17
+ phone: string,
18
+ taxesType: string,
19
+ taxOne?: ITax,
20
+ isActive: boolean,
21
+ allowPrePaid: boolean,
22
+ taxTwo?: ITax,
23
+ taxThree?: ITax,
24
+ paymentConfig: IPaymentConfig,
25
+ orderPageConfig: IOrderPageConfig,
26
+ printingConfig: IPrintingConfig,
27
+ notificationConfig: INotificationConfig,
28
+ schedule?: ISchedule,
29
+ pickupDeliverySchedule?: IPickupDeliverySchedule,
30
+ sections?: Array<ISection | string>
31
+ storeImages: Array<IStoreImage | string>
32
+ staffs?: Array<IStaff | string>,
33
+ currencySymbol: string,
34
+ inventory?: IInventory,
35
+ supplies?: ISupplies,
36
+ cashUpReports?: ICashUpReport,
37
+ cashierBoxes?: ICashierBox,
38
+ ticketStructure?: ITicketStructure | null,
39
+ ticketForLaundryStructure?: ITicketForLaundryStructure | null,
40
+ storeDiscounts: IStoreDiscount | null,
41
+ discountCodes: IDiscountCode | null,
42
+ marketingConfig: IMarketingConfig,
43
+ emailReportSuscribed: boolean,
44
+ emailReportFrequency: string,
45
+ emailReportDateRange: string
46
+ }
47
+
48
+ export interface ITaxConfig {
49
+ name: string,
50
+ value: number
51
+ }
52
+
53
+ export interface IProductStockActivity {
54
+ type: string,
55
+ date: Date,
56
+ amount: number,
57
+ order?: IOrder | string,
58
+ addedBy?: IUser | string,
59
+ notes?: string
60
+ }
61
+
62
+ export interface ISupplyStockActivity {
63
+ type: string,
64
+ date: Date,
65
+ amount: number,
66
+ order?: IOrder | string,
67
+ product?: IProduct | string,
68
+ addedBy?: IUser | string,
69
+ notes?: string
70
+ }
71
+
72
+ export interface IInventory {
73
+ store: IStore | string,
74
+ product: IProduct | string,
75
+ stock: number,
76
+ alertOnStock: number,
77
+ stockActivityHistory: Array<IProductStockActivity | string>,
78
+ isActive: boolean
79
+ }
80
+
81
+ export interface IInventory {
82
+ store: IStore | string,
83
+ product: IProduct | string,
84
+ stock: number,
85
+ alertOnStock: number,
86
+ stockActivityHistory: Array<IProductStockActivity | string>,
87
+ isActive: boolean
88
+ }
89
+
90
+ export interface ISupplies {
91
+ name: String,
92
+ code: String,
93
+ purchaseUnit: String,
94
+ usageUnit: String,
95
+ usageFactor: number,
96
+ stock: number,
97
+ alertOnStock: number,
98
+ supplyActivityHistory: Array<ISupplyStockActivity | string>
99
+ isActive: boolean
100
+ }
101
+
102
+ export interface ISupplies {
103
+ name: String,
104
+ code: String,
105
+ purchaseUnit: String,
106
+ usageUnit: String,
107
+ usageFactor: number,
108
+ stock: number,
109
+ alertOnStock: number,
110
+ supplyActivityHistory: Array<ISupplyStockActivity | string>,
111
+ isActive: boolean
112
+ }
113
+
114
+ export interface ICashUpReportLine {
115
+ type: string,
116
+ orderPaymentLineId: string | null | IOrderPaymentLines,
117
+ order: string | null | IOrder,
118
+ movement: string | null | IInOutMovement,
119
+ amount: number,
120
+ paymentMethod: string,
121
+ }
122
+
123
+ export interface ICashUpReport {
124
+ createdBy: IUser | string,
125
+ createdDate: Date,
126
+ startingCashDate: Date,
127
+ startingCash: number,
128
+ cardFromOrders: number,
129
+ totalCashCalculated: number,
130
+ totalCardCalculated: number,
131
+ totalTransferCalculated?: number,
132
+ cashFromOrders: number,
133
+ cashPayIns: number,
134
+ cardPayIns: number,
135
+ cardPayOuts: number,
136
+ cashPayOuts: number,
137
+ transferPayIns?: number,
138
+ transferPayOuts?: number,
139
+ transferFromOrders?: number,
140
+ declaredCash: number,
141
+ declaredCard: number,
142
+ declaredTransfer?: number,
143
+ leftInDrawer: number,
144
+ cashToBank: number,
145
+ expectedCash: number,
146
+ variance: number,
147
+ notes: string,
148
+ cashierBox: ICashierBox | string,
149
+ orders: Array<IOrder> | Array<string>,
150
+ movements: Array<IInOutMovement> | Array<string>,
151
+ lines: Array<ICashUpReportLine>,
152
+ }
153
+
154
+ export interface ICashUpReport {
155
+ createdBy: IUser | string,
156
+ createdDate: Date,
157
+ startingCashDate: Date,
158
+ startingCash: number,
159
+ cardFromOrders: number,
160
+ totalCashCalculated: number,
161
+ totalCardCalculated: number,
162
+ totalTransferCalculated?: number,
163
+ cashFromOrders: number,
164
+ transferPayIns?: number,
165
+ transferPayOuts?: number,
166
+ transferFromOrders?: number,
167
+ cashPayIns: number,
168
+ cashPayOuts: number,
169
+ declaredCash: number,
170
+ declaredCard: number,
171
+ declaredTransfer?: number,
172
+ leftInDrawer: number,
173
+ cashToBank: number,
174
+ expectedCash: number,
175
+ variance: number,
176
+ notes: string,
177
+ cashierBox: ICashierBox | string,
178
+ orders: Array<IOrder> | Array<string>,
179
+ movements: Array<IInOutMovement> | Array<string>,
180
+ }
181
+
182
+
183
+ export interface IInOutMovement {
184
+ type: string,
185
+ date: Date,
186
+ amount: number,
187
+ notes: string,
188
+ paymentMethod: string | null,
189
+ isOnACashUpReport: Boolean,
190
+ createdBy: IUser | string,
191
+ }
192
+ export interface ICashierBox {
193
+ createdBy: IUser | string,
194
+ name: string,
195
+ inOutMovements?: IInOutMovement,
196
+ isActive: boolean
197
+ }
198
+
199
+ export interface ITax {
200
+ name: string,
201
+ value: number
202
+ }
203
+
204
+ export interface INotificationConfig {
205
+ notifyOrderCreated: boolean,
206
+ notifyPickedUp: boolean,
207
+ notifyCleaned: boolean,
208
+ notifyCollected: boolean,
209
+ notifyDelivered: boolean,
210
+ notifyOwnerOnOrderCreated: boolean,
211
+ notifyEmail: string
212
+ }
213
+
214
+ export interface IPaymentConfig {
215
+ defaultPaymentMethod: string
216
+ }
217
+
218
+ export interface IPrintingConfig {
219
+ printLogoOnTicket: Boolean,
220
+ printTicketForLaundry: Boolean
221
+ }
222
+
223
+ export interface IMarketingConfig {
224
+ googlePlaceID: string,
225
+ facebookUrl: string,
226
+ ordersForFirstReview: number,
227
+ ordersForSecondReview: number,
228
+ sendReviewByEmail: Boolean,
229
+ sendReviewBySMS: Boolean,
230
+ }
231
+
232
+ export interface IOrderPageConfig {
233
+ showProductSearchBarWeb: Boolean,
234
+ defaultDeliveryDate: string,
235
+ defaultDeliveryTime: string,
236
+ defaultNotifyMethod: string,
237
+ printTicketAfterOrder: Boolean,
238
+ shippingServiceCost: number,
239
+ }
240
+
241
+ export interface ITicketStructure {
242
+ showTotalPieces: Boolean,
243
+ showEmisionDate: Boolean,
244
+ showEmisionTime: Boolean,
245
+ showLegend: Boolean,
246
+ showPaymentMethod: Boolean,
247
+ showStorePhone: Boolean,
248
+ showDeliveryDate: Boolean,
249
+ showDeliveryTime: Boolean,
250
+ ticketLegendText: String,
251
+ showStoreName: Boolean,
252
+ showCustomerName: Boolean,
253
+ showCreatedByName: Boolean,
254
+ showOrderNotes: Boolean,
255
+ showTaxes: Boolean,
256
+ showDiscounts: Boolean,
257
+ showCredit: Boolean,
258
+ }
259
+
260
+ export interface ITicketForLaundryStructure {
261
+ showTotalPieces: Boolean,
262
+ showEmisionDate: Boolean,
263
+ showEmisionTime: Boolean,
264
+ showLegend: Boolean,
265
+ showPaymentMethod: Boolean,
266
+ showStorePhone: Boolean,
267
+ showDeliveryDate: Boolean,
268
+ showDeliveryTime: Boolean,
269
+ ticketLegendText: String,
270
+ printLogoOnTicket: Boolean,
271
+ showStoreName: Boolean,
272
+ showCustomerName: Boolean,
273
+ showCreatedByName: Boolean,
274
+ showOrderNotes: Boolean,
275
+ showTaxes: Boolean,
276
+ showDiscounts: Boolean,
277
+ showCredit: Boolean,
278
+ }
279
+
280
+ export interface ITiming {
281
+ openingTime: Date,
282
+ closingTime: Date
283
+ }
284
+
285
+ export interface IPickupDeliveryTiming {
286
+ fromTime: String,
287
+ toTime: String
288
+ }
289
+ export interface IPickupDeliverySchedule {
290
+ 1: [IPickupDeliveryTiming],
291
+ 2: [IPickupDeliveryTiming],
292
+ 3: [IPickupDeliveryTiming],
293
+ 4: [IPickupDeliveryTiming],
294
+ 5: [IPickupDeliveryTiming],
295
+ 6: [IPickupDeliveryTiming],
296
+ 7: [IPickupDeliveryTiming],
297
+ }
298
+
299
+ export interface ISchedule {
300
+ sunday: ITiming,
301
+ monday: ITiming,
302
+ tuesday: ITiming,
303
+ wednesday: ITiming,
304
+ thursday: ITiming,
305
+ friday: ITiming,
306
+ saturday: ITiming
307
+ }
308
+
309
+ export interface IStoreDiscount {
310
+ name: String,
311
+ type: String,
312
+ value: number,
313
+ fromDate: Date,
314
+ toDate: Date,
315
+ fromTime: string,
316
+ toTime: string,
317
+ weekDays: Array<Number>,
318
+ products: Array<IProduct | string>
319
+ createdBy: IUser | string,
320
+ isActive: boolean
321
+ }
322
+
323
+ export interface IBuyAndGetCondition {
324
+ buyConditions: Array<any>,
325
+ getConditions: Array<any>,
326
+ getDiscountType: string,
327
+ discountValue: number
328
+ }
329
+
330
+ export interface IDiscountCode {
331
+ name: String,
332
+ code: String,
333
+ type: String,
334
+ value: number,
335
+ fromDate: Date,
336
+ toDate: Date,
337
+ fromTime: string,
338
+ toTime: string,
339
+ weekDays: Array<Number>,
340
+ products: Array<IProduct | string>
341
+ createdBy: IUser | string,
342
+ isActive: boolean,
343
+ applyOnceOnOrder: boolean,
344
+ applyToAllProducts: boolean,
345
+ hasUseLimit: boolean,
346
+ useLimitQty: number,
347
+ usedCounter: number,
348
+ onePerCustomer: boolean,
349
+ buyAndGetConditions: Array<IBuyAndGetCondition | string>,
350
+ }
@@ -0,0 +1,9 @@
1
+ import { IUser } from "./User"
2
+
3
+ export interface IStoreImage {
4
+ resourceUrl?: string,
5
+ name: string,
6
+ description?: string,
7
+ createdBy: IUser | string,
8
+ createdDate: Date,
9
+ }
@@ -0,0 +1,43 @@
1
+ import { IPermission } from "./Permission";
2
+ import { ICashierBox, IStore } from "./Store";
3
+
4
+ interface IPrinterConfig {
5
+ name: String;
6
+ paperSize: String;
7
+ }
8
+ export interface IUser {
9
+ email: string
10
+ name: string
11
+ password: string
12
+ roleNum: number,
13
+ languagePreference?: string
14
+ phoneNumber: string,
15
+ roleChanged: boolean,
16
+ lastLogonDate: Date,
17
+ freshChatRestoreID: String,
18
+ permission: IPermission,
19
+ isActive: boolean,
20
+ verified: boolean,
21
+ cashierBox?: ICashierBox | string | null,
22
+ printer?: IPrinterConfig,
23
+ }
24
+
25
+ export interface ISecretCode {
26
+ email: string
27
+ code: string
28
+ dateCreated: Date,
29
+ }
30
+
31
+ export interface IStoreAdmin extends IUser {
32
+ }
33
+
34
+ export interface ISuperAdmin extends IUser {
35
+ // company: ICompany | string,
36
+ hasMultiStore: boolean,
37
+ stripeCustomerId: string,
38
+ }
39
+
40
+ export interface IStaff extends IUser {
41
+ store: IStore | string,
42
+ cashierBox: ICashierBox | string,
43
+ }
@@ -0,0 +1 @@
1
+ export * from './orders';
@@ -0,0 +1,60 @@
1
+ import { DiscountCodeTypes } from "../../enum";
2
+ import { ICustomer } from "../../interfaces/Customer";
3
+ import { IStore } from "../../interfaces/Store";
4
+ import { calculateTotalTaxesIncluded } from "./calculateTotalTaxesIncluded";
5
+ import { calculateTotalTaxesOverPrice } from "./calculateTotalTaxesOverPrice";
6
+ import { getCreditApplied, getProductLineTotals, getShippingCost } from "./helpers";
7
+
8
+ export const calculateOrderTotal = (
9
+ order: any,
10
+ selectedCustomer: { customer: ICustomer } | undefined,
11
+ storeSettings: IStore,
12
+ hasShippingCost: boolean,
13
+ storeDiscounts: any[] = [],
14
+ discountCodeObj: any
15
+ ): any => {
16
+ try {
17
+ const appliedOrderDiscounts: any = {};
18
+ const productTableCalculator = storeSettings?.taxesType === 'over_price' ? calculateTotalTaxesOverPrice : calculateTotalTaxesIncluded;
19
+ const productTableImports = productTableCalculator(order, selectedCustomer, storeSettings, storeDiscounts, appliedOrderDiscounts, discountCodeObj);
20
+
21
+ // PRODUCT LINE TOTALS
22
+ const {
23
+ totalQuantity,
24
+ totalImportWithDiscount,
25
+ totalImportWithoutDiscount,
26
+ totalImporTaxes,
27
+ totalDiscountAmount
28
+ } = getProductLineTotals(productTableImports);
29
+
30
+ // DISCOUNT TOTAL AND SHIPPING SERVICE COST
31
+ let discountCodeAmount = 0;
32
+ let shippingCost = getShippingCost(discountCodeObj, hasShippingCost, storeSettings);
33
+
34
+ if (discountCodeObj && discountCodeObj.type === DiscountCodeTypes.NUMBER && discountCodeObj.applyOnceOnOrder) {
35
+ const includesProducts = discountCodeObj.applyToAllProducts || order.products.some((curr: any) => discountCodeObj.products.includes(curr._id));
36
+ discountCodeAmount = includesProducts ? discountCodeObj.value : 0;
37
+ }
38
+
39
+ // ORDER TOTAL CALCULATION AND CREDIT APPLIED
40
+ let orderTotalWithOutCredit = +(totalImportWithDiscount + totalImporTaxes + shippingCost - discountCodeAmount).toFixed(2);
41
+ let creditApplied = getCreditApplied(selectedCustomer, orderTotalWithOutCredit);
42
+ let orderTotal = +(orderTotalWithOutCredit - creditApplied).toFixed(2);
43
+
44
+ return {
45
+ ...order,
46
+ totalQuantity,
47
+ customerDiscount: order.discountCode ? 0 : selectedCustomer?.customer?.discount,
48
+ productTotal: totalImportWithDiscount,
49
+ taxesTotal: totalImporTaxes,
50
+ total: orderTotal,
51
+ creditApplied,
52
+ productTotalWithoutDiscount: totalImportWithoutDiscount,
53
+ totalDiscountAmount: totalDiscountAmount + discountCodeAmount,
54
+ shippingServiceTotal: shippingCost,
55
+ appliedOrderDiscounts
56
+ };
57
+ } catch (error) {
58
+ throw error;
59
+ }
60
+ };
@@ -0,0 +1,75 @@
1
+ import { IOrderProduct } from "../../interfaces/Product";
2
+ import { getProductTaxesPercentage } from "./helpers";
3
+
4
+ export const calculateTotalTaxesIncluded = (
5
+ order: any,
6
+ selectedCustomer: any,
7
+ storeSettings: any,
8
+ storeDiscounts: any[],
9
+ appliedOrderDiscounts: any,
10
+ discountCodeObj: any | null
11
+ ) => {
12
+ const productTableImports = [...order.products, ...order.buyAndGetProducts].map((current: IOrderProduct) => {
13
+ let discPercentageInteger = 0;
14
+ let productPercentageDiscount = 0;
15
+ let customerDiscount = 0;
16
+ let qty = current.qty || 0;
17
+ const extraAmountPerUnit = current.extraAmount / qty;
18
+ const prodPrice = (order.express ? current.expressPrice : current.price) + extraAmountPerUnit;
19
+
20
+ if (!order.discountCode) {
21
+ const discountsToApply = storeDiscounts.filter(
22
+ (discount) => discount.products.includes(current._id) && discount.isActive
23
+ );
24
+ customerDiscount = selectedCustomer?.customer?.discount || 0;
25
+ productPercentageDiscount = discountsToApply.reduce((prev, next) => {
26
+ if (next.type === 'percentage') {
27
+ return prev + next.value;
28
+ }
29
+ return prev;
30
+ }, 0);
31
+ discPercentageInteger = +((productPercentageDiscount + customerDiscount) / 100).toFixed(2);
32
+ discountsToApply.forEach((discount) => (appliedOrderDiscounts[discount._id] = discount));
33
+ } else {
34
+ if (discountCodeObj?.type === 'percentage') {
35
+ discPercentageInteger = +(discountCodeObj.value / 100).toFixed(2);
36
+ if (!discountCodeObj.applyToAllProducts) {
37
+ discPercentageInteger = discountCodeObj.products?.includes(current._id)
38
+ ? +(discountCodeObj.value / 100).toFixed(2)
39
+ : 0;
40
+ }
41
+ }
42
+ if (discountCodeObj?.type === 'buyXGetY') {
43
+ const discountType = discountCodeObj.buyAndGetConditions[0].getDiscountType;
44
+ const discountValue = discountCodeObj.buyAndGetConditions[0].discountValue;
45
+ if (discountType === 'percentage' && current.isBuyAndGetProduct) {
46
+ discPercentageInteger = +(discountValue / 100).toFixed(2);
47
+ }
48
+ }
49
+ }
50
+
51
+ const taxPercentage = getProductTaxesPercentage(current, storeSettings);
52
+ const taxPercentageInteger = taxPercentage / 100;
53
+
54
+ const unitPrice = prodPrice / (1 + taxPercentageInteger);
55
+ const discountAmountPerUnit = discPercentageInteger
56
+ ? unitPrice * discPercentageInteger
57
+ : (current.discountAmount || 0) / (1 + taxPercentageInteger);
58
+
59
+ const prodPriceWithDiscountPerUnit = unitPrice - discountAmountPerUnit;
60
+ const taxesAmountPerUnit = prodPriceWithDiscountPerUnit * taxPercentageInteger;
61
+ const totalTaxesApplied = +(taxesAmountPerUnit * qty).toFixed(2);
62
+ const lineDiscount = qty * discountAmountPerUnit;
63
+ const prodLinePriceWithDiscount = +(qty * prodPriceWithDiscountPerUnit).toFixed(2);
64
+
65
+ return {
66
+ product: current,
67
+ qty: qty,
68
+ productLineImportTotal: unitPrice * qty,
69
+ productLineTotalWithDiscount: prodLinePriceWithDiscount,
70
+ productLineTaxesTotal: totalTaxesApplied,
71
+ lineDiscountAmount: lineDiscount
72
+ };
73
+ });
74
+ return productTableImports;
75
+ };
@@ -0,0 +1,83 @@
1
+ import { BuyAndGetConditionsTypes, DiscountCodeTypes } from "../../enum";
2
+ import { getProductTaxesPercentage } from "./helpers";
3
+
4
+ export const calculateTotalTaxesOverPrice = (
5
+ order: any,
6
+ selectedCustomer: any,
7
+ storeSettings: any,
8
+ storeDiscounts: any[],
9
+ appliedOrderDiscounts: any,
10
+ discountCodeObj: any | null
11
+
12
+
13
+ ) => {
14
+ const productTableImports = [...order.products, ...order.buyAndGetProducts].map((current) => {
15
+ let discPercentageInteger = 0;
16
+ let productPercentageDiscount = 0;
17
+ let customerDiscount = 0;
18
+ let qty = current.qty;
19
+ // extraAmount es en general sin importar el qty, entonces aqui lo repartimos por igual
20
+ const extraAmountPerUnit = current.extraAmount / qty;
21
+ const prodPrice = (order.express ? current.expressPrice : current.price) + extraAmountPerUnit;
22
+
23
+ if (!order.discountCode) {
24
+ //IF ORDER HAS A DISCOUNT CODE WE DON'T APPLY ANY OTHER DISCOUNT (AUTOMATICALLY OR CUSTOMER DISCOUNT)
25
+ //THIS WILL GET THE DISCOUNTS OF THE CURRENT PRODUCT
26
+ // get store discounts if product applies and customer discount
27
+ const discountsToApply = storeDiscounts.filter(
28
+ (discount) => discount.products.includes(current._id) && discount.isActive
29
+ );
30
+ customerDiscount = selectedCustomer?.customer?.discount || 0;
31
+ productPercentageDiscount = discountsToApply.reduce((prev, next) => {
32
+ if (next.type === 'percentage') {
33
+ // for now we just sum percetange type discounts
34
+ return prev + next.value;
35
+ }
36
+ return prev;
37
+ }, 0);
38
+ discPercentageInteger = +((productPercentageDiscount + customerDiscount) / 100).toFixed(2);
39
+ discountsToApply.forEach((discount) => (appliedOrderDiscounts[discount._id] = discount)); // it will do this for every product, if two products has the same discount it will just overwrite
40
+ } else {
41
+ if (discountCodeObj.type === DiscountCodeTypes.PERCENTAGE) {
42
+ discPercentageInteger = +(discountCodeObj.value / 100).toFixed(2);
43
+ if (!discountCodeObj.applyToAllProducts) {
44
+ discPercentageInteger = discountCodeObj.products.includes(current._id)
45
+ ? +(discountCodeObj.value / 100).toFixed(2)
46
+ : 0;
47
+ }
48
+ }
49
+ if (discountCodeObj.type === DiscountCodeTypes.BUY_X_GET_Y) {
50
+ const discountType = discountCodeObj.buyAndGetConditions[0].getDiscountType;
51
+ const discountValue = discountCodeObj.buyAndGetConditions[0].discountValue;
52
+ if (discountType === BuyAndGetConditionsTypes.PERCENTAGE && current.isBuyAndGetProduct) {
53
+ discPercentageInteger = +(discountValue / 100).toFixed(2);
54
+ }
55
+ }
56
+ }
57
+
58
+ //GET DISCOUNT AMOUNT (IN CASE discPercentageInteger is 0 it could be a discount of a integer number)
59
+ const discountAmountPerUnit = discPercentageInteger
60
+ ? prodPrice * discPercentageInteger
61
+ : (current.discountAmount || 0);
62
+ //GET PRODUCT PRICE WITH DISCOUNT
63
+ const prodPriceWithDiscountPerUnit = prodPrice - discountAmountPerUnit;
64
+ //GET PRODUCT TAXES APPLIED TO FINAL PRICE PER UNIT
65
+ const taxPercentage = getProductTaxesPercentage(current, storeSettings);
66
+ const taxPercentageInteger = taxPercentage / 100;
67
+ const prodPriceWithoutTaxesPerUnit = prodPriceWithDiscountPerUnit;
68
+ const taxesAmountPerUnit = prodPriceWithoutTaxesPerUnit * taxPercentageInteger;
69
+ const totalTaxesApplied = +(taxesAmountPerUnit * qty).toFixed(2);
70
+ let lineDiscount = qty * discountAmountPerUnit;
71
+ let prodLinePriceWithDiscount = +(qty * prodPriceWithDiscountPerUnit).toFixed(2);
72
+
73
+ return {
74
+ product: current,
75
+ qty: qty,
76
+ productLineImportTotal: prodPrice * qty, //this is line without discount
77
+ productLineTotalWithDiscount: prodLinePriceWithDiscount,
78
+ productLineTaxesTotal: totalTaxesApplied,
79
+ lineDiscountAmount: lineDiscount
80
+ };
81
+ });
82
+ return productTableImports;
83
+ };
@@ -0,0 +1,73 @@
1
+ import { DiscountCodeTypes } from "../../enum";
2
+ import { ICustomer } from "../../interfaces/Customer";
3
+ import { IOrderProduct, ProductLineTotals } from "../../interfaces/Product";
4
+ import { IStore, ITaxConfig } from "../../interfaces/Store";
5
+
6
+ export const getProductTaxesPercentage = (productObj: IOrderProduct, store: IStore): number => {
7
+ const getTaxValue = (tax: ITaxConfig | null | undefined, isTaxExempt: boolean): number => {
8
+ if (!tax) {
9
+ // If no store tax configured, always return 0
10
+ return 0;
11
+ }
12
+
13
+ if (isTaxExempt) {
14
+ // If store tax is configured and taxExempt is true, return 0
15
+ return 0;
16
+ }
17
+
18
+ // If store tax configured and taxExempt is false, return store tax
19
+ return tax.value;
20
+ };
21
+
22
+ const tax1 = getTaxValue(store.taxOne, !productObj.taxExemptOne);
23
+ const tax2 = getTaxValue(store.taxTwo, !productObj.taxExemptTwo);
24
+ const tax3 = getTaxValue(store.taxThree, !productObj.taxExemptThree);
25
+
26
+ return tax1 + tax2 + tax3;
27
+ };
28
+
29
+ export const getProductLineTotals = (productLinesTotals: ProductLineTotals[]) => {
30
+ const totalQuantity = +productLinesTotals.reduce((acum, line) => acum + line.qty, 0).toFixed(2);
31
+ const totalImportWithDiscount = +productLinesTotals
32
+ .reduce((acum, line) => acum + line.productLineTotalWithDiscount, 0)
33
+ .toFixed(2);
34
+ const totalImportWithoutDiscount = +productLinesTotals
35
+ .reduce((acum, line) => acum + line.productLineImportTotal, 0)
36
+ .toFixed(2);
37
+ const totalImporTaxes = +productLinesTotals
38
+ .reduce((acum, line) => acum + line.productLineTaxesTotal, 0)
39
+ .toFixed(2);
40
+ const totalDiscountAmount = +productLinesTotals
41
+ .reduce((acum, line) => acum + line.lineDiscountAmount, 0)
42
+ .toFixed(2);
43
+
44
+ return {
45
+ totalQuantity,
46
+ totalImportWithDiscount,
47
+ totalImportWithoutDiscount,
48
+ totalImporTaxes,
49
+ totalDiscountAmount
50
+ };
51
+ };
52
+
53
+ export const getShippingCost = (discountObject: any, requireShippingService: boolean, store: IStore): number => {
54
+ const shippingCost = requireShippingService ? store?.orderPageConfig?.shippingServiceCost ?? 0 : 0;
55
+
56
+ if (discountObject?.type === DiscountCodeTypes.FREE_DELIVERY) {
57
+ return 0;
58
+ }
59
+
60
+ return shippingCost;
61
+ };
62
+
63
+ export const getCreditApplied = (selectedCustomer: { customer: ICustomer } | undefined, orderTotal: number): number => {
64
+ const customerCredit = selectedCustomer?.customer?.credit ?? 0;
65
+
66
+ if (customerCredit === 0 || !selectedCustomer) {
67
+ return 0;
68
+ }
69
+
70
+ return Math.min(customerCredit, orderTotal);
71
+ };
72
+
73
+
@@ -0,0 +1,5 @@
1
+ import { calculateOrderTotal } from './calculateOrderTotal';
2
+
3
+ export {
4
+ calculateOrderTotal
5
+ }