diff --git a/Report/Report.csproj b/Report/Report.csproj
index c89e066c6..f0c1d272b 100644
--- a/Report/Report.csproj
+++ b/Report/Report.csproj
@@ -542,6 +542,7 @@
+
diff --git a/Report/ReportObjects/MonatlicherSollIstVergleichRO.cs b/Report/ReportObjects/MonatlicherSollIstVergleichRO.cs
new file mode 100644
index 000000000..c6de61403
--- /dev/null
+++ b/Report/ReportObjects/MonatlicherSollIstVergleichRO.cs
@@ -0,0 +1,204 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using BeWo.Data.Access;
+using BeWo.Data.Entities;
+using BeWo.Service.DCEntityMapper;
+using BeWo.Service.Plugins;
+using BS.Shared;
+using BS.Shared.Core;
+using BS.Shared.DataContracts;
+using BS.Shared.Extensions;
+using BS.Shared.Services;
+
+namespace BeWo.Report.ReportObjects
+{
+ public class MonatlicherSollIstVergleichRO : AbstractBeWoReportObject
+ {
+ public SupportConceptCostBearerRelDC Costbearer2SupportConceptDC { get; set; }
+ public CustomerDC CustomerDC { get; set; }
+ public DateTime BewilligtStart { get; set; }
+ public DateTime BewilligtEnde { get; set; }
+ public DateTime EndDate { get; set; }
+ public List MonatsZeilen { get; set; }
+ public decimal SummeBewilligteStunden { get; set; }
+ public decimal SummeErbrachteStunden { get; set; }
+ public decimal SummeStundenDifferenz { get; set; }
+ public decimal SummeStundenDifKumJahresbeginn { get; set; }
+ public decimal SummeBetragPauschal { get; set; }
+ public decimal SummeBetragErbracht { get; set; }
+
+
+ public static MonatlicherSollIstVergleichRO Create(long c2sOid, DateTime end, long? scapOid, long? catOid, bool nurScap = true)
+ {
+ var ro = new MonatlicherSollIstVergleichRO();
+ var c2s = DAOFactory.GenericDAO.LoadByID(c2sOid);
+ ro.Costbearer2SupportConceptDC = MapperFactory.SupportConceptCostBearerRelDC_CostBearer2SupportConcept.MapToNewDC(c2s);
+ ro.CustomerDC = MapperFactory.CustomerDC_Customer.MapToNewDC(c2s.SupportConcept.Customer);
+ ro.BewilligtStart = c2s.StartDate.Value;
+ ro.BewilligtEnde = c2s.EndDate.Value;
+ ro.EndDate = end;
+ end = new DateTime(end.Year, 12, 31);
+ if (ro.BewilligtEnde < end)
+ {
+ end = ro.BewilligtEnde;
+ }
+ SupportConceptApprovalPeriodDC scap = null;
+ IEnumerable scaps = null;
+ var calc = PluginLoader.FindClass();
+
+ // Für Aufruf aus ServiceOverview mit catOid/scapOid, ansonsten als Bericht mit Auswahl der Leistungskategorie
+ if (scapOid.HasValue && ro.Costbearer2SupportConceptDC.ApprovalPeriodList != null)
+ {
+ scap = ro.Costbearer2SupportConceptDC.ApprovalPeriodList.FirstOrDefault(i => i.SupportConceptApprovalPeriodOid == scapOid.Value);
+ if (nurScap == false)
+ {
+ scaps = ro.Costbearer2SupportConceptDC.ApprovalPeriodList.Where(i => i.ServiceCategory.ServiceCategoryOid == scap.ServiceCategory.ServiceCategoryOid).ToList();
+ }
+ }
+ else if (catOid.HasValue)
+ {
+ scaps = ro.Costbearer2SupportConceptDC.ApprovalPeriodList.Where(i => i.ServiceCategory.ServiceCategoryOid == catOid.Value);
+ if (scaps == null)
+ {
+ return ro;
+ }
+ else if (nurScap && scaps.Count() > 0)
+ {
+ scap = ro.Costbearer2SupportConceptDC.ApprovalPeriodList.FirstOrDefault(i => ro.BewilligtStart.InBetween(i.Span, true) && i.ServiceCategory.ServiceCategoryOid == catOid.Value);
+ if (scap == null || catOid.HasValue && scap.ServiceCategory.ServiceCategoryOid != catOid.Value)
+ {
+ return ro;
+ }
+ }
+ }
+ long? cat = null;
+ if (catOid.HasValue)
+ {
+ cat = catOid.Value;
+ }
+ else if (scap != null)
+ {
+ cat = scap.ServiceCategory.ServiceCategoryOid;
+ }
+ if (!cat.HasValue)
+ {
+ return ro;
+ }
+
+ ro.MonatsZeilen = new List();
+ var zeilenDict = new Dictionary();
+ decimal bewilligtProMonat = 0;
+ int year = ro.BewilligtStart.Year;
+ int idx = 0;
+
+ if (!nurScap && scaps != null && scaps.Count() > 0)
+ {
+ foreach (var sc in scaps)
+ {
+ SetBewilligungsdaten(ro, sc, zeilenDict, bewilligtProMonat, year, idx, end, calc);
+ }
+ }
+ else if (scap != null)
+ {
+ SetBewilligungsdaten(ro, scap, zeilenDict, bewilligtProMonat, year, idx, end, calc);
+ }
+
+ // Nach Bewilligungsdaten ergänze jeden Monat mit erbrachten Leistungen und den darausfolgenden Daten
+ var srList = c2s.ServiceRecords;
+ foreach (var item in srList)
+ {
+ if (item.Start <= end)
+ {
+ String MonthKey = String.Format("{0}_{1}", item.Start.Value.Year, item.Start.Value.Month);
+ if (zeilenDict.ContainsKey(MonthKey) && item.ServiceDescription.ServiceCategory.Oid == scap.ServiceCategory.ServiceCategoryOid)
+ {
+ var wz = zeilenDict[MonthKey];
+ wz.erbrachteStunden += item.RoundedDuration / 60;
+ }
+ }
+ }
+
+ foreach (var mz in ro.MonatsZeilen)
+ {
+ mz.erbrachteStunden = Math.Round(mz.erbrachteStunden, 2, MidpointRounding.AwayFromZero);
+ mz.StundenDifferenz = mz.erbrachteStunden - mz.bewilligteStunden;
+ mz.erbrachteStundenKumuliert = ro.SummeErbrachteStunden + mz.erbrachteStunden;
+ mz.StundenDifferenzKumuliert = ro.SummeStundenDifferenz + mz.StundenDifferenz;
+ mz.BetragErbracht = Math.Round(mz.erbrachteStunden * mz.Stundensatz.Value, 2, MidpointRounding.AwayFromZero);
+ mz.BetragPauschal = Math.Round(mz.bewilligteStunden * (decimal)mz.Stundensatz, 2, MidpointRounding.AwayFromZero);
+
+ ro.SummeStundenDifferenz += mz.StundenDifferenz ?? 0;
+ ro.SummeErbrachteStunden += mz.erbrachteStunden;
+ ro.SummeBetragErbracht += mz.BetragErbracht ?? 0;
+ if (mz.MonatStartDate.Year < ro.EndDate.Year)
+ {
+ ro.SummeStundenDifKumJahresbeginn += mz.StundenDifferenz ?? 0;
+ }
+ }
+ return ro;
+ }
+
+ private static void SetBewilligungsdaten(MonatlicherSollIstVergleichRO ro, SupportConceptApprovalPeriodDC scap, Dictionary zeilenDict, decimal bewilligtProMonat, int year, int idx, DateTime end, Calculations calc)
+ {
+ DateTime start = scap.StartDate ?? ro.BewilligtStart;
+ DateTime ende = scap.EndDate ?? ro.BewilligtEnde;
+ if (scap.ApprovedBEPerInterval.HasValue && scap.ApprovedBEInterval.HasValue && scap.ApprovedBEInterval == SupportConceptApprovalInterval.Monthly)
+ {
+ bewilligtProMonat = scap.ApprovedBEPerInterval.Value;
+ }
+ else
+ {
+ var months = calc.GetTotalMonths(start, ende);
+ var flsTotal = calc.GetApprovedHoursTotal(scap, ro.Costbearer2SupportConceptDC.CostBearer.CostRatePeriods);
+ bewilligtProMonat = flsTotal / months ?? 0;
+ }
+
+ //Erstelle über gesamten Bewilligungszeitraum eine leere Zeile pro Monat und Jahr und fülle mit Bewilligungsdaten
+ DateTime dt = start;
+ while (dt <= ende)
+ {
+ String monthKey = String.Format("{0}_{1}", dt.Year, dt.Month);
+ if (!zeilenDict.ContainsKey(monthKey))
+ {
+ //Neuer Monat
+ var mz = new SollIstVergleichMonatsZeile();
+ mz.MonatStartDate = dt;
+ mz.bewilligteStunden = Math.Round(bewilligtProMonat, 2, MidpointRounding.AwayFromZero);
+ mz.bewilligteStundenKumuliert = ro.SummeBewilligteStunden + mz.bewilligteStunden;
+ ro.SummeBewilligteStunden += mz.bewilligteStunden;
+
+ // Beträge vorbereitet, für Testfall nicht nötig -> nochmal checken
+ var data = calc.GetFixedBillingData(scap, mz.MonatStartDate, mz.MonatStartDate.AddMonths(1).AddDays(-1));
+ if (data != null && data.Count != 0)
+ {
+ mz.Stundensatz = data[0].AmountTotal;
+ }
+ mz.BetragPauschal = Math.Round(bewilligtProMonat * (decimal)mz.Stundensatz, 2, MidpointRounding.AwayFromZero);
+ ro.SummeBetragPauschal += mz.BetragPauschal ?? 0;
+
+ ro.MonatsZeilen.Add(mz);
+ zeilenDict.Add(monthKey, mz);
+ }
+
+ dt = dt.AddDays(1);
+ }
+ }
+ }
+
+ public class SollIstVergleichMonatsZeile
+ {
+ public List ServiceRecords { get; set; }
+ public DateTime MonatStartDate { get; set; }
+ public decimal bewilligteStunden { get; set; }
+ public decimal bewilligteStundenKumuliert { get; set; }
+ public decimal erbrachteStunden { get; set; }
+ public decimal erbrachteStundenKumuliert { get; set; }
+ public decimal? StundenDifferenz { get; set; }
+ public decimal? StundenDifferenzKumuliert { get; set; }
+ public decimal? Stundensatz { get; set; }
+ public decimal? BetragPauschal { get; set; }
+ public decimal? BetragErbracht { get; set; }
+ }
+}
\ No newline at end of file