sahab-utils 1.2.0 → 1.2.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.
package/package.json CHANGED
@@ -1,25 +1,27 @@
1
1
  {
2
- "name": "sahab-utils",
3
- "version": "1.2.0",
4
- "description": "This package containts types and utils fuctions",
5
- "main": "index.ts",
6
- "scripts": {
7
- "test": "echo \"Error: no test specified\" && exit 1"
8
- },
9
- "repository": {
10
- "type": "git",
11
- "url": "git+https://github.com/SahabApp/sahab-utils.git"
12
- },
13
- "keywords": [
14
- "sahab"
15
- ],
16
- "author": "Sahab",
17
- "license": "ISC",
18
- "bugs": {
19
- "url": "https://github.com/SahabApp/sahab-utils/issues"
20
- },
21
- "homepage": "https://github.com/SahabApp/sahab-utils#readme",
22
- "dependencies": {
23
- "firebase": "^10.7.1"
24
- }
2
+ "name": "sahab-utils",
3
+ "version": "1.2.1",
4
+ "description": "This package containts types and utils fuctions",
5
+ "main": "index.ts",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/SahabApp/sahab-utils.git"
12
+ },
13
+ "keywords": [
14
+ "sahab"
15
+ ],
16
+ "author": "Sahab",
17
+ "license": "ISC",
18
+ "bugs": {
19
+ "url": "https://github.com/SahabApp/sahab-utils/issues"
20
+ },
21
+ "homepage": "https://github.com/SahabApp/sahab-utils#readme",
22
+ "dependencies": {
23
+ "firebase": "^10.7.1",
24
+ "lodash": "^4.17.21"
25
+ },
26
+ "packageManager": "yarn@4.9.1+sha512.f95ce356460e05be48d66401c1ae64ef84d163dd689964962c6888a9810865e39097a5e9de748876c2e0bf89b232d583c33982773e9903ae7a76257270986538"
25
27
  }
package/ts/calcs.ts CHANGED
@@ -1,195 +1,287 @@
1
- import { CarService, Order, OrderPaymentType, ProvidedAddon, ProvidedService, ReduxOrder } from '../constants/types';
2
- import { preventNaN } from './utils';
3
-
4
- export function getServicesTotal(order: Order | ReduxOrder | undefined) {
5
- let total = 0;
6
- if (order) {
7
- if (order.services) {
8
- order.services.forEach((carService) => {
9
- carService.services.forEach((service) => {
10
- if (service.price) {
11
- const price = service.price.price;
12
- total += price;
13
- }
14
- });
15
- });
16
- }
17
- }
18
- return total;
1
+ import sum from 'lodash/sum';
2
+ import { Discount, Order, OrderPaymentType, ProvidedAddon, ProvidedService } from '../constants/types';
3
+ import { isEmpty, preventNaN, toFixed } from './utils';
4
+
5
+ export const SAHAB_PERCENTAGE = 0;
6
+ export const ONLINE_SAHAB_PERCENTAGE = 0.03;
7
+ export const CLIENT_SAHAB_PERCENTAGE = 0.03;
8
+
9
+ export function getServicesTotal(order?: Order) {
10
+ let total = 0;
11
+ if (order) {
12
+ if (order.services) {
13
+ order.services.forEach((carService) => {
14
+ carService.services.forEach((service) => {
15
+ if (service.price) {
16
+ const price = service.price.price;
17
+ total += price;
18
+ }
19
+ });
20
+ });
21
+ }
22
+ }
23
+ return total;
19
24
  }
20
25
 
21
- export const getSahabDiscountsAmount = (order: Order | ReduxOrder | undefined) => {
22
- const orderTotal = getServicesTotal(order);
23
- let discounts = 0;
24
-
25
- if (order?.promoCode?.amount && order?.promoCode?.amount > 0 && !order?.promoCode?.createdByProvider) {
26
- if (order?.promoCode?.isPercentage) {
27
- discounts += (preventNaN(order?.promoCode?.amount) / 100) * orderTotal;
28
- } else {
29
- discounts += preventNaN(order?.promoCode?.amount);
30
- }
31
- }
32
-
33
- // Sahab Services Discounts
34
- (order?.services ?? [])?.forEach((carService) => {
35
- (carService?.services || []).forEach((service) => {
36
- let sahabDiscounts = (service?.discounts ?? []).filter((discount) => !discount?.createdByProvider);
37
-
38
- if (sahabDiscounts.length) {
39
- sahabDiscounts.forEach((discount) => {
40
- if (discount.isPercentage) {
41
- discounts += (preventNaN(discount?.amount ?? 0) / 100) * (service?.price?.price ?? 0);
42
- } else {
43
- discounts += preventNaN(discount?.amount ?? 0);
44
- }
45
- });
46
- }
47
- });
48
- });
49
-
50
- if (order?.usedBalance && order?.usedBalance > 0) {
51
- discounts += order?.usedBalance;
52
- }
53
-
54
- return discounts;
55
- };
56
-
57
- export const getProviderDiscountsAmount = (order: Order | ReduxOrder | undefined) => {
58
- const orderTotal = getServicesTotal(order);
59
- let discounts = 0;
60
-
61
- if (order?.promoCode?.amount && order?.promoCode?.amount > 0 && order?.promoCode?.createdByProvider) {
62
- if (order?.promoCode?.isPercentage) {
63
- discounts += (preventNaN(order?.promoCode?.amount) / 100) * orderTotal;
64
- } else {
65
- discounts += preventNaN(order?.promoCode?.amount);
66
- }
67
- }
68
-
69
- (order?.services ?? [])?.forEach((carService) => {
70
- (carService?.services || []).forEach((service) => {
71
- let sahabDiscounts = (service?.discounts ?? []).filter((discount) => discount?.createdByProvider);
72
-
73
- if (sahabDiscounts.length) {
74
- sahabDiscounts.forEach((discount) => {
75
- if (discount.isPercentage) {
76
- discounts += (preventNaN(discount?.amount ?? 0) / 100) * (service?.price?.price ?? 0);
77
- } else {
78
- discounts += preventNaN(discount?.amount ?? 0);
79
- }
80
- });
81
- }
82
- });
83
- });
84
-
85
- return discounts;
86
- };
87
-
88
- export const getCustomerTotalToPay = (order: Order | ReduxOrder | undefined) => {
89
- const orderTotal = getServicesTotal(order);
90
- const discounts = getSahabDiscountsAmount(order) + getProviderDiscountsAmount(order);
91
-
92
- return orderTotal - discounts;
93
- };
94
-
95
- export const getProviderTransferAmount = (order: Order | ReduxOrder | undefined) => {
96
- const orderTotal = getServicesTotal(order) - getProviderDiscountsAmount(order);
97
- const paymentAmount = preventNaN(order?.paymentAmount ?? 0);
98
-
99
- const originalPrice = orderTotal / (1 + (order?.sahabClientPercentage ?? 0));
100
- const minimumProviderAmount = originalPrice - originalPrice * (order?.sahabProviderPercentage ?? 0);
101
-
102
- if (order?.paymentType === OrderPaymentType.CASH) {
103
- return minimumProviderAmount - paymentAmount;
104
- } else {
105
- const orderTotal = getServicesTotal(order) - getProviderDiscountsAmount(order);
106
- const onlinePercentage = getOnlineProcessingFees(order);
107
- const sahabFees = paymentAmount < minimumProviderAmount ? orderTotal - minimumProviderAmount : paymentAmount - minimumProviderAmount;
108
-
109
- return orderTotal - sahabFees - onlinePercentage;
110
- }
111
- };
112
-
113
- export const getProviderProfits = (order: Order | ReduxOrder | undefined) => {
114
- return order?.paymentType === OrderPaymentType.CASH
115
- ? getCustomerTotalToPay(order) + getProviderTransferAmount(order)
116
- : getProviderTransferAmount(order);
117
- };
118
-
119
- export const getOnlineProcessingFees = (order: Order | ReduxOrder | undefined) => {
120
- if (order?.paymentType !== OrderPaymentType.CASH) {
121
- const orderTotal = preventNaN(order?.paymentAmount ?? 0);
122
-
123
- return preventNaN(order?.sahabOnlinePercentage ?? 0) * orderTotal;
124
- }
125
-
126
- return 0;
127
- };
128
-
129
- export const getSahabFees = (order: Order | ReduxOrder | undefined) => {
130
- const orderTotal = getServicesTotal(order) - getProviderDiscountsAmount(order);
131
- const paymentAmount = preventNaN(order?.paymentAmount ?? 0);
132
-
133
- const originalPrice = orderTotal / (1 + (order?.sahabClientPercentage ?? 0));
134
- const minimumProviderAmount = originalPrice - originalPrice * (order?.sahabProviderPercentage ?? 0);
135
-
136
- if (paymentAmount < minimumProviderAmount) {
137
- return 0;
138
- } else {
139
- return paymentAmount - minimumProviderAmount;
140
- }
141
- };
26
+ export function getSahabDiscountsAmount(order: Order) {
27
+ const orderTotal = getServicesTotal(order);
28
+ let discounts = 0;
29
+
30
+ if (
31
+ ['CHOCO', 'ROSE', 'ركن', 'الإيمان', 'التقوى', 'نور العترة', 'Zhraa_fit', 'Greens_fit', 'لوكيت', 'المنتزه'].includes(
32
+ order?.promoCode?.promoCode || ''
33
+ )
34
+ ) {
35
+ discounts += 0.05 * orderTotal;
36
+ } else if (order?.promoCode?.amount && order?.promoCode?.amount > 0 && !order?.promoCode?.createdByProvider) {
37
+ if (order?.promoCode?.isPercentage) {
38
+ discounts += (preventNaN(order?.promoCode?.amount) / 100) * orderTotal;
39
+ } else {
40
+ discounts += preventNaN(order?.promoCode?.amount);
41
+ }
42
+ }
43
+
44
+ // Sahab Services Discounts
45
+ (order?.services ?? [])?.forEach((carService) => {
46
+ (carService?.services || []).forEach((service) => {
47
+ let sahabDiscounts = [service?.discount].filter((discount) => !discount?.createdByProvider) as Discount[];
48
+
49
+ if (sahabDiscounts.length) {
50
+ sahabDiscounts.forEach((discount) => {
51
+ if (discount?.isPercentage) {
52
+ discounts += (preventNaN(discount?.amount ?? 0) / 100) * (service?.price?.price ?? 0);
53
+ } else {
54
+ discounts += preventNaN(discount?.amount ?? 0);
55
+ }
56
+ });
57
+ }
58
+ });
59
+ });
60
+
61
+ if (order?.usedBalance && order?.usedBalance > 0) {
62
+ discounts += order?.usedBalance;
63
+ }
64
+
65
+ return discounts;
66
+ }
67
+
68
+ export function getProviderDiscountsAmount(order: Order) {
69
+ const orderTotal = getServicesTotal(order);
70
+ let discounts = 0;
71
+
72
+ if (
73
+ ['CHOCO', 'ROSE', 'ركن', 'الإيمان', 'التقوى', 'نور العترة', 'Zhraa_fit', 'Greens_fit', 'لوكيت', 'المنتزه'].includes(
74
+ order?.promoCode?.promoCode || ''
75
+ )
76
+ ) {
77
+ discounts += 0.05 * orderTotal;
78
+ } else if (order?.promoCode?.amount && order?.promoCode?.amount > 0 && order?.promoCode?.createdByProvider) {
79
+ if (order?.promoCode?.isPercentage) {
80
+ discounts += (preventNaN(order?.promoCode?.amount) / 100) * orderTotal;
81
+ } else {
82
+ discounts += preventNaN(order?.promoCode?.amount);
83
+ }
84
+ }
85
+
86
+ (order?.services ?? [])?.forEach((carService) => {
87
+ (carService?.services || []).forEach((service) => {
88
+ let sahabDiscounts = [service?.discount].filter((discount) => discount?.createdByProvider) as Discount[];
89
+
90
+ if (sahabDiscounts.length) {
91
+ sahabDiscounts.forEach((discount) => {
92
+ if (discount?.isPercentage) {
93
+ discounts += (preventNaN(discount?.amount ?? 0) / 100) * (service?.price?.price ?? 0);
94
+ } else {
95
+ discounts += preventNaN(discount?.amount ?? 0);
96
+ }
97
+ });
98
+ }
99
+ });
100
+ });
101
+
102
+ return discounts;
103
+ }
104
+
105
+ export function getOrderTotalDiscountsAmount(order: Order) {
106
+ return getSahabDiscountsAmount(order) + getProviderDiscountsAmount(order);
107
+ }
108
+
109
+ export function getCustomerTotalToPay(order: Order) {
110
+ const sahabExtraPaymentAmount = order?.paymentType === OrderPaymentType.CASH ? order?.sahabExtraPaymentAmount || 0 : 0;
111
+ const orderTotal = getServicesTotal(order) + sahabExtraPaymentAmount;
112
+ const discounts = getSahabDiscountsAmount(order) + getProviderDiscountsAmount(order);
113
+
114
+ return orderTotal - discounts;
115
+ }
116
+
117
+ export function getProviderTransferAmount(order: Order) {
118
+ const orderTotal = getServicesTotal(order) - getProviderDiscountsAmount(order);
119
+ const paymentAmount = preventNaN(order?.paymentAmount ?? 0);
120
+
121
+ const originalPrice = orderTotal / (1 + preventNaN(order?.sahabClientPercentage ?? 0));
122
+ const minimumProviderAmount = originalPrice - originalPrice * (order?.sahabProviderPercentage ?? 0);
123
+
124
+ if (order?.paymentType === OrderPaymentType.CASH) {
125
+ return minimumProviderAmount - paymentAmount;
126
+ } else {
127
+ const onlinePercentage = getOnlineProcessingFees(order);
128
+ const sahabFees = paymentAmount < minimumProviderAmount ? orderTotal - minimumProviderAmount : paymentAmount - minimumProviderAmount;
129
+
130
+ return orderTotal - sahabFees - onlinePercentage;
131
+ }
132
+ }
133
+
134
+ export function getProviderProfits(order: Order) {
135
+ const sahabExtraPaymentAmount = order?.paymentType === OrderPaymentType.CASH ? order?.sahabExtraPaymentAmount || 0 : 0;
136
+ return order?.paymentType === OrderPaymentType.CASH
137
+ ? getCustomerTotalToPay(order) - sahabExtraPaymentAmount + getProviderTransferAmount(order)
138
+ : getProviderTransferAmount(order);
139
+ }
140
+
141
+ export function getOnlineProcessingFees(order: Order) {
142
+ if (order?.paymentType !== OrderPaymentType.CASH) {
143
+ const orderTotal = preventNaN(order?.paymentAmount ?? 0);
144
+
145
+ return preventNaN(order?.sahabOnlinePercentage ?? 0) * orderTotal;
146
+ }
147
+
148
+ return 0;
149
+ }
150
+
151
+ export function getSahabFees(order: Order) {
152
+ const orderTotal = getServicesTotal(order) - getProviderDiscountsAmount(order);
153
+ const paymentAmount = preventNaN(order?.paymentAmount ?? 0);
154
+
155
+ const originalPrice = orderTotal / (1 + preventNaN(order?.sahabClientPercentage ?? 0));
156
+ const minimumProviderAmount = originalPrice - originalPrice * (order?.sahabProviderPercentage ?? 0);
157
+
158
+ const sahabExtraPaymentAmount = order?.paymentType === OrderPaymentType.CASH ? order?.sahabExtraPaymentAmount || 0 : 0;
159
+
160
+ if (paymentAmount < minimumProviderAmount) {
161
+ return 0 + sahabExtraPaymentAmount;
162
+ } else {
163
+ return paymentAmount - minimumProviderAmount + sahabExtraPaymentAmount;
164
+ }
165
+ }
166
+
167
+ export function calcOrdersData(orders: Order[]) {
168
+ //Filter Orders
169
+ const cashOrders = orders.filter((o) => o.paymentType === OrderPaymentType.CASH);
170
+ const onlineOrders = orders.filter((o) => o.paymentType !== OrderPaymentType.CASH);
171
+
172
+ const sahabOnlineRevenue = sum(onlineOrders.map((o) => getSahabFees(o)));
173
+ const totalOnlineTransfer = sum(onlineOrders.map((o) => getProviderTransferAmount(o)));
174
+ const providerOnlineRevenue = sum(onlineOrders.map((o) => getProviderProfits(o)));
175
+
176
+ const sahabCashRevenue = sum(cashOrders.map((o) => getSahabFees(o)));
177
+ const totalCashTransfer = sum(cashOrders.map((o) => getProviderTransferAmount(o)));
178
+ const providerCashRevenue = sum(cashOrders.map((o) => getProviderProfits(o)));
179
+
180
+ //Calculate Percentages
181
+ const totalTransfer = totalOnlineTransfer + totalCashTransfer;
182
+ const totalSahabRevenue = sahabOnlineRevenue + sahabCashRevenue;
183
+ const totalProviderRevenue = providerOnlineRevenue + providerCashRevenue;
184
+
185
+ return {
186
+ name: orders?.[0]?.providerName?.ar ?? '',
187
+ numCashOrders: cashOrders.length,
188
+ numOnlineOrders: onlineOrders.length,
189
+ providerCashRevenue: toFixed(providerCashRevenue),
190
+ providerOnlineRevenue: toFixed(providerOnlineRevenue),
191
+ totalProviderRevenue: toFixed(totalProviderRevenue),
192
+ totalCashTransfer: toFixed(totalCashTransfer),
193
+ totalOnlineTransfer: toFixed(totalOnlineTransfer),
194
+ sahabCashRevenue: toFixed(sahabCashRevenue),
195
+ sahabOnlineRevenue: toFixed(sahabOnlineRevenue),
196
+ totalTransfer: toFixed(totalTransfer),
197
+ totalSahabRevenue: toFixed(totalSahabRevenue),
198
+ };
199
+ }
200
+
201
+ export function calculatePromoCodeAmount(order: Order) {
202
+ if (isEmpty(order?.promoCode) || (order?.promoCode?.amount && order?.promoCode?.amount <= 0)) {
203
+ return 0;
204
+ }
205
+
206
+ const orderTotal = getServicesTotal(order) - getProviderDiscountsAmount(order) - getSahabDiscountsAmount(order);
207
+ if (order?.promoCode?.isPercentage) {
208
+ return (preventNaN(order?.promoCode?.amount) / 100) * orderTotal;
209
+ }
210
+ return preventNaN(order?.promoCode?.amount);
211
+ }
142
212
 
143
213
  export function calculateDiscountAmount(order: Order) {
144
- let discounts = 0;
145
-
146
- if (!order?.promoCode?.amount && !order?.services?.some((service) => service?.services?.some((s) => s?.discounts?.length))) {
147
- return 0;
148
- }
149
-
150
- const orderTotal = getServicesTotal(order);
151
- if (order?.promoCode?.isPercentage) {
152
- discounts += (preventNaN(order?.promoCode?.amount ?? 0) / 100) * orderTotal;
153
- } else if (order?.promoCode?.amount) {
154
- discounts += preventNaN(order?.promoCode?.amount ?? 0);
155
- }
156
-
157
- if (order?.services?.some((service) => service?.services?.some((s) => s?.discounts?.length))) {
158
- (order?.services ?? [])?.forEach((carService) => {
159
- (carService?.services || []).forEach((service) => {
160
- let sahabDiscounts = service?.discounts ?? [];
161
-
162
- if (sahabDiscounts.length) {
163
- sahabDiscounts.forEach((discount) => {
164
- if (discount.isPercentage) {
165
- discounts += (preventNaN(discount?.amount ?? 0) / 100) * (service?.price?.price ?? 0);
166
- } else {
167
- discounts += preventNaN(discount?.amount ?? 0);
168
- }
169
- });
170
- }
171
- });
172
- });
173
- }
174
-
175
- return discounts;
214
+ let discounts = 0;
215
+
216
+ if (!order?.promoCode?.amount && !order?.services?.some((service) => service?.services?.some((s) => s?.discount))) {
217
+ return 0;
218
+ }
219
+
220
+ const orderTotal = getServicesTotal(order);
221
+ if (order?.promoCode?.isPercentage) {
222
+ discounts += (preventNaN(order?.promoCode?.amount ?? 0) / 100) * orderTotal;
223
+ } else if (order?.promoCode?.amount) {
224
+ discounts += preventNaN(order?.promoCode?.amount ?? 0);
225
+ }
226
+
227
+ if (order?.services?.some((service) => service?.services?.some((s) => s?.discount))) {
228
+ (order?.services ?? [])?.forEach((carService) => {
229
+ (carService?.services || []).forEach((service) => {
230
+ let sahabDiscounts = [service?.discount] as Discount[];
231
+
232
+ if (sahabDiscounts.length) {
233
+ sahabDiscounts.forEach((discount) => {
234
+ if (discount.isPercentage) {
235
+ discounts += (preventNaN(discount?.amount ?? 0) / 100) * (service?.price?.price ?? 0);
236
+ } else {
237
+ discounts += preventNaN(discount?.amount ?? 0);
238
+ }
239
+ });
240
+ }
241
+ });
242
+ });
243
+ }
244
+
245
+ return discounts;
176
246
  }
177
247
 
178
248
  export function getServiceTotal(providedService: ProvidedService | ProvidedAddon) {
179
- let total = 0;
180
-
181
- total += providedService?.price?.price ?? 0;
182
- let sahabDiscounts = providedService?.discounts ?? [];
183
-
184
- if (sahabDiscounts.length) {
185
- sahabDiscounts.forEach((discount) => {
186
- if (discount.isPercentage) {
187
- total -= (preventNaN(discount?.amount ?? 0) / 100) * (providedService?.price?.price ?? 0);
188
- } else {
189
- total -= preventNaN(discount?.amount ?? 0);
190
- }
191
- });
192
- }
193
-
194
- return total;
249
+ let total = 0;
250
+
251
+ total += providedService?.price?.price ?? 0;
252
+ let sahabDiscounts = [providedService?.discount] as Discount[];
253
+
254
+ if (sahabDiscounts.length) {
255
+ sahabDiscounts.forEach((discount) => {
256
+ if (discount.isPercentage) {
257
+ total -= (preventNaN(discount?.amount ?? 0) / 100) * (providedService?.price?.price ?? 0);
258
+ } else {
259
+ total -= preventNaN(discount?.amount ?? 0);
260
+ }
261
+ });
262
+ }
263
+
264
+ if (total < 0) {
265
+ total = 0;
266
+ }
267
+
268
+ const clientPercentage = 0.03 * total;
269
+
270
+ return total + clientPercentage;
271
+ }
272
+
273
+ export function calculateOrderPercentage({
274
+ isPaid,
275
+ paymentId,
276
+ providerPercentage,
277
+ }: {
278
+ isPaid: boolean;
279
+ paymentId: string;
280
+ providerPercentage: number;
281
+ }) {
282
+ if (isPaid && paymentId && !isEmpty(providerPercentage)) {
283
+ return ONLINE_SAHAB_PERCENTAGE + SAHAB_PERCENTAGE + CLIENT_SAHAB_PERCENTAGE + providerPercentage;
284
+ } else {
285
+ return SAHAB_PERCENTAGE + CLIENT_SAHAB_PERCENTAGE + providerPercentage;
286
+ }
195
287
  }
package/ts/utils.ts CHANGED
@@ -1,6 +1,21 @@
1
1
  export function preventNaN(x?: number | string) {
2
- if (x === undefined || x === null || isNaN(x as any)) {
3
- return 0;
4
- }
5
- return Number(x);
6
- }
2
+ if (x === undefined || x === null || isNaN(x as any)) {
3
+ return 0;
4
+ }
5
+ return Number(x);
6
+ }
7
+
8
+ export const toFixed = (num: any) => {
9
+ const decimal_places = 2;
10
+ num = Number(num || 0);
11
+ return (Math.round(num * 10 ** decimal_places) / 10 ** decimal_places).toFixed(decimal_places);
12
+ };
13
+
14
+ export const isEmpty = (text: any) => {
15
+ const txt = typeof text === 'string' ? text.trim() : text;
16
+
17
+ if ((txt !== 0 && !txt) || txt === '' || txt === null || txt === 'null' || txt === ' ' || txt === undefined || txt === 'undefined') {
18
+ return true;
19
+ }
20
+ return false;
21
+ };