Files
BeWoPlaner/ReportImp/AkggMid/LeistungsnachweisHelper.cs
2023-03-06 16:45:02 +01:00

359 lines
12 KiB
C#

using BeWo.Data.Access;
using BeWo.Report.ReportObjects;
using BS.Shared.Core;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AkggMid
{
public class LeistungsnachweisHelper
{
public static List<ServicesOverviewRO.ServiceDetail> ErstelleDummyRecords(ServicesOverviewRO pRO)
{
Dictionary<int, ServicesOverviewRO.ServiceDetail> day2Detail = new Dictionary<int, ServicesOverviewRO.ServiceDetail>();
var result = new List<ServicesOverviewRO.ServiceDetail>();
foreach (var sr in pRO.Services)
{
//result.Add(sr);
if (!day2Detail.ContainsKey(sr.StartDate.Day))
{
sr.StartDateString = String.Format("{0:dd}.", sr.StartDate);
day2Detail.Add(sr.StartDate.Day, sr);
result.Add(sr);
}
else
{
var dsr = day2Detail[sr.StartDate.Day];
dsr.Minutes += sr.Minutes;
if (!String.IsNullOrWhiteSpace(sr.Notice))
{
if (!String.IsNullOrWhiteSpace(dsr.Notice))
{
dsr.Notice += ", " + sr.Notice;
}
else
{
dsr.Notice = sr.Notice;
}
}
if (!String.IsNullOrWhiteSpace(sr.Notice3))
{
if (!String.IsNullOrWhiteSpace(dsr.Notice3))
{
dsr.Notice3 += ", " + sr.Notice3;
}
else
{
dsr.Notice3 = sr.Notice3;
}
}
if (!String.IsNullOrWhiteSpace(sr.Notice4))
{
if (!String.IsNullOrWhiteSpace(dsr.Notice4))
{
dsr.Notice4 += ", " + sr.Notice4;
}
else
{
dsr.Notice4 = sr.Notice4;
}
}
}
}
var abrAbwTagDict = GetAbrechenbareAbwesenheiten(pRO);
for (int i = 1; i <= 31; i++)
{
if (!day2Detail.ContainsKey(i))
{
var newSr = new ServicesOverviewRO.ServiceDetail();
if (i <= pRO.EndDate.Day)
{
newSr.StartDate = new DateTime(pRO.StartDate.Year, pRO.StartDate.Month, i);
newSr.StartDateString = String.Format("{0:dd}.", newSr.StartDate);
if (abrAbwTagDict.ContainsKey(newSr.StartDate))
{
newSr.Minutes = BerechneMinutenProTag(BerechneStundenProWoche(pRO, newSr.StartDate));
newSr.Notice = "Erster Tag Abwesenheit";
}
}
else
{
newSr.StartDateString = String.Format("{0}.", i);
}
result.Add(newSr);
day2Detail.Add(i, newSr);
}
else
{
day2Detail[i].Minutes = Rundeauf15Minuten(day2Detail[i].Minutes);
}
}
double minutenGesamt = 0;
foreach (var record in result)
{
if (IstAbwesend(pRO, record.StartDate))
{
record.Notice5 = "x";
}
else
{
record.Notice5 = "";
}
minutenGesamt += record.Minutes;
}
pRO.TotalFLM = minutenGesamt;
return result.OrderBy(r => r.StartDateString).ToList();
}
public static void PruefeWochenBudget(ServicesOverviewRO ro)
{
Calendar cal = CultureInfo.CurrentCulture.Calendar;
var ersterTag = new DateTime(ro.StartDate.Year, ro.StartDate.Month, 1);
//Laut Herr Kloss darf die Wochenbewilligung nicht überschritten werden und die letzten Einträge einer Kalenderwoche sollen entsprechend gekürzt werden.
var tempListe = new List<ServicesOverviewRO.ServiceDetail>();
tempListe.AddRange(HoleFehlendeWochentageVormonat(ro));
tempListe.AddRange(ro.Services);
int kwAktuelleWoche = cal.GetWeekOfYear(ersterTag, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
double wochenSumme = 0;
foreach (var item in tempListe)
{
// Übertrags Dummy rausfiltern
if (item.ServiceDescription == "Übertrag:")
continue;
var kwAktuellerTag = cal.GetWeekOfYear(item.StartDate, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
if (kwAktuelleWoche != kwAktuellerTag)
{
kwAktuelleWoche = kwAktuellerTag;
wochenSumme = 0;
}
wochenSumme += item.Minutes / 60;
double wochenBudget = BerechneStundenProWoche(ro, item.StartDate);
if (wochenSumme > wochenBudget)
{
item.Minutes -= (double)(wochenSumme - wochenBudget) * 60;
if (item.Minutes < 0)
{
item.Minutes = 0;
}
}
}
double minutenGesamt = 0;
foreach (var record in ro.Services)
{
minutenGesamt += record.Minutes;
}
ro.TotalFLM = minutenGesamt;
}
private static double BerechneStundenProWoche(ServicesOverviewRO ro, DateTime datum)
{
if (ro.SupportConceptCostBearer != null)
{
decimal wochenGesamtBudget = 0;
foreach (var ap in ro.SupportConceptCostBearer.ApprovalPeriodList)
{
if (ap.StartDate <= datum.Date && ap.EndDate >= datum.Date && ap.ApprovedBEInterval.Value == BS.Shared.SupportConceptApprovalInterval.Weekly)
{
var wochenBudget = ap.ApprovedBEPerInterval ?? 0;
decimal prozentualeBetreuung = 0;
foreach (var item in ap.SupportConceptApprovalPeriodEmployeeRelations)
{
if (!item.IsAbsolut)
{
prozentualeBetreuung += item.Betreuungsschluessel;
}
}
if (prozentualeBetreuung > 0)
{
wochenBudget *= prozentualeBetreuung / 100;
}
wochenGesamtBudget += wochenBudget;
}
}
if (wochenGesamtBudget > 0)
{
return (double)Math.Round(wochenGesamtBudget, 2, MidpointRounding.AwayFromZero);
}
}
return (double)ro.ApprovedFLSPerWeek;
}
private static IEnumerable<ServicesOverviewRO.ServiceDetail> HoleFehlendeWochentageVormonat(ServicesOverviewRO ro)
{
var fehlendeRecords = new List<ServicesOverviewRO.ServiceDetail>();
var ersterDesMonats = new DateTime(ro.StartDate.Year, ro.StartDate.Month, 1);
if (ersterDesMonats.DayOfWeek != DayOfWeek.Monday)
{
if (ro.SupportConceptCostBearer != null && ro.SupportConceptCostBearer.CostBearer2SupportConceptOid != null)
{
var startDate = ersterDesMonats;
while (startDate.DayOfWeek != DayOfWeek.Monday)
{
startDate = startDate.AddDays(-1);
}
var span = new DateTimeSpan(startDate, ersterDesMonats);
var liste = DAOFactory.SearchDAO.FindServiceRecordsInSpan(ro.SupportConceptCostBearer.CostBearer2SupportConceptOid.Value, span);
foreach (var item in liste)
{
var newRecord = new ServicesOverviewRO.ServiceDetail();
newRecord.StartDate = item.Start.Value;
newRecord.Minutes = (double)item.RoundedDuration;
fehlendeRecords.Add(newRecord);
}
}
}
return fehlendeRecords.OrderBy(r => r.StartDate);
}
public static bool IstAbwesend(ServicesOverviewRO pRO, DateTime startDate)
{
foreach (var at in pRO.Abwesenheiten)
{
if (startDate >= at.Start && (!at.End.HasValue || startDate <= at.End))
{
return true;
}
}
return false;
}
public static Dictionary<DateTime, bool> GetAbrechenbareAbwesenheiten(ServicesOverviewRO ro)
{
//Herr Kloss meint, der erste Tag einer Abwesenheit darf ein fünftel der Wochenstundenzahl abgerechnet werden, aber nur bis 5 mal im Zeitraum 01.01.2022 bis 30.06.2022 und bis 10 mal im Schuljahr ab 2023/2024
DateTime startSchuljahr = DateTime.MinValue;
DateTime endeSchuljahr = DateTime.MinValue;
DateTime dt;
if (DateTime.TryParse(ro.ApprovedStartDate, out dt))
{
startSchuljahr = dt;
}
if (DateTime.TryParse(ro.ApprovedEndDate, out dt))
{
endeSchuljahr = dt;
}
int maxAnzahl = 10;
if (startSchuljahr < new DateTime(2022, 6, 30))
{
startSchuljahr = new DateTime(2022, 1, 1);
endeSchuljahr = new DateTime(2022, 6, 30);
maxAnzahl = 5;
}
int gesamtAnzahl = 0;
Dictionary<DateTime, bool> abrechenbareTage = new Dictionary<DateTime, bool>();
DateTime lastend = DateTime.MinValue;
foreach (var at in ro.Abwesenheiten) //sortieren?
{
if (at.Start >= startSchuljahr && at.Start <= endeSchuljahr && (at.End == null || at.End >= startSchuljahr))
{
//Prüfe ob mindestens ein Tag zwischen zwei Abwesenheiten liegt.
var days = at.Start.Value.Subtract(lastend).TotalDays;
if (days > 1)
{
if (gesamtAnzahl <= maxAnzahl)
{
abrechenbareTage.Add(at.Start.Value, true);
gesamtAnzahl++;
}
}
}
if (at.End.HasValue)
{
lastend = at.End.Value;
}
else
{
lastend = DateTime.MaxValue;
}
}
return abrechenbareTage;
}
public static double BerechneMinutenProTag(double flsPerWeek)
{
var minutenProTag = flsPerWeek * 60 / 5;
//die Minuten müssen auf volle Viertelstunden auf oder abgerundet werden
return Rundeauf15Minuten(minutenProTag);
}
public static double Rundeauf15Minuten(double minuten)
{
var minutenGerundet = minuten;
//die Minuten müssen auf volle Viertelstunden auf oder abgerundet werden
var modulo = minutenGerundet % 15;
if (modulo <= 7)
{
minutenGerundet -= modulo;
}
else
{
minutenGerundet += 15 - modulo;
}
return minutenGerundet;
}
}
}