MH: VSD Hamm Kappung in der Sammelrechnung
SupportOID=168627
This commit is contained in:
@@ -25,7 +25,7 @@ namespace VSDHammReports.Invoicing
|
||||
// da nur hier noch die Wochen-/Monatszuordnung über ItemPeriodStart möglich ist.
|
||||
public override IList<InvoiceItem> CreateSummaryInvoiceItems(IList<InvoiceItem> itemList, DateTimeSpan invoicePeriod, SupportConceptApprovalPeriod scap, Calculations calc)
|
||||
{
|
||||
KappeBeiUeberschreitungDesIntervallBudgets(itemList, scap, calc);
|
||||
KappeBeiUeberschreitungDesIntervallBudgets(itemList, scap);
|
||||
return base.CreateSummaryInvoiceItems(itemList, invoicePeriod, scap, calc, false, true);
|
||||
}
|
||||
|
||||
@@ -40,6 +40,79 @@ namespace VSDHammReports.Invoicing
|
||||
base.CheckMaxApprovedAmount(invoice, sip, scap, costBearer2SupportConcept, invoicePeriod, serviceRecords);
|
||||
}
|
||||
|
||||
// Claude: Die im Report angezeigten Werte "bewilligte Stunden/Betrag im Zeitraum"
|
||||
// (xrTableCell18 = [ApprovedHours]/[ApprovedBE], xrTableCell29 = [ApprovedAmount])
|
||||
// an die Kappung angleichen. Die Basisklasse setzt sie über GetApprovedHoursForPeriod,
|
||||
// das bei Weekly/Monthly Std/Tag * Tage rechnet und den bewilligten Intervallwert verfehlt
|
||||
// (z.B. 5 h/Monat -> 4,93 h bei 30 Tagen). Hier wird stattdessen je vollem Kalenderintervall
|
||||
// der bewilligte Wert angesetzt - konsistent zur Kappung. Die Korrektur erfolgt auf der
|
||||
// Entity vor dem Mapping ins ReportObject, daher stimmen automatisch auch die Summen.
|
||||
public override void SetServiceInvoicePeriods(ServiceInvoice invoice, CostBearer2SupportConcept costBearer2SupportConcept, DateTimeSpan invoicePeriod, List<ServiceRecordDC> serviceRecords)
|
||||
{
|
||||
// Claude: Nur die in diesem Aufruf (= für diesen c2s) neu hinzugefügten Perioden nachziehen,
|
||||
// damit bei Sammelrechnungen keine Perioden anderer c2s mit falschen CostRates überschrieben werden.
|
||||
int startIndex = invoice.ServiceInvoicePeriodList.Count;
|
||||
|
||||
base.SetServiceInvoicePeriods(invoice, costBearer2SupportConcept, invoicePeriod, serviceRecords);
|
||||
|
||||
var costRates = MapperFactory.CostRatePeriodDC_CostRatePeriod.MapToNewDCs(costBearer2SupportConcept.CostBearer.CostRatePeriods);
|
||||
for (int i = startIndex; i < invoice.ServiceInvoicePeriodList.Count; i++)
|
||||
{
|
||||
ZieheBewilligtImZeitraumGleich(invoice.ServiceInvoicePeriodList[i], costRates);
|
||||
}
|
||||
}
|
||||
|
||||
private void ZieheBewilligtImZeitraumGleich(ServiceInvoicePeriod sip, List<CostRatePeriodDC> costRates)
|
||||
{
|
||||
if (sip.SupportConceptApprovalPeriod == null || !sip.Start.HasValue || !sip.End.HasValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var scapDC = MapperFactory.SupportConceptApprovalPeriodDC_SupportConceptApprovalPeriod.MapToNewDC(sip.SupportConceptApprovalPeriod);
|
||||
|
||||
if (!IstIntervallKappung(scapDC.ApprovedBEInterval, scapDC.ApprovedBEPerInterval, scapDC.IsApprovedBEShifting))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var serviceUnit = costRates.GetCostRatePeriodForDate(CostRatePeriodType.MinutesPerServiceUnit, sip.Start.Value);
|
||||
if (serviceUnit == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Claude: bewilligte Stunden je vollem Intervall (z.B. 5 h/Monat), unabhängig von der Kalenderlänge -
|
||||
// dieselbe Basis wie die Kappung in KappeBeiUeberschreitungDesIntervallBudgets.
|
||||
decimal stundenProIntervall = serviceUnit.GetBEInHours(scapDC.ApprovedBEPerInterval) ?? 0;
|
||||
|
||||
// Claude: Anzahl der vom Zeitraum berührten Kalenderintervalle (Wochen/Monate) - wie bei der Kappung,
|
||||
// wo jedes berührte Kalenderintervall sein volles Budget erhält.
|
||||
int anzahlIntervalle = ZaehleIntervalle(scapDC.ApprovedBEInterval.Value, sip.Start.Value, sip.End.Value);
|
||||
|
||||
decimal bewilligteStunden = stundenProIntervall * anzahlIntervalle;
|
||||
|
||||
sip.ApprovedHours = bewilligteStunden;
|
||||
sip.ApprovedBE = serviceUnit.GetHoursInBE(bewilligteStunden);
|
||||
|
||||
var hourlyRate = costRates.GetCostRatePeriodForDate(CostRatePeriodType.HourlyRate, sip.Start.Value);
|
||||
if (hourlyRate != null && hourlyRate.CostRateValue.HasValue)
|
||||
{
|
||||
sip.ApprovedAmountDefaultHourlyRate = bewilligteStunden * hourlyRate.CostRateValue.Value;
|
||||
}
|
||||
}
|
||||
|
||||
private int ZaehleIntervalle(SupportConceptApprovalInterval interval, DateTime start, DateTime end)
|
||||
{
|
||||
if (interval == SupportConceptApprovalInterval.Monthly)
|
||||
{
|
||||
return (end.Year * 12 + end.Month) - (start.Year * 12 + start.Month) + 1;
|
||||
}
|
||||
// Claude: Weekly - Anzahl berührter Kalenderwochen (Montag als Wochenstart).
|
||||
DateTime ersterMontag = start.GetLast(DayOfWeek.Monday).Date;
|
||||
return ((end.Date - ersterMontag).Days / 7) + 1;
|
||||
}
|
||||
|
||||
private bool IstIntervallKappung(SupportConceptApprovalInterval? approvedBEInterval, decimal? approvedBEPerInterval, bool isApprovedBEShifting)
|
||||
{
|
||||
return !isApprovedBEShifting &&
|
||||
@@ -48,7 +121,7 @@ namespace VSDHammReports.Invoicing
|
||||
approvedBEInterval.Value == SupportConceptApprovalInterval.Monthly);
|
||||
}
|
||||
|
||||
private void KappeBeiUeberschreitungDesIntervallBudgets(IList<InvoiceItem> itemList, SupportConceptApprovalPeriod scap, Calculations calc)
|
||||
private void KappeBeiUeberschreitungDesIntervallBudgets(IList<InvoiceItem> itemList, SupportConceptApprovalPeriod scap)
|
||||
{
|
||||
if (scap == null || itemList == null || itemList.Count == 0)
|
||||
{
|
||||
@@ -77,12 +150,16 @@ namespace VSDHammReports.Invoicing
|
||||
|
||||
if (!intervalMaxStunden.ContainsKey(intervalKey))
|
||||
{
|
||||
// Claude: Bewilligte Stunden für das volle Intervall über dieselbe Berechnung
|
||||
// ermitteln, mit der die Basisklasse auch ApprovedHours bestimmt (inkl. BE-Umrechnung).
|
||||
DateTime intervalEnde = interval == SupportConceptApprovalInterval.Weekly
|
||||
? intervalKey.AddDays(6)
|
||||
: intervalKey.AddMonths(1).AddDays(-1);
|
||||
intervalMaxStunden[intervalKey] = calc.GetApprovedHoursForPeriod(scapDC, costRates, intervalKey, intervalEnde) ?? 0;
|
||||
// Claude: Budget = die je Intervall bewilligten Stunden direkt aus der bewilligten BE-Menge.
|
||||
// NICHT über GetApprovedHoursForPeriod (= Stunden-pro-Tag * Tage), denn das schwankt mit der
|
||||
// Monats-/Wochenlaenge (z.B. 30 Tage -> 4,93 h, 31 Tage -> 5,10 h) und trifft die bewilligten
|
||||
// 5 h fast nie exakt, wodurch bei der Kappung ein Rest-Euro fehlt oder zu viel entsteht.
|
||||
// GetBEInHours liefert fuer ein volles Intervall exakt den bewilligten Wert (z.B. 5 h) -
|
||||
// genau wie die Basisklasse es in GetApprovedHoursPerWeek fuer Weekly macht.
|
||||
var serviceUnit = costRates.GetCostRatePeriodForDate(CostRatePeriodType.MinutesPerServiceUnit, ii.ItemPeriodStart.Value);
|
||||
intervalMaxStunden[intervalKey] = serviceUnit != null
|
||||
? (serviceUnit.GetBEInHours(scapDC.ApprovedBEPerInterval) ?? 0)
|
||||
: 0;
|
||||
}
|
||||
decimal maxStunden = intervalMaxStunden[intervalKey];
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace VSDHammReports
|
||||
double total = 0;
|
||||
foreach (var value in dict.Values)
|
||||
{
|
||||
if (!value.ServiceDescription.Contains("80"))
|
||||
if (!value.ServiceDescription.Contains("80") && !value.ServiceDescription.Contains("fehlkontakt ohne"))
|
||||
{
|
||||
value.Minutes *= (double)rateFactor;
|
||||
}
|
||||
|
||||
@@ -30,9 +30,9 @@ namespace VSDHammReports
|
||||
}
|
||||
|
||||
if (item.ServiceDescription.ToLower().Contains("fehlkontakt"))
|
||||
summeFehlkontakte += item.UnitCount.Value * item.AmountPerUnit.Value * faktor;
|
||||
summeFehlkontakte += item.UnitCount.Value * item.AmountPerUnit.Value;
|
||||
else
|
||||
summeFachleistungen += item.UnitCount.Value * item.AmountPerUnit.Value * faktor;
|
||||
summeFachleistungen += item.UnitCount.Value * item.AmountPerUnit.Value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user