using System; using System.Collections.Generic; using System.Linq; using BeWo.Data.Access; using BeWo.Data.Entities; using BeWo.Service.DCEntityMapper; using BS.Shared; using BS.Shared.Core; using BS.Shared.DataContracts; using BS.Shared.Extensions; using BS.Shared.Services; namespace BeWo.Service.Invoicing { public class LWLDiggaBerechnung : AbstractIDSpecificDefaultClass { public DateTime? Umstellungsdatum { get; set; } public DateTime BewilligtStart { get; set; } public DateTime BewilligtEnde { get; set; } public List Entgeltzeitraeume { get; set; } public List MonatsZeilen { get; set; } public decimal RateFactor { get; set; } public decimal SummeFLMinuten { get; set; } public decimal SummeFaktorMinuten { get; set; } public decimal SummeGesamtMinuten { get; set; } public decimal SummeFLStunden { get; set; } public decimal SummeFehlkontakte { get; set; } public decimal SummeFehlkontakteStunden { get; set; } public decimal SummeFaktorStunden { get; set; } public decimal SummeGesamtStunden { get; set; } public decimal SummeGesamtStundenMitFK { get; set; } public virtual void InitBerechnung() { // Nur für abgeleitete Klassen, wenn benötigt, z.B. zum Setzen des Umstellungsdatums // letzter Tag mit alter Rundung (Variante 1) in Zeitervassung // Umstellungsdatum = new DateTime(2025, 08, 31); } public virtual void CreateLWLDiggaBerechnung(Settlement2DC si, CostBearer2SupportConcept cb2sc, DateTime? BewilligtStart, DateTime? BewilligtEnde) { InitBerechnung(); var serviceRecords = GetBillableServiceRecords(cb2sc); this.BewilligtStart = si.AccountingPeriodStart.Value; this.BewilligtEnde = si.AccountingPeriodEnd.Value; MonatsZeilen = new List(); Entgeltzeitraeume = new List(); CreateEntgeltzeitraeume(Entgeltzeitraeume, cb2sc, this.BewilligtStart, this.BewilligtEnde); var span = new DateTimeSpan(); span.StartDateTime = si.AccountingPeriodStart.Value; span.EndDateTime = si.AccountingPeriodEnd.Value.AddDays(1).AddTicks(-1); Dictionary monat2Zeile = new Dictionary(); DateTime monat = new DateTime(this.BewilligtStart.Year, this.BewilligtStart.Month, this.BewilligtStart.Day); CalculateMonatsbasisWerte(Entgeltzeitraeume, cb2sc, serviceRecords, span, monat2Zeile, monat); CalculateMonatsMinutenWerteMitRundung(MonatsZeilen); foreach (var e in this.Entgeltzeitraeume) { e.SummeFaktorStunden = Math.Round(e.SummeFaktorMinuten / 60, 2, MidpointRounding.AwayFromZero); Math.Round(e.SummeFehlkontakteGerundet / 60, 2, MidpointRounding.AwayFromZero); e.SummeGesamtStunden = Math.Round(e.SummeMinutenGerundet / 60, 2, MidpointRounding.AwayFromZero); e.SummeGesamtStundenMitFK = e.SummeFehlkontakteStunden + e.SummeGesamtStunden; SummeFLMinuten += e.SummeFLMinuten; SummeFaktorMinuten += e.SummeFaktorMinuten; SummeGesamtMinuten += e.SummeMinutenGerundet; SummeFLStunden += e.SummeFLStunden; SummeFaktorStunden += e.SummeFaktorStunden; SummeGesamtStunden += e.SummeGesamtStunden; SummeFehlkontakte += e.SummeFehlkontakte; SummeFehlkontakteStunden += e.SummeFehlkontakteStunden; SummeGesamtStundenMitFK += e.SummeGesamtStundenMitFK; } } public virtual IList GetBillableServiceRecords(CostBearer2SupportConcept c2s) { return c2s.ServiceRecords.Where(IsServiceRecordBillable).OrderBy(s => s.Start).ToList(); } public virtual bool IsServiceRecordBillable(ServiceRecord iRecord) { return true; } private void CalculateMonatsMinutenWerteMitRundung(List MonatsZeilen) { foreach (var mz in MonatsZeilen) { if (!Umstellungsdatum.HasValue || Umstellungsdatum.HasValue && mz.Monat > Umstellungsdatum) { mz.SummeMinutenGerundet = Math.Ceiling((mz.SummeFLMinuten + mz.SummeFLMinuten * 0.2m) / 10) * 10; mz.SummeFLStunden = Math.Round(mz.SummeMinutenGerundet / 60, 2, MidpointRounding.AwayFromZero); mz.SummeFaktorMinuten = mz.SummeMinutenGerundet - mz.SummeFLMinuten; mz.SummeFehlkontakteStunden = Math.Round(mz.SummeFehlkontakte / 60, 2, MidpointRounding.AwayFromZero); mz.SummeGesamtMinutenMitFKGerundet = mz.SummeMinutenGerundet + mz.SummeFehlkontakte; mz.SummeGesamtStundenMitFKGerundet = Math.Round(mz.SummeGesamtMinutenMitFKGerundet / 60, 2, MidpointRounding.AwayFromZero); } else { mz.SummeFaktorMinuten = Math.Round(mz.SummeFLMinuten * 0.2m, 2, MidpointRounding.AwayFromZero); mz.SummeMinutenGerundet = mz.SummeFLMinuten + mz.SummeFaktorMinuten; mz.SummeFLStunden = Math.Round(mz.SummeMinutenGerundet / 60, 2, MidpointRounding.AwayFromZero); mz.SummeFehlkontakteStunden = Math.Round(mz.SummeFehlkontakte / 60, 2, MidpointRounding.AwayFromZero); mz.SummeGesamtMinutenMitFKGerundet = mz.SummeMinutenGerundet + mz.SummeFehlkontakte; mz.SummeGesamtStundenMitFKGerundet = Math.Round(mz.SummeGesamtMinutenMitFKGerundet / 60, 2, MidpointRounding.AwayFromZero); } foreach (var e in Entgeltzeitraeume) { if (e.Index == mz.Entgeltzeitraum) { e.ServiceRecords.AddRange(mz.ServiceRecords); e.SummeFLMinuten += mz.SummeFLMinuten; e.SummeFaktorMinuten += mz.SummeFaktorMinuten; e.SummeMinutenGerundet += mz.SummeMinutenGerundet; e.SummeFLStunden += mz.SummeFLStunden; e.SummeFehlkontakte += mz.SummeFehlkontakte; e.SummeFehlkontakteStunden += mz.SummeFehlkontakteStunden; e.SummeGesamtStundenMitFK += mz.SummeGesamtStundenMitFKGerundet; } } } } public virtual void CreateEntgeltzeitraeume(List entgeltzeitraeume, CostBearer2SupportConcept cb2sc, DateTime bewilligtStart, DateTime bewilligtEnde) { var crList = MapperFactory.CostRatePeriodDC_CostRatePeriod.MapToNewDCs(cb2sc.CostBearer.CostRatePeriods.Where(c => c.CostRateType == CostRatePeriodType.HourlyRate)); var crRfList = MapperFactory.CostRatePeriodDC_CostRatePeriod.MapToNewDCs(cb2sc.CostBearer.CostRatePeriods.Where(c => c.CostRateType == CostRatePeriodType.RateFactor)); var rf = crRfList.GetCostRatePeriodForDate(CostRatePeriodType.RateFactor, this.BewilligtEnde); if (rf != null && rf.CostRateValue.HasValue) { this.RateFactor = rf.CostRateValue.Value; } foreach (var cr in crList) { if (!cr.EndDate.HasValue) { cr.EndDate = this.BewilligtEnde.AddDays(1).AddMilliseconds(-1); if (cr.StartDate.HasValue && cr.StartDate.Value > cr.EndDate.Value) //manchmal werden schon aberwitzige Preise in der Zukunft hinterlegt { cr.EndDate = cr.StartDate.Value.AddMonths(1); } } } crList = crList.OrderBy(c => c.EndDate).ToList(); DateTime start = DateTime.MinValue; int idx = 1; foreach (var cr in crList) { if (!cr.StartDate.HasValue) { cr.StartDate = start; } if (cr.StartDate > DateTime.MinValue) { cr.StartDate = cr.StartDate.Value.AddDays(1); } if (cr.EndDate >= this.BewilligtStart && cr.StartDate <= this.BewilligtEnde) { var ez = new EntgeltzeitraumDigga(); ez.Index = idx++; ez.Start = cr.StartDate.Value; ez.Ende = cr.EndDate.Value; if (ez.Start == DateTime.MinValue || ez.Start < BewilligtStart) { ez.Start = this.BewilligtStart; } if (ez.Ende == DateTime.MaxValue) { ez.Ende = this.BewilligtEnde; } ez.CostRatePeriod = cr; ez.ServiceRecords = new List(); ez.RateFactor = 0.20m; // Variabel setzen Entgeltzeitraeume.Add(ez); } start = cr.EndDate.Value; } } public virtual void CalculateMonatsbasisWerte(List entgeltzeitraeume, CostBearer2SupportConcept cb2sc, IList serviceRecords, DateTimeSpan span, Dictionary monat2Zeile, DateTime monat) { while (monat <= this.BewilligtEnde) { String key = String.Format("{0:MM.yyyy}", monat); var zeile = new BudgetnachweisDiggaMonatsZeile(); zeile.ServiceRecords = new List(); zeile.Monat = monat; zeile.SummeFLMinuten = 0; zeile.SummeFehlkontakte = 0; zeile.SummeGesamtMinutenMitFKGerundet = 0; zeile.SummeGesamtStundenMitFKGerundet = 0; foreach (var e in Entgeltzeitraeume) { if (e.Start <= monat && monat <= e.Ende) { zeile.Entgeltzeitraum = e.Index; } } if (monat.Day != 1) { monat = new DateTime(monat.Year, monat.Month, 1); } monat = monat.AddMonths(1); monat2Zeile.Add(key, zeile); } var groupBookingDict = new Dictionary(); foreach (var sr in serviceRecords) { if (sr.ServiceDescription.ServiceCategory.IsBillable && (!sr.GroupOid.HasValue || !groupBookingDict.ContainsKey(sr.GroupOid.Value))) { if (sr.GroupOid.HasValue) { groupBookingDict.Add(sr.GroupOid.Value, true); } var srDc = MapperFactory.ServiceRecordDC_ServiceRecord.MapToNewDC(sr); String key = String.Format("{0:MM.yyyy}", sr.Start); if (monat2Zeile.ContainsKey(key)) { if (monat2Zeile[key].Monat <= sr.Start.Value.Date) { monat2Zeile[key].ServiceRecords.Add(srDc); decimal minuten = sr.RoundedDuration; // Check this decimal prozent = sr.ServiceDescription.ServiceCategory.ProzentAbrechnung; if (sr.ServiceDescription.Name.ToLower().Contains("fehlkontakt")) { monat2Zeile[key].SummeFehlkontakte += minuten; } else { monat2Zeile[key].SummeFLMinuten += minuten; } } } } } MonatsZeilen.AddRange(monat2Zeile.Values.OrderBy(m => m.Monat)); } } public class BudgetnachweisDiggaMonatsZeile { public List ServiceRecords { get; set; } public DateTime Monat { get; set; } public decimal SummeFLMinuten { get; set; } public decimal SummeFaktorMinuten { get; set; } public decimal SummeMinutenGerundet { get; set; } public decimal SummeFLStunden { get; set; } public decimal SummeFehlkontakte { get; set; } public decimal SummeFehlkontakteStunden { get; set; } public decimal SummeGesamtMinutenMitFKGerundet { get; set; } public decimal SummeGesamtStundenMitFKGerundet { get; set; } public int Entgeltzeitraum { get; set; } public decimal? Betrag { get; set; } } public class EntgeltzeitraumDigga { public List ServiceRecords { get; set; } public CostRatePeriodDC CostRatePeriod { get; set; } public DateTime Start { get; set; } public DateTime Ende { get; set; } public decimal RateFactor { get; set; } public decimal SummeFLMinuten { get; set; } public decimal SummeFaktorMinuten { get; set; } public decimal SummeMinutenGerundet { get; set; } public decimal SummeFLStunden { get; set; } public decimal SummeFehlkontakte { get; set; } public decimal SummeFehlkontakteGerundet { get; set; } public decimal SummeFehlkontakteStunden { get; set; } public decimal SummeFaktorStunden { get; set; } public decimal SummeGesamtStunden { get; set; } public decimal SummeGesamtStundenMitFK { get; set; } public int Index { get; set; } } }