using AccountsDAL.CustomCode.ETDS; using AccountsDAL.DTO.ETDS; using GB5Shared.DTO.Framework.Criteria; using GB5Shared.DTO.Framework.Login; using GB5Shared.QueryExecutor; using System.Linq; using System.Text; namespace AccountsBLL.ETDS { public class EtdsBLL : IEtdsBLL { private readonly IEtdsDAL _etdsDAL; private readonly IQueryExecutor _queryExecutor; public EtdsBLL(IEtdsDAL etdsDAL, IQueryExecutor queryExecutor) { _etdsDAL = etdsDAL; _queryExecutor = queryExecutor; } // Ported from GB4 EtdsBLL/EtdsDAL.UnDoPostingTDSReturnForm (TDSCategory.svc's // /ETDS/TDSUndoPosting/ operation) — reverses an e-TDS quarterly return filing batch by // hard-deleting every row tied to the matching TDSRETURNID(s) for a given // OU+Period+FormType+PeriodType. This is NOT related to voucher/TDS-payment posting. // // Deliberate fix over GB4 (per explicit direction): GB4's FormType->FileType/FormNumber // mapping checked "else if (FileType == "1"/"2"/"3")" instead of FormType, so only // FormType=0 (24Q) ever actually matched — the 26Q/27Q/27EQ branches were dead code. // Fixed here to check FormType in every branch. public async Task TDSUndoPosting(CriteriaDTO criteriaDTO, LoginDTO loginDTO) { string ouIdText = ReadCriteria(criteriaDTO, "ouid"); string periodIdText = ReadCriteria(criteriaDTO, "periodid"); string formType = ReadCriteria(criteriaDTO, "formtype"); string periodType = ReadCriteria(criteriaDTO, "periodtype"); if (string.IsNullOrEmpty(ouIdText)) throw new InvalidOperationException("Please Select OrganizationUnit"); if (string.IsNullOrEmpty(periodIdText)) throw new InvalidOperationException("Please Select Period"); if (string.IsNullOrEmpty(formType)) throw new InvalidOperationException("Please Select FormType"); if (string.IsNullOrEmpty(periodType)) throw new InvalidOperationException("Please Select PeriodType"); var (fileType, formNumber) = formType switch { "0" => ("SL1", "24Q"), "1" => ("NS1", "26Q"), "2" => ("27Q", "27Q"), "3" => ("27EQ", "27EQ"), _ => throw new InvalidOperationException($"Unrecognized FormType '{formType}'.") }; string mappedPeriodType = periodType switch { "0" => "Q1", "1" => "Q2", "2" => "Q3", "3" => "Q4", _ => throw new InvalidOperationException($"Unrecognized PeriodType '{periodType}'.") }; int ouId = int.Parse(ouIdText); int periodId = int.Parse(periodIdText); var tdsReturnIds = await _etdsDAL .GetTDSReturnIdsForUndo(ouId, periodId, fileType, formNumber, mappedPeriodType, loginDTO) .ConfigureAwait(false); if (tdsReturnIds.Count == 0) throw new InvalidOperationException("No Records Found To UnDo Posting For Given Criteria"); var tx = await _queryExecutor.BeginTransactionAsync(loginDTO).ConfigureAwait(false); try { await _etdsDAL.UndoPostingTDSReturnForm(tdsReturnIds, loginDTO, tx).ConfigureAwait(false); await _queryExecutor.CommitAsync(tx).ConfigureAwait(false); return "Undo Posting Done"; } catch { await _queryExecutor.RollbackAsync(tx).ConfigureAwait(false); throw; } } // Ported from GB4 EtdsDAL.GetTDSReturnForm (TDSCategory.svc's /ETDS/Form24Q123/ operation) — // builds the NSDL/TIN e-TDS quarterly-return flat file (FH/BH/CD/DD/SD/S16/C6A records, // '^'-delimited, "\r\n" terminated) for a single TDSReturnId. GB4 wrote this to local disk; // per explicit direction, GB5 instead returns (FileName, Content) so the SL endpoint can // stream it back as an HTTP download. public async Task<(string FileName, string Content)> GetTDSReturnForm(CriteriaDTO criteriaDTO, LoginDTO loginDTO) { string tdsReturnIdText = ReadCriteria(criteriaDTO, "tdsreturnid"); if (string.IsNullOrEmpty(tdsReturnIdText)) throw new InvalidOperationException("Please Select TDSReturnId"); int tdsReturnId = int.Parse(tdsReturnIdText); var tdsReturn = await _etdsDAL.GetTDSReturn(tdsReturnId, loginDTO).ConfigureAwait(false); if (tdsReturn == null) throw new InvalidOperationException("TDS Return not found for the given TDSReturnId"); var batches = await _etdsDAL.GetTDSReturnBatch(tdsReturnId, loginDTO).ConfigureAwait(false); var challans = await _etdsDAL.GetTDSReturnChallan(tdsReturnId, loginDTO).ConfigureAwait(false); var employees = await _etdsDAL.GetTDSReturnEmployee(tdsReturnId, loginDTO).ConfigureAwait(false); var salaryDetails = await _etdsDAL.GetTDSSalaryDetail(tdsReturnId, loginDTO).ConfigureAwait(false); var section16s = await _etdsDAL.GetTDSSection16(tdsReturnId, loginDTO).ConfigureAwait(false); var section6as = await _etdsDAL.GetTDSSection6A(tdsReturnId, loginDTO).ConfigureAwait(false); tdsReturn.TDSRetrunBatchDTOs = batches; foreach (var batch in batches) { batch.TDSReturnChallanDTOs = challans.Where(c => c.TDSReturnBatchId == batch.TDSReturnBatchId).ToList(); foreach (var challan in batch.TDSReturnChallanDTOs) { challan.TDSReturnEmployeeDTOs = employees.Where(e => e.TDSReturnChallanId == challan.TDSReturnChallanId).ToList(); challan.TDSSalaryDetailDTOs = salaryDetails.Where(s => s.TDSReturnChallanId == challan.TDSReturnChallanId).ToList(); foreach (var salaryDetail in challan.TDSSalaryDetailDTOs) { salaryDetail.TDSSection16DTOs = section16s .Where(s => s.TDSSalaryDetailId == salaryDetail.TDSSalaryDetailId && s.SlNo == salaryDetail.SlNo) .ToList(); salaryDetail.TDSSection6ADTOs = section6as .Where(s => s.TDSSalaryDetailId == salaryDetail.TDSSalaryDetailId && s.SlNo == salaryDetail.SlNo) .ToList(); } } } var sb = new StringBuilder(); int lineNumber = tdsReturn.LineNumber; string fileName = string.Empty; AppendReturn(sb, tdsReturn); foreach (var batch in tdsReturn.TDSRetrunBatchDTOs) { lineNumber++; AppendBatch(sb, lineNumber, batch); fileName = batch.FormNumber + "R" + batch.Period + ".txt"; foreach (var challan in batch.TDSReturnChallanDTOs) { lineNumber++; AppendChallan(sb, lineNumber, challan, batch.FormNumber, batch.Period); foreach (var employee in challan.TDSReturnEmployeeDTOs) { lineNumber++; AppendEmployee(sb, lineNumber, employee, batch.FormNumber); } foreach (var salaryDetail in challan.TDSSalaryDetailDTOs) { lineNumber++; AppendSalaryDetail(sb, lineNumber, salaryDetail); foreach (var section16 in salaryDetail.TDSSection16DTOs) { lineNumber++; AppendSection16(sb, lineNumber, section16); } foreach (var section6a in salaryDetail.TDSSection6ADTOs) { lineNumber++; AppendSection6A(sb, lineNumber, section6a); } } } } return (fileName, sb.ToString()); } private static void AppendReturn(StringBuilder sb, TDSReturnDTO tdsReturn) { sb.Append(tdsReturn.LineNumber).Append('^') .Append(tdsReturn.RecordType).Append('^') .Append(tdsReturn.FileType).Append('^') .Append(tdsReturn.UploadType).Append('^') .Append(tdsReturn.FileCreationDate).Append('^') .Append(tdsReturn.FileSequenceNumber).Append('^') .Append(tdsReturn.UploaderType).Append('^') .Append(tdsReturn.TAN).Append('^') .Append(tdsReturn.TotalBatches).Append('^') .Append(tdsReturn.SoftwareName).Append("^^^^^^^^\r\n"); } private static void AppendBatch(StringBuilder sb, int lineNumber, TDSRetrunBatchDTO batch) { sb.Append(lineNumber).Append('^') .Append(batch.RecordType).Append('^') .Append(batch.BatchNumber).Append('^') .Append(batch.NumberOfChallan).Append('^') .Append(batch.FormNumber).Append('^') .Append(batch.TransactionType).Append('^') .Append(batch.BatchUpdation).Append('^') .Append(batch.OriginalToken).Append('^') .Append(batch.PreviousTokenNumber).Append('^') .Append(batch.TokenNumber).Append('^') .Append(batch.TokenNumberDate).Append('^') .Append(batch.EmployerLastTAN).Append('^') .Append(batch.EmployerTAN).Append('^') .Append(batch.TIN).Append('^') .Append(batch.EmployerPAN).Append('^') .Append(batch.AssesmentYear).Append('^') .Append(batch.FinancialYear).Append('^') .Append(batch.Period).Append('^') .Append(batch.EmployerName).Append('^') .Append(batch.EmployerBranch).Append('^') .Append(batch.EmployerAddress1).Append('^') .Append(batch.EmployerAddress2).Append('^') .Append(batch.EmployerAddress3).Append('^') .Append(batch.EmployerAddress4).Append('^') .Append(batch.EmployerAddress5).Append('^') .Append(batch.EmployerState).Append('^') .Append(batch.EmployerPinCode).Append('^') .Append(batch.EmployerEmail).Append('^') .Append(batch.EmployerSTDCode).Append('^') .Append(batch.EmployerPhone).Append('^') .Append(batch.IsAddressChanged).Append('^') .Append(batch.DeductorType).Append('^') .Append(batch.ResponsiblePersonName).Append('^') .Append(batch.PersonDesignation).Append('^') .Append(batch.PersonAddress1).Append('^') .Append(batch.PersonAddress2).Append('^') .Append(batch.PersonAddress3).Append('^') .Append(batch.PersonAddress4).Append('^') .Append(batch.PersonAddress5).Append('^') .Append(batch.PersonState).Append('^') .Append(batch.PersonPinCode).Append('^') .Append(batch.PersonEmail).Append('^') .Append(batch.PersonMobile).Append('^') .Append(batch.PersonSTDCode).Append('^') .Append(batch.PersonPhone).Append('^') .Append(batch.IsPersonAddressChanged).Append('^') .Append(batch.TotalDepositAmount).Append('^') .Append(batch.NumberOfUnmatchedChallan ?? string.Empty).Append('^') .Append(batch.CountOfSalaryRecords ?? (batch.FormNumber == "24Q" ? "0" : string.Empty)).Append('^') .Append(batch.TotalGrossIncome ?? string.Empty).Append('^') .Append(batch.AOApproval).Append('^') .Append(batch.IsPreviousPeriodField).Append('^') .Append(batch.PreviousDeductorType).Append('^') .Append(batch.StateName).Append('^') .Append(batch.PAOCode).Append('^') .Append(batch.DDOCode).Append('^') .Append(batch.MinistryName).Append('^') .Append(batch.MinistryNameOther).Append('^') .Append(batch.PersonPAN).Append('^') .Append(batch.PAORegistrationNumber).Append('^') .Append(batch.DDORegistrationNumber).Append('^') .Append(batch.EmployerAlternateSTDCode).Append('^') .Append(batch.EmployerAlternatePhone).Append('^') .Append(batch.EmployerAlternateEmail).Append('^') .Append(batch.PersonAlternateSTDCode).Append('^') .Append(batch.PersonAlternatePhone).Append('^') .Append(batch.PersonAlternateEmail).Append('^') .Append(batch.AIN).Append('^') .Append(batch.GSTIN).Append("^\r\n"); } private static void AppendChallan(StringBuilder sb, int lineNumber, TDSReturnChallanDTO challan, string batchFormNumber, string batchPeriod) { sb.Append(lineNumber).Append('^') .Append(challan.RecordType).Append('^') .Append(challan.BatchNumber).Append('^') .Append(challan.ChallanDetailRecordNumber).Append('^') .Append(challan.CountOfDeductee).Append('^') .Append(challan.IsNullChallan).Append('^') .Append(challan.ChallanUpdationIndicator).Append('^') .Append(challan.Filler2).Append('^') .Append(challan.Filler3).Append('^') .Append(challan.Filler4).Append('^') .Append(challan.LastChallanSlNo ?? string.Empty).Append('^') .Append(challan.ChallanSlNo).Append('^') .Append(challan.LastDDOSlNo).Append('^') .Append(challan.DDOSlNo ?? string.Empty).Append('^') .Append(challan.LastBankBranchCode).Append('^') .Append(challan.BankBranchCode).Append('^') .Append(challan.LastDateOfBankChallan).Append('^') .Append(challan.DataOfBankChallan).Append('^') .Append(challan.Filler5).Append('^') .Append(challan.Filler6).Append('^') .Append(challan.Section).Append('^') .Append(challan.ItAmount).Append('^') .Append(challan.SCAmount).Append('^') .Append(challan.CessAmount).Append('^') .Append(challan.InterestAmount).Append('^') .Append(challan.OtherAmount).Append('^') .Append(challan.TotalAmount).Append('^') .Append(challan.LastTotalAmount).Append('^') .Append(challan.AnnexureDeposit).Append('^') .Append(challan.AnnexureIt).Append('^') .Append(challan.AnnexureSC).Append('^') .Append(challan.AnnexureCess).Append('^') .Append(challan.AnnexureTotal).Append('^') .Append(challan.AnnexureIntrest).Append('^') .Append(challan.AnnexureOthers).Append('^') .Append(challan.ChequeNumber).Append('^') .Append(challan.IsBookOrCash).Append('^') .Append(challan.Remarks).Append('^') .Append(challan.FeeAmount ?? string.Empty).Append('^'); string minOrChallanHead = challan.MinOrChallanHead ?? string.Empty; if (batchFormNumber == "24Q" && batchPeriod != "Q4") sb.Append(minOrChallanHead).Append("^^\r\n"); else sb.Append(minOrChallanHead).Append("^\r\n"); } private static void AppendEmployee(StringBuilder sb, int lineNumber, TDSReturnEmployeeDTO employee, string batchFormNumber) { string lastTotalDeposited = string.IsNullOrEmpty(employee.LastTotalDeposited) ? (batchFormNumber == "27EQ" ? "0.00" : string.Empty) : employee.LastTotalDeposited; string dateDeposit = employee.DateDeposit == "01011900" ? string.Empty : employee.DateDeposit; sb.Append(lineNumber).Append('^') .Append(employee.RecordType).Append('^') .Append(employee.BatchNumber).Append('^') .Append(employee.ChallenDetailRecordNumber).Append('^') .Append(employee.DetailSlNo).Append('^') .Append(employee.Mode).Append('^') .Append(employee.EmployeeCode ?? string.Empty).Append('^') .Append(employee.Deductee ?? string.Empty).Append('^') .Append(employee.LastEmployeePAN).Append('^') .Append(employee.EmployeePAN).Append('^') .Append(employee.LastEmployeePANRefNo).Append('^') .Append(employee.EmployeePANRefNo).Append('^') .Append(employee.EmployeeName).Append('^') .Append(employee.IncomeTax).Append('^') .Append(employee.Surcharge).Append('^') .Append(employee.CESS).Append('^') .Append(employee.Total).Append('^') .Append(employee.LastTotal).Append('^') .Append(employee.TotalDeposited).Append('^') .Append(employee.TotalPurchase).Append('^') .Append(lastTotalDeposited).Append('^') .Append(employee.AmountPaid).Append('^') .Append(employee.DatePayCredit).Append('^') .Append(employee.DateDeduct).Append('^') .Append(dateDeposit).Append('^') .Append(employee.RateTaxDeducted ?? string.Empty).Append('^') .Append(employee.GrossingUpIndicator).Append('^') .Append(employee.BookOrCashIndicator).Append('^') .Append(employee.FurnishingDate).Append('^') .Append(employee.Remarks1 ?? string.Empty).Append('^') .Append(employee.Remarks2 ?? string.Empty).Append('^') .Append(employee.Remarks3 ?? string.Empty).Append('^') .Append(employee.Section).Append('^') .Append(employee.CertificateNumber).Append("^^^^^^^^^\r\n"); } private static void AppendSalaryDetail(StringBuilder sb, int lineNumber, TDSSalaryDetailDTO salaryDetail) { string contributionFromDate = salaryDetail.ContributionFromDate == "01011900" ? string.Empty : salaryDetail.ContributionFromDate; string contributionToDate = salaryDetail.ContributionToDate == "01011900" ? string.Empty : salaryDetail.ContributionToDate; sb.Append(lineNumber).Append('^') .Append(salaryDetail.RecordType).Append('^') .Append(salaryDetail.BatchNumber).Append('^') .Append(salaryDetail.SlNo).Append('^') .Append(salaryDetail.Mode).Append('^') .Append(salaryDetail.Filter7).Append('^') .Append(salaryDetail.EPan).Append('^') .Append(salaryDetail.EPanRefNumber).Append('^') .Append(salaryDetail.EName).Append('^') .Append(salaryDetail.ECategory).Append('^') .Append(salaryDetail.EmploymentFrom).Append('^') .Append(salaryDetail.EmploymentTo).Append('^') .Append(salaryDetail.TotalSalary).Append('^') .Append(salaryDetail.Filter8).Append('^') .Append(salaryDetail.CountOfSalaryDetail).Append('^') .Append(salaryDetail.TotalDeduction).Append('^') .Append(salaryDetail.SalaryIncome).Append('^') .Append(salaryDetail.OtherInCome).Append('^') .Append(salaryDetail.GrossTotalIncome).Append('^') .Append(salaryDetail.LastGrossTotalIncome).Append('^') .Append(salaryDetail.CountOf6ADetail).Append('^') .Append(salaryDetail.GrossTotalDeduction6A).Append('^') .Append(salaryDetail.TotalTaxableIncome).Append('^') .Append(salaryDetail.TotalIT).Append('^') .Append(salaryDetail.TotalSC).Append('^') .Append(salaryDetail.TotalCess).Append('^') .Append(salaryDetail.ITRelief).Append('^') .Append(salaryDetail.NetItPayable).Append('^') .Append(salaryDetail.TotalTDS).Append('^') .Append(salaryDetail.ShortOrExcess).Append('^') .Append(salaryDetail.TotalDeduction80).Append('^') .Append(salaryDetail.Remarks1).Append('^') .Append(salaryDetail.Remarks2).Append('^') .Append(salaryDetail.CurrentTaxable).Append('^') .Append(salaryDetail.PreviousTaxable).Append('^') .Append(salaryDetail.CurrentTotalTDS).Append('^') .Append(salaryDetail.PreviouTotalTDS).Append('^') .Append(salaryDetail.IsHigherRate).Append('^') .Append(salaryDetail.IsRentAbove).Append('^') .Append(salaryDetail.CountOfLandLoardPan).Append('^') .Append(salaryDetail.LL1Pan).Append('^') .Append(salaryDetail.LL1Name).Append('^') .Append(salaryDetail.LL2Pan).Append('^') .Append(salaryDetail.LL2Name).Append('^') .Append(salaryDetail.LL3Pan).Append('^') .Append(salaryDetail.LL3Name).Append('^') .Append(salaryDetail.LL4Pan).Append('^') .Append(salaryDetail.LL4Name).Append('^') .Append(salaryDetail.IsInterestPaid).Append('^') .Append(salaryDetail.CountOfLenderPan).Append('^') .Append(salaryDetail.Lender1Pan).Append('^') .Append(salaryDetail.Lender1Name).Append('^') .Append(salaryDetail.Lender2Pan).Append('^') .Append(salaryDetail.Lender2Name).Append('^') .Append(salaryDetail.Lender3Pan).Append('^') .Append(salaryDetail.Lender3Name).Append('^') .Append(salaryDetail.Lender4Pan).Append('^') .Append(salaryDetail.Lender4Name).Append('^') .Append(salaryDetail.IsSuperAnnuationByTrustees).Append('^') .Append(salaryDetail.FundName).Append('^') .Append(contributionFromDate).Append('^') .Append(contributionToDate).Append('^') .Append(salaryDetail.ContributionAmountRepaid).Append('^') .Append(salaryDetail.AvgRateOfTaxDeduction).Append('^') .Append(salaryDetail.SuperAnnuationTDS).Append('^') .Append(salaryDetail.GrossTotalOfSuperAnnuationFund).Append('^') .Append(salaryDetail.GrossSalary).Append('^') .Append(salaryDetail.PerQuisites).Append('^') .Append(salaryDetail.ProfitInLieu).Append('^') .Append(salaryDetail.Travel).Append('^') .Append(salaryDetail.Gratuity).Append('^') .Append(salaryDetail.CommutedPension).Append('^') .Append(salaryDetail.LeaveSalary).Append('^') .Append(salaryDetail.HRA).Append('^') .Append(salaryDetail.OtherExemption).Append('^') .Append(salaryDetail.TotalException).Append('^') .Append(salaryDetail.IncodeFromOtherSource).Append('^') .Append(salaryDetail.Rebate).Append("^\r\n"); } private static void AppendSection16(StringBuilder sb, int lineNumber, TDSSection16DTO section16) { sb.Append(lineNumber).Append('^') .Append(section16.RecordType).Append('^') .Append(section16.BatchNumber).Append('^') .Append(section16.SlNo).Append('^') .Append(section16.Section16SlNo).Append('^') .Append(section16.SectionId).Append('^') .Append(section16.TotalDeduction).Append("^\r\n"); } private static void AppendSection6A(StringBuilder sb, int lineNumber, TDSSection6ADTO section6a) { sb.Append(lineNumber).Append('^') .Append(section6a.RecordType).Append('^') .Append(section6a.BatchNumber).Append('^') .Append(section6a.SlNo).Append('^') .Append(section6a.Section6ASlNo).Append('^') .Append(section6a.Section6AId).Append('^') .Append(section6a.TotalAmount).Append("^\r\n"); } private static string ReadCriteria(CriteriaDTO criteriaDTO, string fieldName) { if (criteriaDTO?.SectionCriteriaList == null) return string.Empty; foreach (var section in criteriaDTO.SectionCriteriaList) { if (section?.AttributesCriteriaList == null) continue; foreach (var attr in section.AttributesCriteriaList) { if (!string.Equals(attr.FieldName, fieldName, StringComparison.OrdinalIgnoreCase)) continue; return attr.FieldValue?.ToString() ?? string.Empty; } } return string.Empty; } } }