Files
BeWoPlaner/ReportImp/AkggMid/LeistungsnachweisHelper.cs
Christian 4e7d7426ec Fibu Übergabeprotokoll ASB Rhein Ruhr+Die Perspektiven
+ Bugfix fehlendes Icon im Kalender nach Übertrag in Zeiterfassung
2023-03-28 00:02:15 +02:00

508 lines
19 KiB
C#

using BeWo.Data.Access;
using BeWo.Data.Entities;
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
{
private ServicesOverviewRO servicesOverviewRO;
private LeistungsnachweisHelper tandemBetreuungHelper = null;
public LeistungsnachweisHelper(ServicesOverviewRO ro, bool checkMehrfachBetreuung)
{
servicesOverviewRO = ro;
//Pruefe ob eine 1 zu 2 Betreuung vorliegt
if (checkMehrfachBetreuung)
{
var customers = Get1Zu2BetreuungCustomerOids();
if (customers.Count > 1)
{
foreach (var oid in customers)
{
if (oid != ro.CustomerOid)
{
//public static ServicesOverviewRO Create(long pCustomerOid, int pMonth, int pYear, bool disableEmptySupportConcepts, long orgaOid, long empOid, int start, int end, bool searchServiceRecordsByEndDate, long? serviceCategoryOid = null, bool checkQbStatus = false)
var tandemBetreuungRO = ServicesOverviewRO.Create(oid, ro.StartDate.Month, ro.StartDate.Year, false, 0, 0, ro.StartDate.Day, ro.EndDate.Day, null);
tandemBetreuungHelper = new LeistungsnachweisHelper(tandemBetreuungRO, false);
}
}
}
}
}
public 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:dddd dd.MM.}", 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();
double wochensumme = 0;
for (int i = 1; i <= pRO.EndDate.Day; i++)
{
if (!day2Detail.ContainsKey(i))
{
//Erstelle Dummy Records für fehlende Tage
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:dddd dd.MM.}", newSr.StartDate);
if (abrAbwTagDict.ContainsKey(newSr.StartDate))
{
newSr.Minutes = BerechneMinutenProTag(BerechneStundenProWoche(pRO, newSr.StartDate));
newSr.Notice = "Abwesenheit (erstattet)";
}
}
else
{
newSr.StartDateString = String.Format("", i);
}
result.Add(newSr);
day2Detail.Add(i, newSr);
}
else
{
//day2Detail[i].Minutes = Rundeauf15Minuten(day2Detail[i].Minutes);
}
//Erstelle Dummy Record für Wochensumme
var record = day2Detail[i];
day2Detail[i].TimeRangeString = String.Format("{0:00}", i); // Benutzer TimeRangeString für die Sortierung
wochensumme += record.Minutes;
if (record.StartDate.DayOfWeek == DayOfWeek.Friday || i == pRO.EndDate.Day)
{
var newSr = new ServicesOverviewRO.ServiceDetail();
newSr.StartDateString = "";
newSr.Notice = "Wochensumme";
newSr.IstFerien = true;
newSr.TimeRangeString = String.Format("{0:00}z", i);
newSr.Minutes = Rundeauf15Minuten(wochensumme);
wochensumme = 0;
result.Add(newSr);
}
}
double minutenGesamt = 0;
foreach (var record in result)
{
if (record.StartDate.DayOfWeek != DayOfWeek.Saturday && record.StartDate.DayOfWeek != DayOfWeek.Sunday && IstAbwesend(record.StartDate))
{
record.Notice5 = "x";
}
else
{
record.Notice5 = "";
}
if (record.IstFerien) // Wochensumme
{
minutenGesamt += record.Minutes;
}
if (record.StartDate.DayOfWeek == DayOfWeek.Saturday)
{
record.IstSamstag = true;
}
else if (record.StartDate.DayOfWeek == DayOfWeek.Sunday)
{
record.IstSonntag = true;
}
}
pRO.TotalFLM = minutenGesamt;
return result.OrderBy(r => r.TimeRangeString).ToList();
}
public 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 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 List<long> Get1Zu2BetreuungCustomerOids()
{
List<long> result = new List<long>();
if (this.servicesOverviewRO.SupportConceptCostBearer != null)
{
foreach (var ap in servicesOverviewRO.SupportConceptCostBearer.ApprovalPeriodList)
{
if (ap.StartDate <= servicesOverviewRO.EndDate.Date && ap.EndDate >= servicesOverviewRO.StartDate.Date)
{
foreach (var item in ap.SupportConceptApprovalPeriodEmployeeRelations)
{
if (!item.IsAbsolut && item.Betreuungsschluessel == 50)
{
//Ja ist eine 1:2 Betreuung
var sql = String.Format(@"select c.oid
from supportconceptapprovalperiod2employee scap2e
join supportconceptapprovalperiod scap on scap2e.SupportConceptApprovalPeriodOid = scap.oid
join costbearer2supportconcept c2s on scap.CostBearer2SupportConceptOid = c2s.oid
join supportconcept sc on c2s.SupportConceptOid = sc.oid
join customer c on sc.customeroid = c.oid
where scap2e.EmployeeOid = {0} and scap.Start <= '{1:yyyy-MM-dd}' and scap.EndDate >= '{2:yyyy-MM-dd}' and scap2e.Betreuungsschluessel = 50", item.Employee.EmployeeOid, servicesOverviewRO.EndDate.Date, servicesOverviewRO.StartDate.Date);
var sqlresult = DAOFactory.SearchDAO.GetSqlResult(sql);
foreach (long oid in sqlresult)
{
result.Add(oid);
}
}
}
}
}
}
return result;
}
private 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 bool IstAbwesend(DateTime startDate)
{
foreach (var at in servicesOverviewRO.Abwesenheiten)
{
if (startDate >= at.Start && (!at.End.HasValue || startDate <= at.End))
{
return true;
}
}
return false;
}
public Dictionary<DateTime, bool> GetAbrechenbareAbwesenheiten()
{
//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.2023 bis 21.07.2023 und bis 10 mal im Schuljahr ab 2023/2024
DateTime startSchuljahr = DateTime.MinValue;
DateTime endeSchuljahr = DateTime.MinValue;
DateTime dt;
if (DateTime.TryParse(servicesOverviewRO.ApprovedStartDate, out dt))
{
startSchuljahr = dt;
}
if (DateTime.TryParse(servicesOverviewRO.ApprovedEndDate, out dt))
{
endeSchuljahr = dt;
}
int maxAnzahl = 10;
if (startSchuljahr < new DateTime(2023, 7, 21))
{
startSchuljahr = new DateTime(2023, 1, 1);
endeSchuljahr = new DateTime(2023, 7, 21);
maxAnzahl = 5;
}
int gesamtAnzahl = 0;
Dictionary<DateTime, bool> abrechenbareTage = new Dictionary<DateTime, bool>();
var c = DAOFactory.GenericDAO.LoadByID<Customer>(servicesOverviewRO.CustomerOid);
foreach (AbsenceTime at in c.AbsenceTimes.OrderBy(a => a.Start))
{
if (at.Start >= startSchuljahr && at.Start <= endeSchuljahr && (at.End == null || at.End >= startSchuljahr))
{
DateTime dtIterator = at.Start.Value;
DateTime end = endeSchuljahr;
if (at.End.HasValue)
{
end = at.End.Value;
}
while (dtIterator <= end && gesamtAnzahl < maxAnzahl)
{
if (dtIterator.DayOfWeek != DayOfWeek.Saturday && dtIterator.DayOfWeek != DayOfWeek.Sunday)
{
bool istAbrechenbar = true;
if (tandemBetreuungHelper != null)
{
istAbrechenbar = false;
if (tandemBetreuungHelper.IstAbwesend(dtIterator))
{
istAbrechenbar = true;
}
}
if (istAbrechenbar)
{
abrechenbareTage.Add(dtIterator, true);
gesamtAnzahl++;
}
}
dtIterator = dtIterator.AddDays(1);
}
}
}
//int gesamtAnzahl = 0;
//Dictionary<DateTime, bool> abrechenbareTage = new Dictionary<DateTime, bool>();
//DateTime lastend = DateTime.MinValue;
//foreach (var at in ro.Abwesenheiten)
//{
// 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 double BerechneMinutenProTag(double flsPerWeek)
{
var minutenProTag = flsPerWeek * 60 / 5;
return minutenProTag;
//die Minuten müssen auf volle Viertelstunden auf oder abgerundet werden
//return Rundeauf15Minuten(minutenProTag);
}
public 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;
}
}
}