shareneus 1.4.95 → 1.4.97
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.d.ts +4 -0
- package/dist/index.js +9 -1
- package/dist/sales-receive/sales-receive-pdf.service.d.ts +272 -0
- package/dist/sales-receive/sales-receive-pdf.service.js +578 -0
- package/dist/sales-receive/sales-receive-print.service.d.ts +13 -0
- package/dist/sales-receive/sales-receive-print.service.js +187 -0
- package/dist/sales-receive/sales-receive-totals.service.d.ts +212 -0
- package/dist/sales-receive/sales-receive-totals.service.js +573 -0
- package/dist/sales-receive/sales-total-calculation.d.ts +5 -0
- package/dist/sales-receive/sales-total-calculation.js +152 -0
- package/package.json +1 -1
|
@@ -0,0 +1,573 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SalesReceiveTotalsService = void 0;
|
|
4
|
+
const tr_utils_1 = require("../utils/tr-utils");
|
|
5
|
+
const aggregation_1 = require("../aggregation/aggregation");
|
|
6
|
+
/**
|
|
7
|
+
* Service class for calculating sales receive totals including taxes, discounts and final amounts
|
|
8
|
+
*/
|
|
9
|
+
class SalesReceiveTotalsService {
|
|
10
|
+
/**
|
|
11
|
+
* Main method to calculate totals for sales receive operations
|
|
12
|
+
* @param opCodesList - Array of operation codes/labor items
|
|
13
|
+
* @param PartsList - Array of parts/items to be processed
|
|
14
|
+
* @param IsIndependentTax - Whether tax is calculated independently
|
|
15
|
+
* @param DetailedInfo - Whether to include detailed breakdown information
|
|
16
|
+
* @param Disc - Discount amount
|
|
17
|
+
* @param Perc - Discount percentage
|
|
18
|
+
* @param TaxCodes - Available tax codes for GST calculations
|
|
19
|
+
* @param WithItems - Whether to include items in the response
|
|
20
|
+
* @param Settings - General settings object
|
|
21
|
+
* @param EntitySettings - Entity-specific settings including decimal places
|
|
22
|
+
* @returns Object containing calculated totals and breakdown information
|
|
23
|
+
*/
|
|
24
|
+
static GetTotalsValue(opCodesList, PartsList, IsIndependentTax, DetailedInfo, Disc, Perc, TaxCodes, WithItems, Settings, EntitySettings = {}) {
|
|
25
|
+
// Sanitize input parameters to ensure valid values
|
|
26
|
+
Perc = tr_utils_1.TrUtils.SetPercToStringIfNull(Perc);
|
|
27
|
+
Disc = tr_utils_1.TrUtils.SetValueToZeroIfNull(Disc);
|
|
28
|
+
// Calculate labor part values with tax considerations
|
|
29
|
+
PartsList = this.CalculateLaborPartValues(PartsList, IsIndependentTax);
|
|
30
|
+
// Get the main totals data
|
|
31
|
+
let finalTotalsData = this.GetFinalRODataForSave(opCodesList, PartsList, IsIndependentTax, Disc, Perc, DetailedInfo, Settings, EntitySettings.DecimalsNumber);
|
|
32
|
+
// Add detailed breakdown if requested
|
|
33
|
+
if (DetailedInfo) {
|
|
34
|
+
finalTotalsData = this.GetDetailedTotalsData(finalTotalsData, IsIndependentTax, opCodesList, PartsList, TaxCodes, EntitySettings.DecimalsNumber);
|
|
35
|
+
}
|
|
36
|
+
// Include items in response if requested
|
|
37
|
+
if (WithItems) {
|
|
38
|
+
finalTotalsData.Items = PartsList;
|
|
39
|
+
}
|
|
40
|
+
return finalTotalsData;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Calculates labor part values including discounts and taxes
|
|
44
|
+
* @param PartsList - Array of parts to be processed
|
|
45
|
+
* @param IsIndependentTax - Whether tax is calculated independently
|
|
46
|
+
* @returns Processed parts list with calculated values
|
|
47
|
+
*/
|
|
48
|
+
static CalculateLaborPartValues(PartsList, IsIndependentTax) {
|
|
49
|
+
PartsList = this.ResetLaborPartValues(PartsList, IsIndependentTax);
|
|
50
|
+
return PartsList;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Resets and recalculates labor part values including discounts and taxes
|
|
54
|
+
* @param PartsList - Array of parts to be processed
|
|
55
|
+
* @param IsIndependentTax - Whether tax is calculated independently
|
|
56
|
+
* @returns Parts list with reset and recalculated values
|
|
57
|
+
*/
|
|
58
|
+
static ResetLaborPartValues(PartsList, IsIndependentTax) {
|
|
59
|
+
PartsList.forEach((Part) => {
|
|
60
|
+
// Reset invalid values to defaults
|
|
61
|
+
Part = this.ResetLaborPartValueIfInvalid(Part);
|
|
62
|
+
// Set minimum quantity to 1 if zero
|
|
63
|
+
if (tr_utils_1.TrUtils.IsZero(Part.Qty)) {
|
|
64
|
+
Part.Qty = 1;
|
|
65
|
+
}
|
|
66
|
+
// Calculate total discounted price
|
|
67
|
+
Part.DiscountedPrice = (0, aggregation_1.addition)(Part.Disc, Part.RecDisc);
|
|
68
|
+
// Calculate amount after discount
|
|
69
|
+
Part.AfterPartDisc = (0, aggregation_1.subtraction)(Part.UnAmt, Part.Disc, Part.RecDisc);
|
|
70
|
+
// Calculate amount after tax based on tax type
|
|
71
|
+
if (IsIndependentTax) {
|
|
72
|
+
Part.AfterPartTax = (0, aggregation_1.addition)(Part.AfterPartDisc, Part.CGST, Part.SGST, Part.IGST);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
Part.AfterPartTax = Part.AfterPartDisc;
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
return PartsList;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Resets part values to zero if they are null or invalid
|
|
82
|
+
* @param Part - Individual part item to reset
|
|
83
|
+
* @returns Part with reset values
|
|
84
|
+
*/
|
|
85
|
+
static ResetLaborPartValueIfInvalid(Part) {
|
|
86
|
+
Part.UnPr = tr_utils_1.TrUtils.SetValueToZeroIfNull(Part.UnPr);
|
|
87
|
+
Part.Disc = tr_utils_1.TrUtils.SetValueToZeroIfNull(Part.Disc);
|
|
88
|
+
Part.RecDisc = tr_utils_1.TrUtils.SetValueToZeroIfNull(Part.RecDisc);
|
|
89
|
+
Part.CGST = tr_utils_1.TrUtils.SetValueToZeroIfNull(Part.CGST);
|
|
90
|
+
Part.SGST = tr_utils_1.TrUtils.SetValueToZeroIfNull(Part.SGST);
|
|
91
|
+
Part.IGST = tr_utils_1.TrUtils.SetValueToZeroIfNull(Part.IGST);
|
|
92
|
+
return Part;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Prepares final repair order data for saving with calculated totals
|
|
96
|
+
* @param LaborList - Array of labor items
|
|
97
|
+
* @param PartsList - Array of parts
|
|
98
|
+
* @param IsIndependentTax - Whether tax is calculated independently
|
|
99
|
+
* @param Disc - Discount amount
|
|
100
|
+
* @param Perc - Discount percentage
|
|
101
|
+
* @param DetailedInfo - Whether to include detailed information
|
|
102
|
+
* @param Settings - General settings
|
|
103
|
+
* @param DecimalsNumber - Number of decimal places for calculations
|
|
104
|
+
* @returns Final totals data object ready for saving
|
|
105
|
+
*/
|
|
106
|
+
static GetFinalRODataForSave(LaborList, PartsList, IsIndependentTax, Disc, Perc, DetailedInfo, Settings, DecimalsNumber) {
|
|
107
|
+
let finalTotalsData = {};
|
|
108
|
+
// Set discount values
|
|
109
|
+
finalTotalsData = this.SetMainDiscountValues(Disc, Perc, finalTotalsData, DetailedInfo);
|
|
110
|
+
// Add settings to response
|
|
111
|
+
finalTotalsData.Settings = Settings;
|
|
112
|
+
// Calculate customer totals
|
|
113
|
+
finalTotalsData = this.GetFinalCustomerTotalsData(finalTotalsData, [], PartsList, IsIndependentTax, DetailedInfo, DecimalsNumber);
|
|
114
|
+
return finalTotalsData;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Sets main discount values in the totals data object
|
|
118
|
+
* @param Disc - Discount amount
|
|
119
|
+
* @param Perc - Discount percentage
|
|
120
|
+
* @param finalTotalsData - Totals data object to update
|
|
121
|
+
* @param DetailedInfo - Whether to include detailed information
|
|
122
|
+
* @returns Updated totals data with discount values
|
|
123
|
+
*/
|
|
124
|
+
static SetMainDiscountValues(Disc, Perc, finalTotalsData, DetailedInfo) {
|
|
125
|
+
finalTotalsData.Disc = Disc;
|
|
126
|
+
finalTotalsData.Perc = Perc;
|
|
127
|
+
if (DetailedInfo) {
|
|
128
|
+
finalTotalsData.FixedDisc = Disc;
|
|
129
|
+
}
|
|
130
|
+
return finalTotalsData;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Calculates final customer totals including subtotals, taxes, and rounded amounts
|
|
134
|
+
* @param finalTotalsData - Existing totals data object
|
|
135
|
+
* @param LaborList - Array of labor items
|
|
136
|
+
* @param PartsList - Array of parts
|
|
137
|
+
* @param IsIndependentTax - Whether tax is calculated independently
|
|
138
|
+
* @param DetailedInfo - Whether to include detailed information
|
|
139
|
+
* @param DecimalsNumber - Number of decimal places for calculations
|
|
140
|
+
* @returns Updated totals data with customer calculations
|
|
141
|
+
*/
|
|
142
|
+
static GetFinalCustomerTotalsData(finalTotalsData, LaborList, PartsList, IsIndependentTax, DetailedInfo, DecimalsNumber = 2) {
|
|
143
|
+
// Calculate subtotal after discounts
|
|
144
|
+
let CustomerAfterDiscTotals = this.GetSubTotalFor([], PartsList);
|
|
145
|
+
// Calculate parts tax total
|
|
146
|
+
let CustPartTaxTotal = this.GetPartsTaxTotalFor(PartsList, IsIndependentTax);
|
|
147
|
+
// Set subtotal with proper decimal formatting
|
|
148
|
+
finalTotalsData.SubTotal = tr_utils_1.TrUtils.FixedTo(CustomerAfterDiscTotals, DecimalsNumber);
|
|
149
|
+
// Calculate discount totals
|
|
150
|
+
let CustPartsDiscTotal = this.GetPartDiscountedTotal(PartsList, IsIndependentTax, finalTotalsData);
|
|
151
|
+
let CustPartsTotalAfterDisc = this.GetPartsTotalAfterDiscount(PartsList);
|
|
152
|
+
// Calculate sum total
|
|
153
|
+
finalTotalsData.STotal = (0, aggregation_1.addition)(CustPartsDiscTotal, CustPartsTotalAfterDisc);
|
|
154
|
+
// Calculate final customer total
|
|
155
|
+
let CustTotal = this.GetCustomerTotalBasedOnTaxType(finalTotalsData, 0, CustPartTaxTotal, [], PartsList, IsIndependentTax);
|
|
156
|
+
// Calculate rounding difference and final total
|
|
157
|
+
finalTotalsData.Round = (0, aggregation_1.subtraction)(Math.round(CustTotal), CustTotal);
|
|
158
|
+
finalTotalsData.Total = Math.round(CustTotal);
|
|
159
|
+
// Add detailed information if requested
|
|
160
|
+
if (DetailedInfo) {
|
|
161
|
+
finalTotalsData.FixedSubTotal = tr_utils_1.TrUtils.FixedTo(CustomerAfterDiscTotals, DecimalsNumber);
|
|
162
|
+
finalTotalsData.FixedTotal = tr_utils_1.TrUtils.FixedTo(CustTotal, DecimalsNumber);
|
|
163
|
+
}
|
|
164
|
+
return finalTotalsData;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Calculates subtotal for labor and parts combined
|
|
168
|
+
* @param LaborList - Array of labor items
|
|
169
|
+
* @param PartsList - Array of parts
|
|
170
|
+
* @returns Calculated subtotal amount
|
|
171
|
+
*/
|
|
172
|
+
static GetSubTotalFor(LaborList, PartsList) {
|
|
173
|
+
let PartsTotalAfterDisc = this.GetPartsTotalAfterDiscount(PartsList);
|
|
174
|
+
return PartsTotalAfterDisc;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Calculates total amount for parts after applying discounts
|
|
178
|
+
* @param PartsList - Array of parts
|
|
179
|
+
* @returns Total parts amount after discounts
|
|
180
|
+
*/
|
|
181
|
+
static GetPartsTotalAfterDiscount(PartsList) {
|
|
182
|
+
let PartsTotalAfterDisc = 0;
|
|
183
|
+
PartsList.forEach((Part) => {
|
|
184
|
+
PartsTotalAfterDisc = (0, aggregation_1.addition)(PartsTotalAfterDisc, Part.AfterPartDisc);
|
|
185
|
+
});
|
|
186
|
+
return PartsTotalAfterDisc;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Generates detailed totals data including tax breakdowns and groupings
|
|
190
|
+
* @param finalTotalsData - Existing totals data
|
|
191
|
+
* @param IsIndependentTax - Whether tax is calculated independently
|
|
192
|
+
* @param opCodesList - Array of operation codes
|
|
193
|
+
* @param PartsList - Array of parts
|
|
194
|
+
* @param TaxCodes - Available tax codes
|
|
195
|
+
* @param DecimalsNumber - Number of decimal places
|
|
196
|
+
* @returns Enhanced totals data with detailed breakdowns
|
|
197
|
+
*/
|
|
198
|
+
static GetDetailedTotalsData(finalTotalsData, IsIndependentTax, opCodesList, PartsList, TaxCodes, DecimalsNumber = 2) {
|
|
199
|
+
// Add parts discount and total information
|
|
200
|
+
finalTotalsData.CustPartsDiscTotal = this.GetPartDiscountedTotal(PartsList, IsIndependentTax, finalTotalsData);
|
|
201
|
+
finalTotalsData.CustPartsTotalAfterDisc = this.GetPartsTotalAfterDiscount(PartsList);
|
|
202
|
+
finalTotalsData.CustPartsTotalBeforeDisc = (0, aggregation_1.addition)(finalTotalsData.CustPartsTotalAfterDisc, finalTotalsData.CustPartsDiscTotal);
|
|
203
|
+
// Get GST tax breakdown
|
|
204
|
+
let TaxInfo = this.GetPartGSTTaxTotal(PartsList, IsIndependentTax);
|
|
205
|
+
finalTotalsData.CustPartITax = tr_utils_1.TrUtils.SetValueToZeroIfNull(TaxInfo[3]);
|
|
206
|
+
finalTotalsData.CustPartCGST = tr_utils_1.TrUtils.SetValueToZeroIfNull(TaxInfo[0]);
|
|
207
|
+
finalTotalsData.CustPartIGST = tr_utils_1.TrUtils.SetValueToZeroIfNull(TaxInfo[2]);
|
|
208
|
+
finalTotalsData.CustPartSGST = tr_utils_1.TrUtils.SetValueToZeroIfNull(TaxInfo[1]);
|
|
209
|
+
// Calculate after tax amount
|
|
210
|
+
finalTotalsData.CustPartAfterTax = (0, aggregation_1.addition)(finalTotalsData.CustPartITax, finalTotalsData.CustPartsTotalAfterDisc);
|
|
211
|
+
// Add tax grouping information
|
|
212
|
+
finalTotalsData.CustTaxGroupData = this.GetTaxGroupingForPartsByHSN(tr_utils_1.TrUtils.Stringify(PartsList), TaxCodes, DecimalsNumber);
|
|
213
|
+
finalTotalsData.CustTaxGroupDataByPerc = this.GetTaxGroupingForPartsByPerc(PartsList, TaxCodes, DecimalsNumber);
|
|
214
|
+
// Add rounding information
|
|
215
|
+
finalTotalsData.CustTotalRoundedBy = tr_utils_1.TrUtils.FixedTo(finalTotalsData.Round, DecimalsNumber);
|
|
216
|
+
finalTotalsData.CustRoundedTotal = tr_utils_1.TrUtils.FixedTo(finalTotalsData.Total, DecimalsNumber);
|
|
217
|
+
// Format all numeric values to proper decimal places
|
|
218
|
+
for (var key in finalTotalsData) {
|
|
219
|
+
if (key !== 'Total' && key !== 'SubTotal' &&
|
|
220
|
+
key !== 'LDisc' && key !== 'LPerc' && key !== 'PDisc' &&
|
|
221
|
+
key !== 'PPerc' && key !== 'Disc' && key !== 'Perc' && key !== 'Tax'
|
|
222
|
+
&& typeof finalTotalsData[key] === 'number') {
|
|
223
|
+
finalTotalsData[key] = tr_utils_1.TrUtils.FixPriceValue(finalTotalsData[key], DecimalsNumber);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return finalTotalsData;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Groups parts by tax percentage for consolidated tax reporting
|
|
230
|
+
* @param Parts - Array of parts to group
|
|
231
|
+
* @param TaxCodes - Available tax codes
|
|
232
|
+
* @param DecimalsNumber - Number of decimal places
|
|
233
|
+
* @returns Array of parts grouped by tax percentage
|
|
234
|
+
*/
|
|
235
|
+
static GetTaxGroupingForPartsByPerc(Parts, TaxCodes, DecimalsNumber) {
|
|
236
|
+
// Add combined tax percentage to each part
|
|
237
|
+
Parts = this.GetCombinedTaxPercentage(tr_utils_1.TrUtils.Stringify(Parts), TaxCodes);
|
|
238
|
+
// Group parts with same tax percentages
|
|
239
|
+
let FinalMatchedParts = this.ComparePartsByPerc(Parts, TaxCodes);
|
|
240
|
+
// Generate tax grouping information
|
|
241
|
+
return this.GetTaxGroupingInfoByHSN(FinalMatchedParts, TaxCodes, DecimalsNumber);
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Compares and groups parts by tax percentage rates
|
|
245
|
+
* @param Parts - Array of parts to compare
|
|
246
|
+
* @param TaxCodes - Available tax codes
|
|
247
|
+
* @returns Array of grouped parts with same tax percentages
|
|
248
|
+
*/
|
|
249
|
+
static ComparePartsByPerc(Parts, TaxCodes) {
|
|
250
|
+
let FinalMatchedParts = [];
|
|
251
|
+
Parts === null || Parts === void 0 ? void 0 : Parts.forEach((Part) => {
|
|
252
|
+
// Find parts with matching tax amounts that haven't been grouped yet
|
|
253
|
+
let MatchedPartsBasedOnHSN = Parts.filter((argPart) => {
|
|
254
|
+
let PartFound = false;
|
|
255
|
+
// Check if part is already in a group
|
|
256
|
+
FinalMatchedParts.forEach((FinalArgParts) => {
|
|
257
|
+
let PartIndex = FinalArgParts.findIndex((FinalArgPart) => {
|
|
258
|
+
return FinalArgPart._id === argPart._id;
|
|
259
|
+
});
|
|
260
|
+
if (PartIndex !== -1) {
|
|
261
|
+
PartFound = true;
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
// Return parts with same tax percentages that aren't already grouped
|
|
265
|
+
return (!PartFound) &&
|
|
266
|
+
(argPart.CGSTAmt === Part.CGSTAmt) && (argPart.IGSTAmt === Part.IGSTAmt) &&
|
|
267
|
+
(argPart.SGSTAmt === Part.SGSTAmt);
|
|
268
|
+
});
|
|
269
|
+
// Add group if it contains parts
|
|
270
|
+
if (MatchedPartsBasedOnHSN.length !== 0) {
|
|
271
|
+
FinalMatchedParts.push(MatchedPartsBasedOnHSN);
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
return FinalMatchedParts;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Calculates total discounted amount for all parts
|
|
278
|
+
* @param PartsList - Array of parts
|
|
279
|
+
* @param isTaxable - Whether parts are taxable
|
|
280
|
+
* @param finalTotalsData - Existing totals data
|
|
281
|
+
* @returns Total discounted amount including overall part discount
|
|
282
|
+
*/
|
|
283
|
+
static GetPartDiscountedTotal(PartsList, isTaxable, finalTotalsData) {
|
|
284
|
+
let PartsDiscountedTotal = 0;
|
|
285
|
+
let overallPartDisc = 0;
|
|
286
|
+
// Add overall part discount if not taxable
|
|
287
|
+
if (!isTaxable) {
|
|
288
|
+
overallPartDisc = tr_utils_1.TrUtils.SetValueToZeroIfNull(finalTotalsData.PDisc);
|
|
289
|
+
}
|
|
290
|
+
// Sum up individual part discounts
|
|
291
|
+
PartsList.forEach((Part) => {
|
|
292
|
+
PartsDiscountedTotal = (0, aggregation_1.addition)(PartsDiscountedTotal, Part.DiscountedPrice);
|
|
293
|
+
});
|
|
294
|
+
return (0, aggregation_1.addition)(PartsDiscountedTotal, overallPartDisc);
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Calculates total tax amount for all parts
|
|
298
|
+
* @param PartsList - Array of parts
|
|
299
|
+
* @param IsIndependentTax - Whether tax is calculated independently
|
|
300
|
+
* @returns Total tax amount for all parts
|
|
301
|
+
*/
|
|
302
|
+
static GetPartsTaxTotalFor(PartsList, IsIndependentTax) {
|
|
303
|
+
let TotalTaxAmt = 0;
|
|
304
|
+
if (IsIndependentTax) {
|
|
305
|
+
PartsList.forEach((Part) => {
|
|
306
|
+
TotalTaxAmt = (0, aggregation_1.addition)(TotalTaxAmt, Part.CGST, Part.SGST, Part.IGST);
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
return TotalTaxAmt;
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Calculates customer total based on tax calculation type
|
|
313
|
+
* @param finalTotalsData - Existing totals data
|
|
314
|
+
* @param LaborTaxAmount - Total labor tax amount
|
|
315
|
+
* @param PartsTaxAmount - Total parts tax amount
|
|
316
|
+
* @param LaborList - Array of labor items
|
|
317
|
+
* @param PartsList - Array of parts
|
|
318
|
+
* @param IsIndependentTax - Whether tax is calculated independently
|
|
319
|
+
* @returns Final customer total based on tax type
|
|
320
|
+
*/
|
|
321
|
+
static GetCustomerTotalBasedOnTaxType(finalTotalsData, LaborTaxAmount, PartsTaxAmount, LaborList, PartsList, IsIndependentTax) {
|
|
322
|
+
let PartsTotalAfterDisc = this.GetPartsTotalAfterDiscount(PartsList);
|
|
323
|
+
if (IsIndependentTax) {
|
|
324
|
+
// Add tax amounts to the total
|
|
325
|
+
return (0, aggregation_1.addition)(PartsTotalAfterDisc, LaborTaxAmount, PartsTaxAmount);
|
|
326
|
+
}
|
|
327
|
+
else {
|
|
328
|
+
// Subtract discount from the total
|
|
329
|
+
return (0, aggregation_1.subtraction)(PartsTotalAfterDisc, finalTotalsData.Disc);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Calculates items total after applying discounts (percentage or fixed)
|
|
334
|
+
* @param PartsTotalAfterDisc - Parts total after discount
|
|
335
|
+
* @param PartsTaxAmount - Parts tax amount
|
|
336
|
+
* @param MainPDisc - Main parts discount amount
|
|
337
|
+
* @param PDiscInPerc - Parts discount percentage
|
|
338
|
+
* @returns Final items total after all discounts
|
|
339
|
+
*/
|
|
340
|
+
static ItemsTotalAfterDiscount(PartsTotalAfterDisc, PartsTaxAmount, MainPDisc, PDiscInPerc) {
|
|
341
|
+
let ItemsTotal = (0, aggregation_1.addition)(PartsTotalAfterDisc, PartsTaxAmount);
|
|
342
|
+
// Apply discount if present
|
|
343
|
+
if (!tr_utils_1.TrUtils.IsZero(MainPDisc)) {
|
|
344
|
+
if (!tr_utils_1.TrUtils.IsEmpty(PDiscInPerc)) {
|
|
345
|
+
// Apply percentage discount
|
|
346
|
+
ItemsTotal = (0, aggregation_1.subtraction)(ItemsTotal, (0, aggregation_1.division)((0, aggregation_1.multiply)(ItemsTotal, Number(PDiscInPerc)), 100));
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
// Apply fixed discount
|
|
350
|
+
ItemsTotal = (0, aggregation_1.subtraction)(ItemsTotal, MainPDisc);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
return ItemsTotal;
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Calculates total CGST tax amount for labor items
|
|
357
|
+
* @param opCodesList - Array of operation codes/labor
|
|
358
|
+
* @param IsIndependentTax - Whether tax is calculated independently
|
|
359
|
+
* @returns Total CGST amount for labor
|
|
360
|
+
*/
|
|
361
|
+
static GetLaborCGSTTaxTotal(opCodesList, IsIndependentTax) {
|
|
362
|
+
let TotalTaxAmt = 0;
|
|
363
|
+
if (IsIndependentTax) {
|
|
364
|
+
opCodesList.forEach((Labor) => {
|
|
365
|
+
TotalTaxAmt = (0, aggregation_1.addition)(TotalTaxAmt, Labor.CGST);
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
return TotalTaxAmt;
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Calculates total IGST tax amount for labor items
|
|
372
|
+
* @param opCodesList - Array of operation codes/labor
|
|
373
|
+
* @param IsIndependentTax - Whether tax is calculated independently
|
|
374
|
+
* @returns Total IGST amount for labor
|
|
375
|
+
*/
|
|
376
|
+
static GetLaborIGSTTaxTotal(opCodesList, IsIndependentTax) {
|
|
377
|
+
let TotalTaxAmt = 0;
|
|
378
|
+
if (IsIndependentTax) {
|
|
379
|
+
opCodesList.forEach((Labor) => {
|
|
380
|
+
TotalTaxAmt = (0, aggregation_1.addition)(TotalTaxAmt, Labor.IGST);
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
return TotalTaxAmt;
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Calculates total SGST tax amount for labor items
|
|
387
|
+
* @param opCodesList - Array of operation codes/labor
|
|
388
|
+
* @param IsIndependentTax - Whether tax is calculated independently
|
|
389
|
+
* @returns Total SGST amount for labor
|
|
390
|
+
*/
|
|
391
|
+
static GetLaborSGSTTaxTotal(opCodesList, IsIndependentTax) {
|
|
392
|
+
let TotalTaxAmt = 0;
|
|
393
|
+
if (IsIndependentTax) {
|
|
394
|
+
opCodesList.forEach((Labor) => {
|
|
395
|
+
TotalTaxAmt = (0, aggregation_1.addition)(TotalTaxAmt, Labor.SGST);
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
return TotalTaxAmt;
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Calculates GST tax breakdown for all parts (CGST, SGST, IGST, Total)
|
|
402
|
+
* @param PartsList - Array of parts
|
|
403
|
+
* @param IsIndependentTax - Whether tax is calculated independently
|
|
404
|
+
* @returns Array containing [CGST, SGST, IGST, Total Tax] amounts
|
|
405
|
+
*/
|
|
406
|
+
static GetPartGSTTaxTotal(PartsList, IsIndependentTax) {
|
|
407
|
+
let TotalCGSTAmt = 0;
|
|
408
|
+
let TotalSGSTAmt = 0;
|
|
409
|
+
let TotalIGSTAmt = 0;
|
|
410
|
+
let TotalTaxAmt = 0;
|
|
411
|
+
if (IsIndependentTax) {
|
|
412
|
+
PartsList.forEach((Part) => {
|
|
413
|
+
TotalCGSTAmt = (0, aggregation_1.addition)(TotalCGSTAmt, Part.CGST);
|
|
414
|
+
TotalIGSTAmt = (0, aggregation_1.addition)(TotalIGSTAmt, Part.IGST);
|
|
415
|
+
TotalSGSTAmt = (0, aggregation_1.addition)(TotalSGSTAmt, Part.SGST);
|
|
416
|
+
TotalTaxAmt = (0, aggregation_1.addition)(TotalTaxAmt, Part.CGST, Part.SGST, Part.IGST);
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
return [TotalCGSTAmt, TotalSGSTAmt, TotalIGSTAmt, TotalTaxAmt];
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Groups parts by HSN code for tax reporting and compliance
|
|
423
|
+
* @param Parts - Array of parts to group
|
|
424
|
+
* @param TaxCodes - Available tax codes
|
|
425
|
+
* @param DecimalsNumber - Number of decimal places
|
|
426
|
+
* @returns Tax grouping information organized by HSN codes
|
|
427
|
+
*/
|
|
428
|
+
static GetTaxGroupingForPartsByHSN(Parts, TaxCodes, DecimalsNumber) {
|
|
429
|
+
// Add combined tax percentage to parts
|
|
430
|
+
Parts = this.GetCombinedTaxPercentage(Parts, TaxCodes);
|
|
431
|
+
// Group parts by HSN code
|
|
432
|
+
let FinalMatchedParts = this.ComparePartsByHSN(Parts, TaxCodes);
|
|
433
|
+
// Generate HSN-based tax grouping information
|
|
434
|
+
return this.GetTaxGroupingInfoByHSN(FinalMatchedParts, TaxCodes, DecimalsNumber);
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Adds combined tax percentage calculation to each part based on tax codes
|
|
438
|
+
* @param Parts - Array of parts to process
|
|
439
|
+
* @param TaxCodes - Available tax codes for lookup
|
|
440
|
+
* @returns Parts array with added tax percentage information
|
|
441
|
+
*/
|
|
442
|
+
static GetCombinedTaxPercentage(Parts, TaxCodes) {
|
|
443
|
+
Parts.forEach((Part) => {
|
|
444
|
+
// Ensure HSN is not null
|
|
445
|
+
if (tr_utils_1.TrUtils.IsNull(Part.HSN)) {
|
|
446
|
+
Part.HSN = '';
|
|
447
|
+
}
|
|
448
|
+
// Get GST values based on tax code
|
|
449
|
+
let GSTValues = this.GetGSTValueBasedOnTaxCode(Part.TCode, TaxCodes);
|
|
450
|
+
Part.CGSTAmt = tr_utils_1.TrUtils.SetValueToZeroIfNull(GSTValues[0]);
|
|
451
|
+
Part.SGSTAmt = tr_utils_1.TrUtils.SetValueToZeroIfNull(GSTValues[1]);
|
|
452
|
+
Part.IGSTAmt = tr_utils_1.TrUtils.SetValueToZeroIfNull(GSTValues[2]);
|
|
453
|
+
// Calculate combined tax percentage
|
|
454
|
+
Part.CombinedTaxPercentage = (0, aggregation_1.addition)(Part.CGSTAmt, Part.SGSTAmt, Part.IGSTAmt);
|
|
455
|
+
});
|
|
456
|
+
return Parts;
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Compares and groups parts by HSN code and tax rates
|
|
460
|
+
* @param Parts - Array of parts to compare
|
|
461
|
+
* @param TaxCodes - Available tax codes
|
|
462
|
+
* @returns Array of parts grouped by HSN code and tax rates
|
|
463
|
+
*/
|
|
464
|
+
static ComparePartsByHSN(Parts, TaxCodes) {
|
|
465
|
+
let FinalMatchedParts = [];
|
|
466
|
+
Parts.forEach((Part) => {
|
|
467
|
+
// Find parts with same HSN and tax rates that haven't been grouped
|
|
468
|
+
let MatchedPartsBasedOnHSN = Parts.filter((argPart) => {
|
|
469
|
+
let PartFound = false;
|
|
470
|
+
// Check if part is already in a group
|
|
471
|
+
FinalMatchedParts.forEach((FinalArgParts) => {
|
|
472
|
+
let PartIndex = FinalArgParts.findIndex((FinalArgPart) => {
|
|
473
|
+
return FinalArgPart._id === argPart._id;
|
|
474
|
+
});
|
|
475
|
+
if (PartIndex !== -1) {
|
|
476
|
+
PartFound = true;
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
// Return parts with same HSN and tax rates that aren't grouped yet
|
|
480
|
+
return (argPart.HSN === Part.HSN) && (!PartFound) &&
|
|
481
|
+
(argPart.CGSTAmt === Part.CGSTAmt) && (argPart.IGSTAmt === Part.IGSTAmt) &&
|
|
482
|
+
(argPart.SGSTAmt === Part.SGSTAmt);
|
|
483
|
+
});
|
|
484
|
+
// Add group if it contains parts
|
|
485
|
+
if (MatchedPartsBasedOnHSN.length !== 0) {
|
|
486
|
+
FinalMatchedParts.push(MatchedPartsBasedOnHSN);
|
|
487
|
+
}
|
|
488
|
+
});
|
|
489
|
+
return FinalMatchedParts;
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* Generates detailed tax information grouped by HSN codes for compliance reporting
|
|
493
|
+
* @param FinalMatchedParts - Array of grouped parts by HSN
|
|
494
|
+
* @param TaxCodes - Available tax codes
|
|
495
|
+
* @param DecimalsNumber - Number of decimal places for formatting
|
|
496
|
+
* @returns Array of HSN-wise tax information objects
|
|
497
|
+
*/
|
|
498
|
+
static GetTaxGroupingInfoByHSN(FinalMatchedParts, TaxCodes, DecimalsNumber) {
|
|
499
|
+
let HSNTaxInfo = [];
|
|
500
|
+
FinalMatchedParts.forEach((MatchedPart) => {
|
|
501
|
+
let TaxInfo = {};
|
|
502
|
+
let TaxOnAmount = 0;
|
|
503
|
+
let TaxAmount = 0;
|
|
504
|
+
let CGSTAmt = 0;
|
|
505
|
+
let SGSTAmt = 0;
|
|
506
|
+
let IGSTAmt = 0;
|
|
507
|
+
// Get HSN code and tax percentage from first item
|
|
508
|
+
let HSN = MatchedPart[0].HSN;
|
|
509
|
+
TaxInfo.CombinedTaxPercentage = MatchedPart[0].CombinedTaxPercentage;
|
|
510
|
+
// Calculate totals for all parts in this HSN group
|
|
511
|
+
MatchedPart.forEach((argMatchedGSTPart) => {
|
|
512
|
+
TaxOnAmount = (0, aggregation_1.addition)(TaxOnAmount, tr_utils_1.TrUtils.FixedTo(argMatchedGSTPart.AfterPartDisc, DecimalsNumber));
|
|
513
|
+
TaxAmount = (0, aggregation_1.addition)(TaxAmount, tr_utils_1.TrUtils.FixedTo(argMatchedGSTPart.CGST, DecimalsNumber));
|
|
514
|
+
TaxAmount = (0, aggregation_1.addition)(TaxAmount, tr_utils_1.TrUtils.FixedTo(argMatchedGSTPart.IGST, DecimalsNumber));
|
|
515
|
+
TaxAmount = (0, aggregation_1.addition)(TaxAmount, tr_utils_1.TrUtils.FixedTo(argMatchedGSTPart.SGST, DecimalsNumber));
|
|
516
|
+
CGSTAmt = (0, aggregation_1.addition)(CGSTAmt, tr_utils_1.TrUtils.FixedTo(argMatchedGSTPart.CGST, DecimalsNumber));
|
|
517
|
+
SGSTAmt = (0, aggregation_1.addition)(SGSTAmt, tr_utils_1.TrUtils.FixedTo(argMatchedGSTPart.SGST, DecimalsNumber));
|
|
518
|
+
IGSTAmt = (0, aggregation_1.addition)(IGSTAmt, tr_utils_1.TrUtils.FixedTo(argMatchedGSTPart.IGST, DecimalsNumber));
|
|
519
|
+
});
|
|
520
|
+
// Build tax information object
|
|
521
|
+
TaxInfo.HSN = HSN;
|
|
522
|
+
TaxInfo.CGSTAmt = CGSTAmt;
|
|
523
|
+
TaxInfo.SGSTAmt = SGSTAmt;
|
|
524
|
+
TaxInfo.IGSTAmt = IGSTAmt;
|
|
525
|
+
TaxInfo.TotalTaxableAmount = tr_utils_1.TrUtils.FixPriceValue(TaxOnAmount, DecimalsNumber);
|
|
526
|
+
TaxInfo.TotalTaxAmount = tr_utils_1.TrUtils.FixPriceValue(TaxAmount, DecimalsNumber);
|
|
527
|
+
TaxInfo.ItemsCount = MatchedPart.length;
|
|
528
|
+
TaxInfo.CGST = MatchedPart[0].CGSTAmt;
|
|
529
|
+
TaxInfo.IGST = MatchedPart[0].IGSTAmt;
|
|
530
|
+
TaxInfo.SGST = MatchedPart[0].SGSTAmt;
|
|
531
|
+
// Only add if there's a taxable amount
|
|
532
|
+
if (TaxOnAmount !== 0) {
|
|
533
|
+
HSNTaxInfo.push(TaxInfo);
|
|
534
|
+
}
|
|
535
|
+
});
|
|
536
|
+
return HSNTaxInfo;
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Retrieves GST values (CGST, SGST, IGST) based on tax code lookup
|
|
540
|
+
* @param TCode - Tax code identifier
|
|
541
|
+
* @param TaxCodes - Array of available tax codes
|
|
542
|
+
* @returns Array containing [CGST, SGST, IGST] values for the tax code
|
|
543
|
+
*/
|
|
544
|
+
static GetGSTValueBasedOnTaxCode(TCode, TaxCodes) {
|
|
545
|
+
let CGST = 0;
|
|
546
|
+
let SGST = 0;
|
|
547
|
+
let IGST = 0;
|
|
548
|
+
// Return zeros if tax code is null
|
|
549
|
+
if (tr_utils_1.TrUtils.IsNull(TCode)) {
|
|
550
|
+
return [CGST, SGST, IGST];
|
|
551
|
+
}
|
|
552
|
+
// Find tax code in the array
|
|
553
|
+
let TCodeIndex = TaxCodes.findIndex((TaxCode) => {
|
|
554
|
+
return TaxCode._id === Number(TCode);
|
|
555
|
+
});
|
|
556
|
+
// Return appropriate tax values based on tax type
|
|
557
|
+
if (TCodeIndex !== -1) {
|
|
558
|
+
if (TaxCodes[TCodeIndex].Type === 'Intra') {
|
|
559
|
+
// Intra-state: CGST + SGST
|
|
560
|
+
return [TaxCodes[TCodeIndex].CGST, TaxCodes[TCodeIndex].SGST, 0];
|
|
561
|
+
}
|
|
562
|
+
else {
|
|
563
|
+
// Inter-state: IGST only
|
|
564
|
+
return [0, 0, TaxCodes[TCodeIndex].IGST];
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
else {
|
|
568
|
+
// Tax code not found, return zeros
|
|
569
|
+
return [CGST, SGST, IGST];
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
exports.SalesReceiveTotalsService = SalesReceiveTotalsService;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function SalesTotalCalculations(items?: any[], ops?: any[], isTaxable?: boolean): any;
|
|
2
|
+
/**
|
|
3
|
+
* Enhanced version with decimal places control
|
|
4
|
+
*/
|
|
5
|
+
export declare function SalesTotalCalculationsWithDecimals(items?: any[], ops?: any[], isTaxable?: boolean, decimalPlaces?: number): any;
|