diff --git a/ReportImp/CaritasVerbandDuerenJuelichEvBeWo/Export/DiamantExporter.cs b/ReportImp/CaritasVerbandDuerenJuelichEvBeWo/Export/DiamantExporter.cs index 3fabd1dcb..5164176c8 100644 --- a/ReportImp/CaritasVerbandDuerenJuelichEvBeWo/Export/DiamantExporter.cs +++ b/ReportImp/CaritasVerbandDuerenJuelichEvBeWo/Export/DiamantExporter.cs @@ -49,10 +49,12 @@ namespace CaritasverbandDuerenJuelichEV.Export else { query.FileName = String.Format("005F{0:yyyyMM}.er2", dt); + var dtMonatlich = ExecuteQuery(GetMonatlicheAbrechnungSql(), dt); + var dtSpitz = ExecuteQuery(GetSpitzabrechnungSql(), dt); var dtAbgrenzungen = ExecuteQuery(GetAbgrenzungsLvrLwlSql(), dt); Dictionary oid2InvoiceNumbers; - query.QueryResult = GetAbrechnungenString(dt, customerOid, dtAbgrenzungen, out oid2InvoiceNumbers); - query.Attachments = CreateAttachmentFile(dt, dtAbgrenzungen, oid2InvoiceNumbers); + query.QueryResult = GetAbrechnungenString(dt, customerOid, dtMonatlich, dtSpitz, dtAbgrenzungen, out oid2InvoiceNumbers); + query.Attachments = CreateAttachmentFile(dt, dtMonatlich, dtSpitz, dtAbgrenzungen, oid2InvoiceNumbers); } } @@ -158,22 +160,22 @@ namespace CaritasverbandDuerenJuelichEV.Export public static String GetAbrechnungenString(DateTime date, long? customerOid, DataTable dtAbgrenzungen = null) { Dictionary _; - return GetAbrechnungenString(date, customerOid, dtAbgrenzungen, out _); + return GetAbrechnungenString(date, customerOid, null, null, dtAbgrenzungen, out _); } - public static String GetAbrechnungenString(DateTime date, long? customerOid, DataTable dtAbgrenzungen, out Dictionary oid2InvoiceNumbers) + public static String GetAbrechnungenString(DateTime date, long? customerOid, DataTable dtMonatlich, DataTable dtSpitz, DataTable dtAbgrenzungen, out Dictionary oid2InvoiceNumbers) { StringBuilder sb = new StringBuilder(); // 1. Monatliche Abrechnungen - var s = GetMonatlicheAbrechnungString(date, customerOid); + var s = GetMonatlicheAbrechnungString(date, customerOid, dtMonatlich); if (!String.IsNullOrWhiteSpace(s)) { sb.Append(s); } // 2. Spitzabrechnungen - s = GetSpitzabrechnungString(date, customerOid); + s = GetSpitzabrechnungString(date, customerOid, dtSpitz); if (!String.IsNullOrWhiteSpace(s)) { if (sb.Length > 0) @@ -182,7 +184,7 @@ namespace CaritasverbandDuerenJuelichEV.Export } // 3. Abgrenzungsbuchungen LVR/LWL - // DataTable wird von außen übergeben (aus CreateQuery), um doppelte SQL-Ausführung zu vermeiden. + // DataTables werden von außen übergeben (aus CreateQuery), um doppelte SQL-Ausführung zu vermeiden. // Falls nicht übergeben (z.B. aus CreateExportString), wird die SQL hier ausgeführt. var abgrenzungenTable = dtAbgrenzungen ?? ExecuteQuery(GetAbgrenzungsLvrLwlSql(), date); s = GetAbgrenzungsString(abgrenzungenTable, out oid2InvoiceNumbers); @@ -199,19 +201,19 @@ namespace CaritasverbandDuerenJuelichEV.Export return sb.ToString(); } - public static String GetMonatlicheAbrechnungString(DateTime date, long? customerOid) + public static String GetMonatlicheAbrechnungString(DateTime date, long? customerOid, DataTable dtMonatlich = null) { // Export enthält Rechnungsangaben Zeilen (Zeile F) und Kostenstellen/Rechnungspositionsangaben (Zeile K) in zwei Zeilen // Kommen aus Export in einer Zeile und werden hier getrennt, aber nur falls die Rechnung mehrere Positionen hat // Systemrechnungsnummern (ib.InvoiceNumber) werden direkt verwendet, kein Generator - var dt = ExecuteQuery(GetMonatlicheAbrechnungSql(), date); + var dt = dtMonatlich ?? ExecuteQuery(GetMonatlicheAbrechnungSql(), date); return BuildDiamantLines(dt, null); } - public static String GetSpitzabrechnungString(DateTime date, long? customerOid) + public static String GetSpitzabrechnungString(DateTime date, long? customerOid, DataTable dtSpitz = null) { // Systemrechnungsnummern (ib.InvoiceNumber) werden direkt verwendet, kein Generator - var dt = ExecuteQuery(GetSpitzabrechnungSql(), date); + var dt = dtSpitz ?? ExecuteQuery(GetSpitzabrechnungSql(), date); return BuildDiamantLines(dt, null); } @@ -559,49 +561,36 @@ ORDER BY stunden.LastName, stunden.FirstName return sql; } - private static List CreateAttachmentFile(DateTime date, DataTable dtAbgrenzungen, Dictionary oid2GeneratedNumber) + private static List CreateAttachmentFile(DateTime date, DataTable dtMonatlich, DataTable dtSpitz, DataTable dtAbgrenzungen, Dictionary oid2GeneratedNumber) { try { - // Spalten aus der bereits ausgeführten Abgrenzungs-DataTable verwenden: - // 0 = OID, 11 = DebitorNumber, 12 = 'Abgrenzung OrgName', 15 = Betrag, 16 = 'Abgr. Nachname, Vorname' - DataTable table = new DataTable(); - string[] spalten = { "Rechnungsnr.", "Empfänger", "Debitornr.", "Erlöskonto", "Kostenstelle", "Verwendung", "Betrag" }; - foreach (var spalte in spalten) - table.Columns.Add(spalte, typeof(string)); + // Block 1: Rechnungen (monatliche Abrechnungen + Spitzabrechnungen) mit Zwischensumme + decimal summeRechnungen = 0; + DataTable tableRechnungen = CreateBelegTable(); + summeRechnungen += AddBelegRows(tableRechnungen, dtMonatlich, null, null, "Re. "); + summeRechnungen += AddBelegRows(tableRechnungen, dtSpitz, null, null, "Re. "); + AddSummenRow(tableRechnungen, "Summe Rechnungen", summeRechnungen); - foreach (DataRow booking in dtAbgrenzungen.Rows) - { - string oid = booking[0].ToString(); - string invoiceNumber = String.Empty; - if (oid2GeneratedNumber != null && oid2GeneratedNumber.ContainsKey(oid)) - invoiceNumber = oid2GeneratedNumber[oid]; + // Block 2 (nach Seitenumbruch): Abgrenzungsbuchungen mit Zwischensumme und Gesamtsumme + decimal summeAbgrenzungen = 0; + DataTable tableAbgrenzungen = CreateBelegTable(); + summeAbgrenzungen += AddBelegRows(tableAbgrenzungen, dtAbgrenzungen, oid2GeneratedNumber, "Abgrenzung ", "Abgr. "); + AddSummenRow(tableAbgrenzungen, "Summe Abgrenzungen", summeAbgrenzungen); + AddSummenRow(tableAbgrenzungen, "Gesamtsumme", summeRechnungen + summeAbgrenzungen); - string erloeskonto = SetKonto(booking[12]); + var reportRechnungen = CreateBelegReport(String.Format("Buchungsbeleg {0:MMMM yyyy} - Rechnungen", date), tableRechnungen); + var reportAbgrenzungen = CreateBelegReport(String.Format("Buchungsbeleg {0:MMMM yyyy} - Abgrenzungsbuchungen", date), tableAbgrenzungen); - DataRow row = table.NewRow(); - row[0] = invoiceNumber; - row[1] = booking[12].ToString().Replace("Abgrenzung ", ""); - row[2] = booking[11]; - row[3] = erloeskonto; - row[4] = booking[36]; // c.CostCenter - row[5] = booking[16].ToString().Replace("Abgr. ", ""); - row[6] = String.Format("{0:0.00}", booking[15]); - table.Rows.Add(row); - } - - var queryReportObject = QueryRO.Create(new Query() { Title = "Export" }, table); - queryReportObject.Name = String.Format("Abgrenzungsbuchungen {0:MMMM yyyy}", date); - - var queryReport = new Bericht(); - queryReport.SetReportDataSource(queryReportObject); - queryReport.CreateDocument(); + // Beide Berichte zu einem PDF zusammenführen → Abgrenzungen beginnen auf neuer Seite + reportRechnungen.Pages.AddRange(reportAbgrenzungen.Pages); + reportRechnungen.PrintingSystem.ContinuousPageNumbering = true; var pdf = new FileAttachmentDC(); - pdf.FileName = String.Format("Abgrenzungsbuchungen{0:MMyyyy}.pdf", date); + pdf.FileName = String.Format("Buchungsbeleg{0:MMyyyy}.pdf", date); using (var ms = new MemoryStream()) { - queryReport.ExportToPdf(ms); + reportRechnungen.ExportToPdf(ms); pdf.BinaryData = ms.ToArray(); } @@ -613,6 +602,87 @@ ORDER BY stunden.LastName, stunden.FirstName } } + private static DataTable CreateBelegTable() + { + DataTable table = new DataTable(); + string[] spalten = { "Rechnungsnr.", "Empfänger", "Debitornr.", "Erlöskonto", "Kostenstelle", "Verwendung", "Betrag" }; + foreach (var spalte in spalten) + { + table.Columns.Add(spalte, typeof(string)); + } + return table; + } + + // Spaltenpositionen sind in allen drei Buchungs-DataTables identisch: + // 0 = OID, 10 = InvoiceNumber, 11 = DebitorNumber, 12 = Buchungstext, 15 = Betrag, 16 = Verwendung, 36 = c.CostCenter + // Dedupliziert wie BuildDiamantLines über die OID (Spalte 0), damit Rechnungen mit mehreren Positionen nur einmal (F-Zeilen-Betrag) erscheinen. + // Rückgabe: Summe der Beträge der ausgegebenen Zeilen. + private static decimal AddBelegRows(DataTable table, DataTable dtBookings, Dictionary oid2GeneratedNumber, string empfaengerPrefix, string verwendungPrefix) + { + decimal summe = 0; + HashSet seenOids = new HashSet(); + + foreach (DataRow booking in dtBookings.Rows) + { + string oid = booking[0].ToString(); + if (!seenOids.Add(oid)) + { + continue; + } + + string invoiceNumber = booking[10].ToString(); + if (oid2GeneratedNumber != null && oid2GeneratedNumber.ContainsKey(oid)) + { + invoiceNumber = oid2GeneratedNumber[oid]; + } + + string empfaenger = booking[12].ToString(); + if (!String.IsNullOrEmpty(empfaengerPrefix)) + { + empfaenger = empfaenger.Replace(empfaengerPrefix, ""); + } + + string verwendung = booking[16].ToString(); + if (!String.IsNullOrEmpty(verwendungPrefix)) + { + verwendung = verwendung.Replace(verwendungPrefix, ""); + } + + DataRow row = table.NewRow(); + row[0] = invoiceNumber; + row[1] = empfaenger; + row[2] = booking[11]; + row[3] = SetKonto(booking[12]); + row[4] = booking[36]; + row[5] = verwendung; + row[6] = String.Format("{0:0.00}", booking[15]); + table.Rows.Add(row); + + summe += Convert.ToDecimal(booking[15]); + } + + return summe; + } + + private static void AddSummenRow(DataTable table, string label, decimal summe) + { + DataRow row = table.NewRow(); + row[5] = label; + row[6] = String.Format("{0:0.00}", summe); + table.Rows.Add(row); + } + + private static Bericht CreateBelegReport(string name, DataTable table) + { + var queryReportObject = QueryRO.Create(new Query() { Title = "Export" }, table); + queryReportObject.Name = name; + + var queryReport = new Bericht(); + queryReport.SetReportDataSource(queryReportObject); + queryReport.CreateDocument(); + return queryReport; + } + public static DataTable ExecuteQuery(String sql, DateTime dt) { var newsql = sql;