MH: EndartFabrik Kappung von InvoiceItems Faktor Fix

This commit is contained in:
2026-05-27 16:09:26 +02:00
parent 1b4c640004
commit 671cd2de67

View File

@@ -74,26 +74,24 @@ namespace EndartFabrik.Invoicing
if (!ii.UnitCount.HasValue)
continue;
// Claude: Multiplikator aus dem RateFactor berechnen (z.B. 20% → rf = 1,2)
// Claude: RateFactor-Multiplikator nur für die Betragsberechnung vormerken, NICHT für den Budgetvergleich
decimal rf = 1;
if (ii.RateFactor.HasValue && ii.RateFactor.Value != 0)
rf = (100 + ii.RateFactor.Value) / 100;
// Claude: Effektive Stunden inkl. Faktor ermitteln, dann auf verbleibendes Budget kappen
var countMitFactorVoll = Math.Round(ii.UnitCount.Value * rf, 2, MidpointRounding.AwayFromZero);
var countMitFactor = countMitFactorVoll;
if (maxApproved < countMitFactor)
countMitFactor = maxApproved;
// Claude: Rohstunden (ohne Faktor) ermitteln und gegen verbleibendes Budget kappen
var rawCount = Math.Round(ii.UnitCount.Value, 2, MidpointRounding.AwayFromZero);
var cappedRawCount = rawCount;
if (maxApproved < cappedRawCount)
cappedRawCount = maxApproved;
// Claude: Verbrauchte effektive Stunden vom Restbudget abziehen
maxApproved -= countMitFactor;
// Claude: Verbrauchte Rohstunden vom Restbudget abziehen (Faktor hat keinen Einfluss auf das Budget)
maxApproved -= cappedRawCount;
if (ii.AmountPerUnit.HasValue)
{
var unitCountVoll = ii.UnitCount;
// Claude: Teilkappung ein separates Item für die weggekappten Stunden anlegen (wird ohne Betrag dargestellt)
if (countMitFactorVoll - countMitFactor > 0 && countMitFactor != 0)
// Claude: Teilkappung separates Item für die weggekappten Rohstunden anlegen (ohne Betrag)
if (rawCount - cappedRawCount > 0 && cappedRawCount != 0)
{
gekapptesItem = new InvoiceItem
{
@@ -106,25 +104,25 @@ namespace EndartFabrik.Invoicing
MaxApprovedUnitCount = ii.MaxApprovedUnitCount,
RateFactor = ii.RateFactor,
SupportConceptApprovalPeriodOid = ii.SupportConceptApprovalPeriodOid,
UnitCount = countMitFactorVoll - countMitFactor,
UnitCount = rawCount - cappedRawCount,
UnitDescription = ii.UnitDescription
// GrossAmountTotal bleibt null → 0 EUR
};
}
// Claude: UnitCount auf die abrechenbaren effektiven Stunden (inkl. Faktor) setzen
ii.UnitCount = countMitFactor;
// Claude: UnitCount auf die abrechenbaren Rohstunden setzen (ohne Faktor)
ii.UnitCount = cappedRawCount;
if (countMitFactor != 0)
if (cappedRawCount != 0)
{
// Claude: Betrag aus abrechenbaren Stunden × Stundensatz berechnen (Faktor bereits in UnitCount enthalten)
// Claude: Nettobetrag aus Rohstunden × Stundensatz, Faktor erst beim Bruttobetrag anwenden
ii.AmountTotal = ii.UnitCount.Value * ii.AmountPerUnit.Value;
ii.GrossAmountTotal = Math.Round(ii.AmountTotal.Value, 2, MidpointRounding.AwayFromZero);
ii.GrossAmountTotal = Math.Round(ii.AmountTotal.Value * rf, 2, MidpointRounding.AwayFromZero);
}
else
{
// Claude: Vollständige Kappung UnitCount für Anzeige wiederherstellen, aber 0 EUR abrechnen
ii.UnitCount = unitCountVoll.Value * rf;
// Claude: Vollständige Kappung Rohstunden für Anzeige wiederherstellen, aber 0 EUR abrechnen
ii.UnitCount = rawCount;
ii.AmountTotal = null;
ii.GrossAmountTotal = null;
}