shareneus 1.6.18 → 1.6.20

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.
@@ -11,6 +11,86 @@ const util_1 = require("../shared/util");
11
11
  function safeArray(arr) {
12
12
  return Array.isArray(arr) ? arr : [];
13
13
  }
14
+ function getLineNetAmount(line) {
15
+ return (0, math_operations_1.Subtract)((0, util_1.GetNumber)(line.UnAmt || line.Amt), (0, math_operations_1.Add)((0, util_1.GetNumber)(line.Disc), (0, util_1.GetNumber)(line.RecDisc)));
16
+ }
17
+ function getTaxCodeById(taxCodes, taxCodeId) {
18
+ const normalizedTaxCodeId = Number(taxCodeId);
19
+ if (!normalizedTaxCodeId) {
20
+ return null;
21
+ }
22
+ return taxCodes.find((taxCode) => Number(taxCode._id) === normalizedTaxCodeId) || null;
23
+ }
24
+ function getTaxComponentRate(taxCode, code) {
25
+ const component = safeArray(taxCode === null || taxCode === void 0 ? void 0 : taxCode.Components).find((item) => (item === null || item === void 0 ? void 0 : item.Code) === code);
26
+ if (component) {
27
+ return (0, util_1.GetNumber)(component.Rate);
28
+ }
29
+ return (0, util_1.GetNumber)(taxCode === null || taxCode === void 0 ? void 0 : taxCode[code]);
30
+ }
31
+ function buildTaxesFromFlatFields(line, taxCode, netAmount) {
32
+ const flatTaxes = [
33
+ { Code: "CGST", Amt: (0, util_1.GetNumber)(line.CGST) },
34
+ { Code: "SGST", Amt: (0, util_1.GetNumber)(line.SGST) },
35
+ { Code: "IGST", Amt: (0, util_1.GetNumber)(line.IGST) }
36
+ ];
37
+ return flatTaxes
38
+ .filter((tax) => tax.Amt > 0)
39
+ .map((tax) => ({
40
+ Code: tax.Code,
41
+ Amt: tax.Amt,
42
+ Rate: getTaxComponentRate(taxCode, tax.Code) || (netAmount > 0 ? (0, math_operations_1.Multiply)((0, math_operations_1.Divide)(tax.Amt, netAmount), 100) : 0),
43
+ TaxCodeId: (0, util_1.GetNumber)(line.TCode) || (0, util_1.GetNumber)(taxCode === null || taxCode === void 0 ? void 0 : taxCode._id)
44
+ }));
45
+ }
46
+ function buildTaxesFromTaxCode(line, taxCode, netAmount) {
47
+ if (!taxCode) {
48
+ return [];
49
+ }
50
+ const taxComponents = safeArray(taxCode.Components);
51
+ if (taxComponents.length > 0) {
52
+ return taxComponents
53
+ .filter((component) => ["CGST", "SGST", "IGST"].includes(component === null || component === void 0 ? void 0 : component.Code))
54
+ .map((component) => ({
55
+ Code: component.Code,
56
+ Amt: (0, math_operations_1.Multiply)(netAmount, (0, math_operations_1.Divide)((0, util_1.GetNumber)(component.Rate), 100)),
57
+ Rate: (0, util_1.GetNumber)(component.Rate),
58
+ TaxCodeId: (0, util_1.GetNumber)(taxCode._id)
59
+ }))
60
+ .filter((tax) => tax.Amt > 0);
61
+ }
62
+ const legacyTaxes = [
63
+ { Code: "CGST", Rate: (0, util_1.GetNumber)(taxCode.CGST) },
64
+ { Code: "SGST", Rate: (0, util_1.GetNumber)(taxCode.SGST) },
65
+ { Code: "IGST", Rate: (0, util_1.GetNumber)(taxCode.IGST) }
66
+ ];
67
+ return legacyTaxes
68
+ .filter((tax) => tax.Rate > 0)
69
+ .map((tax) => ({
70
+ Code: tax.Code,
71
+ Amt: (0, math_operations_1.Multiply)(netAmount, (0, math_operations_1.Divide)(tax.Rate, 100)),
72
+ Rate: tax.Rate,
73
+ TaxCodeId: (0, util_1.GetNumber)(taxCode._id)
74
+ }));
75
+ }
76
+ function getResolvedTaxes(line, taxCodes = []) {
77
+ const lineTaxes = safeArray(line === null || line === void 0 ? void 0 : line.Taxes);
78
+ if (lineTaxes.length > 0) {
79
+ return lineTaxes.map((tax) => (Object.assign(Object.assign({}, tax), { Code: tax === null || tax === void 0 ? void 0 : tax.Code, Amt: (0, util_1.GetNumber)(tax === null || tax === void 0 ? void 0 : tax.Amt), Rate: (0, util_1.GetNumber)(tax === null || tax === void 0 ? void 0 : tax.Rate), TaxCodeId: (0, util_1.GetNumber)(tax === null || tax === void 0 ? void 0 : tax.TaxCodeId) }))).filter((tax) => !!tax.Code);
80
+ }
81
+ const netAmount = getLineNetAmount(line);
82
+ const taxCode = getTaxCodeById(taxCodes, line === null || line === void 0 ? void 0 : line.TCode);
83
+ const taxesFromFlatFields = buildTaxesFromFlatFields(line, taxCode, netAmount);
84
+ if (taxesFromFlatFields.length > 0) {
85
+ return taxesFromFlatFields;
86
+ }
87
+ return buildTaxesFromTaxCode(line, taxCode, netAmount);
88
+ }
89
+ function getTaxAmountByCode(taxes, code) {
90
+ return taxes
91
+ .filter((tax) => tax.Code === code)
92
+ .reduce((sum, tax) => (0, math_operations_1.Add)(sum, (0, util_1.GetNumber)(tax.Amt)), 0);
93
+ }
14
94
  function SalesTotalCalculations(items = [], ops = [], isTaxable = false, taxCodes = [], Adjust = 0) {
15
95
  // Handle null/undefined arrays
16
96
  const safeItems = safeArray(items);
@@ -60,9 +140,10 @@ function SalesTotalCalculations(items = [], ops = [], isTaxable = false, taxCode
60
140
  // Add to return subtotal (net amount after discounts)
61
141
  returnSubtotal = (0, math_operations_1.Add)(returnSubtotal, itemUnAmt);
62
142
  if (isTaxable) {
63
- const itemSGST = (0, util_1.GetNumber)(item.SGST);
64
- const itemCGST = (0, util_1.GetNumber)(item.CGST);
65
- const itemIGST = (0, util_1.GetNumber)(item.IGST);
143
+ const resolvedItemTaxes = getResolvedTaxes(item, safeTaxCodes);
144
+ const itemSGST = getTaxAmountByCode(resolvedItemTaxes, "SGST");
145
+ const itemCGST = getTaxAmountByCode(resolvedItemTaxes, "CGST");
146
+ const itemIGST = getTaxAmountByCode(resolvedItemTaxes, "IGST");
66
147
  const itemTotalTax = (0, math_operations_1.Add)(itemSGST, itemCGST, itemIGST);
67
148
  // Add to return tax
68
149
  returnTax = (0, math_operations_1.Add)(returnTax, itemTotalTax);
@@ -80,9 +161,10 @@ function SalesTotalCalculations(items = [], ops = [], isTaxable = false, taxCode
80
161
  subtotalOnItems = (0, math_operations_1.Add)(subtotalOnItems, itemUnAmt);
81
162
  // Only calculate tax if taxable
82
163
  if (isTaxable) {
83
- const itemSGST = (0, util_1.GetNumber)(item.SGST);
84
- const itemCGST = (0, util_1.GetNumber)(item.CGST);
85
- const itemIGST = (0, util_1.GetNumber)(item.IGST);
164
+ const resolvedItemTaxes = getResolvedTaxes(item, safeTaxCodes);
165
+ const itemSGST = getTaxAmountByCode(resolvedItemTaxes, "SGST");
166
+ const itemCGST = getTaxAmountByCode(resolvedItemTaxes, "CGST");
167
+ const itemIGST = getTaxAmountByCode(resolvedItemTaxes, "IGST");
86
168
  // Add individual tax amounts for items
87
169
  totalSGSTOnItems = (0, math_operations_1.Add)(totalSGSTOnItems, itemSGST);
88
170
  totalCGSTOnItems = (0, math_operations_1.Add)(totalCGSTOnItems, itemCGST);
@@ -100,9 +182,10 @@ function SalesTotalCalculations(items = [], ops = [], isTaxable = false, taxCode
100
182
  subtotalOnLabor = (0, math_operations_1.Add)(subtotalOnLabor, opAmt);
101
183
  // Only calculate tax if taxable
102
184
  if (isTaxable) {
103
- const opSGST = (0, util_1.GetNumber)(op.SGST);
104
- const opCGST = (0, util_1.GetNumber)(op.CGST);
105
- const opIGST = (0, util_1.GetNumber)(op.IGST);
185
+ const resolvedOpTaxes = getResolvedTaxes(op, safeTaxCodes);
186
+ const opSGST = getTaxAmountByCode(resolvedOpTaxes, "SGST");
187
+ const opCGST = getTaxAmountByCode(resolvedOpTaxes, "CGST");
188
+ const opIGST = getTaxAmountByCode(resolvedOpTaxes, "IGST");
106
189
  // Add individual tax amounts for operations/labor
107
190
  totalSGSTOnLabor = (0, math_operations_1.Add)(totalSGSTOnLabor, opSGST);
108
191
  totalCGSTOnLabor = (0, math_operations_1.Add)(totalCGSTOnLabor, opCGST);
@@ -180,11 +263,11 @@ function SalesTotalCalculations(items = [], ops = [], isTaxable = false, taxCode
180
263
  result.totalSGSTOnLabor = totalSGSTOnLabor;
181
264
  result.totalCGSTOnLabor = totalCGSTOnLabor;
182
265
  result.totalIGSTOnLabor = totalIGSTOnLabor;
183
- // Calculate tax summary only if taxable and taxCodes provided
266
+ // Calculate tax summary for both new Taxes[] and legacy tax-code based records
184
267
  // Filter out items where Ret is true (only include non-return items)
185
268
  const nonReturnItems = safeItems.filter((item) => item.Ret !== true);
186
- result.itemsTaxSummary = safeTaxCodes.length > 0 ? CalculateTaxSummary(nonReturnItems, safeTaxCodes) : [];
187
- result.opsTaxSummary = safeTaxCodes.length > 0 ? CalculateTaxSummary(safeOps, safeTaxCodes) : [];
269
+ result.itemsTaxSummary = CalculateTaxSummary(nonReturnItems, safeTaxCodes);
270
+ result.opsTaxSummary = CalculateTaxSummary(safeOps, safeTaxCodes);
188
271
  }
189
272
  return result;
190
273
  }
@@ -242,15 +325,16 @@ function SalesTotalCalculationsWithDecimals(items = [], ops = [], isTaxable = fa
242
325
  return roundedResult;
243
326
  }
244
327
  function CalculateTaxSummary(items, taxCodes) {
245
- // Create lookup for tax codes
246
- const taxMap = Object.fromEntries(taxCodes.map(tc => [tc._id, tc]));
247
328
  return Object.values(items.reduce((acc, item) => {
248
- const tax = taxMap[item.TCode];
249
- if (!tax)
329
+ const taxes = getResolvedTaxes(item, taxCodes);
330
+ if (taxes.length === 0)
250
331
  return acc;
251
- const percent = (((tax.IGST || 0) + (tax.CGST || 0) + (tax.SGST || 0)) + "%");
252
- // taxable value after discounts
253
- const taxable = (0, math_operations_1.Subtract)((0, util_1.GetNumber)(item.UnAmt || item.Amt), (0, math_operations_1.Add)((0, util_1.GetNumber)(item.Disc), (0, util_1.GetNumber)(item.RecDisc)));
332
+ const percent = (taxes.reduce((sum, tax) => (0, math_operations_1.Add)(sum, (0, util_1.GetNumber)(tax.Rate)), 0) + "%");
333
+ const taxable = getLineNetAmount(item);
334
+ const cgstAmount = getTaxAmountByCode(taxes, "CGST");
335
+ const sgstAmount = getTaxAmountByCode(taxes, "SGST");
336
+ const igstAmount = getTaxAmountByCode(taxes, "IGST");
337
+ const totalTaxAmount = (0, math_operations_1.Add)(cgstAmount, sgstAmount, igstAmount);
254
338
  if (!acc[percent]) {
255
339
  acc[percent] = {
256
340
  Tax: percent,
@@ -262,10 +346,10 @@ function CalculateTaxSummary(items, taxCodes) {
262
346
  };
263
347
  }
264
348
  acc[percent].TaxableAmount = (0, math_operations_1.Add)(acc[percent].TaxableAmount, taxable);
265
- acc[percent].TaxAmount = (0, math_operations_1.Add)(acc[percent].TaxAmount, (0, math_operations_1.Add)((0, math_operations_1.Divide)((0, math_operations_1.Multiply)(taxable, (0, util_1.GetNumber)(tax.CGST)), 100), (0, math_operations_1.Divide)((0, math_operations_1.Multiply)(taxable, (0, util_1.GetNumber)(tax.SGST)), 100), (0, math_operations_1.Divide)((0, math_operations_1.Multiply)(taxable, (0, util_1.GetNumber)(tax.IGST)), 100)));
266
- acc[percent].CGSTAmount = (0, math_operations_1.Add)(acc[percent].CGSTAmount, (0, math_operations_1.Divide)((0, math_operations_1.Multiply)(taxable, (0, util_1.GetNumber)(tax.CGST)), 100));
267
- acc[percent].SGSTAmount = (0, math_operations_1.Add)(acc[percent].SGSTAmount, (0, math_operations_1.Divide)((0, math_operations_1.Multiply)(taxable, (0, util_1.GetNumber)(tax.SGST)), 100));
268
- acc[percent].IGSTAmount = (0, math_operations_1.Add)(acc[percent].IGSTAmount, (0, math_operations_1.Divide)((0, math_operations_1.Multiply)(taxable, (0, util_1.GetNumber)(tax.IGST)), 100));
349
+ acc[percent].TaxAmount = (0, math_operations_1.Add)(acc[percent].TaxAmount, totalTaxAmount);
350
+ acc[percent].CGSTAmount = (0, math_operations_1.Add)(acc[percent].CGSTAmount, cgstAmount);
351
+ acc[percent].SGSTAmount = (0, math_operations_1.Add)(acc[percent].SGSTAmount, sgstAmount);
352
+ acc[percent].IGSTAmount = (0, math_operations_1.Add)(acc[percent].IGSTAmount, igstAmount);
269
353
  return acc;
270
354
  }, {}));
271
355
  }
@@ -4,6 +4,6 @@
4
4
  * This is the entry point for all tax-related functionality.
5
5
  * Import from "shareneus/tax" in both UI and API code.
6
6
  */
7
- export type { TaxComponentType, CalcMethod, AppliedOn, RoundingMethod, TaxCategory, SupplyType, ResolvedSupplyType, WithholdingType, ResolverType, IRegimeComponent, IRegimeFeatures, IRounding, ITreatment, ITaxRegime, ITaxCodeComponent, ITaxCode, ITaxComponent, ITaxSummaryLine, ITaxSummary, IWithholding, IWithholdingCalcInput, IComponentOverride, ITaxCalcLineInput, ITaxSummaryInput, IRoundingConfig, IDocumentTotalsInput, IDocumentTotals, ITaxIdLabel, ITaxIdEntry, ITaxExemption, ITaxAuthority, IExternalProvider, } from "./tax.types";
7
+ export type { TaxComponentType, CalcMethod, AppliedOn, RoundingMethod, TaxCategory, SupplyType, ResolvedSupplyType, WithholdingType, ResolverType, IRegimeComponent, IRegimeFeatures, IRounding, ITreatment, ITaxRegime, ITaxCodeComponent, ITaxCode, ITaxComponent, ITaxSummaryLine, ITaxSummary, IWithholding, IWithholdingCalcInput, ILineAmountFields, IComponentOverride, ITaxCalcLineInput, ITaxSummaryInput, IRoundingConfig, IDocumentTotalsInput, IDocumentTotals, ITaxIdLabel, ITaxIdEntry, ITaxExemption, ITaxAuthority, IExternalProvider, } from "./tax.types";
8
8
  export type { IInclusiveResult } from "./tax-calculator";
9
- export { CalculateLineTax, ExtractNetFromInclusive, SumTaxComponents, ComputeTaxSummary, ComputeDocumentTotals, DetermineSupplyType, FindTaxCodeByRateAndSupplyType, CalculateWithholding, RoundAmount, ValidateTaxId, ValidateHSNSACLength, ConvertFlatToTaxes, GetDefaultTaxIdLabels, GetPrintableTaxIds, } from "./tax-calculator";
9
+ export { CalculateNetAmt, CalculateLineTax, ExtractNetFromInclusive, SumTaxComponents, ComputeTaxSummary, ComputeDocumentTotals, DetermineSupplyType, FindTaxCodeByRateAndSupplyType, CalculateWithholding, RoundAmount, ValidateTaxId, ValidateHSNSACLength, ConvertFlatToTaxes, GetDefaultTaxIdLabels, GetPrintableTaxIds, } from "./tax-calculator";
package/dist/tax/index.js CHANGED
@@ -6,8 +6,9 @@
6
6
  * Import from "shareneus/tax" in both UI and API code.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.GetPrintableTaxIds = exports.GetDefaultTaxIdLabels = exports.ConvertFlatToTaxes = exports.ValidateHSNSACLength = exports.ValidateTaxId = exports.RoundAmount = exports.CalculateWithholding = exports.FindTaxCodeByRateAndSupplyType = exports.DetermineSupplyType = exports.ComputeDocumentTotals = exports.ComputeTaxSummary = exports.SumTaxComponents = exports.ExtractNetFromInclusive = exports.CalculateLineTax = void 0;
9
+ exports.GetPrintableTaxIds = exports.GetDefaultTaxIdLabels = exports.ConvertFlatToTaxes = exports.ValidateHSNSACLength = exports.ValidateTaxId = exports.RoundAmount = exports.CalculateWithholding = exports.FindTaxCodeByRateAndSupplyType = exports.DetermineSupplyType = exports.ComputeDocumentTotals = exports.ComputeTaxSummary = exports.SumTaxComponents = exports.ExtractNetFromInclusive = exports.CalculateLineTax = exports.CalculateNetAmt = void 0;
10
10
  var tax_calculator_1 = require("./tax-calculator");
11
+ Object.defineProperty(exports, "CalculateNetAmt", { enumerable: true, get: function () { return tax_calculator_1.CalculateNetAmt; } });
11
12
  Object.defineProperty(exports, "CalculateLineTax", { enumerable: true, get: function () { return tax_calculator_1.CalculateLineTax; } });
12
13
  Object.defineProperty(exports, "ExtractNetFromInclusive", { enumerable: true, get: function () { return tax_calculator_1.ExtractNetFromInclusive; } });
13
14
  Object.defineProperty(exports, "SumTaxComponents", { enumerable: true, get: function () { return tax_calculator_1.SumTaxComponents; } });
@@ -14,36 +14,58 @@
14
14
  * IMPORTANT: All monetary calculations use Big.js to avoid floating-point
15
15
  * precision issues. Never use plain JS arithmetic (* / + -) for money.
16
16
  */
17
- import { ITaxCode, ITaxComponent, ITaxSummary, ITaxCalcLineInput, ITaxSummaryInput, IRoundingConfig, IDocumentTotalsInput, IDocumentTotals, ResolvedSupplyType, IWithholding, IWithholdingCalcInput, ITaxIdLabel, ITaxIdEntry } from "./tax.types";
17
+ import { ITaxCode, ITaxComponent, ITaxSummary, ILineAmountFields, ITaxCalcLineInput, ITaxSummaryInput, IRoundingConfig, IDocumentTotalsInput, IDocumentTotals, ResolvedSupplyType, IWithholding, IWithholdingCalcInput, ITaxIdLabel, ITaxIdEntry } from "./tax.types";
18
+ /**
19
+ * Computes the net taxable amount from line item fields.
20
+ *
21
+ * Formula: NetAmt = (Qty × UnitPrice) - Disc - RecDisc
22
+ *
23
+ * Generic across both goods and services:
24
+ * For Items (goods): pass UnitPrice = item.UnPr
25
+ * For Ops (services): pass UnitPrice = op.Pr
26
+ *
27
+ * @param input - Line amount fields: Qty, UnitPrice, Disc, RecDisc
28
+ * @returns The net taxable amount
29
+ *
30
+ * @example
31
+ * // Item: 10 units × Rs 500, line discount Rs 200, record discount Rs 100
32
+ * CalculateNetAmt({ Qty: 10, UnitPrice: 500, Disc: 200, RecDisc: 100 });
33
+ * // Returns: 4700 (5000 - 200 - 100)
34
+ *
35
+ * @example
36
+ * // Op: 2 hours × Rs 1500, no discounts
37
+ * CalculateNetAmt({ Qty: 2, UnitPrice: 1500 });
38
+ * // Returns: 3000
39
+ */
40
+ export declare function CalculateNetAmt(input: ILineAmountFields): number;
18
41
  /**
19
42
  * Calculates tax for a single line item based on the provided TaxCode.
20
43
  *
21
44
  * This is the MAIN function used by the UI when a user selects a tax code
22
45
  * and the system needs to compute CGST, SGST, IGST, Cess, etc.
23
46
  *
24
- * @param input - Line item context (NetAmt, Qty, TaxCode, RCM flag)
47
+ * @param input - Line item context (Qty, UnitPrice, Disc, RecDisc, TaxCode, RCM flag)
25
48
  * @param rounding - Rounding configuration (from TaxRegime.Rounding)
26
49
  * @returns Array of ITaxComponent — one entry per tax component
27
50
  *
28
51
  * @example
29
- * // India GST 18% Intra-State on Rs 5,000 item
52
+ * // India GST 18% Intra-State: 10 units × Rs 500
30
53
  * const result = CalculateLineTax({
31
- * NetAmt: 5000,
54
+ * Qty: 10, UnitPrice: 500,
32
55
  * TaxCode: gst18IntraTaxCode,
33
56
  * });
34
- * // Returns: [
57
+ * // NetAmt = 5000, Returns: [
35
58
  * // { Code: "CGST", Rate: 9, Amt: 450, TaxCodeId: 106 },
36
59
  * // { Code: "SGST", Rate: 9, Amt: 450, TaxCodeId: 106 },
37
60
  * // ]
38
61
  *
39
62
  * @example
40
- * // India GST 28% + Specific Cess (Rs 12/liter) on 100 liters
63
+ * // India GST 28% + Specific Cess (Rs 12/liter) on 100 liters × Rs 100
41
64
  * const result = CalculateLineTax({
42
- * NetAmt: 10000,
43
- * Qty: 100,
65
+ * Qty: 100, UnitPrice: 100,
44
66
  * TaxCode: gst28CessDrinkTaxCode,
45
67
  * });
46
- * // Returns: [
68
+ * // NetAmt = 10000, Returns: [
47
69
  * // { Code: "CGST", Rate: 14, Amt: 1400, TaxCodeId: 201 },
48
70
  * // { Code: "SGST", Rate: 14, Amt: 1400, TaxCodeId: 201 },
49
71
  * // { Code: "CESS", Rate: 0, Amt: 1200, TaxCodeId: 201 },
@@ -103,7 +125,7 @@ export declare function SumTaxComponents(taxes: ITaxComponent[] | undefined | nu
103
125
  * Computes the document-level TaxSummary by aggregating all line items' Taxes[].
104
126
  *
105
127
  * This is a PURE FUNCTION — it does not read from database.
106
- * Caller must derive NetAmt from line item fields and pass it in.
128
+ * Computes NetAmt per line internally from Qty/UnitPrice/Disc/RecDisc.
107
129
  *
108
130
  * Groups tax amounts by Code+Rate (e.g., CGST@9 and CGST@14 are separate buckets).
109
131
  * TaxableAmt per bucket = sum of line NetAmt for lines that have that Code+Rate.
@@ -113,14 +135,14 @@ export declare function SumTaxComponents(taxes: ITaxComponent[] | undefined | nu
113
135
  * - TaxComponentTotal ON: each bucket's Amt is rounded to Precision
114
136
  * - Otherwise: Amts are at currency precision (from CalculateLineTax)
115
137
  *
116
- * @param input - All line items with Taxes[] and NetAmt, plus regime code and optional rounding
138
+ * @param input - All line items with Qty/UnitPrice/Disc/RecDisc and Taxes[], plus regime code and optional rounding
117
139
  * @returns ITaxSummary — the aggregated summary (stored on the document)
118
140
  *
119
141
  * @example
120
142
  * const summary = ComputeTaxSummary({
121
143
  * Lines: invoice.Items.map(item => ({
144
+ * Qty: item.Qty, UnitPrice: item.UnPr, Disc: item.Disc, RecDisc: item.RecDisc,
122
145
  * Taxes: item.Taxes,
123
- * NetAmt: item.UnAmt - item.Disc - item.RecDisc,
124
146
  * })),
125
147
  * RegimeCode: "IN_GST",
126
148
  * Rounding: { Method: "Round", Precision: 0, TaxComponentTotal: true },
@@ -155,17 +177,19 @@ export declare function ComputeTaxSummary(input: ITaxSummaryInput): ITaxSummary;
155
177
  * The caller applies those after this function returns:
156
178
  * FinalPayable = Total + Adjust - Withholding.Amt
157
179
  *
158
- * @param input - Line items with NetAmt and Taxes[], plus RoundingConfig
180
+ * @param input - Line items with Qty/UnitPrice/Disc/RecDisc and Taxes[], plus RoundingConfig
159
181
  * @returns IDocumentTotals — all stored financial fields
160
182
  *
161
183
  * @example
162
184
  * // India GST invoice with 2 lines
163
185
  * const totals = ComputeDocumentTotals({
164
186
  * Lines: [
165
- * { NetAmt: 5000, Taxes: [{ Code: "CGST", Rate: 9, Amt: 450, TaxCodeId: 1 },
166
- * { Code: "SGST", Rate: 9, Amt: 450, TaxCodeId: 1 }] },
167
- * { NetAmt: 3000, Taxes: [{ Code: "CGST", Rate: 9, Amt: 270, TaxCodeId: 1 },
168
- * { Code: "SGST", Rate: 9, Amt: 270, TaxCodeId: 1 }] },
187
+ * { Qty: 10, UnitPrice: 500,
188
+ * Taxes: [{ Code: "CGST", Rate: 9, Amt: 450, TaxCodeId: 1 },
189
+ * { Code: "SGST", Rate: 9, Amt: 450, TaxCodeId: 1 }] },
190
+ * { Qty: 6, UnitPrice: 500,
191
+ * Taxes: [{ Code: "CGST", Rate: 9, Amt: 270, TaxCodeId: 1 },
192
+ * { Code: "SGST", Rate: 9, Amt: 270, TaxCodeId: 1 }] },
169
193
  * ],
170
194
  * Rounding: { Method: "Round", Precision: 0, TaxComponentTotal: true, DocTotal: true },
171
195
  * RegimeCode: "IN_GST",
@@ -19,6 +19,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
19
19
  return (mod && mod.__esModule) ? mod : { "default": mod };
20
20
  };
21
21
  Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.CalculateNetAmt = CalculateNetAmt;
22
23
  exports.CalculateLineTax = CalculateLineTax;
23
24
  exports.ExtractNetFromInclusive = ExtractNetFromInclusive;
24
25
  exports.SumTaxComponents = SumTaxComponents;
@@ -37,6 +38,42 @@ const big_js_1 = __importDefault(require("big.js"));
37
38
  const util_1 = require("../shared/util");
38
39
  const math_operations_1 = require("../shared/math-operations");
39
40
  // ============================================================
41
+ // Net Amount Calculation
42
+ // ============================================================
43
+ /**
44
+ * Computes the net taxable amount from line item fields.
45
+ *
46
+ * Formula: NetAmt = (Qty × UnitPrice) - Disc - RecDisc
47
+ *
48
+ * Generic across both goods and services:
49
+ * For Items (goods): pass UnitPrice = item.UnPr
50
+ * For Ops (services): pass UnitPrice = op.Pr
51
+ *
52
+ * @param input - Line amount fields: Qty, UnitPrice, Disc, RecDisc
53
+ * @returns The net taxable amount
54
+ *
55
+ * @example
56
+ * // Item: 10 units × Rs 500, line discount Rs 200, record discount Rs 100
57
+ * CalculateNetAmt({ Qty: 10, UnitPrice: 500, Disc: 200, RecDisc: 100 });
58
+ * // Returns: 4700 (5000 - 200 - 100)
59
+ *
60
+ * @example
61
+ * // Op: 2 hours × Rs 1500, no discounts
62
+ * CalculateNetAmt({ Qty: 2, UnitPrice: 1500 });
63
+ * // Returns: 3000
64
+ */
65
+ function CalculateNetAmt(input) {
66
+ const grossAmt = (0, math_operations_1.Multiply)((0, util_1.GetNumber)(input.Qty), (0, util_1.GetNumber)(input.UnitPrice));
67
+ let netAmt = grossAmt;
68
+ if (input.Disc) {
69
+ netAmt = (0, math_operations_1.Subtract)(netAmt, (0, util_1.GetNumber)(input.Disc));
70
+ }
71
+ if (input.RecDisc) {
72
+ netAmt = (0, math_operations_1.Subtract)(netAmt, (0, util_1.GetNumber)(input.RecDisc));
73
+ }
74
+ return netAmt;
75
+ }
76
+ // ============================================================
40
77
  // Core Tax Calculation
41
78
  // ============================================================
42
79
  /**
@@ -45,29 +82,28 @@ const math_operations_1 = require("../shared/math-operations");
45
82
  * This is the MAIN function used by the UI when a user selects a tax code
46
83
  * and the system needs to compute CGST, SGST, IGST, Cess, etc.
47
84
  *
48
- * @param input - Line item context (NetAmt, Qty, TaxCode, RCM flag)
85
+ * @param input - Line item context (Qty, UnitPrice, Disc, RecDisc, TaxCode, RCM flag)
49
86
  * @param rounding - Rounding configuration (from TaxRegime.Rounding)
50
87
  * @returns Array of ITaxComponent — one entry per tax component
51
88
  *
52
89
  * @example
53
- * // India GST 18% Intra-State on Rs 5,000 item
90
+ * // India GST 18% Intra-State: 10 units × Rs 500
54
91
  * const result = CalculateLineTax({
55
- * NetAmt: 5000,
92
+ * Qty: 10, UnitPrice: 500,
56
93
  * TaxCode: gst18IntraTaxCode,
57
94
  * });
58
- * // Returns: [
95
+ * // NetAmt = 5000, Returns: [
59
96
  * // { Code: "CGST", Rate: 9, Amt: 450, TaxCodeId: 106 },
60
97
  * // { Code: "SGST", Rate: 9, Amt: 450, TaxCodeId: 106 },
61
98
  * // ]
62
99
  *
63
100
  * @example
64
- * // India GST 28% + Specific Cess (Rs 12/liter) on 100 liters
101
+ * // India GST 28% + Specific Cess (Rs 12/liter) on 100 liters × Rs 100
65
102
  * const result = CalculateLineTax({
66
- * NetAmt: 10000,
67
- * Qty: 100,
103
+ * Qty: 100, UnitPrice: 100,
68
104
  * TaxCode: gst28CessDrinkTaxCode,
69
105
  * });
70
- * // Returns: [
106
+ * // NetAmt = 10000, Returns: [
71
107
  * // { Code: "CGST", Rate: 14, Amt: 1400, TaxCodeId: 201 },
72
108
  * // { Code: "SGST", Rate: 14, Amt: 1400, TaxCodeId: 201 },
73
109
  * // { Code: "CESS", Rate: 0, Amt: 1200, TaxCodeId: 201 },
@@ -75,7 +111,7 @@ const math_operations_1 = require("../shared/math-operations");
75
111
  */
76
112
  function CalculateLineTax(input, rounding = { Method: "Round", Precision: 2 }) {
77
113
  const { TaxCode, RCM, ComponentOverrides } = input;
78
- const netAmt = (0, util_1.GetNumber)(input.NetAmt);
114
+ const netAmt = CalculateNetAmt(input);
79
115
  const qty = (0, util_1.GetNumber)(input.Qty, 1);
80
116
  // Exempt / Nil / NonTaxable — no components
81
117
  if (!TaxCode.Components || TaxCode.Components.length === 0) {
@@ -300,7 +336,7 @@ function SumTaxComponents(taxes) {
300
336
  * Computes the document-level TaxSummary by aggregating all line items' Taxes[].
301
337
  *
302
338
  * This is a PURE FUNCTION — it does not read from database.
303
- * Caller must derive NetAmt from line item fields and pass it in.
339
+ * Computes NetAmt per line internally from Qty/UnitPrice/Disc/RecDisc.
304
340
  *
305
341
  * Groups tax amounts by Code+Rate (e.g., CGST@9 and CGST@14 are separate buckets).
306
342
  * TaxableAmt per bucket = sum of line NetAmt for lines that have that Code+Rate.
@@ -310,14 +346,14 @@ function SumTaxComponents(taxes) {
310
346
  * - TaxComponentTotal ON: each bucket's Amt is rounded to Precision
311
347
  * - Otherwise: Amts are at currency precision (from CalculateLineTax)
312
348
  *
313
- * @param input - All line items with Taxes[] and NetAmt, plus regime code and optional rounding
349
+ * @param input - All line items with Qty/UnitPrice/Disc/RecDisc and Taxes[], plus regime code and optional rounding
314
350
  * @returns ITaxSummary — the aggregated summary (stored on the document)
315
351
  *
316
352
  * @example
317
353
  * const summary = ComputeTaxSummary({
318
354
  * Lines: invoice.Items.map(item => ({
355
+ * Qty: item.Qty, UnitPrice: item.UnPr, Disc: item.Disc, RecDisc: item.RecDisc,
319
356
  * Taxes: item.Taxes,
320
- * NetAmt: item.UnAmt - item.Disc - item.RecDisc,
321
357
  * })),
322
358
  * RegimeCode: "IN_GST",
323
359
  * Rounding: { Method: "Round", Precision: 0, TaxComponentTotal: true },
@@ -340,7 +376,7 @@ function ComputeTaxSummary(input) {
340
376
  for (const line of Lines) {
341
377
  if (!line.Taxes || line.Taxes.length === 0)
342
378
  continue;
343
- const lineNetAmt = (0, util_1.GetNumber)(line.NetAmt);
379
+ const lineNetAmt = CalculateNetAmt(line);
344
380
  // Track this line's taxable amount at document level (once per line, not per component)
345
381
  totalTaxable = (0, math_operations_1.Add)(totalTaxable, lineNetAmt);
346
382
  // Track which Code+Rate buckets we've already added this line's NetAmt to
@@ -411,17 +447,19 @@ function ComputeTaxSummary(input) {
411
447
  * The caller applies those after this function returns:
412
448
  * FinalPayable = Total + Adjust - Withholding.Amt
413
449
  *
414
- * @param input - Line items with NetAmt and Taxes[], plus RoundingConfig
450
+ * @param input - Line items with Qty/UnitPrice/Disc/RecDisc and Taxes[], plus RoundingConfig
415
451
  * @returns IDocumentTotals — all stored financial fields
416
452
  *
417
453
  * @example
418
454
  * // India GST invoice with 2 lines
419
455
  * const totals = ComputeDocumentTotals({
420
456
  * Lines: [
421
- * { NetAmt: 5000, Taxes: [{ Code: "CGST", Rate: 9, Amt: 450, TaxCodeId: 1 },
422
- * { Code: "SGST", Rate: 9, Amt: 450, TaxCodeId: 1 }] },
423
- * { NetAmt: 3000, Taxes: [{ Code: "CGST", Rate: 9, Amt: 270, TaxCodeId: 1 },
424
- * { Code: "SGST", Rate: 9, Amt: 270, TaxCodeId: 1 }] },
457
+ * { Qty: 10, UnitPrice: 500,
458
+ * Taxes: [{ Code: "CGST", Rate: 9, Amt: 450, TaxCodeId: 1 },
459
+ * { Code: "SGST", Rate: 9, Amt: 450, TaxCodeId: 1 }] },
460
+ * { Qty: 6, UnitPrice: 500,
461
+ * Taxes: [{ Code: "CGST", Rate: 9, Amt: 270, TaxCodeId: 1 },
462
+ * { Code: "SGST", Rate: 9, Amt: 270, TaxCodeId: 1 }] },
425
463
  * ],
426
464
  * Rounding: { Method: "Round", Precision: 0, TaxComponentTotal: true, DocTotal: true },
427
465
  * RegimeCode: "IN_GST",
@@ -437,10 +475,10 @@ function ComputeTaxSummary(input) {
437
475
  */
438
476
  function ComputeDocumentTotals(input) {
439
477
  const { Lines, Rounding, RegimeCode } = input;
440
- // 1. SubTotal = sum of line NetAmts
478
+ // 1. SubTotal = sum of line NetAmts (computed from Qty × UnitPrice - Disc - RecDisc)
441
479
  let subTotal = 0;
442
480
  for (const line of Lines) {
443
- subTotal = (0, math_operations_1.Add)(subTotal, (0, util_1.GetNumber)(line.NetAmt));
481
+ subTotal = (0, math_operations_1.Add)(subTotal, CalculateNetAmt(line));
444
482
  }
445
483
  // 2. TaxSummary (handles TaxComponentTotal rounding internally)
446
484
  const taxSummary = ComputeTaxSummary({
@@ -235,12 +235,26 @@ export interface IComponentOverride {
235
235
  PerUnitAmt?: number;
236
236
  Unit?: string;
237
237
  }
238
+ /**
239
+ * Base fields for computing taxable amount (NetAmt) from line item quantities and prices.
240
+ * NetAmt = (Qty × UnitPrice) - Disc - RecDisc
241
+ *
242
+ * Generic across both goods and services:
243
+ * For Items (goods): UnitPrice maps to UnPr (unit price)
244
+ * For Ops (services): UnitPrice maps to Pr (operation rate)
245
+ */
246
+ export interface ILineAmountFields {
247
+ /** Quantity */
248
+ Qty: number;
249
+ /** Unit price — Items: UnPr, Ops: Pr */
250
+ UnitPrice: number;
251
+ /** Line-level discount amount */
252
+ Disc?: number;
253
+ /** Record-level (document-level) discount allocated to this line */
254
+ RecDisc?: number;
255
+ }
238
256
  /** Input context for calculating tax on a single line item */
239
- export interface ITaxCalcLineInput {
240
- /** Net amount after discounts (taxable value) */
241
- NetAmt: number;
242
- /** Quantity — needed for PerUnit calculations (excise, specific cess) */
243
- Qty?: number;
257
+ export interface ITaxCalcLineInput extends ILineAmountFields {
244
258
  /** The TaxCode to apply */
245
259
  TaxCode: ITaxCode;
246
260
  /** Is this a reverse charge line? */
@@ -264,14 +278,12 @@ export interface ITaxCalcLineInput {
264
278
  /** Input context for computing document-level TaxSummary.
265
279
  *
266
280
  * Since TaxableAmt is NOT stored on TaxComponent (it's derivable from line item fields),
267
- * each line must provide its own NetAmt (taxable value) for summary computation.
268
- * This is a pure function — caller derives NetAmt from line item fields and passes it in.
281
+ * each line provides Qty/UnitPrice/Disc/RecDisc and shareneus computes NetAmt internally.
269
282
  */
270
283
  export interface ITaxSummaryInput {
271
- /** All line items with their calculated Taxes[] arrays and taxable value */
272
- Lines: Array<{
284
+ /** All line items with amount fields and calculated Taxes[] arrays */
285
+ Lines: Array<ILineAmountFields & {
273
286
  Taxes?: ITaxComponent[];
274
- NetAmt: number;
275
287
  }>;
276
288
  /** Tax regime code for the snapshot */
277
289
  RegimeCode?: string;
@@ -303,9 +315,8 @@ export interface IRoundingConfig {
303
315
  }
304
316
  /** Input for computing all document-level totals in one call */
305
317
  export interface IDocumentTotalsInput {
306
- /** All line items caller derives NetAmt from line item fields (UnAmt - Disc - RecDisc) */
307
- Lines: Array<{
308
- NetAmt: number;
318
+ /** All line items with amount fields (Qty, UnitPrice, Disc, RecDisc) and Taxes[] */
319
+ Lines: Array<ILineAmountFields & {
309
320
  Taxes?: ITaxComponent[];
310
321
  }>;
311
322
  /** Rounding configuration (from TaxRegime.Rounding or Entity Settings) */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shareneus",
3
- "version": "1.6.18",
3
+ "version": "1.6.20",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",