import { Add, Divide, Multiply, Subtract } from "../../shared/math-operations"; import { TrUtils } from "../../utils/tr-utils"; export class InvoiceTotalsService { static GetTaxAmountFromTaxes(item: any, taxCode: string) { const taxes = Array.isArray(item?.Taxes) ? item.Taxes : []; const matchedTaxes = taxes.filter((tax: any) => tax?.Code === taxCode); if (matchedTaxes.length !== 0) { return matchedTaxes.reduce((total: number, tax: any) => Add(total, tax?.Amt), 0); } return 0; } static GetTaxRateFromTaxes(item: any, taxCode: string) { const taxes = Array.isArray(item?.Taxes) ? item.Taxes : []; const matchedTaxes = taxes.filter((tax: any) => tax?.Code === taxCode); if (matchedTaxes.length !== 0) { return matchedTaxes.reduce((total: number, tax: any) => Add(total, tax?.Rate), 0); } return 0; } static GetTCodeFromTaxes(item: any) { const taxes = Array.isArray(item?.Taxes) ? item.Taxes : []; const matchedTax = taxes.find((tax: any) => !TrUtils.IsNull(tax?.TaxCodeId)); if (!TrUtils.IsNull(matchedTax?.TaxCodeId)) { return matchedTax.TaxCodeId; } return item?.TCode; } static GetTotalsValue(opCodesList: any, PartsList: any, IsIndependentTax: boolean, DetailedInfo: boolean, LDisc: any, LPerc: string, PDisc: any, PPerc: string, Disc: any, Perc: string, TaxCodes: any, WithItems: boolean, Settings: any, Adjust: number, isRoundable: boolean, EntitySettings: any) { LPerc = TrUtils.SetPercToStringIfNull(LPerc); PPerc = TrUtils.SetPercToStringIfNull(PPerc); Perc = TrUtils.SetPercToStringIfNull(Perc); LDisc = TrUtils.SetValueToZeroIfNull(LDisc); PDisc = TrUtils.SetValueToZeroIfNull(PDisc); Disc = TrUtils.SetValueToZeroIfNull(Disc); if (TrUtils.IsNull(opCodesList)) { opCodesList = []; } if (TrUtils.IsNull(PartsList)) { PartsList = []; } opCodesList = this.CalculateLaborValues(opCodesList, IsIndependentTax); PartsList = this.CalculateLaborPartValues(PartsList, IsIndependentTax); let finalTotalsData: any = this.GetFinalRODataForSave(opCodesList, PartsList, IsIndependentTax, LDisc, LPerc, PDisc, PPerc, Disc, Perc, DetailedInfo, Settings, TrUtils.SetValueToZeroIfNull(Adjust), isRoundable, EntitySettings.DecimalsNumber); if (DetailedInfo) { finalTotalsData = this.GetDetailedTotalsData(finalTotalsData, IsIndependentTax, opCodesList, PartsList, TaxCodes, EntitySettings.DecimalsNumber); } if (WithItems) { finalTotalsData.Ops = opCodesList; finalTotalsData.Items = PartsList; } return finalTotalsData; } static CalculateLaborValues(opCodesList: any, IsIndependentTax: boolean) { opCodesList = this.ResetLaborValues(opCodesList, IsIndependentTax); // opCodesList = this.GetOperationsDiscountPrice(opCodesList); // opCodesList = this.GetOperationsAfterDiscount(opCodesList,IsIndependentTax); // opCodesList = this.GetOperationsAfterTax(opCodesList, IsIndependentTax); return opCodesList; } static ResetLaborValues(opCodesList: any, IsIndependentTax: boolean) { opCodesList.forEach((Operation: any) => { Operation = this.ResetLaborValueIfInvalid(Operation); Operation.DiscountedPrice = Add(Operation.Disc, Operation.RecDisc); if (TrUtils.IsNull(Operation.Amt)) { Operation.Amt = Operation.Pr; } if (IsIndependentTax) { let NetAmt: number = Subtract(Operation.Amt, Operation.Disc, Operation.RecDisc); Operation.AfterLaborDisc = NetAmt; Operation.AfterLaborTax = Add(Operation.AfterLaborDisc, Operation.CGST, Operation.SGST, Operation.IGST); } else { Operation.AfterLaborDisc = Subtract(Operation.Amt, Operation.Disc, Operation.RecDisc); Operation.AfterLaborTax = Operation.AfterLaborDisc; } }); return opCodesList; } static ResetLaborValueIfInvalid(Operation: any) { Operation.Pr = TrUtils.SetValueToZeroIfNull(Operation.Pr); Operation.RecDisc = TrUtils.SetValueToZeroIfNull(Operation.RecDisc); Operation.Disc = TrUtils.SetValueToZeroIfNull(Operation.Disc); Operation.CGST = TrUtils.SetValueToZeroIfNull(this.GetTaxAmountFromTaxes(Operation, 'CGST')); Operation.SGST = TrUtils.SetValueToZeroIfNull(this.GetTaxAmountFromTaxes(Operation, 'SGST')); Operation.IGST = TrUtils.SetValueToZeroIfNull(this.GetTaxAmountFromTaxes(Operation, 'IGST')); Operation.TCode = this.GetTCodeFromTaxes(Operation); return Operation; } static CalculateLaborPartValues(PartsList: any, IsIndependentTax: boolean) { PartsList = this.ResetLaborPartValues(PartsList, IsIndependentTax); // PartsList = this.GetLaborPartsDiscountPrice(PartsList); // PartsList = this.GetLaborPartsAfterDiscount(PartsList,IsIndependentTax); // PartsList = this.GetPartsAfterTax(PartsList, IsIndependentTax); return PartsList; } static ResetLaborPartValues(PartsList: any, IsIndependentTax: boolean) { PartsList.forEach((Part: any) => { Part = this.ResetLaborPartValueIfInvalid(Part); Part.DiscountedPrice = Add(Part.Disc, Part.RecDisc); if (IsIndependentTax) { let NetAmt: number = Subtract(Part.UnAmt, Part.Disc, Part.RecDisc); Part.AfterPartDisc = NetAmt; Part.AfterPartTax = Add(Part.AfterPartDisc, Part.CGST, Part.SGST, Part.IGST); } else { Part.AfterPartDisc = Subtract(Part.UnAmt, Part.Disc, Part.RecDisc); Part.AfterPartTax = Part.AfterPartDisc; } }); return PartsList; } static ResetLaborPartValueIfInvalid(Part: any) { Part.UnPr = TrUtils.SetValueToZeroIfNull(Part.UnPr); Part.Disc = TrUtils.SetValueToZeroIfNull(Part.Disc); Part.RecDisc = TrUtils.SetValueToZeroIfNull(Part.RecDisc); Part.CGST = TrUtils.SetValueToZeroIfNull(this.GetTaxAmountFromTaxes(Part, 'CGST')); Part.SGST = TrUtils.SetValueToZeroIfNull(this.GetTaxAmountFromTaxes(Part, 'SGST')); Part.IGST = TrUtils.SetValueToZeroIfNull(this.GetTaxAmountFromTaxes(Part, 'IGST')); Part.TCode = this.GetTCodeFromTaxes(Part); return Part; } static GetFinalRODataForSave(LaborList: any, PartsList: any, IsIndependentTax: boolean, LDisc: any, LPerc: string, PDisc: string, PPerc: string, Disc: any, Perc: string, DetailedInfo: boolean, Settings: any, Adjust: number, isRoundable: boolean, DecimalsNumber: any) { let finalTotalsData: any = {}; finalTotalsData = this.SetMainDiscountValues(LPerc, PPerc, LDisc, PDisc, Disc, Perc, finalTotalsData, DetailedInfo); finalTotalsData.Settings = Settings; finalTotalsData = this.GetFinalCustomerTotalsData(finalTotalsData, LaborList, PartsList, IsIndependentTax, DetailedInfo, Adjust, isRoundable, DecimalsNumber); return finalTotalsData; } static SetMainDiscountValues(LPerc: string, PPerc: string, LDisc: any, PDisc: any, Disc: any, Perc: string, finalTotalsData: any, DetailedInfo: boolean) { finalTotalsData.LDisc = LDisc; finalTotalsData.LPerc = LPerc; finalTotalsData.PDisc = PDisc; finalTotalsData.PPerc = PPerc; finalTotalsData.Disc = Disc; finalTotalsData.Perc = Perc; if (DetailedInfo) { finalTotalsData.FixedLDisc = LDisc; finalTotalsData.FixedPDisc = PDisc; finalTotalsData.FixedDisc = Disc; } return finalTotalsData; } static GetPartsAfterDiscount1(PartsList: any) { let AfterIndvidualDisc: number = 0; PartsList.forEach((Part: any) => { if (!Part.Ret) { AfterIndvidualDisc = Add(AfterIndvidualDisc, Subtract(Part.UnAmt, Part.Disc)); } }); return AfterIndvidualDisc; } static GetLaborTotalAfterDiscount1(OperationsList: any) { let AfterIndvidualDisc: number = 0; OperationsList.forEach((Operation: any) => { if (TrUtils.IsNull(Operation.Amt)) { Operation.Amt = Operation.Pr; } AfterIndvidualDisc = Add(AfterIndvidualDisc, Subtract(Operation.Amt, Operation.Disc)); }); return AfterIndvidualDisc; } static GetFinalCustomerTotalsData(finalTotalsData: any, LaborList: any, PartsList: any, IsIndependentTax: boolean, DetailedInfo: boolean, Adjust: number, isRoundable: boolean, DecimalsNumber: any) { let CustomerAfterDiscTotals: number = this.GetSubTotalFor(LaborList, PartsList); let CustLaborTaxTotal = this.GetLaborTaxTotalFor(LaborList, IsIndependentTax); let CustPartTaxTotal = this.GetPartsTaxTotalFor(PartsList, IsIndependentTax); let RetCustParrtTaxTotal = this.GetRetPartsTaxTotalFor(PartsList, IsIndependentTax); let NonRetCustParrtTaxTotal = this.GetNonRetPartsTaxTotalFor(PartsList, IsIndependentTax); finalTotalsData.SubTotal = TrUtils.FixedTo(CustomerAfterDiscTotals, DecimalsNumber); let CustLaborDiscTotal = this.GetLaborDiscountedTotal(LaborList, IsIndependentTax, finalTotalsData); let CustPartsDiscTotal = this.GetPartDiscountedTotal(PartsList, IsIndependentTax, finalTotalsData); let CustLaborTotalAfterDisc = this.GetLaborTotalAfterDiscount(LaborList); let CustPartsTotalAfterDisc = this.GetPartsTotalAfterDiscount(PartsList); // if (IsIndependentTax) { finalTotalsData.STotal = Add(CustLaborDiscTotal, CustPartsDiscTotal, CustLaborTotalAfterDisc, CustPartsTotalAfterDisc); // } else { // finalTotalsData.STotal = Add(CustLaborTotalAfterDisc, CustPartsTotalAfterDisc); // } let CustLaborTotalAfterDisc1: number = this.GetLaborTotalAfterDiscount1(LaborList); let CustPartsTotalAfterDisc1: number = this.GetPartsAfterDiscount1(PartsList); let AmtAfterIndvidualItemDisc: number = Add(CustLaborTotalAfterDisc1, CustPartsTotalAfterDisc1); finalTotalsData.SIndTotal = AmtAfterIndvidualItemDisc; // finalTotalsData.Disc = !TrUtils.IsZero(finalTotalsData.Perc) ? TrUtils.ConvertPercToVal(finalTotalsData.Perc, AmtAfterIndvidualItemDisc, DecimalsNumber) : finalTotalsData.Disc; let CustTotal: any = this.GetCustomerTotalBasedOnTaxType(finalTotalsData, CustLaborTaxTotal, CustPartTaxTotal, LaborList, PartsList, IsIndependentTax, Adjust); let RetCustTotal: any = this.GetRetCustomerTotalBasedOnTaxType(finalTotalsData, CustLaborTaxTotal, RetCustParrtTaxTotal, LaborList, PartsList, IsIndependentTax, Adjust, DecimalsNumber); let NonRetCustTotal: any = this.GetNonRetCustomerTotalBasedOnTaxType(finalTotalsData, CustLaborTaxTotal, NonRetCustParrtTaxTotal, LaborList, PartsList, IsIndependentTax, Adjust, DecimalsNumber); if (isRoundable) { finalTotalsData.Round = Subtract(Math.round(CustTotal), CustTotal); finalTotalsData.Total = Math.round(CustTotal); } else { finalTotalsData.Total = TrUtils.FixedTo(CustTotal, DecimalsNumber); } finalTotalsData.RetTotal = TrUtils.FixedTo(RetCustTotal, DecimalsNumber); finalTotalsData.NonRetTotal = TrUtils.FixedTo(NonRetCustTotal, DecimalsNumber); if (DetailedInfo) { finalTotalsData.FixedSubTotal = TrUtils.FixedTo(CustomerAfterDiscTotals, DecimalsNumber); finalTotalsData.FixedTotal = TrUtils.FixedTo(CustTotal, DecimalsNumber); finalTotalsData.Adj = TrUtils.FixedTo(Adjust, DecimalsNumber); } return finalTotalsData; } static GetSubTotalFor(LaborList: any, PartsList: any) { let LaborTotalAfterDisc: any = this.GetLaborTotalAfterDiscount(LaborList); let PartsTotalAfterDisc: any = this.GetPartsTotalAfterDiscount(PartsList); return Add(LaborTotalAfterDisc, PartsTotalAfterDisc); } static GetLaborTotalAfterDiscount(LaborList: any) { let LaborTotalAfterDisc: any = 0; LaborList.forEach((Labor: any) => { LaborTotalAfterDisc = Add(LaborTotalAfterDisc, Labor.AfterLaborDisc); }); return LaborTotalAfterDisc; } static GetPartsTotalAfterDiscount(PartsList: any) { let PartsTotalAfterDisc: any = 0; let RetPartsTotalAfterDisc: any = 0; PartsList.forEach((Part: any) => { if (Part.Ret === true) { RetPartsTotalAfterDisc = Add(RetPartsTotalAfterDisc, Part.AfterPartDisc); } else { PartsTotalAfterDisc = Add(PartsTotalAfterDisc, Part.AfterPartDisc); } }); return Subtract(PartsTotalAfterDisc, RetPartsTotalAfterDisc); } static GetRetPartsTotalAfterDiscount(PartsList: any) { let RetPartsTotalAfterDisc: any = 0; PartsList.forEach((Part: any) => { if (Part.Ret === true) { RetPartsTotalAfterDisc = Add(RetPartsTotalAfterDisc, Part.AfterPartDisc); } }); return RetPartsTotalAfterDisc; } static GetNonRetPartsTotalAfterDiscount(PartsList: any) { let NonRetPartsTotalAfterDisc: any = 0; PartsList.forEach((Part: any) => { if (TrUtils.IsNull(Part.Ret) || Part.Ret === false) { NonRetPartsTotalAfterDisc = Add(NonRetPartsTotalAfterDisc, Part.AfterPartDisc); } }); return NonRetPartsTotalAfterDisc; } static GetDetailedTotalsData(finalTotalsData: any, IsIndependentTax: boolean, opCodesList: any, PartsList: any, TaxCodes: any, DecimalsNumber: any) { finalTotalsData.CustLaborDiscTotal = this.GetLaborDiscountedTotal(opCodesList, IsIndependentTax, finalTotalsData); finalTotalsData.CustPartsDiscTotal = this.GetPartDiscountedTotal(PartsList, IsIndependentTax, finalTotalsData); finalTotalsData.CustLaborTotalAfterDisc = this.GetLaborTotalAfterDiscount(opCodesList); finalTotalsData.CustPartsTotalAfterDisc = this.GetPartsTotalAfterDiscount(PartsList); finalTotalsData.CustLaborTotalBeforeDisc = Add(finalTotalsData.CustLaborTotalAfterDisc , finalTotalsData.CustLaborDiscTotal); if (IsIndependentTax) { finalTotalsData.CustPartsTotalBeforeDisc = Add(finalTotalsData.CustPartsTotalAfterDisc , finalTotalsData.CustPartsDiscTotal); } else { finalTotalsData.CustPartsTotalBeforeDisc = finalTotalsData.CustPartsTotalAfterDisc; } let LaborTaxInfo: any = this.GetLaborGSTTaxTotal(opCodesList, IsIndependentTax); finalTotalsData.CustLaborITax = TrUtils.SetValueToZeroIfNull(LaborTaxInfo[3]); finalTotalsData.CustLaborSGST = TrUtils.SetValueToZeroIfNull(LaborTaxInfo[1]); finalTotalsData.CustLaborCGST = TrUtils.SetValueToZeroIfNull(LaborTaxInfo[0]); finalTotalsData.CustLaborIGST = TrUtils.SetValueToZeroIfNull(LaborTaxInfo[2]); let PartTaxInfo: any = this.GetPartGSTTaxTotal(PartsList, IsIndependentTax); finalTotalsData.CustPartITax = this.GetPartsTaxTotalFor(PartsList, IsIndependentTax); finalTotalsData.CustPartCGST = TrUtils.SetValueToZeroIfNull(PartTaxInfo[0]); finalTotalsData.CustPartIGST = TrUtils.SetValueToZeroIfNull(PartTaxInfo[2]); finalTotalsData.CustPartSGST = TrUtils.SetValueToZeroIfNull(PartTaxInfo[1]); finalTotalsData.CustLaborAfterTax = Add(finalTotalsData.CustLaborITax, finalTotalsData.CustLaborTotalAfterDisc); finalTotalsData.CustPartAfterTax = Add(finalTotalsData.CustPartITax, finalTotalsData.CustPartsTotalAfterDisc); finalTotalsData.CustTaxGroupData = this.GetTaxGroupingForPartsByHSN(PartsList, TaxCodes, DecimalsNumber); finalTotalsData.CustTaxGroupDataByPerc = this.GetTaxGroupingForPartsByPerc(PartsList, TaxCodes, DecimalsNumber); finalTotalsData.CustLaborTaxGroupDataByPerc = this.GetTaxGroupingForLaborByPerc(opCodesList, TaxCodes, DecimalsNumber); finalTotalsData.TaxSummary = this.groupTaxData(finalTotalsData.CustTaxGroupData, finalTotalsData.CustLaborTaxGroupDataByPerc); finalTotalsData.CustTotalRoundedBy = TrUtils.FixedTo(finalTotalsData.Round, DecimalsNumber); finalTotalsData.CustRoundedTotal = TrUtils.FixedTo(finalTotalsData.Total, DecimalsNumber); finalTotalsData.CustRetRoundedTotal = TrUtils.FixedTo(finalTotalsData.RetTotal, DecimalsNumber); finalTotalsData.CustNonRetRoundedTotal = TrUtils.FixedTo(finalTotalsData.NonRetTotal, DecimalsNumber); for (var key in finalTotalsData) { if (key !== 'Total' && key !== 'SubTotal' && key !== 'LDisc' && key !== 'LPerc' && key !== 'PDisc' && key !== 'PPerc' && key !== 'Disc' && key !== 'Perc' && key !== 'Tax' && typeof finalTotalsData[key] === 'number') { finalTotalsData[key] = TrUtils.FixPriceValue(finalTotalsData[key], DecimalsNumber); } } return finalTotalsData; } static groupTaxData( items: any[], ops: any[] ): any[] { if (TrUtils.IsNull(items)) { items = []; } if (TrUtils.IsNull(ops)) { ops = []; } const combined = [...items, ...ops]; const groupedMap = new Map(); combined.forEach(item => { if (groupedMap.has(item.CombinedTaxPercentage)) { const existing = groupedMap.get(item.CombinedTaxPercentage)!; existing.CGSTAmt = Add(existing.CGSTAmt, item.CGSTAmt); existing.SGSTAmt = Add(existing.SGSTAmt, item.SGSTAmt); // Sum IGST if present if (item.IGSTAmt !== undefined) { existing.IGSTAmt = Add(existing.IGSTAmt || 0, item.IGSTAmt); } existing.TotalTaxAmount = Add(existing.TotalTaxAmount || 0, item.TotalTaxAmount || 0); existing.TotalTaxableAmount = Add(existing.TotalTaxableAmount || 0, item.TotalTaxableAmount || 0); } else { // Clone the object to avoid mutation groupedMap.set(item.CombinedTaxPercentage, { ...item }); } }); return Array.from(groupedMap.values()); } static GetTaxGroupingForLaborByPerc(opCodesList: any, TaxCodes: any, DecimalsNumber: any) { opCodesList = this.GetCombinedTaxPercentage(TrUtils.Stringify(opCodesList), TaxCodes); // opCodesList = this.ResetPartsHSNIfInvalid(opCodesList); let FinalMatchedParts: any[] = this.CompareLaborByPerc(opCodesList, TaxCodes); return this.GetTaxGroupingInfoBySAC(FinalMatchedParts, TaxCodes, DecimalsNumber); } static GetTaxGroupingForPartsByPerc(Parts: any, TaxCodes: any, DecimalsNumber: any) { Parts = this.GetCombinedTaxPercentage(TrUtils.Stringify(Parts), TaxCodes); // Parts = this.ResetPartsHSNIfInvalid(Parts); let FinalMatchedParts: any[] = this.ComparePartsByPerc(Parts, TaxCodes); return this.GetTaxGroupingInfoByHSN(FinalMatchedParts, TaxCodes, DecimalsNumber); } static GetTaxGroupingInfoBySAC(FinalMatchedLabors: any, TaxCodes: any, DecimalsNumber: any) { let SACTaxInfo: any[] = []; FinalMatchedLabors?.forEach((MatchedLabor: any) => { let TaxInfo: any = {}; let TaxOnAmount: any = 0; let TaxAmount: any = 0; let CGSTAmt: any = 0; let SGSTAmt: any = 0; let IGSTAmt: any = 0; let SAC: any = MatchedLabor[0].SAC; TaxInfo.CombinedTaxPercentage = MatchedLabor[0].CombinedTaxPercentage; MatchedLabor?.forEach((argMatchedGSTLabor: any) => { TaxOnAmount = Add(TaxOnAmount, TrUtils.FixedTo(argMatchedGSTLabor.AfterLaborDisc, DecimalsNumber)); TaxAmount = Add(TaxAmount, TrUtils.FixedTo(argMatchedGSTLabor.CGST, DecimalsNumber)); TaxAmount = Add(TaxAmount, TrUtils.FixedTo(argMatchedGSTLabor.IGST, DecimalsNumber)); TaxAmount = Add(TaxAmount, TrUtils.FixedTo(argMatchedGSTLabor.SGST, DecimalsNumber)); CGSTAmt = Add(CGSTAmt, TrUtils.FixedTo(argMatchedGSTLabor.CGST, DecimalsNumber)); SGSTAmt = Add(SGSTAmt, TrUtils.FixedTo(argMatchedGSTLabor.SGST, DecimalsNumber)); IGSTAmt = Add(IGSTAmt, TrUtils.FixedTo(argMatchedGSTLabor.IGST, DecimalsNumber)); }); TaxInfo.SAC = SAC; TaxInfo.CGSTAmt = CGSTAmt; TaxInfo.SGSTAmt = SGSTAmt; TaxInfo.IGSTAmt = IGSTAmt; TaxInfo.TotalTaxableAmount = TrUtils.FixPriceValue(TaxOnAmount, DecimalsNumber); TaxInfo.TotalTaxAmount = TrUtils.FixPriceValue(TaxAmount, DecimalsNumber); TaxInfo.ItemsCount = MatchedLabor.length; TaxInfo.CGST = this.GetTaxRateFromTaxes(MatchedLabor[0], 'CGST'); TaxInfo.SGST = this.GetTaxRateFromTaxes(MatchedLabor[0], 'SGST'); TaxInfo.IGST = this.GetTaxRateFromTaxes(MatchedLabor[0], 'IGST'); if (TaxOnAmount !== 0) { SACTaxInfo.push(TaxInfo); } }); return SACTaxInfo; } static CompareLaborByPerc(opCodesList: any, TaxCodes: any) { let FinalMatchedLabors: any[] = []; opCodesList?.forEach((Labor: any) => { let MatchedLaborsBasedOnPerc = opCodesList.filter((argLabor: any) => { let PartFound: boolean = false; FinalMatchedLabors.forEach((FinalArgLabors: any) => { let PartIndex: any = FinalArgLabors.findIndex((FinalArgPart: any) => { return FinalArgPart._id === argLabor._id; }); if (PartIndex !== -1) { PartFound = true; } }); // let argGSTValues: any[] = this.GetGSTValueBasedOnTaxCode(argLabor.TCode, TaxCodes); // let argCGST = argGSTValues[0]; // let argSGST = argGSTValues[1]; // let argIGST = argGSTValues[2]; // let laborGSTValues: any[] = this.GetGSTValueBasedOnTaxCode(Labor.TCode, TaxCodes); // let laborCGST = laborGSTValues[0]; // let laborSGST = laborGSTValues[1]; // let laborIGST = laborGSTValues[2]; return (!PartFound) && (argLabor.CGSTAmt === Labor.CGSTAmt) && (argLabor.IGSTAmt === Labor.IGSTAmt) && (argLabor.SGSTAmt === Labor.SGSTAmt); }); if (MatchedLaborsBasedOnPerc.length !== 0) { FinalMatchedLabors.push(MatchedLaborsBasedOnPerc); } }); return FinalMatchedLabors; } static ComparePartsByPerc(Parts: any, TaxCodes: any) { let FinalMatchedParts: any[] = []; Parts?.forEach((Part: any) => { let MatchedPartsBasedOnHSN = Parts.filter((argPart: any) => { let PartFound: boolean = false; FinalMatchedParts.forEach((FinalArgParts: any) => { let PartIndex: any = FinalArgParts.findIndex((FinalArgPart: any) => { return FinalArgPart._id === argPart._id; }); if (PartIndex !== -1) { PartFound = true; } }); // let argGSTValues: any[] = this.GetGSTValueBasedOnTaxCode(argPart.TCode, TaxCodes); // let argCGST = argGSTValues[0]; // let argSGST = argGSTValues[1]; // let argIGST = argGSTValues[2]; // let partGSTValues: any[] = this.GetGSTValueBasedOnTaxCode(Part.TCode, TaxCodes); // let partCGST = partGSTValues[0]; // let partSGST = partGSTValues[1]; // let partIGST = partGSTValues[2]; return (!PartFound) && (argPart.CGSTAmt === Part.CGSTAmt) && (argPart.IGSTAmt === Part.IGSTAmt) && (argPart.SGSTAmt === Part.SGSTAmt); }); if (MatchedPartsBasedOnHSN.length !== 0) { FinalMatchedParts.push(MatchedPartsBasedOnHSN); } }); return FinalMatchedParts; } static GetLaborDiscountedTotal(LaborList: any, isTaxable: boolean, finalTotalsData: any) { let LaborDiscountedTotal: any = 0; let overallLaborDisc: number = 0; // if (!isTaxable) { // overallLaborDisc = TrUtils.SetValueToZeroIfNull(finalTotalsData.LDisc) // } else { LaborList.forEach((Labor: any) => { LaborDiscountedTotal = Add(LaborDiscountedTotal, Labor.DiscountedPrice); }); // } return Add(LaborDiscountedTotal, overallLaborDisc); } static GetPartDiscountedTotal(PartsList: any, isTaxable: boolean, finalTotalsData: any) { let PartsDiscountedTotal: any = 0; let RetPartsDiscountedTotal: any = 0; let overallPartDisc: number = 0; // if (!isTaxable) { // overallPartDisc = TrUtils.SetValueToZeroIfNull(finalTotalsData.PDisc) // } else { PartsList.forEach((Part: any) => { if (Part.Ret === true) { RetPartsDiscountedTotal = Add(RetPartsDiscountedTotal, Part.DiscountedPrice); } else { PartsDiscountedTotal = Add(PartsDiscountedTotal, Part.DiscountedPrice); } }); // } return Add(Subtract(PartsDiscountedTotal, RetPartsDiscountedTotal), overallPartDisc); } static GetLaborTaxTotalFor(opCodesList: any, IsIndependentTax: boolean) { let TotalTaxAmt: any = 0; if (IsIndependentTax) { opCodesList.forEach((Labor: any) => { TotalTaxAmt = Add(TotalTaxAmt, Labor.CGST, Labor.SGST, Labor.IGST); }); } return TotalTaxAmt; } static GetPartsTaxTotalFor(PartsList: any, IsIndependentTax: boolean) { let TotalTaxAmt: any = 0; let RetTotalTaxAmt: any = 0; if (IsIndependentTax) { PartsList.forEach((Part: any) => { if (Part.Ret === true) { RetTotalTaxAmt = Add(RetTotalTaxAmt, Part.CGST, Part.SGST, Part.IGST); } else { TotalTaxAmt = Add(TotalTaxAmt, Part.CGST, Part.SGST, Part.IGST); } }); } return Subtract(TotalTaxAmt, RetTotalTaxAmt); } static GetRetPartsTaxTotalFor(PartsList: any, IsIndependentTax: boolean) { let RetTotalTaxAmt: any = 0; if (IsIndependentTax) { PartsList.forEach((Part: any) => { if (Part.Ret === true) { RetTotalTaxAmt = Add(RetTotalTaxAmt, Part.CGST, Part.SGST, Part.IGST); } }); } return RetTotalTaxAmt; } static GetNonRetPartsTaxTotalFor(PartsList: any, IsIndependentTax: boolean) { let NonRetTotalTaxAmt: any = 0; if (IsIndependentTax) { PartsList.forEach((Part: any) => { if (TrUtils.IsNull(Part.Ret) || Part.Ret === false) { NonRetTotalTaxAmt = Add(NonRetTotalTaxAmt, Part.CGST, Part.SGST, Part.IGST); } }); } return NonRetTotalTaxAmt; } static GetCustomerTotalBasedOnTaxType(finalTotalsData: any, LaborTaxAmount: number, PartsTaxAmount: number , LaborList: any, PartsList: any, IsIndependentTax: boolean, Adjust: any) { let LaborTotalAfterDisc: any = this.GetLaborTotalAfterDiscount(LaborList); let PartsTotalAfterDisc: any = this.GetPartsTotalAfterDiscount(PartsList); if (IsIndependentTax) { return Add(LaborTotalAfterDisc, PartsTotalAfterDisc, LaborTaxAmount, PartsTaxAmount, Adjust); } else { return Add(LaborTotalAfterDisc, PartsTotalAfterDisc, Adjust); } } static GetRetLaborTotalAfterDiscount(LaborList: any) { return 0; } static GetRetCustomerTotalBasedOnTaxType(finalTotalsData: any, LaborTaxAmount: number, PartsTaxAmount: number , LaborList: any, PartsList: any, IsIndependentTax: boolean, Adjust: any, DecimalsNumber: any) { LaborTaxAmount = 0; let LaborTotalAfterDisc: any = this.GetRetLaborTotalAfterDiscount(LaborList); let PartsTotalAfterDisc: any = this.GetRetPartsTotalAfterDiscount(PartsList); if (IsIndependentTax) { return Add(LaborTotalAfterDisc, PartsTotalAfterDisc, LaborTaxAmount, PartsTaxAmount); } else { return TrUtils.FixedTo(Add(LaborTotalAfterDisc, PartsTotalAfterDisc), DecimalsNumber); } } static GetNonRetCustomerTotalBasedOnTaxType(finalTotalsData: any, LaborTaxAmount: number, PartsTaxAmount: number , LaborList: any, PartsList: any, IsIndependentTax: boolean, Adjust: any, DecimalsNumber: any) { let LaborTotalAfterDisc: any = this.GetLaborTotalAfterDiscount(LaborList); let PartsTotalAfterDisc: any = this.GetNonRetPartsTotalAfterDiscount(PartsList); if (IsIndependentTax) { return Add(LaborTotalAfterDisc, PartsTotalAfterDisc, LaborTaxAmount, PartsTaxAmount); } else { return TrUtils.FixedTo(Add(LaborTotalAfterDisc, PartsTotalAfterDisc), DecimalsNumber); } } static LaborTotalAfterDiscount(LaborTotalAfterDisc: number, LaborTaxAmount: number, MainLDisc: number, LDiscInPerc: string) { let LaborTotal: number = Add(LaborTotalAfterDisc, LaborTaxAmount); if (!TrUtils.IsZero(MainLDisc)) { if (!TrUtils.IsEmpty(LDiscInPerc)) { LaborTotal = Subtract(LaborTotal, Divide(Multiply(LaborTotal, Number(LDiscInPerc)), 100)); } else { LaborTotal = Subtract(LaborTotal, MainLDisc); } } return LaborTotal; } static ItemsTotalAfterDiscount(PartsTotalAfterDisc: number, PartsTaxAmount: number, MainPDisc: number, PDiscInPerc: string) { let ItemsTotal: number = Add(PartsTotalAfterDisc, PartsTaxAmount); if (!TrUtils.IsZero(MainPDisc)) { if (!TrUtils.IsEmpty(PDiscInPerc)) { ItemsTotal = Subtract(ItemsTotal, Divide(Multiply(ItemsTotal, Number(PDiscInPerc)), 100)); } else { ItemsTotal = Subtract(ItemsTotal, MainPDisc); } } return ItemsTotal; } static GetLaborGSTTaxTotal(opCodesList: any, IsIndependentTax: boolean) { let TotalCGSTAmt: number = 0; let TotalSGSTAmt: number = 0; let TotalIGSTAmt: number = 0; let TotalTaxAmt: number = 0; if (IsIndependentTax) { opCodesList.forEach((Labor: any) => { TotalCGSTAmt = Add(TotalCGSTAmt, Labor.CGST); TotalSGSTAmt = Add(TotalSGSTAmt, Labor.SGST); TotalIGSTAmt = Add(TotalIGSTAmt, Labor.IGST); TotalTaxAmt = Add(TotalTaxAmt, Labor.CGST, Labor.SGST, Labor.IGST); }); } return [TotalCGSTAmt, TotalSGSTAmt, TotalIGSTAmt, TotalTaxAmt]; } static GetPartGSTTaxTotal(PartsList: any, IsIndependentTax: boolean) { let TotalCGSTAmt: number = 0; let RetTotalCGSTAmt: number = 0; let RetTotalIGSTAmt: number = 0; let TotalIGSTAmt: number = 0; let TotalSGSTAmt: number = 0; let RetTotalSGSTAmt: number = 0; if (IsIndependentTax) { PartsList.forEach((Part: any) => { if (Part.Ret === true) { RetTotalCGSTAmt = Add(RetTotalCGSTAmt, Part.CGST); RetTotalSGSTAmt = Add(RetTotalSGSTAmt, Part.SGST); RetTotalIGSTAmt = Add(RetTotalIGSTAmt, Part.IGST); } else { TotalCGSTAmt = Add(TotalCGSTAmt, Part.CGST); TotalSGSTAmt = Add(TotalSGSTAmt, Part.SGST); TotalIGSTAmt = Add(TotalIGSTAmt, Part.IGST); } }); } return [TotalCGSTAmt, TotalSGSTAmt, TotalIGSTAmt]; } static GetTaxGroupingForPartsByHSN(Parts: any, TaxCodes: any, DecimalsNumber: any) { Parts = this.GetCombinedTaxPercentage(TrUtils.Stringify(Parts), TaxCodes); // Parts = this.ResetPartsHSNIfInvalid(Parts); let FinalMatchedParts: any[] = this.ComparePartsByHSN(Parts, TaxCodes); return this.GetTaxGroupingInfoByHSN(FinalMatchedParts, TaxCodes, DecimalsNumber); } static GetCombinedTaxPercentage(Parts: any, TaxCodes: any) { Parts.forEach((Part: any) => { if (TrUtils.IsNull(Part.HSN)) { Part.HSN = ''; } Part.CGSTAmt = TrUtils.SetValueToZeroIfNull(this.GetTaxRateFromTaxes(Part, 'CGST')); Part.SGSTAmt = TrUtils.SetValueToZeroIfNull(this.GetTaxRateFromTaxes(Part, 'SGST')); Part.IGSTAmt = TrUtils.SetValueToZeroIfNull(this.GetTaxRateFromTaxes(Part, 'IGST')); Part.CombinedTaxPercentage = Add(Part.CGSTAmt, Part.SGSTAmt, Part.IGSTAmt); }); return Parts; } static ComparePartsByHSN(Parts: any, TaxCodes: any) { let FinalMatchedParts: any[] = []; Parts.forEach((Part: any) => { let MatchedPartsBasedOnHSN = Parts.filter((argPart: any) => { let PartFound: boolean = false; FinalMatchedParts.forEach((FinalArgParts: any) => { let PartIndex: any = FinalArgParts.findIndex((FinalArgPart: any) => { return FinalArgPart._id === argPart._id; }); if (PartIndex !== -1) { PartFound = true; } }); // let argGSTValues: any[] = this.GetGSTValueBasedOnTaxCode(argPart.TCode, TaxCodes); // let argCGST = argGSTValues[0]; // let argSGST = argGSTValues[1]; // let argIGST = argGSTValues[2]; // let partGSTValues: any[] = this.GetGSTValueBasedOnTaxCode(Part.TCode, TaxCodes); // let partCGST = partGSTValues[0]; // let partSGST = partGSTValues[1]; // let partIGST = partGSTValues[2]; return (argPart.HSN === Part.HSN) && (!PartFound) && (argPart.CGSTAmt === Part.CGSTAmt) && (argPart.IGSTAmt === Part.IGSTAmt) && (argPart.SGSTAmt === Part.SGSTAmt); }); if (MatchedPartsBasedOnHSN.length !== 0) { FinalMatchedParts.push(MatchedPartsBasedOnHSN); } }); return FinalMatchedParts; } static GetTaxGroupingInfoByHSN(FinalMatchedParts: any, TaxCodes: any, DecimalsNumber: any) { let HSNTaxInfo: any[] = []; FinalMatchedParts.forEach((MatchedPart: any) => { let TaxInfo: any = {}; let TaxOnAmount: any = 0; let TaxAmount: any = 0; let CGSTAmt: any = 0; let SGSTAmt: any = 0; let IGSTAmt: any = 0; let HSN: any = MatchedPart[0].HSN; TaxInfo.CombinedTaxPercentage = MatchedPart[0].CombinedTaxPercentage; MatchedPart.forEach((argMatchedGSTPart: any) => { TaxOnAmount = Add(TaxOnAmount, TrUtils.FixedTo(argMatchedGSTPart.AfterPartDisc, DecimalsNumber)); TaxAmount = Add(TaxAmount, TrUtils.FixedTo(argMatchedGSTPart.CGST, DecimalsNumber)); TaxAmount = Add(TaxAmount, TrUtils.FixedTo(argMatchedGSTPart.IGST, DecimalsNumber)); TaxAmount = Add(TaxAmount, TrUtils.FixedTo(argMatchedGSTPart.SGST, DecimalsNumber)); CGSTAmt = Add(CGSTAmt, TrUtils.FixedTo(argMatchedGSTPart.CGST, DecimalsNumber)); SGSTAmt = Add(SGSTAmt, TrUtils.FixedTo(argMatchedGSTPart.SGST, DecimalsNumber)); IGSTAmt = Add(IGSTAmt, TrUtils.FixedTo(argMatchedGSTPart.IGST, DecimalsNumber)); }); TaxInfo.HSN = HSN; TaxInfo.CGSTAmt = CGSTAmt; TaxInfo.SGSTAmt = SGSTAmt; TaxInfo.IGSTAmt = IGSTAmt; TaxInfo.TotalTaxableAmount = TrUtils.FixPriceValue(TaxOnAmount, DecimalsNumber); TaxInfo.TotalTaxAmount = TrUtils.FixPriceValue(TaxAmount, DecimalsNumber); TaxInfo.ItemsCount = MatchedPart.length; // let GSTValues: any[] = this.GetGSTValueBasedOnTaxCode(MatchedPart[0].TCode, TaxCodes); // TaxInfo.CGST = GSTValues[0]; // TaxInfo.SGST = GSTValues[1]; // TaxInfo.IGST = GSTValues[2]; TaxInfo.CGST = MatchedPart[0].CGSTAmt; TaxInfo.IGST = MatchedPart[0].IGSTAmt; TaxInfo.SGST = MatchedPart[0].SGSTAmt; if (TaxOnAmount !== 0) { HSNTaxInfo.push(TaxInfo); } }); return HSNTaxInfo; } static GetGSTValueBasedOnTaxCode(TCode: any, TaxCodes: any) { let CGST: number = 0; let SGST: number = 0; let IGST: number = 0; if (TrUtils.IsNull(TCode)) { return [CGST, SGST, IGST]; } let TCodeIndex: any = TaxCodes.findIndex((TaxCode: any) => { return TaxCode._id === Number(TCode); }); if (TCodeIndex !== -1) { if (TaxCodes[TCodeIndex].Type === 'Intra') { return [TaxCodes[TCodeIndex].CGST, TaxCodes[TCodeIndex].SGST, 0]; } else { return [0, 0, TaxCodes[TCodeIndex].IGST]; } } else { return [CGST, SGST, IGST]; } } }