using System; using System.Collections.Generic; using System.Data; using System.IO; using System.Text; using BeWo.Data.Access; using BeWo.Data.Entities; using BeWo.Service.DCEntityMapper; using BS.Shared; using BS.Shared.DataContracts; using BS.Shared.Extensions; namespace DiakonischesWerkMuelheimTwg.Export { public class DatevExporter { public static QueryDC CreateQuery(QueryDC query) { DateTime dt = DateTime.Now; DateTime.TryParse(query.Parameter[0].Value.ToString(), out dt); query.FileName = String.Format("Datev Export {0:yyyyMM}.csv", dt); query.QueryResult = GetAbrechnungenString(dt); return query; } public static String GetAbrechnungenString(DateTime date) { StringBuilder sb = new StringBuilder(); sb.Append("Betrag;S/H;BU;Gegenkonto;Blg 1;Dat;Konto;Kst;Text"); var s = GetMonatlicheRechnungenString(date); if (!String.IsNullOrWhiteSpace(s)) { sb.AppendLine(); sb.Append(s); } return sb.ToString(); } public static String GetMonatlicheRechnungenString(DateTime date) { var sql = GetMonatlicheRechnungenSql(date); var dt = ExecuteQuery(sql, date); StringBuilder sb = new StringBuilder(); foreach (DataRow row in dt.Rows) { if (sb.Length > 0) { sb.AppendLine(); } String buchungstext = ""; long? c2sOid = (long?)row[5]; if (c2sOid.HasValue) { var c2s = DAOFactory.GenericDAO.LoadByID(c2sOid.Value); var c = c2s.SupportConcept.Customer; buchungstext = String.Format("{0}, {1} {2:MM}/{2:yy}", c.Person.LastName, c.Person.FirstName, row[8]); } string konto = String.Format("{0}", row[1]).Trim(); // customer.DebitorNumber string kostenstelle = String.Format("{0}", row[4]).Trim(); // customer.CostCenter string belegfeld1 = String.Format("{0}", row[3]).Trim(); // ib.invoicenumber string gegenkonto = ErmittleErloeskonto((long)row[10]); // ib.Oid -> 40920 Pflege/Barbetrag, sonst 40910 ABW sb.Append(BuildBuchungszeile(row[0], konto, gegenkonto, belegfeld1, row[2], kostenstelle, buchungstext)); } return sb.ToString(); } // Spalten: Betrag;S/H;BU;Gegenkonto;Blg 1;Dat;Konto;Kst;Text private static String BuildBuchungszeile(object betrag, string konto, string gegenkonto, string belegfeld1, object belegdatum, string kostenstelle, string buchungstext) { StringBuilder sb = new StringBuilder(); sb.Append(String.Format("{0:0.00}", betrag)); // Betrag sb.Append(";S"); // S/H sb.Append(";"); // BU (leer) sb.Append(";"); sb.Append(gegenkonto); // Gegenkonto sb.Append(";"); sb.Append(belegfeld1); // Blg 1 sb.Append(";"); sb.Append(String.Format("{0:ddMM}", belegdatum)); // Dat sb.Append(";"); sb.Append(konto); // Konto sb.Append(";"); sb.Append(kostenstelle); // Kst (leer) sb.Append(";"); sb.Append(buchungstext); // Text return sb.ToString(); } // Kunde hat kein festes Erloeskonto: 40920 fuer Pflege/Barbetrag, 40910 fuer ABW. // Massgeblich ist die UnitDescription der InvoiceItems; ist diese leer (Rechnung vor Juli 2026), gilt die ItemDescription. private static String ErmittleErloeskonto(long invoiceBaseOid) { var invoice = DAOFactory.SearchDAO.GetServiceInvoiceByInvoiceBaseOid(invoiceBaseOid); if (invoice != null && invoice.ServiceInvoicePeriodList != null) { foreach (var period in invoice.ServiceInvoicePeriodList) { if (period.InvoiceItemList == null) { continue; } foreach (var item in period.InvoiceItemList) { string text = !String.IsNullOrWhiteSpace(item.UnitDescription) ? item.UnitDescription : item.ItemDescription; if (EnthaeltPflege(text)) { return "40920"; // Pflege } } } } return "40910"; // ABW (Umkehrschluss: kein Pflege/Barbetrag) } private static bool EnthaeltPflege(string text) { if (String.IsNullOrEmpty(text)) { return false; } return text.IndexOf("Pflege", StringComparison.OrdinalIgnoreCase) >= 0; } private static String GetMonatlicheRechnungenSql(DateTime date) { String sql = @" select sip.Claim, c.DebitorNumber, ib.InvoiceDate, ib.invoicenumber, c.CostCenter, c2s.Oid, ib.InvoiceId, c2s.Notice AS 'Kostenstelle', ib.`AccountingPeriodEnd`, ib.`AccountingPeriodStart`, ib.Oid from person p inner join customer c on c.personoid = p.oid inner join supportconcept sc on sc.customeroid = c.oid inner join costbearer2supportconcept c2s on c2s.supportconceptoid = sc.oid inner join invoicebase ib on ib.costbearer2supportconceptoid = c2s.oid inner join serviceinvoice si on si.invoicebaseoid = ib.oid inner join serviceinvoiceperiod sip on sip.serviceinvoiceoid = si.oid WHERE ib.`AccountingPeriodEnd` >= ':Monat_Start' AND ib.`AccountingPeriodEnd` < ':Monat_End' and ib.IsActive = 1 AND (ib.InvoiceId <> 'Bar' OR ib.InvoiceId IS NULL) AND ib.IsExported = 0 order by ib.invoicenumber "; return sql; } public static DataTable ExecuteQuery(String sql, DateTime dt) { var newsql = sql; newsql = newsql.Replace(":Abrechnungsmonat", String.Format("{0:dd.MM.yyyy}", dt)); newsql = newsql.Replace(":Belegnr", String.Format("{0:yyMM}", dt)); newsql = newsql.Replace(":Monat_MM", String.Format("{0:MM}", dt)); newsql = newsql.Replace(":Monat_Start", String.Format("{0:yyyy-MM}-01", dt)); dt = dt.AddMonths(1); newsql = newsql.Replace(":Monat_End", String.Format("{0:yyyy-MM}-01", dt)); return DAOFactory.AdoDAO.ExecuteQuery(newsql).Tables[0]; } } }