From 0e80ae2499f46f7a16a7c1b05d7cdbc542ed2d82 Mon Sep 17 00:00:00 2001 From: Marcel Hirschle Date: Fri, 10 Feb 2023 10:01:01 +0100 Subject: [PATCH] MH: Rundung input Familienhilfe --- .../InputFamilienhilfe.csproj | 1 + .../CustomSettlementInvoiceCreation.cs | 368 ++++++++++++++++++ 2 files changed, 369 insertions(+) create mode 100644 ReportImp/InputFamilienhilfe/Invoicing/CustomSettlementInvoiceCreation.cs diff --git a/ReportImp/InputFamilienhilfe/InputFamilienhilfe.csproj b/ReportImp/InputFamilienhilfe/InputFamilienhilfe.csproj index f8e5d0258..3a3db7da5 100644 --- a/ReportImp/InputFamilienhilfe/InputFamilienhilfe.csproj +++ b/ReportImp/InputFamilienhilfe/InputFamilienhilfe.csproj @@ -63,6 +63,7 @@ InvoiceCustomerReport.cs + diff --git a/ReportImp/InputFamilienhilfe/Invoicing/CustomSettlementInvoiceCreation.cs b/ReportImp/InputFamilienhilfe/Invoicing/CustomSettlementInvoiceCreation.cs new file mode 100644 index 000000000..984e817b3 --- /dev/null +++ b/ReportImp/InputFamilienhilfe/Invoicing/CustomSettlementInvoiceCreation.cs @@ -0,0 +1,368 @@ +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.Extensions; +using BS.Shared.Services; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace InputFamilienhilfe.Invoicing +{ + class CustomSettlementInvoiceCreation : SettlementInvoiceCreation + { + public override void CreateInvoiceDetailsTheOldWay(Settlement2DC si, CostBearer2SupportConcept c2s) + { + bool isLWL = false; + String id = c2s.CostBearer.ID; + if (String.IsNullOrEmpty(id)) + { + if (!String.IsNullOrEmpty(si.RecipientOrganisation) && si.RecipientOrganisation.Trim().ToLower().IndexOf("lwl") == 0) + { + isLWL = true; + id = "LWL"; + } + + } + var calc = PluginLoader.FindClass(id) ?? Calculations.GetInstance(id); + var relDC = c2s.MapToNewDC(); + + decimal lDurationInWeeks = + calc.GetIntervalCountForDays( + Convert.ToDecimal((c2s.EndDate.Value - c2s.StartDate.Value).Days + 1), + SupportConceptApprovalInterval.Weekly); + + decimal lApprovedFLSWeeklyForMaxAmountCalculation = 0; + + CalculateSettlementInvoiceApprovedAmounts(si, relDC, calc); + + DateTime periodStart = si.AccountingPeriodStart.Value.Date; + DateTime periodEnd = si.AccountingPeriodEnd.Value.Date; + + //Prüfe ob vorher abgemeldet + if (c2s.SupportConcept.Customer.TerminationDate.HasValue && + c2s.SupportConcept.Customer.TerminationDate.Value < periodEnd) + { + periodEnd = c2s.SupportConcept.Customer.TerminationDate.Value; + si.ErrorNotice = + String.Format( + "Achtung: Die Betreuung endete am {0:dd.MM.yyyy}. Alle nachträglich eingegebenen Stunden werden nicht abgerechnet!", + periodEnd); + + } + //Prüfe ob Enddatum in Zukunft liegt: + if (periodEnd > DateTime.Now) + { + var srList = c2s.ServiceRecords; + + var max = srList.Max(s => s.End); + + if (max.HasValue && max < periodEnd) + { + periodEnd = max.Value; + } + } + + + var tolerancesInSpanList = relDC.CostBearer.CostRatePeriods.GetSpans(CostRatePeriodType.ServiceTolerance, periodStart, periodEnd).ToList(); + + var hourlyRatesInSpanList = relDC.CostBearer.CostRatePeriods.GetSpans(CostRatePeriodType.HourlyRate, periodStart, periodEnd).ToList(); + + si.DifferentHourlyRateCount = hourlyRatesInSpanList.Count; + + if (hourlyRatesInSpanList.Count > 1) + { + if (hourlyRatesInSpanList.Count == 2) + { + si.WeeksWithOldHourlyRate = + calc.GetIntervalCountForDays(Convert.ToDecimal(hourlyRatesInSpanList.First().Value.GetTimeSpan().Days + 1), + SupportConceptApprovalInterval.Weekly); + si.WeeksWithNewHourlyRate = + calc.GetIntervalCountForDays( + Convert.ToDecimal((c2s.EndDate.Value - hourlyRatesInSpanList.Last().Value.StartDate).Days + 1), + SupportConceptApprovalInterval.Weekly); + si.WeeksWithHourlyRate3 = 0; + } + else if (hourlyRatesInSpanList.Count == 3) + { + si.WeeksWithHourlyRate3 = + calc.GetIntervalCountForDays(Convert.ToDecimal(hourlyRatesInSpanList.First().Value.GetTimeSpan().Days + 1), + SupportConceptApprovalInterval.Weekly); + si.WeeksWithOldHourlyRate = + calc.GetIntervalCountForDays(Convert.ToDecimal(hourlyRatesInSpanList.ElementAt(1).Value.GetTimeSpan().Days + 1), + SupportConceptApprovalInterval.Weekly); + si.WeeksWithNewHourlyRate = + calc.GetIntervalCountForDays( + Convert.ToDecimal((c2s.EndDate.Value - hourlyRatesInSpanList.Last().Value.StartDate).Days + 1), + SupportConceptApprovalInterval.Weekly); + } + } + else + { + si.WeeksWithNewHourlyRate = lDurationInWeeks; + } + + decimal currentRateFactor = 0; + decimal currentHourlyRate = 0; + + decimal lastHourlyRate = 0; + decimal thirdHourlyRate = 0; + + var rateFactorsInSpanList = relDC.CostBearer.CostRatePeriods.GetSpans(CostRatePeriodType.RateFactor, periodStart, periodEnd).ToList(); + + if (hourlyRatesInSpanList.Count > 0) + { + var cdc = hourlyRatesInSpanList.Last().Key; + if (cdc.CostRateValue.HasValue) + currentHourlyRate = cdc.CostRateValue.Value; + } + + if (rateFactorsInSpanList.Count > 0) + { + var cdc = rateFactorsInSpanList.Last().Key; + if (cdc.CostRateValue.HasValue) + currentRateFactor = cdc.CostRateValue.Value; + } + + + if (hourlyRatesInSpanList.Count > 1) + { + var cdc = hourlyRatesInSpanList[hourlyRatesInSpanList.Count - 2].Key; + if (cdc.CostRateValue.HasValue) + lastHourlyRate = cdc.CostRateValue.Value; + si.HourlyRateOldEndDate = hourlyRatesInSpanList[hourlyRatesInSpanList.Count - 2].Value.EndDate; + si.HourlyRateNewStartDate = hourlyRatesInSpanList[hourlyRatesInSpanList.Count - 1].Value.StartDate; + } + + if (hourlyRatesInSpanList.Count > 2) + { + var cdc = hourlyRatesInSpanList[hourlyRatesInSpanList.Count - 3].Key; + if (cdc.CostRateValue.HasValue) + thirdHourlyRate = cdc.CostRateValue.Value; + si.HourlyRateEndDate3 = hourlyRatesInSpanList[hourlyRatesInSpanList.Count - 3].Value.EndDate; + si.HourlyRateOldStartDate = hourlyRatesInSpanList[hourlyRatesInSpanList.Count - 2].Value.StartDate; + } + + if (si.ApprovedFLSWeekly == null) + { + si.ApprovedFLSWeekly = 0; + } + + + //decimal maxAmount = 0; + + //decimal maxFLS = lApprovedFLSWeeklyForMaxAmountCalculation * si.WeeksWithNewHourlyRate; + //maxFLS += lApprovedFLSWeeklyForMaxAmountCalculation * si.WeeksWithOldHourlyRate; + //maxFLS += lApprovedFLSWeeklyForMaxAmountCalculation * si.WeeksWithHourlyRate3; + + si.RateFactor = currentRateFactor; + si.HourlyRateNew = currentHourlyRate; + + si.HourlyRateOld = lastHourlyRate; + si.HourlyRate3 = thirdHourlyRate; + + //decimal totalAmount = 0; + + + var records = GetBillableServiceRecords(c2s); + + records = + records.Where(i => i.Start.HasValue && i.Start.Value.InBetween(periodStart, periodEnd, true)).ToList(); + + + var recordDCS = records.MapToNewDCs(); + + var absenceTimes = MapperFactory.AbsenceTimeDC_AbsenceTime.MapToNewDCs(c2s.SupportConcept.Customer.AbsenceTimes); + Dictionary span2Hours = calc.GetAbsencesTimesNotBillable(absenceTimes); + + + si.RecordedBillableFLSNotBillableCustomerAbsent + = calc.GetHoursNotBillableDueToAbsenceTimes(relDC, recordDCS, + span2Hours, false, false); + + si.RecordedBillableFLSNotBillableOutOfApprovedSpan = calc.GetHoursNotBillableDueToOutOfSpan(relDC, recordDCS); + //calc.GetHoursNotBillableDueToMoreThanApproved(relDC, recordDCS, false, false); + + Dictionary groupBookingDict = new Dictionary(); + + decimal flsCleared = 0; + records = + records.OrderBy(sr => sr.Start.HasValue ? sr.Start.Value : DateTime.MinValue) + .ToList(); + + decimal tolerance = 100; + if (tolerancesInSpanList.Count > 0) + { + if (tolerancesInSpanList[0].Key.CostRateValue.HasValue && tolerancesInSpanList[0].Key.CostRateValue.Value > 0) + { + tolerance = tolerancesInSpanList[0].Key.CostRateValue ?? 100; + } + } + + decimal approved = si.ApprovedFLS ?? 0; + if (tolerance != 100) + { + approved = (approved * tolerance) / 100m; + } + + if (!CheckMaxApprovedHours()) + { + approved = Decimal.MaxValue; + } + foreach (var iRecord in records) + { + if (iRecord.ServiceDescription.ServiceCategory.IsBillable && IsServiceRecordBillable(iRecord)) + { + if (iRecord.GroupOid == null || !groupBookingDict.ContainsKey(iRecord.GroupOid.Value)) + { + // + if (iRecord.GroupPersonCount != null || iRecord.GroupPersonCount > 0) + iRecord.RoundedDuration = iRecord.GroupRoundedDuration.Value / iRecord.GroupPersonCount.Value; + decimal rd = iRecord.RoundedDuration; + var prozent = iRecord.ServiceDescription.ServiceCategory.ProzentAbrechnung; + if (iRecord.ServiceDescription.ProzentAbrechnung.HasValue) + { + prozent = iRecord.ServiceDescription.ProzentAbrechnung.Value; + } + rd = (rd * prozent) / 100; + + decimal duration = rd / 60; + if (si.RecordedBillableFLSBrutto == null) + { + si.RecordedBillableFLSBrutto = 0; + } + + si.RecordedBillableFLSBrutto += duration; + si.RecordedBillableFLSNetto += duration; + + + //if (maxAmount == 0) + //{ + if (flsCleared + duration > approved) + { + duration = approved - flsCleared; + flsCleared = approved; + } + else + { + flsCleared += duration; + } + //} + + //decimal? hourlyRate = null; + //decimal? rateFactor = null; + + var rates = c2s.CostBearer.CostRatePeriods.MapToNewDCs(); + //if (iRecord.Start != null) + //{ + + // hourlyRate = rates.GetValidRateValueForDate(CostRatePeriodType.HourlyRate, iRecord.Start.Value); + // rateFactor = rates.GetValidRateValueForDate(CostRatePeriodType.RateFactor, iRecord.Start.Value); + + //} + //else + //{ + // hourlyRate = rates.GetCurrentlyValidRateValue(CostRatePeriodType.HourlyRate); + // rateFactor = rates.GetCurrentlyValidRateValue(CostRatePeriodType.RateFactor); + //} + //if (!hourlyRate.HasValue) + // hourlyRate = 0; + //if (!rateFactor.HasValue) + // rateFactor = 0; + + if (hourlyRatesInSpanList.Count > 2 && iRecord.Start != null && + iRecord.Start < hourlyRatesInSpanList[hourlyRatesInSpanList.Count - 2].Value.StartDateTime) + { + si.ApprovedFLSWithHourlyRate3 += duration; + } + else if (hourlyRatesInSpanList.Count > 1 && iRecord.Start != null && + iRecord.Start < hourlyRatesInSpanList[hourlyRatesInSpanList.Count - 1].Value.StartDateTime) + { + si.ApprovedFLSWithOldHourlyRate += duration; + } + else + { + si.ApprovedFLSWithActualHourlyRate += duration; + } + + if (iRecord.GroupOid != null && !groupBookingDict.ContainsKey(iRecord.GroupOid.Value)) + { + si.HasGroupRecords = true; + groupBookingDict.Add(iRecord.GroupOid.Value, true); + } + + } + } + } + + si.ApprovedFLSWithActualHourlyRate = Math.Round(si.ApprovedFLSWithActualHourlyRate, 2, MidpointRounding.AwayFromZero); + si.ApprovedFLSWithHourlyRate3 = Math.Round(si.ApprovedFLSWithHourlyRate3, 2, MidpointRounding.AwayFromZero); + si.ApprovedFLSWithOldHourlyRate = Math.Round(si.ApprovedFLSWithOldHourlyRate, 2, MidpointRounding.AwayFromZero); + + decimal rf = 1; + if (si.RateFactor.HasValue && si.RateFactor.Value != 0) + { + rf = si.RateFactor.Value; + rf = (100 + rf) / 100; + } + + decimal roundedNewAmount = 0; + decimal amountRateFactor = 0; + + if (si.HourlyRateNew.HasValue) + { + + roundedNewAmount = Math.Round(si.ApprovedFLSWithActualHourlyRate * si.HourlyRateNew.Value * rf, 2, + MidpointRounding.AwayFromZero); + amountRateFactor = + Math.Round( + roundedNewAmount - + Math.Round(si.ApprovedFLSWithActualHourlyRate * si.HourlyRateNew.Value, 2, MidpointRounding.AwayFromZero), 2, + MidpointRounding.AwayFromZero); + } + if (si.HourlyRateOld.HasValue) + { + decimal a2 = Math.Round(si.ApprovedFLSWithOldHourlyRate * si.HourlyRateOld.Value * rf, 2, MidpointRounding.AwayFromZero); + roundedNewAmount += a2; + amountRateFactor += + Math.Round( + a2 - Math.Round(si.ApprovedFLSWithOldHourlyRate * si.HourlyRateOld.Value, 2, MidpointRounding.AwayFromZero), 2, + MidpointRounding.AwayFromZero); + } + if (si.HourlyRate3 > 0) + { + decimal a3 = Math.Round(si.ApprovedFLSWithHourlyRate3 * si.HourlyRate3 * rf, 2, MidpointRounding.AwayFromZero); + roundedNewAmount += a3; + amountRateFactor += + Math.Round(a3 - Math.Round(si.ApprovedFLSWithHourlyRate3 * si.HourlyRate3, 2, MidpointRounding.AwayFromZero), 2, + MidpointRounding.AwayFromZero); + } + + si.AmountWithRateFactor += amountRateFactor; + + var totalAmount = Math.Round(roundedNewAmount, 2, MidpointRounding.AwayFromZero); + + decimal? maxAmount = CalculateMaxAmount(si); + + if (maxAmount.HasValue && totalAmount > maxAmount.Value) + { + totalAmount = maxAmount.Value; + } + si.AmountBillableTotal = totalAmount; + + //AdvancedPayments + CalculateAdvancedPayments(si, c2s, null, null, hourlyRatesInSpanList); + //EquityContribution (Eigenanteil) + CalculateEquityContribution(si, c2s.SupportConcept, null, null); + + si.Claim = si.AmountBillableTotal - (si.AmountAdvancedPayments ?? 0) - si.EquityContribution; + + } + } +}