HshCologne/Invoicing - Finetuning für spezielle Fälle

This commit is contained in:
2025-11-25 15:20:40 +01:00
parent 64941c4952
commit ff71494a3e
4 changed files with 146 additions and 41 deletions

View File

@@ -57,6 +57,7 @@
<ItemGroup>
<Compile Include="CustomReportCreator.cs" />
<Compile Include="Export\CustomDataExporter.cs" />
<Compile Include="Export\CustomExportAndPrintHelper.cs" />
<Compile Include="Export\FibuExporter.cs" />
<Compile Include="InvoiceCustomerReport.cs">
<SubType>Component</SubType>
@@ -102,6 +103,8 @@
<Compile Include="ServiceInvoiceReport.Designer.cs">
<DependentUpon>ServiceInvoiceReport.cs</DependentUpon>
</Compile>
<Compile Include="Service\CustomAccountingService.cs" />
<Compile Include="Service\ServiceRecordValidator.cs" />
<Compile Include="Translation\CustomTranslationDictionary.cs" />
</ItemGroup>
<ItemGroup>

View File

@@ -68,20 +68,88 @@ namespace HshCologne.Invoicing
base.SetInvoiceBaseData(invoiceCounter, invoice, costBearer, invoicePeriod, supportConceptList);
}
public override IList<InvoiceItem> CreateInvoiceItems(List<ServiceRecordDC> serviceRecordsInPeriod, DateTimeSpan invoicePeriod, SupportConceptApprovalPeriod scap, Calculations calc)
{
var list = base.CreateInvoiceItems(serviceRecordsInPeriod, invoicePeriod, scap, calc);
var fitem = CreateFahrkostenInvoiceItem(serviceRecordsInPeriod, scap, calc);
if (fitem != null)
list.Add(fitem);
// normale Items + 2 verschiedene Sorten Fahrtpauschalen + besondere Logik im Fall von Leistungskategorie FAM (Tagespauschale pro Tag mit Leistungskategorie)
var list = new List<InvoiceItem>();
foreach (ServiceRecordDC iServiceRecord in serviceRecordsInPeriod)
{
// Für alle Leistungskategorien normal, außer für FAM - da wird pro geleistetem Tag abgerechnet
if (iServiceRecord.ServiceDescription.Category.IsBillable)
{
if (!iServiceRecord.AlreadyAccounted)
{
InvoiceItem invoiceItem = CreateInvoiceItem(iServiceRecord, scap, calc);
if (invoiceItem != null)
{
list.Add(invoiceItem);
}
iServiceRecord.AlreadyAccounted = true;
}
}
}
if (serviceRecordsInPeriod != null && serviceRecordsInPeriod.Count > 0)
{
// Fahrtkosten aus eingetragenen Kilometern
int km = 0;
decimal custKm = 0;
foreach (var sr in serviceRecordsInPeriod)
{
if (sr.DistanceInMeter.HasValue)
km += sr.DistanceInMeter.Value;
}
if (km > 0)
{
custKm = Convert.ToDecimal(km);
var fitem = CreateFahrkostenInvoiceItem(serviceRecordsInPeriod, scap, calc, custKm);
if (fitem != null)
{
list.Add(fitem);
}
}
// Fahrtkosten bei bestimmten Leistungen, wenn Wert bei Customer.Healthinsurance eingetragen wurde
else
{
var c = DAOFactory.GenericDAO.LoadByID<Customer>(serviceRecordsInPeriod[0].Customer.CustomerOid);
if (c.HealthInsurance.IsNotNullOrEmpty() && decimal.TryParse(c.HealthInsurance, out custKm))
{
var leistungen = new List<string> { "HPG", "Hausbesuch", "Abholung und Begleitung", "Einsatz HPG", "Fachgespräch"};
return list;
int count = serviceRecordsInPeriod.Count(sr => leistungen.Contains(sr.ServiceDescription.Name));
custKm = custKm * count;
var fitem = CreateFahrkostenInvoiceItem(serviceRecordsInPeriod, scap, calc, custKm);
if (fitem != null)
{
list.Add(fitem);
}
}
}
if (serviceRecordsInPeriod.Any(s => s.ServiceDescription.CategoryName == "FAM"))
{
var famItem = CreateFAMInvoiceItem(serviceRecordsInPeriod, scap, calc);
if (famItem != null)
{
list.Add(famItem);
}
}
}
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 = "Fachkraft";
//if (iServiceRecord.CostBearer.Name.Contains("Erftstadt")) // brauchen explizite Zeitangaben, aber Einheit sind 45 min
//{
// ii.UnitCount = Math.Round((decimal)(ii.UnitCount / 45 * 60), 2, MidpointRounding.AwayFromZero);
// ii.AmountTotal = ii.AmountPerUnit * ii.UnitCount;
// ii.GrossAmountTotal = ii.AmountPerUnit * ii.UnitCount;
//}
if (iServiceRecord.GroupOid.HasValue)
{
ii.Notice = "x";
@@ -90,13 +158,21 @@ namespace HshCologne.Invoicing
// Da diverse Kostenträger liegen deren Stundensätze unter Preise
// Während Wesseling und Geilenkirchen für ALLES nur einen Stundensatz haben
// Und Erftstadt macht sowieso ALLES anders :D
//if ( iServiceRecord.CostBearer.Name.Contains("Wesseling") || iServiceRecord.CostBearer.Name.Contains("Geilenkirchen")
// || iServiceRecord.CostBearer.Name.Contains("Erftstadt") || iServiceRecord.ServiceDescription.Category.Abbreviation.ToLower().Contains("sb") )
//{
decimal stundensatz = 0;
if (iServiceRecord.CostBearer.Name.Contains("Wesseling") || iServiceRecord.CostBearer.Name.Contains("Geilenkirchen"))
if (iServiceRecord.ServiceDescription.CategoryName == "FAM")
{
ii.UnitCount = 0;
ii.UnitDescription = "FAM-Eintrag";
ii.AmountTotal = 0;
ii.GrossAmountTotal = 0;
}
else if (iServiceRecord.CostBearer.Name.Contains("Wesseling") || iServiceRecord.CostBearer.Name.Contains("Geilenkirchen"))
{
stundensatz = GetStundensatz(scap.CostBearer2SupportConcept, null, iServiceRecord.Start);
if (iServiceRecord.CostBearer.Name.Contains("Geilenkirchen"))
{
ii.UnitDescription = "Assistenzkraft mit 2 jähriger BE";
}
}
else if (iServiceRecord.Employee.ValueListEntries != null)
{
@@ -168,33 +244,48 @@ namespace HshCologne.Invoicing
return 0;
}
private InvoiceItem CreateFahrkostenInvoiceItem(List<ServiceRecordDC> serviceRecordsInPeriod, SupportConceptApprovalPeriod scap, Calculations calc)
private InvoiceItem CreateFahrkostenInvoiceItem(List<ServiceRecordDC> serviceRecordsInPeriod, SupportConceptApprovalPeriod scap, Calculations calc, decimal km)
{
int km = 0;
foreach (var sr in serviceRecordsInPeriod)
{
if (sr.DistanceInMeter.HasValue)
km += sr.DistanceInMeter.Value;
}
var pauschVar = base.GetPreis("Kilometerpauschale", (DateTime)accountingPeriodStart);
if (pauschVar != 0)
AMOUNT_PER_KM = pauschVar;
if (km > 0)
{
var pauschVar = base.GetPreis("Kilometerpauschale", (DateTime)accountingPeriodStart);
if (pauschVar != 0)
AMOUNT_PER_KM = pauschVar;
var invoiceItem = new InvoiceItem();
invoiceItem.AmountPerUnit = AMOUNT_PER_KM;
invoiceItem.UnitCount = km;
invoiceItem.AmountTotal = invoiceItem.UnitCount * invoiceItem.AmountPerUnit;
invoiceItem.ItemPeriodStart = accountingPeriodStart;
invoiceItem.ItemPeriodEnd = accountingPeriodEnd;
invoiceItem.GrossAmountTotal = invoiceItem.AmountTotal;
invoiceItem.UnitDescription = String.Format("Fahrtkosten");
if (scap != null)
invoiceItem.SupportConceptApprovalPeriodOid = scap.Oid;
var invoiceItem = new InvoiceItem();
invoiceItem.AmountPerUnit = AMOUNT_PER_KM;
invoiceItem.UnitCount = km;
invoiceItem.AmountTotal = invoiceItem.UnitCount * invoiceItem.AmountPerUnit;
invoiceItem.ItemPeriodStart = accountingPeriodStart;
invoiceItem.ItemPeriodEnd = accountingPeriodEnd;
invoiceItem.GrossAmountTotal = invoiceItem.AmountTotal;
invoiceItem.UnitDescription = String.Format("Fahrtkosten");
if (scap != null)
invoiceItem.SupportConceptApprovalPeriodOid = scap.Oid;
return invoiceItem;
}
return invoiceItem;
private InvoiceItem CreateFAMInvoiceItem(List<ServiceRecordDC> serviceRecordsInPeriod, SupportConceptApprovalPeriod scap, Calculations calc)
{
var days = serviceRecordsInPeriod.Where(r => r.ServiceDescription.CategoryName == "FAM").GroupBy(r => r.Start.Value.Date).Count();
if (days > 0)
{
InvoiceItem interimsItem = CreateInvoiceItem(serviceRecordsInPeriod.Where(r => r.ServiceDescription.CategoryName == "FAM").FirstOrDefault(), scap, calc);
if (interimsItem != null)
{
var invoiceItem = new InvoiceItem();
invoiceItem.AmountPerUnit = interimsItem.AmountPerUnit;
invoiceItem.UnitCount = days;
invoiceItem.AmountTotal = days * invoiceItem.AmountPerUnit;
invoiceItem.ItemPeriodStart = interimsItem.ItemPeriodStart;
invoiceItem.ItemPeriodEnd = interimsItem.ItemPeriodEnd;
invoiceItem.RateFactor = null;
invoiceItem.GrossAmountTotal = invoiceItem.AmountTotal;
invoiceItem.UnitDescription = "Tagessatz";
if (scap != null)
invoiceItem.SupportConceptApprovalPeriodOid = scap.Oid;
return invoiceItem;
}
}
return null;
}

View File

@@ -172,10 +172,10 @@ namespace HshCologne
{
sb.AppendLine(pRO.RecipientOrganisation);
}
//if (!String.IsNullOrEmpty(pRO.RecipientAddressLine1))
//{
// sb.AppendLine(pRO.RecipientAddressLine1);
//}
if (!String.IsNullOrEmpty(pRO.RecipientAddressLine1))
{
sb.AppendLine(pRO.RecipientAddressLine1);
}
if (!String.IsNullOrEmpty(pRO.RecipientContactPerson) && !String.IsNullOrEmpty(pRO.RecipientOrganisation) && pRO.RecipientOrganisation.ToLower().Contains("köln"))
{
sb.AppendLine(pRO.RecipientContactPerson);

View File

@@ -45,7 +45,11 @@ namespace HshCologne
{
if (sip.ServiceInvoiceItems.Any(ii => ii.UnitDescription == "Fahrtkosten"))
{
sip.ServiceInvoiceItems = sip.ServiceInvoiceItems.Where(ii => ii.UnitDescription != "Fahrtkosten").ToList();
sip.ServiceInvoiceItems = sip.ServiceInvoiceItems.Where(ii => ii.UnitDescription != "Fahrtkosten" && ii.UnitDescription != "Tagessatz").ToList();
}
if (sip.ServiceInvoiceItems.Any(ii => ii.ServiceDescription == "Tagessatz"))
{
sip.ServiceInvoiceItems = sip.ServiceInvoiceItems.Where(ii => ii.UnitDescription != "Tagessatz").ToList();
}
foreach (var ii in sip.ServiceInvoiceItems)
{
@@ -54,11 +58,18 @@ namespace HshCologne
{
ii.UnitCountString = String.Format("{0:HH:mm}-{1:HH:mm}", ii.ServiceRecord.Start.Value, ii.ServiceRecord.End.Value);
}
ii.Duration = String.Format("{0:ddd}./{0:dd.MM}", ii.ServiceRecord.Start.Value);
if (ii.ServiceRecord.DistanceInMeter.HasValue)
if (ii.ServiceRecord != null)
{
ii.RateFactor = ii.ServiceRecord.DistanceInMeter.Value.ToString("n2");
ii.Duration = String.Format("{0:ddd}./{0:dd.MM}", ii.ServiceRecord.Start.Value);
if (ii.Hours == 0 && ii.ServiceRecord.RoundedDuration != 0)
{
ii.Hours = Math.Round(ii.ServiceRecord.RoundedDuration / 60, 2, MidpointRounding.AwayFromZero);
}
if (ii.ServiceRecord.DistanceInMeter.HasValue)
{
ii.RateFactor = ii.ServiceRecord.DistanceInMeter.Value.ToString("n2");
}
}
}
}