Files
BeWoPlaner/ReportImp/FeidPartnerReports/Invoicing/CollectiveInvoiceCreation.cs

272 lines
12 KiB
C#

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using BeWo.Data.Access;
using BeWo.Data.Entities;
using BeWo.Report.ReportObjects;
using BeWo.Service.DCEntityMapper;
using BeWo.Service.Invoicing;
using BeWo.Service.Plugins;
using BS.Shared;
using BS.Shared.Core;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Compact;
using BS.Shared.Extensions;
using BS.Shared.Services;
namespace FeidPartnerReports.Invoicing
{
public class CollectiveInvoiceCreation : InvoiceCreation
{
private DateTime? accountingPeriodStart = null;
private DateTime? accountingPeriodEnd = null;
private decimal AMOUNT_PER_KMQA = 0.0222m;
private bool monthly = true;
public override void SetInvoiceId(ServiceInvoice invoice)
{
invoice.InvoiceBase.InvoiceId = "Sammelrechnung";
invoice.InvoiceBase.InvoiceTypeText = "Sammelrechnung";
}
public override void SetInvoiceBaseData(int invoiceCounter, ServiceInvoice invoice, CostBearer costBearer, DateTimeSpan invoicePeriod,
IList<CompactSupportConceptDC> supportConceptList)
{
if (invoicePeriod != null)
{
accountingPeriodStart = invoicePeriod.StartDate;
accountingPeriodEnd = invoicePeriod.EndDate;
var pauschVar = base.GetPreis("Fahrzeitenzuschlag qA", (DateTime)accountingPeriodStart);
if (pauschVar != 0)
{
AMOUNT_PER_KMQA = pauschVar;
}
}
base.SetInvoiceBaseData(invoiceCounter, invoice, costBearer, invoicePeriod, supportConceptList);
}
public override void SetInvoiceItems(ServiceInvoice invoice,
ServiceInvoicePeriod serviceInvoicePeriod,
SupportConceptApprovalPeriodDC supportConceptApprovalPeriod,
CostBearer2SupportConcept cb2sc,
DateTimeSpan invoicePeriod,
List<ServiceRecordDC> serviceRecords)
{
BS.Shared.Services.Calculations calc = PluginLoader.FindClass<BS.Shared.Services.Calculations>(_SpecificID) ?? BS.Shared.Services.Calculations.GetInstance(_SpecificID);
CreateFixedAmounts(serviceInvoicePeriod, supportConceptApprovalPeriod, cb2sc);
}
public override ServiceInvoice CreateCollectiveBilling(CostBearer costBearer, DateTimeSpan invoicePeriod, Dictionary<CompactSupportConceptDC, List<ServiceRecordDC>> supportConcepts2ServiceRecords)
{
var invoice = new ServiceInvoice();
var newDict = new Dictionary<CompactSupportConceptDC, List<ServiceRecordDC>>();
bool unbewilligte = true;
if (supportConcepts2ServiceRecords.Any(sc2sr => sc2sr.Key.IsApproved)) // Für normalen Rechnungslauf
{
unbewilligte = false;
}
foreach (var sc2sr in supportConcepts2ServiceRecords)
{
if (!unbewilligte && sc2sr.Key.IsApproved)
{
newDict.Add(sc2sr.Key, sc2sr.Value);
}
else if (unbewilligte)
{
newDict.Add(sc2sr.Key, sc2sr.Value); // Rechnungsvorschau für Unbewilligte Hilfepläne in Berichten
}
}
SetRecipientInformation(invoice, costBearer);
SetSenderInformation(invoice);
SetInvoiceBaseData(0, invoice, costBearer, invoicePeriod, newDict.Keys.ToList());
SetCollectiveBillingBaseData(0, invoice, costBearer, invoicePeriod, newDict);
SetCollectiveBillingServiceInvoicePeriods(invoice, invoicePeriod, newDict);
SetServiceInvoicePeriodAmounts(invoice);
// Spitzabrechnung
if (invoicePeriod == null)
{
SetAmountAdvancePayments(invoice);
}
return invoice;
}
public override void CreateFixedAmounts(ServiceInvoicePeriod serviceInvoicePeriod, SupportConceptApprovalPeriodDC supportConceptApprovalPeriod, CostBearer2SupportConcept cb2sc)
{
var calc = PluginLoader.FindClass<BS.Shared.Services.Calculations>(_SpecificID) ?? BS.Shared.Services.Calculations.GetInstance(_SpecificID);
var data = calc.GetFixedBillingData(supportConceptApprovalPeriod, serviceInvoicePeriod.Start, serviceInvoicePeriod.End);
DateTime start = accountingPeriodStart.Value;
DateTime end = accountingPeriodEnd.Value;
if (supportConceptApprovalPeriod.ServiceCategory != null && data != null && data.Count > 0)
{
if (supportConceptApprovalPeriod.StartDate.HasValue && supportConceptApprovalPeriod.StartDate.Value > start)
{
start = supportConceptApprovalPeriod.StartDate.Value;
}
if (supportConceptApprovalPeriod.EndDate.HasValue && supportConceptApprovalPeriod.EndDate.Value < end)
{
end = supportConceptApprovalPeriod.EndDate.Value;
}
decimal preis = (decimal)Math.Round((double)data[0].AmountTotal, 2, MidpointRounding.AwayFromZero);
decimal days = (decimal)(end - start).TotalDays + 1;
// im Normalfall monatliche Abrechnung
if (start.Year == end.Year && start.Month == end.Month)
{
CreateInvoiceItemsLwv(serviceInvoicePeriod, supportConceptApprovalPeriod, start, end, preis, null);
}
// ...aber es können auch Zeiträume für einzelne Klienten nachträglich abgerechnet werden,
// dann monatliche Rechnungsposition
else
{
monthly = false;
var monthlyDict = data
.GroupBy(e => new DateTime(e.BillingPeriodStart.Value.Year, e.BillingPeriodStart.Value.Month, 1))
.ToDictionary(
g => g.Key,
g => g.OrderBy(e => e.BillingPeriodStart).ToList() // Liste der Einträge in diesem Monat
);
foreach (var kvp in monthlyDict.OrderBy(k => k.Key))
{
var month = kvp.Key; // z.B. 2025-01-01
var entries = kvp.Value;
preis = (decimal)Math.Round((double)entries[0].AmountTotal, 2, MidpointRounding.AwayFromZero);
days = entries.Count;
var lastday = entries.LastOrDefault();
CreateInvoiceItemsLwv(serviceInvoicePeriod, supportConceptApprovalPeriod, entries[0].BillingPeriodStart.Value, lastday.BillingPeriodStart.Value, preis, days);
}
}
}
}
private void CreateInvoiceItemsLwv(ServiceInvoicePeriod serviceInvoicePeriod, SupportConceptApprovalPeriodDC supportConceptApprovalPeriod, DateTime start, DateTime end, decimal preis, decimal? days)
{
if (days == null)
{
days = (decimal)(end - start).TotalDays + 1;
}
var ii = new InvoiceItem
{
ItemPeriodStart = serviceInvoicePeriod.Start,
ItemPeriodEnd = serviceInvoicePeriod.End,
SupportConceptApprovalPeriodOid = supportConceptApprovalPeriod.SupportConceptApprovalPeriodOid,
AccountingInterval = AccountingIntervalType.Daily,
UnitCount = days,
UnitDescription = String.Format("{0:MM.yyyy}", start),
Notice = "keine Minuten"
};
if (supportConceptApprovalPeriod.ServiceCategory.Name.Contains("Bedarfsgruppe"))
{
bool teilmonat = false;
if (supportConceptApprovalPeriod.StartDate != null && supportConceptApprovalPeriod.StartDate > start)
{
start = supportConceptApprovalPeriod.StartDate.Value;
teilmonat = true;
}
if (supportConceptApprovalPeriod.EndDate != null && supportConceptApprovalPeriod.EndDate < end)
{
end = supportConceptApprovalPeriod.EndDate.Value;
teilmonat = true;
}
ii.AccountingInterval = AccountingIntervalType.Monthly;
ii.ItemDescription = supportConceptApprovalPeriod.ServiceCategory.Name;
ii.UnitCount = 1;
ii.AmountPerUnit = preis;
if (teilmonat)
{
var teiltage = (double)(end - start).TotalDays + 1;
ii.AmountPerUnit = (decimal)Math.Round((double)preis / 30.42 * teiltage, 2, MidpointRounding.AwayFromZero);
}
ii.AmountTotal = ii.AmountPerUnit;
ii.GrossAmountTotal = ii.AmountTotal;
ii.Notice = "";
serviceInvoicePeriod.InvoiceItemList.Add(ii);
return;
}
if (supportConceptApprovalPeriod.ApprovedBEPerInterval.HasValue)
{
ii.Notice = String.Format("{0:n0}", supportConceptApprovalPeriod.ApprovedBEPerInterval.Value);
if (!monthly) // Bei Nachberechnung muss der Preis monatlich geprüft werden
{
var pauschVar = base.GetPreis("Fahrzeitenzuschlag qA", start);
if (pauschVar != 0)
{
AMOUNT_PER_KMQA = pauschVar;
}
}
if (supportConceptApprovalPeriod.ServiceCategory.Name.Contains("Fahrzeit"))
{
ii.AmountPerUnit = supportConceptApprovalPeriod.ApprovedBEPerInterval * AMOUNT_PER_KMQA;
ii.ItemDescription = "Fahrzeiten QA";
}
else
{
if (supportConceptApprovalPeriod.ApprovedFixedAmount != null)
{
ii.AmountPerUnit = supportConceptApprovalPeriod.ApprovedFixedAmount;
}
else
{
ii.AmountPerUnit = supportConceptApprovalPeriod.ApprovedBEPerInterval * (decimal)Math.Round((double)preis / 60, 4, MidpointRounding.AwayFromZero);
}
ii.ItemDescription = "Qualifizierte Assistenz";
}
ii.AmountPerUnit = Math.Round((decimal)ii.AmountPerUnit, 2, MidpointRounding.AwayFromZero);
ii.AmountTotal = ii.UnitCount * ii.AmountPerUnit;
ii.GrossAmountTotal = ii.AmountTotal;
}
serviceInvoicePeriod.InvoiceItemList.Add(ii);
if (supportConceptApprovalPeriod.MonthlyPayment.HasValue && supportConceptApprovalPeriod.MonthlyPayment > 0)
{
var equity = supportConceptApprovalPeriod.MonthlyPayment.Value;
if (equity > 0)
{
var iiE = new InvoiceItem();
iiE.UnitCount = 1;
iiE.AmountPerUnit = equity;
iiE.AmountTotal = -equity;
iiE.GrossAmountTotal = -equity;
iiE.ItemPeriodStart = ii.ItemPeriodStart;
iiE.ItemPeriodEnd = ii.ItemPeriodEnd;
iiE.Notice = "";
iiE.SupportConceptApprovalPeriodOid = ii.SupportConceptApprovalPeriodOid;
iiE.ItemDescription = "Eigenanteil";
iiE.UnitDescription = String.Format("{0:MM.yyyy}", start);
serviceInvoicePeriod.InvoiceItemList.Add(iiE);
}
}
}
public override void SetServiceInvoicePeriodAmounts(ServiceInvoice invoice)
{
foreach (ServiceInvoicePeriod iPeriod in invoice.ServiceInvoicePeriodList)
{
iPeriod.Claim = 0;
if (iPeriod.SupportConceptApprovalPeriod.ServiceCategory.Name != "qA" && iPeriod.ApprovedFixedAmount.HasValue && iPeriod.ApprovedFixedAmount.Value != 0)
iPeriod.Claim = iPeriod.ApprovedFixedAmount;
else
{
foreach (InvoiceItem item in iPeriod.InvoiceItemList)
{
if (item.GrossAmountTotal.HasValue)
iPeriod.Claim += item.GrossAmountTotal;
}
}
iPeriod.Claim = Math.Round(iPeriod.Claim.Value, 2, MidpointRounding.AwayFromZero);
}
}
}
}