diff --git a/ReportImp/DiakonischesWerkMuelheimTwg/DiakonischesWerkMuelheimTwg.csproj b/ReportImp/DiakonischesWerkMuelheimTwg/DiakonischesWerkMuelheimTwg.csproj
index 4ba1bebc6..900b5585c 100644
--- a/ReportImp/DiakonischesWerkMuelheimTwg/DiakonischesWerkMuelheimTwg.csproj
+++ b/ReportImp/DiakonischesWerkMuelheimTwg/DiakonischesWerkMuelheimTwg.csproj
@@ -66,6 +66,8 @@
Belegungsquoten.cs
+
+
Component
diff --git a/ReportImp/DiakonischesWerkMuelheimTwg/Export/CustomDataExporter.cs b/ReportImp/DiakonischesWerkMuelheimTwg/Export/CustomDataExporter.cs
new file mode 100644
index 000000000..db955f37e
--- /dev/null
+++ b/ReportImp/DiakonischesWerkMuelheimTwg/Export/CustomDataExporter.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using BeWo.Service.Core;
+using BeWo.Service.Plugins;
+using BS.Shared.Core;
+using BS.Shared.DataContracts;
+using Utils = BS.Shared.Core.Utils;
+
+namespace DiakonischesWerkMuelheimTwg.Export
+{
+ public class CustomDataExporter : DataExporter
+ {
+ public override QueryDC CreateQuery(QueryDC query)
+ {
+ return DatevExporter.CreateQuery(query);
+ }
+ }
+}
diff --git a/ReportImp/DiakonischesWerkMuelheimTwg/Export/DatevExporter.cs b/ReportImp/DiakonischesWerkMuelheimTwg/Export/DatevExporter.cs
new file mode 100644
index 000000000..f55d05e21
--- /dev/null
+++ b/ReportImp/DiakonischesWerkMuelheimTwg/Export/DatevExporter.cs
@@ -0,0 +1,176 @@
+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 (EnthaeltPflegeOderBarbetrag(text))
+ {
+ return "40920"; // Pflege / Barbetrag
+ }
+ }
+ }
+ }
+ return "40910"; // ABW (Umkehrschluss: kein Pflege/Barbetrag)
+ }
+
+ private static bool EnthaeltPflegeOderBarbetrag(string text)
+ {
+ if (String.IsNullOrEmpty(text))
+ {
+ return false;
+ }
+ return text.IndexOf("Pflege", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Barbetrag", 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
+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];
+ }
+ }
+}
diff --git a/ReportImp/DiakonischesWerkMuelheimTwg/Invoicing/BarbetragInvoiceCreation.cs b/ReportImp/DiakonischesWerkMuelheimTwg/Invoicing/BarbetragInvoiceCreation.cs
index f4656835a..f10797252 100644
--- a/ReportImp/DiakonischesWerkMuelheimTwg/Invoicing/BarbetragInvoiceCreation.cs
+++ b/ReportImp/DiakonischesWerkMuelheimTwg/Invoicing/BarbetragInvoiceCreation.cs
@@ -64,7 +64,8 @@ namespace DiakonischesWerkMuelheimTwg.Invoicing
AccountingInterval = billingData.AccountingInterval,
AmountPerUnit = billingData.AmountPerUnit,
UnitCount = billingData.UnitCount,
- ItemDescription = description
+ ItemDescription = description,
+ UnitDescription = "Pflege"
});
}
}
diff --git a/ReportImp/DiakonischesWerkMuelheimTwg/Invoicing/CustomInvoiceCreation.cs b/ReportImp/DiakonischesWerkMuelheimTwg/Invoicing/CustomInvoiceCreation.cs
index 3e4022f7f..f886d99b8 100644
--- a/ReportImp/DiakonischesWerkMuelheimTwg/Invoicing/CustomInvoiceCreation.cs
+++ b/ReportImp/DiakonischesWerkMuelheimTwg/Invoicing/CustomInvoiceCreation.cs
@@ -52,6 +52,13 @@ namespace DiakonischesWerkMuelheimTwg.Invoicing
}
}
+ public override InvoiceItem CreateInvoiceItem(ServiceRecordDC iServiceRecord, SupportConceptApprovalPeriod scap, Calculations calc)
+ {
+ var ii = base.CreateInvoiceItem(iServiceRecord, scap, calc);
+ ii.UnitDescription = "ABW";
+ return ii;
+ }
+
public override IList CreateSummaryInvoiceItems(IList itemList, DateTimeSpan invoicePeriod, SupportConceptApprovalPeriod scap,
Calculations calc, bool summaryPerMonth)
{
@@ -172,7 +179,6 @@ namespace DiakonischesWerkMuelheimTwg.Invoicing
return newlist;
}
-
public bool RundeRateFactorMitBetrag { get; set; }
}
}
diff --git a/ReportImp/DiakonischesWerkMuelheimTwg/Invoicing/CustomInvoiceFactory.cs b/ReportImp/DiakonischesWerkMuelheimTwg/Invoicing/CustomInvoiceFactory.cs
index 66da61b6e..ae046bca1 100644
--- a/ReportImp/DiakonischesWerkMuelheimTwg/Invoicing/CustomInvoiceFactory.cs
+++ b/ReportImp/DiakonischesWerkMuelheimTwg/Invoicing/CustomInvoiceFactory.cs
@@ -40,7 +40,6 @@ namespace DiakonischesWerkMuelheimTwg.Invoicing
return new CustomInvoiceCreation();
- }
-
+ }
}
}
diff --git a/ReportImp/DiakonischesWerkMuelheimTwg/Invoicing/PflegeInvoiceCreation.cs b/ReportImp/DiakonischesWerkMuelheimTwg/Invoicing/PflegeInvoiceCreation.cs
index 28d9af079..5208fe073 100644
--- a/ReportImp/DiakonischesWerkMuelheimTwg/Invoicing/PflegeInvoiceCreation.cs
+++ b/ReportImp/DiakonischesWerkMuelheimTwg/Invoicing/PflegeInvoiceCreation.cs
@@ -101,7 +101,8 @@ namespace DiakonischesWerkMuelheimTwg.Invoicing
ItemPeriodEnd = serviceInvoicePeriod.End,
AccountingInterval = AccountingIntervalType.Daily,
AmountPerUnit = 0,
- UnitCount = 0
+ UnitCount = 0,
+ UnitDescription = supportConceptApprovalPeriod.ServiceCategory != null ? supportConceptApprovalPeriod.ServiceCategory.Name : "Pflege"
};
// Gibt es einen Krankenhausaufenthalt während der Abrechnungszeit, dürfen währenddessen nur 75% abgerechnet werden
var item75Prozent = new InvoiceItem()
@@ -113,7 +114,8 @@ namespace DiakonischesWerkMuelheimTwg.Invoicing
ItemPeriodEnd = serviceInvoicePeriod.End,
AccountingInterval = AccountingIntervalType.Daily,
AmountPerUnit = 0,
- UnitCount = 0
+ UnitCount = 0,
+ UnitDescription = supportConceptApprovalPeriod.ServiceCategory != null ? supportConceptApprovalPeriod.ServiceCategory.Name : "Pflege"
};
var abwesenheiten = cb2sc.SupportConcept.Customer.AbsenceTimes.Where(a => a.AbsenceReason.Description.ToLower().Contains("krankenhaus"));
@@ -163,5 +165,12 @@ namespace DiakonischesWerkMuelheimTwg.Invoicing
return CreateSummaryInvoiceItems(list, invoicePeriod, scap, calc);
}
+
+ public override InvoiceItem CreateInvoiceItem(ServiceRecordDC iServiceRecord, SupportConceptApprovalPeriod scap, Calculations calc)
+ {
+ var ii = base.CreateInvoiceItem(iServiceRecord, scap, calc);
+ ii.UnitDescription = "Pflege";
+ return ii;
+ }
}
}
\ No newline at end of file