@qrwise/pos-calculations 0.0.6 → 0.0.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/index.cjs CHANGED
@@ -66,73 +66,83 @@ function calculateTotals(input) {
66
66
  discountableTotalAmount = 0,
67
67
  nonDiscountableTotalAmount = 0,
68
68
  serviceChargeableTotalAmount = 0,
69
+ togoableTotalAmount = 0,
69
70
  voucherType = null,
70
71
  voucherRate = 0,
71
72
  discountType = null,
72
73
  discountRate = 0,
73
74
  vatRate = 12,
74
75
  serviceChargeRate = 0,
75
- togoCharge = 0,
76
- diningOption = "FOR_HERE"
76
+ togoCharge = 0
77
77
  } = input;
78
- const grossAmount = format2(discountableTotalAmount + nonDiscountableTotalAmount);
79
- let voucherDiscount = 0;
78
+ const totalOrderAmount = format2(discountableTotalAmount + nonDiscountableTotalAmount);
79
+ let voucherDiscounted = 0;
80
80
  if (voucherType === "FIXED") {
81
- voucherDiscount = Math.min(toMoneyNumber(voucherRate), grossAmount);
81
+ voucherDiscounted = -Math.min(toMoneyNumber(voucherRate), totalOrderAmount);
82
82
  }
83
83
  if (voucherType === "PERCENTAGE") {
84
- voucherDiscount = grossAmount * (toMoneyNumber(voucherRate) / 100);
84
+ voucherDiscounted = -(totalOrderAmount * (toMoneyNumber(voucherRate) / 100));
85
85
  }
86
- voucherDiscount = format2(clamp(voucherDiscount, 0, grossAmount));
87
- const subtotalAfterVoucher = format2(grossAmount - voucherDiscount);
88
- const vatDivisor = 1 + toMoneyNumber(vatRate, 12) / 100;
89
- let vatNet = format2(subtotalAfterVoucher / vatDivisor);
90
- let vat = format2(subtotalAfterVoucher - vatNet);
91
- let discount = 0;
92
- const hasDiscount = !!discountType && toMoneyNumber(discountRate) > 0;
93
- if (hasDiscount) {
94
- const discountableVatNet = format2(discountableTotalAmount / vatDivisor);
95
- discount = format2(discountableVatNet * (toMoneyNumber(discountRate) / 100));
96
- vatNet = format2(vatNet - discount);
97
- if (isVatExemptDiscount(discountType)) {
98
- vat = 0;
99
- }
100
- if (isAddVatAfterDiscount(discountType)) {
101
- vat = format2(vatNet * (toMoneyNumber(vatRate, 12) / 100));
86
+ const subtotal = totalOrderAmount + voucherDiscounted;
87
+ const voucherVatNet = Number((totalOrderAmount / vatRate).toFixed(2));
88
+ const voucherVat = Number((voucherVatNet * 0.12).toFixed(2));
89
+ let vatNet = Number((subtotal / vatRate).toFixed(2));
90
+ let vat = Number((vatNet * 0.12).toFixed(2));
91
+ const isSpecial = discountRate > 0;
92
+ const isAddVat = isAddVatAfterDiscount(discountType);
93
+ const discounted = Number((discountRate * -vatNet).toFixed(2));
94
+ if (isSpecial) {
95
+ vatNet = Number((vatNet + discounted).toFixed(2));
96
+ if (!isAddVat) {
97
+ vat = -vat;
102
98
  }
103
99
  }
104
100
  let serviceCharge = 0;
105
- if (diningOption === "FOR_HERE" && serviceChargeRate > 0 && serviceChargeableTotalAmount > 0) {
106
- const serviceChargeVatNet = format2(serviceChargeableTotalAmount / vatDivisor);
107
- serviceCharge = format2(serviceChargeVatNet * (toMoneyNumber(serviceChargeRate) / 100));
101
+ if (serviceChargeRate > 0 && serviceChargeableTotalAmount > 0) {
102
+ const scRate = serviceChargeRate / 100;
103
+ if (isSpecial) {
104
+ serviceCharge = Number(((vatNet + Math.abs(discounted)) * scRate).toFixed(2));
105
+ } else {
106
+ serviceCharge = Number((vatNet * scRate).toFixed(2));
107
+ }
108
108
  }
109
- const finalTogoCharge = diningOption === "TO_GO" ? toMoneyNumber(togoCharge) : 0;
110
- const totalAmount = format2(Math.max(0, vatNet + vat + serviceCharge + finalTogoCharge));
111
- const signedVoucherDiscount = -voucherDiscount;
112
- const signedDiscount = -discount;
109
+ let totalAmount = vatNet + vat + serviceCharge + (togoableTotalAmount > 0 ? togoCharge : 0);
110
+ if (isSpecial && !isAddVat) {
111
+ totalAmount -= vat;
112
+ }
113
+ if (totalAmount < 0) totalAmount = 0;
113
114
  return {
114
- grossAmount,
115
- voucherDiscount: signedVoucherDiscount,
116
- subtotalAfterVoucher,
117
- vatNet,
115
+ gross: subtotal + Math.abs(voucherDiscounted),
116
+ hasVoucher: voucherRate > 0,
117
+ voucher: {
118
+ discount: voucherDiscounted,
119
+ net: subtotal,
120
+ vatNet: voucherVatNet,
121
+ vat: voucherVat,
122
+ forBirDiscount: -(voucherType === "FIXED" ? voucherVatNet - Number(voucherRate.toFixed(2)) : voucherVatNet * Number(voucherRate.toFixed(2)))
123
+ },
124
+ hasDiscount: discountRate > 0,
125
+ discount: {
126
+ discount: discounted,
127
+ net: vatNet
128
+ },
129
+ netOfVat: vatNet + Math.abs(discounted),
118
130
  vat,
119
- discount: signedDiscount,
120
131
  serviceCharge,
121
- togoCharge: finalTogoCharge,
132
+ togoCharge,
122
133
  totalAmount,
123
134
  bir: {
124
- vatSales: vat > 0 ? format2(vatNet + Math.abs(signedDiscount)) : 0,
125
- vatExemptSales: vat <= 0 ? format2(vatNet + Math.abs(signedDiscount)) : 0,
135
+ vatSales: vat > 0 ? vatNet + Math.abs(discounted) : 0,
136
+ vatExemptSales: vat > 0 ? 0 : vatNet + Math.abs(discounted),
126
137
  vatZeroRatedSales: 0,
127
138
  nonTaxableSales: 0,
128
139
  vat,
129
- discount: signedDiscount,
140
+ totalSales: vat > 0 ? subtotal : vatNet + Math.abs(discounted),
141
+ discount: discounted,
130
142
  serviceCharge,
131
- togoCharge: finalTogoCharge,
132
- amountPayable: totalAmount,
133
- totalSales: vat > 0 ? subtotalAfterVoucher : format2(vatNet + Math.abs(signedDiscount))
134
- },
135
- discountBreakdown: getDiscountBreakdown(discountType, signedDiscount)
143
+ togoCharge,
144
+ amountPayable: totalAmount
145
+ }
136
146
  };
137
147
  }
138
148
  // Annotate the CommonJS export names for ESM import in node:
package/dist/index.d.cts CHANGED
@@ -5,6 +5,7 @@ interface CalculateTotalsInput {
5
5
  discountableTotalAmount: number;
6
6
  nonDiscountableTotalAmount: number;
7
7
  serviceChargeableTotalAmount?: number;
8
+ togoableTotalAmount?: number;
8
9
  voucherType?: VoucherType | null;
9
10
  voucherRate?: number;
10
11
  discountType?: DiscountType | null;
@@ -12,15 +13,24 @@ interface CalculateTotalsInput {
12
13
  vatRate?: number;
13
14
  serviceChargeRate?: number;
14
15
  togoCharge?: number;
15
- diningOption?: DiningOption;
16
16
  }
17
17
  interface CalculateTotalsResult {
18
- grossAmount: number;
19
- voucherDiscount: number;
20
- subtotalAfterVoucher: number;
21
- vatNet: number;
18
+ gross: number;
19
+ hasVoucher: boolean;
20
+ voucher: {
21
+ discount: number;
22
+ net: number;
23
+ vatNet: number;
24
+ vat: number;
25
+ forBirDiscount: number;
26
+ };
27
+ hasDiscount: boolean;
28
+ discount: {
29
+ discount: number;
30
+ net: number;
31
+ };
32
+ netOfVat: number;
22
33
  vat: number;
23
- discount: number;
24
34
  serviceCharge: number;
25
35
  togoCharge: number;
26
36
  totalAmount: number;
@@ -30,18 +40,11 @@ interface CalculateTotalsResult {
30
40
  vatZeroRatedSales: number;
31
41
  nonTaxableSales: number;
32
42
  vat: number;
43
+ totalSales: number;
33
44
  discount: number;
34
45
  serviceCharge: number;
35
46
  togoCharge: number;
36
47
  amountPayable: number;
37
- totalSales: number;
38
- };
39
- discountBreakdown: {
40
- sc: number;
41
- pwd: number;
42
- solo: number;
43
- naac: number;
44
- mov: number;
45
48
  };
46
49
  }
47
50
 
package/dist/index.d.ts CHANGED
@@ -5,6 +5,7 @@ interface CalculateTotalsInput {
5
5
  discountableTotalAmount: number;
6
6
  nonDiscountableTotalAmount: number;
7
7
  serviceChargeableTotalAmount?: number;
8
+ togoableTotalAmount?: number;
8
9
  voucherType?: VoucherType | null;
9
10
  voucherRate?: number;
10
11
  discountType?: DiscountType | null;
@@ -12,15 +13,24 @@ interface CalculateTotalsInput {
12
13
  vatRate?: number;
13
14
  serviceChargeRate?: number;
14
15
  togoCharge?: number;
15
- diningOption?: DiningOption;
16
16
  }
17
17
  interface CalculateTotalsResult {
18
- grossAmount: number;
19
- voucherDiscount: number;
20
- subtotalAfterVoucher: number;
21
- vatNet: number;
18
+ gross: number;
19
+ hasVoucher: boolean;
20
+ voucher: {
21
+ discount: number;
22
+ net: number;
23
+ vatNet: number;
24
+ vat: number;
25
+ forBirDiscount: number;
26
+ };
27
+ hasDiscount: boolean;
28
+ discount: {
29
+ discount: number;
30
+ net: number;
31
+ };
32
+ netOfVat: number;
22
33
  vat: number;
23
- discount: number;
24
34
  serviceCharge: number;
25
35
  togoCharge: number;
26
36
  totalAmount: number;
@@ -30,18 +40,11 @@ interface CalculateTotalsResult {
30
40
  vatZeroRatedSales: number;
31
41
  nonTaxableSales: number;
32
42
  vat: number;
43
+ totalSales: number;
33
44
  discount: number;
34
45
  serviceCharge: number;
35
46
  togoCharge: number;
36
47
  amountPayable: number;
37
- totalSales: number;
38
- };
39
- discountBreakdown: {
40
- sc: number;
41
- pwd: number;
42
- solo: number;
43
- naac: number;
44
- mov: number;
45
48
  };
46
49
  }
47
50
 
package/dist/index.js CHANGED
@@ -34,73 +34,83 @@ function calculateTotals(input) {
34
34
  discountableTotalAmount = 0,
35
35
  nonDiscountableTotalAmount = 0,
36
36
  serviceChargeableTotalAmount = 0,
37
+ togoableTotalAmount = 0,
37
38
  voucherType = null,
38
39
  voucherRate = 0,
39
40
  discountType = null,
40
41
  discountRate = 0,
41
42
  vatRate = 12,
42
43
  serviceChargeRate = 0,
43
- togoCharge = 0,
44
- diningOption = "FOR_HERE"
44
+ togoCharge = 0
45
45
  } = input;
46
- const grossAmount = format2(discountableTotalAmount + nonDiscountableTotalAmount);
47
- let voucherDiscount = 0;
46
+ const totalOrderAmount = format2(discountableTotalAmount + nonDiscountableTotalAmount);
47
+ let voucherDiscounted = 0;
48
48
  if (voucherType === "FIXED") {
49
- voucherDiscount = Math.min(toMoneyNumber(voucherRate), grossAmount);
49
+ voucherDiscounted = -Math.min(toMoneyNumber(voucherRate), totalOrderAmount);
50
50
  }
51
51
  if (voucherType === "PERCENTAGE") {
52
- voucherDiscount = grossAmount * (toMoneyNumber(voucherRate) / 100);
52
+ voucherDiscounted = -(totalOrderAmount * (toMoneyNumber(voucherRate) / 100));
53
53
  }
54
- voucherDiscount = format2(clamp(voucherDiscount, 0, grossAmount));
55
- const subtotalAfterVoucher = format2(grossAmount - voucherDiscount);
56
- const vatDivisor = 1 + toMoneyNumber(vatRate, 12) / 100;
57
- let vatNet = format2(subtotalAfterVoucher / vatDivisor);
58
- let vat = format2(subtotalAfterVoucher - vatNet);
59
- let discount = 0;
60
- const hasDiscount = !!discountType && toMoneyNumber(discountRate) > 0;
61
- if (hasDiscount) {
62
- const discountableVatNet = format2(discountableTotalAmount / vatDivisor);
63
- discount = format2(discountableVatNet * (toMoneyNumber(discountRate) / 100));
64
- vatNet = format2(vatNet - discount);
65
- if (isVatExemptDiscount(discountType)) {
66
- vat = 0;
67
- }
68
- if (isAddVatAfterDiscount(discountType)) {
69
- vat = format2(vatNet * (toMoneyNumber(vatRate, 12) / 100));
54
+ const subtotal = totalOrderAmount + voucherDiscounted;
55
+ const voucherVatNet = Number((totalOrderAmount / vatRate).toFixed(2));
56
+ const voucherVat = Number((voucherVatNet * 0.12).toFixed(2));
57
+ let vatNet = Number((subtotal / vatRate).toFixed(2));
58
+ let vat = Number((vatNet * 0.12).toFixed(2));
59
+ const isSpecial = discountRate > 0;
60
+ const isAddVat = isAddVatAfterDiscount(discountType);
61
+ const discounted = Number((discountRate * -vatNet).toFixed(2));
62
+ if (isSpecial) {
63
+ vatNet = Number((vatNet + discounted).toFixed(2));
64
+ if (!isAddVat) {
65
+ vat = -vat;
70
66
  }
71
67
  }
72
68
  let serviceCharge = 0;
73
- if (diningOption === "FOR_HERE" && serviceChargeRate > 0 && serviceChargeableTotalAmount > 0) {
74
- const serviceChargeVatNet = format2(serviceChargeableTotalAmount / vatDivisor);
75
- serviceCharge = format2(serviceChargeVatNet * (toMoneyNumber(serviceChargeRate) / 100));
69
+ if (serviceChargeRate > 0 && serviceChargeableTotalAmount > 0) {
70
+ const scRate = serviceChargeRate / 100;
71
+ if (isSpecial) {
72
+ serviceCharge = Number(((vatNet + Math.abs(discounted)) * scRate).toFixed(2));
73
+ } else {
74
+ serviceCharge = Number((vatNet * scRate).toFixed(2));
75
+ }
76
76
  }
77
- const finalTogoCharge = diningOption === "TO_GO" ? toMoneyNumber(togoCharge) : 0;
78
- const totalAmount = format2(Math.max(0, vatNet + vat + serviceCharge + finalTogoCharge));
79
- const signedVoucherDiscount = -voucherDiscount;
80
- const signedDiscount = -discount;
77
+ let totalAmount = vatNet + vat + serviceCharge + (togoableTotalAmount > 0 ? togoCharge : 0);
78
+ if (isSpecial && !isAddVat) {
79
+ totalAmount -= vat;
80
+ }
81
+ if (totalAmount < 0) totalAmount = 0;
81
82
  return {
82
- grossAmount,
83
- voucherDiscount: signedVoucherDiscount,
84
- subtotalAfterVoucher,
85
- vatNet,
83
+ gross: subtotal + Math.abs(voucherDiscounted),
84
+ hasVoucher: voucherRate > 0,
85
+ voucher: {
86
+ discount: voucherDiscounted,
87
+ net: subtotal,
88
+ vatNet: voucherVatNet,
89
+ vat: voucherVat,
90
+ forBirDiscount: -(voucherType === "FIXED" ? voucherVatNet - Number(voucherRate.toFixed(2)) : voucherVatNet * Number(voucherRate.toFixed(2)))
91
+ },
92
+ hasDiscount: discountRate > 0,
93
+ discount: {
94
+ discount: discounted,
95
+ net: vatNet
96
+ },
97
+ netOfVat: vatNet + Math.abs(discounted),
86
98
  vat,
87
- discount: signedDiscount,
88
99
  serviceCharge,
89
- togoCharge: finalTogoCharge,
100
+ togoCharge,
90
101
  totalAmount,
91
102
  bir: {
92
- vatSales: vat > 0 ? format2(vatNet + Math.abs(signedDiscount)) : 0,
93
- vatExemptSales: vat <= 0 ? format2(vatNet + Math.abs(signedDiscount)) : 0,
103
+ vatSales: vat > 0 ? vatNet + Math.abs(discounted) : 0,
104
+ vatExemptSales: vat > 0 ? 0 : vatNet + Math.abs(discounted),
94
105
  vatZeroRatedSales: 0,
95
106
  nonTaxableSales: 0,
96
107
  vat,
97
- discount: signedDiscount,
108
+ totalSales: vat > 0 ? subtotal : vatNet + Math.abs(discounted),
109
+ discount: discounted,
98
110
  serviceCharge,
99
- togoCharge: finalTogoCharge,
100
- amountPayable: totalAmount,
101
- totalSales: vat > 0 ? subtotalAfterVoucher : format2(vatNet + Math.abs(signedDiscount))
102
- },
103
- discountBreakdown: getDiscountBreakdown(discountType, signedDiscount)
111
+ togoCharge,
112
+ amountPayable: totalAmount
113
+ }
104
114
  };
105
115
  }
106
116
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qrwise/pos-calculations",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "description": "Shared POS calculations for QR Wise POS",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",