Distribution_GL Initialization
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
using General_Ledger_Service.DTOs.Reports;
|
||||
|
||||
namespace General_Ledger_Service.Services.CsvDocuments
|
||||
{
|
||||
// Retrofit 2026-07-31 - Section column carries the classified section name (Non-Current
|
||||
// Assets, Current Assets, Equity, Non-Current/Current Liabilities, Unclassified) rather than
|
||||
// the old AccountType/depth-indentation pair (05_LKAS_Report_PDF_Templates.md Section 10).
|
||||
public static class BalanceSheetCsvDocument
|
||||
{
|
||||
public static byte[] Generate(BalanceSheetReportDto data)
|
||||
{
|
||||
var csv = new CsvBuilder();
|
||||
csv.AddRow("Section", "Account Code", "Account Name", "Balance");
|
||||
|
||||
void WriteSection(string section, BalanceSheetSectionDto s)
|
||||
{
|
||||
foreach (var line in s.Lines)
|
||||
{
|
||||
csv.AddRow(section, line.AccountCode, line.AccountName, line.Balance);
|
||||
}
|
||||
}
|
||||
|
||||
WriteSection("Non-Current Assets", data.NonCurrentAssets);
|
||||
WriteSection("Current Assets", data.CurrentAssets);
|
||||
WriteSection("Unclassified Assets", data.UnclassifiedAssets);
|
||||
csv.AddRow("Asset", "", "TOTAL ASSETS", data.TotalAssets);
|
||||
|
||||
WriteSection("Equity", data.Equity);
|
||||
WriteSection("Non-Current Liabilities", data.NonCurrentLiabilities);
|
||||
WriteSection("Current Liabilities", data.CurrentLiabilities);
|
||||
WriteSection("Unclassified Liabilities", data.UnclassifiedLiabilities);
|
||||
csv.AddRow("Liability/Equity", "", "TOTAL EQUITY AND LIABILITIES", data.TotalEquityAndLiabilities);
|
||||
|
||||
return csv.Build();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using General_Ledger_Service.DTOs.Reports;
|
||||
|
||||
namespace General_Ledger_Service.Services.CsvDocuments
|
||||
{
|
||||
public static class BudgetVsActualCsvDocument
|
||||
{
|
||||
public static byte[] Generate(List<BudgetVsActualRowDto> rows)
|
||||
{
|
||||
var csv = new CsvBuilder();
|
||||
csv.AddRow("Account Code", "Account Name", "Period Id", "Budgeted", "Actual", "Variance");
|
||||
|
||||
foreach (var row in rows)
|
||||
{
|
||||
csv.AddRow(row.AccountCode, row.AccountName, row.PeriodId, row.BudgetedAmount, row.ActualAmount, row.Variance);
|
||||
}
|
||||
|
||||
csv.AddRow("", "TOTAL", "", rows.Sum(r => r.BudgetedAmount), rows.Sum(r => r.ActualAmount), rows.Sum(r => r.Variance));
|
||||
return csv.Build();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using General_Ledger_Service.DTOs.Reports;
|
||||
|
||||
namespace General_Ledger_Service.Services.CsvDocuments
|
||||
{
|
||||
// Same simplification as Services/PdfDocuments/CashFlowPdfDocument - no printed opening/closing
|
||||
// balance row (still in the outputFormat=Json response for the reconciliation check); non-cash
|
||||
// adjustments and working-capital changes combined and re-bucketed by sign.
|
||||
public static class CashFlowCsvDocument
|
||||
{
|
||||
public static byte[] Generate(CashFlowReportDto data)
|
||||
{
|
||||
var operating = data.OperatingActivities;
|
||||
var operatingProfitBeforeWorkingCapital = operating.ProfitForPeriod + operating.NonCashAdjustments.Sum(a => a.Amount);
|
||||
|
||||
var movements = operating.NonCashAdjustments
|
||||
.Select(a => (Description: a.Description, Amount: a.Amount))
|
||||
.Concat(operating.WorkingCapitalChanges.Select(c => (Description: $"{c.Direction} in {c.AccountName}", Amount: c.ChangeAmount)))
|
||||
.ToList();
|
||||
|
||||
var csv = new CsvBuilder();
|
||||
csv.AddRow("Category", "Description", "Amount");
|
||||
|
||||
csv.AddRow("Operating", "Profit for the period", operating.ProfitForPeriod);
|
||||
csv.AddRow("Operating", "Operating profit before working capital changes", operatingProfitBeforeWorkingCapital);
|
||||
|
||||
foreach (var line in movements.Where(m => m.Amount > 0))
|
||||
{
|
||||
csv.AddRow("Operating - Additions to Cash", line.Description, line.Amount);
|
||||
}
|
||||
|
||||
foreach (var line in movements.Where(m => m.Amount <= 0))
|
||||
{
|
||||
csv.AddRow("Operating - Subtractions From Cash", line.Description, line.Amount);
|
||||
}
|
||||
|
||||
csv.AddRow("Operating", "Net Cash from Operating Activities", operating.NetCashFromOperatingActivities);
|
||||
|
||||
foreach (var line in data.InvestingActivities.Lines)
|
||||
{
|
||||
csv.AddRow("Investing", line.AccountName, line.Amount);
|
||||
}
|
||||
csv.AddRow("Investing", "Net Cash from/(used in) Investing Activities", data.InvestingActivities.NetCashFromInvestingActivities);
|
||||
|
||||
foreach (var line in data.FinancingActivities.Lines)
|
||||
{
|
||||
csv.AddRow("Financing", line.AccountName, line.Amount);
|
||||
}
|
||||
csv.AddRow("Financing", "Net Cash from/(used in) Financing Activities", data.FinancingActivities.NetCashFromFinancingActivities);
|
||||
|
||||
csv.AddRow("", "Net Increase/(Decrease) in Cash and Cash Equivalents", data.NetIncreaseDecreaseInCash);
|
||||
return csv.Build();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace General_Ledger_Service.Services.CsvDocuments
|
||||
{
|
||||
// Shared row-building/escaping helper for every report's CSV writer (05_LKAS_Report_PDF_Templates.md
|
||||
// Section 10) - parallel to Services/PdfDocuments/ReportPageHeader.cs, one small shared piece
|
||||
// reused by seven otherwise-independent writer classes, not a base class (CLAUDE.md Rule 2).
|
||||
public class CsvBuilder
|
||||
{
|
||||
private readonly StringBuilder _sb = new();
|
||||
|
||||
public CsvBuilder AddRow(params object?[] values)
|
||||
{
|
||||
_sb.AppendLine(string.Join(",", values.Select(Escape)));
|
||||
return this;
|
||||
}
|
||||
|
||||
public byte[] Build()
|
||||
{
|
||||
// UTF-8 BOM so Excel (the realistic consumer of a downloaded .csv) recognizes the
|
||||
// encoding instead of guessing at a locale-default codepage.
|
||||
var preamble = Encoding.UTF8.GetPreamble();
|
||||
var body = Encoding.UTF8.GetBytes(_sb.ToString());
|
||||
var result = new byte[preamble.Length + body.Length];
|
||||
preamble.CopyTo(result, 0);
|
||||
body.CopyTo(result, preamble.Length);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string Escape(object? value)
|
||||
{
|
||||
var text = value switch
|
||||
{
|
||||
null => "",
|
||||
decimal d => d.ToString(CultureInfo.InvariantCulture),
|
||||
DateOnly d => d.ToString("yyyy-MM-dd"),
|
||||
_ => value.ToString() ?? ""
|
||||
};
|
||||
|
||||
return text.Contains(',') || text.Contains('"') || text.Contains('\n')
|
||||
? $"\"{text.Replace("\"", "\"\"")}\""
|
||||
: text;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using General_Ledger_Service.DTOs.Reports;
|
||||
|
||||
namespace General_Ledger_Service.Services.CsvDocuments
|
||||
{
|
||||
public static class GeneralLedgerCsvDocument
|
||||
{
|
||||
public static byte[] Generate(List<GeneralLedgerLineDto> rows)
|
||||
{
|
||||
var csv = new CsvBuilder();
|
||||
csv.AddRow("Account Code", "Account Name", "Date", "Particulars", "J.R. (Journal No.)", "Debit", "Credit", "Balance");
|
||||
|
||||
foreach (var row in rows)
|
||||
{
|
||||
csv.AddRow(
|
||||
row.AccountCode, row.AccountName, row.EntryDate, row.Narration, row.JournalNo,
|
||||
row.DebitAmount == 0 ? null : row.DebitAmount,
|
||||
row.CreditAmount == 0 ? null : row.CreditAmount,
|
||||
row.RunningBalance);
|
||||
}
|
||||
|
||||
return csv.Build();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using General_Ledger_Service.DTOs.Reports;
|
||||
|
||||
namespace General_Ledger_Service.Services.CsvDocuments
|
||||
{
|
||||
public static class IncomeTaxComputationCsvDocument
|
||||
{
|
||||
public static byte[] Generate(IncomeTaxComputationDto data)
|
||||
{
|
||||
var csv = new CsvBuilder();
|
||||
csv.AddRow("Line", "Amount");
|
||||
|
||||
csv.AddRow("Profit Before Tax", data.ProfitBeforeTax);
|
||||
csv.AddRow("Add: Non-Deductible Expenses", data.NonDeductibleExpenses);
|
||||
csv.AddRow("Less: Allowable Deductions", -data.AllowableDeductions);
|
||||
csv.AddRow("Adjusted Business Profit", data.AdjustedBusinessProfit);
|
||||
csv.AddRow("Add: Other Taxable Income", data.OtherTaxableIncome);
|
||||
csv.AddRow("Assessable Income", data.AssessableIncome);
|
||||
csv.AddRow("Less: Qualifying Payments / Reliefs", -data.QualifyingPaymentsReliefs);
|
||||
csv.AddRow("Taxable Income", data.TaxableIncome);
|
||||
csv.AddRow($"Corporate Income Tax @ {data.TaxRatePercent:0.00}%", data.CorporateIncomeTax);
|
||||
csv.AddRow("Add: Surcharge / Education Levy", data.SurchargeAmount);
|
||||
csv.AddRow("Gross Tax Liability", data.GrossTaxLiability);
|
||||
csv.AddRow("Less: APIT Credit", -data.ApitCredit);
|
||||
csv.AddRow("Less: WHT Credit", -data.WhtCredit);
|
||||
csv.AddRow("Less: Quarterly Tax Payments", -data.QuarterlyTaxPayments);
|
||||
csv.AddRow(data.BalanceTaxPayable < 0 ? "BALANCE TAX REFUNDABLE" : "BALANCE TAX PAYABLE", data.BalanceTaxPayable);
|
||||
|
||||
return csv.Build();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using General_Ledger_Service.DTOs.Reports;
|
||||
|
||||
namespace General_Ledger_Service.Services.CsvDocuments
|
||||
{
|
||||
public static class ProfitAndLossCsvDocument
|
||||
{
|
||||
public static byte[] Generate(ProfitAndLossReportDto data)
|
||||
{
|
||||
var csv = new CsvBuilder();
|
||||
csv.AddRow("Section", "Account Code", "Account Name", "Amount");
|
||||
|
||||
AddSection(csv, "Sales", data.Sales);
|
||||
AddSection(csv, "Cost of Sales", data.CostOfSales);
|
||||
csv.AddRow("", "", "GROSS PROFIT", data.GrossProfit);
|
||||
|
||||
AddSection(csv, "Other Income", data.OtherIncome);
|
||||
AddSection(csv, "Distribution Expenses", data.DistributionExpenses);
|
||||
AddSection(csv, "Administration Expenses", data.AdministrationExpenses);
|
||||
AddSection(csv, "Other Expenses", data.OtherExpenses);
|
||||
AddSection(csv, "Financial Expenses", data.FinancialExpenses);
|
||||
|
||||
if (data.Unclassified.Lines.Count > 0)
|
||||
{
|
||||
AddSection(csv, "Unclassified", data.Unclassified);
|
||||
}
|
||||
|
||||
csv.AddRow("", "", "NET PROFIT FOR THE PERIOD", data.NetProfitForPeriod);
|
||||
return csv.Build();
|
||||
}
|
||||
|
||||
private static void AddSection(CsvBuilder csv, string section, ProfitAndLossSectionDto sectionDto)
|
||||
{
|
||||
foreach (var line in sectionDto.Lines)
|
||||
{
|
||||
csv.AddRow(section, line.AccountCode, line.AccountName, line.Amount);
|
||||
}
|
||||
|
||||
csv.AddRow(section, "", $"Total {section}", sectionDto.Total);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using General_Ledger_Service.DTOs.Reports;
|
||||
|
||||
namespace General_Ledger_Service.Services.CsvDocuments
|
||||
{
|
||||
public static class TrialBalanceCsvDocument
|
||||
{
|
||||
public static byte[] Generate(List<TrialBalanceRowDto> rows)
|
||||
{
|
||||
var csv = new CsvBuilder();
|
||||
csv.AddRow("Account Code", "Account Name", "Debit", "Credit");
|
||||
|
||||
foreach (var row in rows)
|
||||
{
|
||||
csv.AddRow(row.AccountCode, row.AccountName, row.Debit == 0 ? null : row.Debit, row.Credit == 0 ? null : row.Credit);
|
||||
}
|
||||
|
||||
csv.AddRow("TOTAL", "", rows.Sum(r => r.Debit), rows.Sum(r => r.Credit));
|
||||
return csv.Build();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user