854 lines
34 KiB
C#
854 lines
34 KiB
C#
using AkggMid.Service;
|
|
using BeWo.Data.Access;
|
|
using BeWo.Data.Entities;
|
|
using BeWo.Report.ReportObjects;
|
|
using BeWo.Service.DCEntityMapper;
|
|
using BS.Shared;
|
|
using BS.Shared.Core;
|
|
using BS.Shared.DataContracts;
|
|
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;
|
|
|
|
private ServicesOverviewRO _tandemRO = null;
|
|
|
|
private IList<AbsenceTime> allAbsenceTimes = 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)
|
|
|
|
_tandemRO = ServicesOverviewRO.Create(oid, ro.StartDate.Month, ro.StartDate.Year, false, 0, 0, ro.StartDate.Day, ro.EndDate.Day, null);
|
|
//tandemBetreuungHelper = new LeistungsnachweisHelper(tandemBetreuungRO, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
KorrigiereFLSProWoche(ro);
|
|
|
|
|
|
}
|
|
|
|
internal DateTimeSpan BerechneSchuljahr(ServicesOverviewRO ro)
|
|
{
|
|
var span = new DateTimeSpan();
|
|
span.StartDate = DateTime.MinValue;
|
|
span.EndDate = DateTime.MinValue;
|
|
|
|
//Berechne Schuljahrstart
|
|
var vs = new CustomVacationService();
|
|
var ferien = vs.GetFerien(vs.Bundesland);
|
|
FerienDC sommerFerienVorjahr = null;
|
|
FerienDC sommerFerienAktuellesJahr = null;
|
|
FerienDC sommerFerienNaechstesJahr = null;
|
|
foreach (var f in ferien)
|
|
{
|
|
if (f.Name.Contains(String.Format("Sommerferien {0}", ro.StartDate.Year - 1)))
|
|
{
|
|
sommerFerienVorjahr = f;
|
|
}
|
|
else if (f.Name.Contains(String.Format("Sommerferien {0}", ro.StartDate.Year)))
|
|
{
|
|
sommerFerienAktuellesJahr = f;
|
|
}
|
|
else if (f.Name.Contains(String.Format("Sommerferien {0}", ro.StartDate.Year + 1)))
|
|
{
|
|
sommerFerienNaechstesJahr = f;
|
|
}
|
|
}
|
|
|
|
if (sommerFerienAktuellesJahr != null)
|
|
{
|
|
if (ro.EndDate <= sommerFerienAktuellesJahr.Ende)
|
|
{
|
|
span.EndDate = sommerFerienAktuellesJahr.Start.AddDays(-1);
|
|
if (sommerFerienVorjahr != null)
|
|
{
|
|
span.StartDate = sommerFerienVorjahr.Ende.AddDays(1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
span.StartDate = sommerFerienAktuellesJahr.Ende.AddDays(1);
|
|
if (sommerFerienNaechstesJahr != null)
|
|
{
|
|
span.EndDate = sommerFerienNaechstesJahr.Start.AddDays(-1);
|
|
}
|
|
}
|
|
}
|
|
|
|
return span;
|
|
|
|
}
|
|
|
|
public List<ServicesOverviewRO.ServiceDetail> ErstelleDummyRecords(ServicesOverviewRO pRO)
|
|
{
|
|
Dictionary<int, ServicesOverviewRO.ServiceDetail> day2Detail = new Dictionary<int, ServicesOverviewRO.ServiceDetail>();
|
|
|
|
var abrAbwTagDict = BerechneAbrechenbareAbwesenheitsInfos(pRO);
|
|
|
|
var result = new List<ServicesOverviewRO.ServiceDetail>();
|
|
foreach (var sr in pRO.Services)
|
|
{
|
|
//result.Add(sr);
|
|
if (!abrAbwTagDict.ContainsKey(sr.StartDate.Date))
|
|
{
|
|
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;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
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))
|
|
{
|
|
var info = abrAbwTagDict[newSr.StartDate];
|
|
newSr.Minutes = (double)info.MinutenLautStundenplan;
|
|
//newSr.Minutes = BerechneMinutenProTag(BerechneStundenProWoche(pRO, newSr.StartDate));
|
|
newSr.Notice = info.AbwesenheitsNotiz;
|
|
newSr.Notice5 = "x";
|
|
}
|
|
}
|
|
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 += Math.Round(record.Minutes / 60, 2, MidpointRounding.AwayFromZero) * 60; // Die Minuten müssen erst auf Stunden und dann zwei Nachkommastellen gerundet werden bevor sie als Wochensumme summiert werden
|
|
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 = wochensumme; //Rundung am 25.09.2023 entfernt // Rundeauf15Minuten(wochensumme);
|
|
wochensumme = 0;
|
|
result.Add(newSr);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
double stdGesamt = 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
|
|
{
|
|
stdGesamt += Math.Round(record.Minutes / 60, 2, MidpointRounding.AwayFromZero); //Anpassung, das Wochensumme nicht mehr gerundet auf 15 min
|
|
}
|
|
|
|
|
|
if (record.StartDate.DayOfWeek == DayOfWeek.Saturday)
|
|
{
|
|
record.IstSamstag = true;
|
|
}
|
|
else if (record.StartDate.DayOfWeek == DayOfWeek.Sunday)
|
|
{
|
|
record.IstSonntag = true;
|
|
}
|
|
}
|
|
pRO.TotalFLS = stdGesamt;
|
|
return result.OrderBy(r => r.TimeRangeString).ToList();
|
|
}
|
|
|
|
public Dictionary<DateTime, AbwesenheitsInfo> BerechneAbrechenbareAbwesenheitsInfos(ServicesOverviewRO pRO)
|
|
{
|
|
var infos = ErstelleAbwesenheitsInfos(pRO, _tandemRO);
|
|
if (_tandemRO != null)
|
|
{
|
|
var tandemInfos = ErstelleAbwesenheitsInfos(_tandemRO, pRO);
|
|
|
|
foreach (var info in infos.Values)
|
|
{
|
|
if (info.PruefenObDurch2Teilen)
|
|
{
|
|
|
|
if (tandemInfos.ContainsKey(info.Datum))
|
|
{
|
|
var tandemInfo = tandemInfos[info.Datum];
|
|
if (tandemInfo.IstAbrechenbar)
|
|
{
|
|
info.MinutenLautStundenplan /= 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
return infos;
|
|
}
|
|
|
|
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 void KorrigiereFLSProWoche(ServicesOverviewRO ro)
|
|
{
|
|
//In Fällen bei denen sich die Bewilligung mitten im Monat ändern, soll die letzte Bewilligung und nicht die erste herangezogen werden
|
|
if (ro.CostBearer2SupportConceptList != null)
|
|
{
|
|
DateTime bewilligungStart = DateTime.MinValue;
|
|
|
|
foreach (var c2s in ro.CostBearer2SupportConceptList)
|
|
{
|
|
foreach (var scap in c2s.ApprovalPeriodList)
|
|
{
|
|
if (scap.StartDate <= ro.EndDate && scap.EndDate >= ro.StartDate && scap.ApprovedBEInterval.HasValue && scap.ApprovedBEPerInterval.HasValue && scap.ApprovedBEInterval.Value == BS.Shared.SupportConceptApprovalInterval.Weekly)
|
|
{
|
|
if (scap.StartDate > bewilligungStart)
|
|
{
|
|
bewilligungStart = scap.StartDate.Value;
|
|
var wochenBudget = scap.ApprovedBEPerInterval ?? 0;
|
|
|
|
ro.ApprovedFLSPerWeek = wochenBudget;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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>();
|
|
|
|
var c2sDc = this.servicesOverviewRO.SupportConceptCostBearer;
|
|
|
|
if (c2sDc == null && servicesOverviewRO.CustomerOid > 0)
|
|
{
|
|
var c = DAOFactory.GenericDAO.LoadByID<Customer>(servicesOverviewRO.CustomerOid);
|
|
|
|
foreach (var sc in c.SupportConcepts)
|
|
{
|
|
foreach (var c2s in sc.CostBearer2SupportConceptList)
|
|
{
|
|
if (c2s.StartDate.HasValue && c2s.EndDate.HasValue && c2s.StartDate <= servicesOverviewRO.EndDate &&
|
|
c2s.EndDate >= servicesOverviewRO.StartDate)
|
|
{
|
|
c2sDc = MapperFactory.SupportConceptCostBearerRelDC_CostBearer2SupportConcept.MapToNewDC(c2s);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (c2sDc != null)
|
|
{
|
|
foreach (var ap in c2sDc.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(List<AbsenceTime> absenceTimes, DateTime date)
|
|
{
|
|
foreach (var at in absenceTimes)
|
|
{
|
|
if (date >= at.Start && (!at.End.HasValue || date <= at.End))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//public Dictionary<DateTime, AbwesenheitsInfo> GetAllAbwesenheitsInfos()
|
|
//{
|
|
// if (abrechenbareAbwesenheiten == null)
|
|
// {
|
|
// abrechenbareAbwesenheiten = BerechneAbrechenbareAbwesenheiten(this.servicesOverviewRO);
|
|
// }
|
|
|
|
|
|
// return abrechenbareAbwesenheiten;
|
|
//}
|
|
|
|
|
|
public Dictionary<DateTime, AbwesenheitsInfo> ErstelleAbwesenheitsInfos(ServicesOverviewRO ro, ServicesOverviewRO tandemRo)
|
|
{
|
|
//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 // PLUS zusätzlich ein 6. Tag ABER nur im Juli 2023, nicht träglich
|
|
//und bis 6 mal im Schuljahr ab 2023/2024
|
|
|
|
// Abwesensheiten <24h_a dürfen immer abgerechnet werden, da das Bescheidsagen weniger als 24h vor Betreuung geschah
|
|
// Abwesensheiten <24h_n.a dürfen bis 6 mal im Jahr abgerechnet werden, da das Bescheidsagen weniger als 24h vor Betreuung geschah
|
|
// Abwesensheiten >24h dürfen beim Jugendamt nicht abgerechnet werden, das rechtzeitig > 24 h Bescheid gesagt wurde
|
|
// Abwesensheiten >24h dürfen nur beim Sozialamt abgerechnet werden aber nur bis 6 mal im Schuljahr
|
|
// Abwesenheit S_oA soll ignoriert werden
|
|
// Abwesenheit "S_Abwesenheit nicht abrechenbar" soll nur als x angezeigt werden
|
|
|
|
|
|
bool istJugendamt = !String.IsNullOrEmpty(ro.Costbearer) && ro.Costbearer.StartsWith("SEK -Jugend und Familie-");
|
|
|
|
|
|
|
|
Dictionary<string, bool> serviceRecordDates = new Dictionary<string, bool>();
|
|
|
|
if (ro.Services != null)
|
|
{
|
|
foreach (var s in ro.Services)
|
|
{
|
|
if (s.ServiceRecordOid > 0 && !serviceRecordDates.ContainsKey(String.Format("{0:dd.MM.yyyy}", s.StartDate)))
|
|
{
|
|
serviceRecordDates.Add(String.Format("{0:dd.MM.yyyy}", s.StartDate), true);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
int maxAnzahl = 6;
|
|
|
|
//Sonderregelung
|
|
//if (endeSchuljahr <= new DateTime(2023, 7, 21))
|
|
//{
|
|
// startSchuljahr = new DateTime(2023, 1, 1);
|
|
// endeSchuljahr = new DateTime(2023, 7, 21);
|
|
|
|
// maxAnzahl = 5;
|
|
//}
|
|
|
|
|
|
int gesamtAnzahl = 0;
|
|
|
|
var abrechenbareAbwesenheiten = new Dictionary<DateTime, AbwesenheitsInfo>();
|
|
|
|
var c = DAOFactory.GenericDAO.LoadByID<Customer>(ro.CustomerOid);
|
|
|
|
List<AbsenceTime> tandemAbsenceTimes = null;
|
|
if (tandemRo != null)
|
|
{
|
|
var tc = DAOFactory.GenericDAO.LoadByID<Customer>(tandemRo.CustomerOid);
|
|
|
|
|
|
tandemAbsenceTimes = tc.AbsenceTimes.OrderBy(a => a.Start).ToList();
|
|
}
|
|
|
|
var vs = new CustomVacationService();
|
|
|
|
var schuljahr = BerechneSchuljahr(ro);
|
|
|
|
foreach (AbsenceTime at in c.AbsenceTimes.OrderBy(a => a.Start))
|
|
{
|
|
if (at.AbsenceReason.Description.Contains("<24h") || at.AbsenceReason.Description.Contains(">24h") || at.AbsenceReason.Description.Contains("Abwesenheit nicht abrechenbar") || at.AbsenceReason.Description.StartsWith("S_JA") ||
|
|
at.AbsenceReason.Description.StartsWith("SozA") || at.AbsenceReason.Description.StartsWith("S_Abwesenheit nicht abrechenbar") || at.AbsenceReason.Description.StartsWith("JugA"))
|
|
{
|
|
if (at.Start >= schuljahr.StartDate && at.Start <= schuljahr.EndDate && (at.End == null || at.End >= schuljahr.StartDate))
|
|
{
|
|
var maxAnzahlIntern = maxAnzahl;
|
|
|
|
if (at.AbsenceReason.Description.Contains("<24h_SA") || at.AbsenceReason.Description.Contains("unter 24"))
|
|
{
|
|
maxAnzahlIntern = Int32.MaxValue; // Dürfen immer abgerechnet werden
|
|
}
|
|
else if ((at.AbsenceReason.Description.Contains(">24h") && istJugendamt) || at.AbsenceReason.Description.Contains("Abwesenheit nicht abrechenbar"))
|
|
{
|
|
maxAnzahlIntern = 0; // Darf beim Jugendamt nie abgerechnet werden
|
|
}
|
|
|
|
DateTime dtIterator = at.Start.Value;
|
|
DateTime end = schuljahr.EndDate;
|
|
if (at.End.HasValue)
|
|
{
|
|
end = at.End.Value;
|
|
}
|
|
|
|
// PLUS zusätzlich ein 6. Tag ABER nur im Juli 2023, nicht nachträglich
|
|
//while (dtIterator <= end && (gesamtAnzahl < maxAnzahlIntern
|
|
// || (end > new DateTime(2023, 06, 30) && end <= new DateTime(2023, 07, 21) && gesamtAnzahl < maxAnzahlIntern + 1)))
|
|
while (dtIterator <= end)
|
|
{
|
|
//if (dtIterator.DayOfWeek != DayOfWeek.Saturday && dtIterator.DayOfWeek != DayOfWeek.Sunday && !serviceRecordDates.ContainsKey(String.Format("{0:dd.MM.yyyy}", dtIterator)))
|
|
if (dtIterator.DayOfWeek != DayOfWeek.Saturday && dtIterator.DayOfWeek != DayOfWeek.Sunday && !vs.IstFeiertag(dtIterator))
|
|
{
|
|
bool istTandem = false;
|
|
bool istAbrechenbar = true;
|
|
bool mussDurch2Teilen = false;
|
|
|
|
if (tandemRo != null)
|
|
{
|
|
//Bei Doppelbetreuung darf die Abwesenheit bei einem Kind nicht abgerechnet werden, außer beide Kinder sind krank
|
|
istTandem = true;
|
|
istAbrechenbar = false;
|
|
|
|
var aw = IstAbwesend(tandemAbsenceTimes, dtIterator);
|
|
if (aw) //info != null)
|
|
{
|
|
//if (!info.IstAbrechenbar)
|
|
//{
|
|
//mussDurch2Teilen = false;
|
|
//}
|
|
mussDurch2Teilen = true;
|
|
|
|
istAbrechenbar = true;
|
|
}
|
|
}
|
|
|
|
|
|
decimal stunden = BerechneStundenplanZeit(c, dtIterator);
|
|
if (stunden > 0)
|
|
{
|
|
|
|
var info = new AbwesenheitsInfo();
|
|
info.Datum = dtIterator;
|
|
info.AbsenceTime = MapperFactory.AbsenceTimeDC_AbsenceTime.MapToNewDC(at);
|
|
info.AbwesenheitsNotiz = "Abwesenheit nicht abrechenbar";
|
|
info.MaxAbrechenbareTage = maxAnzahl;
|
|
info.IstAbrechenbar = false;
|
|
|
|
if (istAbrechenbar && gesamtAnzahl < maxAnzahlIntern)
|
|
{
|
|
info.IstAbrechenbar = true;
|
|
info.MinutenLautStundenplan = stunden * 60;
|
|
if (mussDurch2Teilen)
|
|
{
|
|
info.PruefenObDurch2Teilen = true;
|
|
//info.MinutenLautStundenplan /= 2;
|
|
}
|
|
if (maxAnzahlIntern < Int32.MaxValue)
|
|
{
|
|
gesamtAnzahl++;
|
|
|
|
info.NummerAbrechenbarerTag = gesamtAnzahl;
|
|
|
|
info.AbwesenheitsNotiz = String.Format("Tag {0:0}/{1:0} (Abwesenheit gem. § 6 LV)", info.NummerAbrechenbarerTag, maxAnzahl);
|
|
}
|
|
}
|
|
|
|
|
|
if (at.AbsenceReason.Description.Contains("<24h_SA") || at.AbsenceReason.Description.Contains("unter 24"))
|
|
{
|
|
info.AbwesenheitsNotiz = "Abwesenheit gem. § 8 Ziff. 3 LV";
|
|
}
|
|
if (istTandem && !istAbrechenbar)
|
|
{
|
|
info.AbwesenheitsNotiz = "";
|
|
}
|
|
if (!abrechenbareAbwesenheiten.ContainsKey(dtIterator))
|
|
{
|
|
abrechenbareAbwesenheiten.Add(dtIterator, info);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
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 abrechenbareAbwesenheiten;
|
|
}
|
|
|
|
|
|
private decimal BerechneStundenplanZeit(Customer kind, DateTime tag)
|
|
{
|
|
decimal stunden = 0;
|
|
|
|
if (kind.Arbeitszeiten != null)
|
|
{
|
|
foreach (var az in kind.Arbeitszeiten)
|
|
{
|
|
if ((!az.GueltigVon.HasValue || az.GueltigVon.Value <= tag) &&
|
|
(!az.GueltigBis.HasValue || az.GueltigBis.Value >= tag))
|
|
{
|
|
stunden = GetArbeitszeitStundenFuerTag(az, tag);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
return stunden;
|
|
}
|
|
|
|
protected decimal GetArbeitszeitStundenFuerTag(Arbeitszeit az, DateTime tag)
|
|
{
|
|
var day = tag.DayOfWeek;
|
|
decimal stunden = 0;
|
|
foreach (var ae in az.ArbeitszeitEintraege)
|
|
{
|
|
if (SindAmGleichenWochentag(day, ae.Tag))
|
|
{
|
|
String dateStr1 = String.Format("{0:dd.MM.yyyy} {1}", tag, ae.UhrzeitVon);
|
|
String dateStr2 = String.Format("{0:dd.MM.yyyy} {1}", tag, ae.UhrzeitBis);
|
|
|
|
DateTime date1;
|
|
DateTime date2;
|
|
|
|
if (DateTime.TryParse(dateStr1, out date1) && DateTime.TryParse(dateStr2, out date2))
|
|
{
|
|
|
|
stunden += (decimal)date2.Subtract(date1).TotalHours;
|
|
}
|
|
}
|
|
}
|
|
|
|
return stunden;
|
|
}
|
|
|
|
private bool SindAmGleichenWochentag(DayOfWeek day, AppointmentDayOfWeek aeTag)
|
|
{
|
|
if (day == DayOfWeek.Monday && aeTag == AppointmentDayOfWeek.Montag)
|
|
{
|
|
return true;
|
|
}
|
|
if (day == DayOfWeek.Tuesday && aeTag == AppointmentDayOfWeek.Dienstag)
|
|
{
|
|
return true;
|
|
}
|
|
if (day == DayOfWeek.Wednesday && aeTag == AppointmentDayOfWeek.Mittwoch)
|
|
{
|
|
return true;
|
|
}
|
|
if (day == DayOfWeek.Thursday && aeTag == AppointmentDayOfWeek.Donnerstag)
|
|
{
|
|
return true;
|
|
}
|
|
if (day == DayOfWeek.Friday && aeTag == AppointmentDayOfWeek.Freitag)
|
|
{
|
|
return true;
|
|
}
|
|
if (day == DayOfWeek.Saturday && aeTag == AppointmentDayOfWeek.Samstag)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
public class AbwesenheitsInfo
|
|
{
|
|
public AbsenceTimeDC AbsenceTime { get; set; }
|
|
|
|
public decimal MinutenLautStundenplan { get; set; }
|
|
|
|
public String AbwesenheitsNotiz { get; set; }
|
|
public int NummerAbrechenbarerTag { get; set; }
|
|
public int MaxAbrechenbareTage { get; set; }
|
|
public bool IstAbrechenbar { get; set; }
|
|
public DateTime Datum { get; set; }
|
|
public bool PruefenObDurch2Teilen { get; internal set; }
|
|
}
|
|
}
|