Files
BeWoPlaner/ReportImp/PraxisPusteblume/Invoicing/IFSSammelInvoiceCreation.cs

389 lines
17 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using BeWo.Data.Access;
using BeWo.Data.Entities;
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;
using DevExpress.Data.Helpers;
namespace PraxisPusteblume.Invoicing
{
public class IFSSammelInvoiceCreation : DefaultInvoiceCreation
{
public override void SetInvoiceId(ServiceInvoice invoice)
{
invoice.InvoiceBase.InvoiceId = "IFSSammelrechnung";
invoice.InvoiceBase.InvoiceTypeText = "IFS Sammelrechnung";
}
public override List<ServiceInvoiceDC> GenerateServiceInvoices(long costBearerOid, DateTimeSpan invoicePeriod, Dictionary<CompactSupportConceptDC, List<ServiceRecordDC>> supportConcepts2ServiceRecords)
{
var costBearer = DAOFactory.GenericDAO.LoadByID<CostBearer>(costBearerOid);
var invoiceList = new List<ServiceInvoice>();
ServiceInvoice invoice = new ServiceInvoice();
SetRecipientInformation(invoice, costBearer);
SetSenderInformation(invoice);
SetInvoiceBaseData(0, invoice, costBearer, invoicePeriod, supportConcepts2ServiceRecords.Keys.ToList());
SetCollectiveBillingBaseData(0, invoice, costBearer, invoicePeriod, supportConcepts2ServiceRecords);
SetCollectiveBillingServiceInvoicePeriods(invoice, invoicePeriod, supportConcepts2ServiceRecords);
// Wenn Bewilligungen mitten im Abrechnungszeitraum beginnen/enden, tauchen die Klienten doppelt auf der Rechnung auf
// Es soll aber jeder nur einmal auftauchen, daher die doppelten ServiceInvoicePeriods zusammenfassen
FasseDoppelteServiceInvoicePeriodsZusammen(invoice, invoicePeriod, supportConcepts2ServiceRecords);
SetServiceInvoicePeriodAmounts(invoice);
invoiceList.Add(invoice);
var result = invoiceList.Select(item => MapperFactory.ServiceInvoiceDC_ServiceInvoice.MapToNewDC(item)).ToList();
return result.Count > 1 ? result.OrderBy(i => i.InvoiceBase.CustomerLastName).ToList() : result;
}
private void FasseDoppelteServiceInvoicePeriodsZusammen(ServiceInvoice invoice, DateTimeSpan invoicePeriod, Dictionary<CompactSupportConceptDC, List<ServiceRecordDC>> supportConcepts2ServiceRecords)
{
// CLAUDE Schritt 1: Alle Customers sammeln, die mehr als einmal in ServiceInvoicePeriodList vorkommen
Dictionary<Customer, List<ServiceInvoicePeriod>> doppler = new Dictionary<Customer, List<ServiceInvoicePeriod>>();
foreach (var item in invoice.ServiceInvoicePeriodList)
{
if (!doppler.ContainsKey(item.Customer))
doppler[item.Customer] = new List<ServiceInvoicePeriod>();
doppler[item.Customer].Add(item);
}
doppler = doppler.Where(kv => kv.Value.Count > 1).ToDictionary(kv => kv.Key, kv => kv.Value);
// CLAUDE Schritt 2: Für jeden doppelten Customer alle InvoiceItems in die erste ServiceInvoicePeriod zusammenführen
// und die übrigen ServiceInvoicePeriods aus der Liste entfernen
foreach (var kv in doppler)
{
var periods = kv.Value;
var firstPeriod = periods[0];
for (int i = 1; i < periods.Count; i++)
{
foreach (var invoiceItem in periods[i].InvoiceItemList)
firstPeriod.InvoiceItemList.Add(invoiceItem);
invoice.ServiceInvoicePeriodList.Remove(periods[i]);
}
}
}
private IList<InvoiceData> SplitServiceRecordsToInvoiceType(List<ServiceRecordDC> allRecords)
{
Dictionary<String, InvoiceData> cat2Data = new Dictionary<String, InvoiceData>();
foreach (var sr in allRecords)
{
var key = sr.ServiceDescription.CategoryName.Replace("IFS -", "").Trim();
if (key != "Eingangsdiagnostik" && key != "Offenes Beratungsangebot")
{
key = "IFS";
}
InvoiceData id = null;
if (!cat2Data.ContainsKey(key))
{
id = new InvoiceData();
id.Title = key;
id.InvoiceId = key;
id.ServiceRecords = new List<ServiceRecordDC>();
cat2Data.Add(key, id);
}
else
{
id = cat2Data[key];
}
id.ServiceRecords.Add(sr);
}
return cat2Data.Values.ToList();
}
public override void SetInvoiceItems(ServiceInvoice invoice, ServiceInvoicePeriod serviceInvoicePeriod,
SupportConceptApprovalPeriodDC scap, CostBearer2SupportConcept cb2sc,
DateTimeSpan invoicePeriod, List<ServiceRecordDC> serviceRecords)
{
base.SetInvoiceItems(invoice, serviceInvoicePeriod, scap, cb2sc, invoicePeriod, serviceRecords);
if (serviceInvoicePeriod.InvoiceItemList != null && serviceInvoicePeriod.InvoiceItemList.Count > 0)
{
var item = CreateTeamSitzungInvoiceItem(scap, invoicePeriod);
if (item != null)
{
serviceInvoicePeriod.InvoiceItemList.Add(item);
}
List<int> vernetzung = new List<int> { 2, 3, 5, 9, 12 };
if (invoicePeriod.StartDate.Year >= 2026)
{
//Ab 2026 erste 5 Monate des Jahres bzw. ersten 5 Monate des HPs, wenn HP erst im laufenden Jahr beginnt
vernetzung.Clear();
if (scap.StartDate.HasValue && scap.StartDate.Value.Year < invoicePeriod.StartDate.Year) // HP begann schon im letzten Jahr
{
vernetzung = new List<int> { 1, 2, 3, 4, 5 };
}
else
{
int monat = scap.StartDate.Value.Month;
int anzahl = 1;
while (anzahl <= 5)
{
vernetzung.Add(monat++);
anzahl++;
}
}
}
if (invoicePeriod.StartDateTime >= new DateTime(2025, 09, 01) && vernetzung.Contains(invoicePeriod.EndDate.Month))
{
var itemVernetzung = CreateVernetzungInvoiceItem(scap, invoicePeriod);
if (itemVernetzung != null)
{
serviceInvoicePeriod.InvoiceItemList.Add(itemVernetzung);
}
}
decimal count = 0;
foreach (var ii in serviceInvoicePeriod.InvoiceItemList)
{
count += ii.UnitCount ?? 0;
}
if (count > 0)
{
var itemInvest = CreateInvestInvoiceItem(scap, invoicePeriod, count, invoice.InvoiceBase.RecipientOrganisation);
if (itemInvest != null)
{
serviceInvoicePeriod.InvoiceItemList.Add(itemInvest);
}
}
}
}
private InvoiceItem CreateVernetzungInvoiceItem(SupportConceptApprovalPeriodDC scap, DateTimeSpan invoicePeriod)
{
var preisVernetzung = base.GetPreis("Team (extern)", invoicePeriod.StartDate);
var invoiceItem = new InvoiceItem();
invoiceItem.AmountPerUnit = preisVernetzung;
invoiceItem.UnitCount = 1;
invoiceItem.AmountTotal = invoiceItem.AmountPerUnit;
invoiceItem.RateFactor = null;
invoiceItem.ItemPeriodStart = invoicePeriod.StartDate;
invoiceItem.ItemPeriodEnd = invoicePeriod.EndDate;
invoiceItem.GrossAmountTotal = invoiceItem.AmountTotal;
invoiceItem.ItemDescription = String.Format("Team (extern)");
if (scap != null)
invoiceItem.SupportConceptApprovalPeriodOid = scap.SupportConceptApprovalPeriodOid;
return invoiceItem;
}
private InvoiceItem CreateTeamSitzungInvoiceItem(SupportConceptApprovalPeriodDC scap, DateTimeSpan invoicePeriod)
{
decimal betrag = 10.88m;
if (invoicePeriod.StartDateTime >= new DateTime(2019, 4, 1))
{
betrag = 11.26m;
}
if (invoicePeriod.StartDateTime >= new DateTime(2020, 3, 1))
{
betrag = 11.38m;
}
if (invoicePeriod.StartDateTime >= new DateTime(2021, 6, 1))
{
betrag = 11.63m;
}
if (invoicePeriod.StartDateTime >= new DateTime(2022, 4, 1))
{
betrag = 11.77m;
}
if (invoicePeriod.StartDateTime >= new DateTime(2023, 12, 1))
{
betrag = 12.81m;
}
if (invoicePeriod.StartDateTime >= new DateTime(2024, 03, 31))
{
betrag = 13.27m;
}
if (invoicePeriod.StartDateTime >= new DateTime(2024,08,01))
{
betrag = base.GetPreis("Team (intern)", invoicePeriod.StartDate);
}
var invoiceItem = new InvoiceItem();
invoiceItem.AmountPerUnit = betrag;
invoiceItem.UnitCount = 1;
invoiceItem.AmountTotal = invoiceItem.AmountPerUnit;
invoiceItem.RateFactor = null;
invoiceItem.ItemPeriodStart = invoicePeriod.StartDate;
invoiceItem.ItemPeriodEnd = invoicePeriod.EndDate;
invoiceItem.GrossAmountTotal = invoiceItem.AmountTotal;
invoiceItem.ItemDescription = String.Format("Team (intern)");
if (scap != null)
invoiceItem.SupportConceptApprovalPeriodOid = scap.SupportConceptApprovalPeriodOid;
return invoiceItem;
}
private InvoiceItem CreateInvestInvoiceItem(SupportConceptApprovalPeriodDC scap, DateTimeSpan invoicePeriod, decimal count, string costBearerName)
{
decimal betrag = 4.84m;
if (DateTime.Now >= new DateTime(2021, 8, 17))
{
betrag = 6.86m;
}
if (invoicePeriod.StartDateTime >= new DateTime(2024, 08, 01))
{
betrag = base.GetPreis("Invest (MQ)", invoicePeriod.StartDate);
}
if (invoicePeriod.StartDateTime >= new DateTime(2024, 09, 01))
{
if (costBearerName.Contains("(TS"))
{
betrag = base.GetPreis("Invest (TS)", invoicePeriod.StartDate);
}
}
var invoiceItem = new InvoiceItem();
invoiceItem.AmountPerUnit = betrag;
invoiceItem.UnitCount = count;
invoiceItem.AmountTotal = invoiceItem.AmountPerUnit * count;
invoiceItem.RateFactor = null;
invoiceItem.ItemPeriodStart = invoicePeriod.StartDate;
invoiceItem.ItemPeriodEnd = invoicePeriod.EndDate;
invoiceItem.GrossAmountTotal = invoiceItem.AmountTotal;
invoiceItem.ItemDescription = String.Format("Invest");
if (scap != null)
invoiceItem.SupportConceptApprovalPeriodOid = scap.SupportConceptApprovalPeriodOid;
return invoiceItem;
}
public override InvoiceItem CreateInvoiceItem(ServiceRecordDC iServiceRecord, SupportConceptApprovalPeriod scap, Calculations calc)
{
if (iServiceRecord.ServiceDescription.Name.Contains("Offenes Beratungsangebot"))
{
return null;
}
var ii = base.CreateInvoiceItem(iServiceRecord, scap, calc);
if (!ii.RateFactor.HasValue)
{
var rateFactor = iServiceRecord.CostBearer.CostRatePeriods.GetCostRatePeriodForDate(CostRatePeriodType.RateFactor, iServiceRecord.Start.Value);
if (rateFactor != null && rateFactor.CostRateValue.HasValue)
{
ii.RateFactor = rateFactor.CostRateValue;
}
InvoiceHelper.InitInvoiceItem(ii);
}
ii.ItemDescription = iServiceRecord.ServiceDescription.Name.Replace("IFS -", "").Trim();
return ii;
}
public override void SetServiceInvoicePeriods(ServiceInvoice invoice, CostBearer2SupportConcept costBearer2SupportConcept,
DateTimeSpan invoicePeriod, List<ServiceRecordDC> serviceRecords)
{
var invoiceAccountingPeriodSpan = new DateTimeSpan
{
StartDateTime = invoice.InvoiceBase.AccountingPeriodStart.Value,
EndDateTime = invoice.InvoiceBase.AccountingPeriodEnd.Value
};
foreach (SupportConceptApprovalPeriod iPeriod in costBearer2SupportConcept.ApprovalPeriodList)
{
SupportConceptApprovalPeriodDC approvalPeriodDC = MapperFactory.SupportConceptApprovalPeriodDC_SupportConceptApprovalPeriod.MapToNewDC(iPeriod);
if (costBearer2SupportConcept.SupportConcept.Customer.Person.LastName == "Achatz")
{
}
if (approvalPeriodDC.Span.EndDateTime < invoiceAccountingPeriodSpan.StartDateTime || approvalPeriodDC.Span.StartDateTime > invoiceAccountingPeriodSpan.EndDate)
{
continue;
}
if (iPeriod.ServiceCategory != null && serviceRecords.All(s => s.ServiceDescription.Category.ServiceCategoryOid != iPeriod.ServiceCategory.Oid))
{
continue;
}
ServiceInvoicePeriod serviceInvoicePeriod = CreateServiceInvoicePeriod(approvalPeriodDC, invoiceAccountingPeriodSpan);
serviceInvoicePeriod.SupportConceptApprovalPeriod = iPeriod;
serviceInvoicePeriod.Customer = costBearer2SupportConcept.SupportConcept.Customer;
CostBearer costBearer = costBearer2SupportConcept.CostBearer;
List<CostRatePeriodDC> costRates = MapperFactory.CostRatePeriodDC_CostRatePeriod.MapToNewDCs(costBearer.CostRatePeriods);
CostRatePeriodDC serviceUnit = costRates.GetCostRatePeriodForDate(CostRatePeriodType.MinutesPerServiceUnit, DateTime.Now);
serviceInvoicePeriod.ServiceUnitName = serviceUnit.UnitName;
Calculations calc = PluginLoader.FindClass<Calculations>(_SpecificID) ?? Calculations.GetInstance(_SpecificID);
if (iPeriod.ApprovedFixedAmount.HasValue && iPeriod.ServiceCategory != null && iPeriod.ServiceCategory.Name.Contains("Eingangsdiagnostik"))
{
serviceInvoicePeriod.ApprovedFixedAmount = iPeriod.ApprovedFixedAmount.Value;
}
else
{
decimal amountPerUnit;
decimal unitCount;
serviceInvoicePeriod.ApprovedFixedAmount = calc.GetApprovedFixedAmountForPeriod(approvalPeriodDC, serviceInvoicePeriod.Start.Value, serviceInvoicePeriod.End.Value, out amountPerUnit, out unitCount);
}
if (!serviceInvoicePeriod.ApprovedFixedAmount.HasValue)
{
serviceInvoicePeriod.ApprovedHours = calc.GetApprovedHoursForPeriod(approvalPeriodDC,
costRates,
serviceInvoicePeriod.Start.Value,
serviceInvoicePeriod.End.Value);
if (serviceInvoicePeriod.ApprovedHours.HasValue)
serviceInvoicePeriod.ApprovedBE = serviceUnit.GetHoursInBE(serviceInvoicePeriod.ApprovedHours.Value);
serviceInvoicePeriod.ApprovedAmountDefaultHourlyRate = calc.GetApprovedAmountDefaultHourlyRateForPeriod(approvalPeriodDC,
costRates,
serviceInvoicePeriod.Start,
serviceInvoicePeriod.End);
}
SetInvoiceItems(invoice, serviceInvoicePeriod, approvalPeriodDC, costBearer2SupportConcept, invoicePeriod, serviceRecords);
CheckMaxApprovedAmount(invoice, serviceInvoicePeriod, approvalPeriodDC, costBearer2SupportConcept, invoicePeriod, serviceRecords);
if (serviceInvoicePeriod.InvoiceItemList.Count > 0)
invoice.ServiceInvoicePeriodList.Add(serviceInvoicePeriod);
}
}
}
}