Files
BeWoPlaner/Service/Invoicing/LWLDiggaBerechnung.cs

295 lines
14 KiB
C#
Raw Normal View History

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<LWLDiggaBerechnung>
{
public DateTime? Umstellungsdatum { get; set; }
public DateTime BewilligtStart { get; set; }
public DateTime BewilligtEnde { get; set; }
public List<EntgeltzeitraumDigga> Entgeltzeitraeume { get; set; }
public List<BudgetnachweisDiggaMonatsZeile> 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<BudgetnachweisDiggaMonatsZeile>();
Entgeltzeitraeume = new List<EntgeltzeitraumDigga>();
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<string, BudgetnachweisDiggaMonatsZeile> monat2Zeile = new Dictionary<string, BudgetnachweisDiggaMonatsZeile>();
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<ServiceRecord> 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<BudgetnachweisDiggaMonatsZeile> 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<EntgeltzeitraumDigga> 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<ServiceRecordDC>();
ez.RateFactor = 0.20m; // Variabel setzen
Entgeltzeitraeume.Add(ez);
}
start = cr.EndDate.Value;
}
}
public virtual void CalculateMonatsbasisWerte(List<EntgeltzeitraumDigga> entgeltzeitraeume, CostBearer2SupportConcept cb2sc, IList<ServiceRecord> serviceRecords, DateTimeSpan span, Dictionary<string, BudgetnachweisDiggaMonatsZeile> monat2Zeile, DateTime monat)
{
while (monat <= this.BewilligtEnde)
{
String key = String.Format("{0:MM.yyyy}", monat);
var zeile = new BudgetnachweisDiggaMonatsZeile();
zeile.ServiceRecords = new List<ServiceRecordDC>();
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<long, bool>();
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<ServiceRecordDC> 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<ServiceRecordDC> 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; }
}
}