389 lines
17 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|
|
}
|