using System; using System.Collections.Generic; using System.IO; 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; using Utils = BS.Shared.Core.Utils; namespace BeWo.Service.Plugins { public class FlexibleReportService : AbstractIDSpecificDefaultClass { private Dictionary> _CategoryOid2Stundensatz; private Dictionary> _LeistungOid2Stundensatz; private Dictionary> _CostbearerOid2Stundensatz; private Dictionary> _CostbearerOid2RateFactor; public virtual FlexibleReportResultDC GetAllFlexibleReportEntrys(FlexibleReportFilterDC filter) { var result = new FlexibleReportResultDC { StartDatum = filter.StartDatum, EndDatum = filter.EndDatum }; var calc = PluginLoader.FindClass(); var filterZeitraum = new DateTimeSpan() { StartDateTime = filter.StartDatum.Date, EndDateTime = filter.EndDatum.Date.AddDays(1).AddTicks(-1) }; // Erstellt die FlexibleReportDummies if (filter.AlleHilfeplaneAnzeigen.HasValue && filter.AlleHilfeplaneAnzeigen.Value) { var alleHelp = DAOFactory.GenericDAO.GetAllActiveAndArchived().ToArray(); if (alleHelp.Length > 0) { var dummies = GetFlexibleReportResult_Dummies(alleHelp, filterZeitraum, calc, filter.SollAnzeigen.HasValue && filter.SollAnzeigen.Value); result.Dummies = dummies.ToList(); } } // Erstellt die FlexibleReportEntries if (filter.AlleServiceBerichteAnzeigen.HasValue && filter.AlleServiceBerichteAnzeigen.Value) { var alleRec = DAOFactory.SearchDAO.FindServiceRecordsInSpan(filterZeitraum, null).ToArray(); if (alleRec.Length > 0) { var entries = GetFlexibleReportResult_Entries(alleRec, filter.IstAnzeigen.HasValue && filter.IstAnzeigen.Value, filter.BetragAnzeigen.HasValue && filter.BetragAnzeigen.Value, filter.GefahreneKilometerAnzeigen.HasValue && filter.GefahreneKilometerAnzeigen.Value); result.Entries = entries.ToList(); } } // Erstellt CustomerDic if (filter.AlleKlientenAnzeigen.HasValue && filter.AlleKlientenAnzeigen.Value) { var alleCos = DAOFactory.GenericDAO.GetAllActive(); if (alleCos.Count > 0) { var customers = GetFlexibleReportResult_Customers(alleCos); result.Customers = customers; } } // Erstellt EmployeeDic if (filter.AlleMitarbeiterAnzeigen.HasValue && filter.AlleMitarbeiterAnzeigen.Value) { var alleEmps = DAOFactory.GenericDAO.GetAllActive(); if (alleEmps.Count > 0) { var employees = GetFlexibleReportResult_Employees(alleEmps); result.Employees = employees; } } return result; } protected virtual decimal? GetStundensatz(ServiceRecord sr) { if (_CategoryOid2Stundensatz == null) BuildStundensatzDictionaries(); if (sr.CostBearer2SupportConcept != null) { if (_LeistungOid2Stundensatz.ContainsKey(sr.ServiceDescription.Oid.Value)) { var crList = _LeistungOid2Stundensatz[sr.ServiceDescription.Oid.Value]; var cr = crList.GetCostRatePeriodForDate(CostRatePeriodType.AmountOfMoney, sr.Start.Value); if (cr != null && cr.CostRateValue.HasValue) { return cr.CostRateValue.Value; } } if (_CategoryOid2Stundensatz.ContainsKey(sr.ServiceDescription.ServiceCategory.Oid.Value)) { var crList = _CategoryOid2Stundensatz[sr.ServiceDescription.ServiceCategory.Oid.Value]; var cr = crList.GetCostRatePeriodForDate(CostRatePeriodType.AmountOfMoney, sr.Start.Value); if (cr != null && cr.CostRateValue.HasValue) { return cr.CostRateValue.Value; } } if (_CostbearerOid2Stundensatz.ContainsKey(sr.CostBearer2SupportConcept.CostBearer.Oid.Value)) { var crList = _CostbearerOid2Stundensatz[sr.CostBearer2SupportConcept.CostBearer.Oid.Value]; var cr = crList.GetCostRatePeriodForDate(CostRatePeriodType.HourlyRate, sr.Start.Value); if (cr?.CostRateValue != null) { var betrag = cr.CostRateValue.Value; if (_CostbearerOid2RateFactor.ContainsKey(sr.CostBearer2SupportConcept.CostBearer.Oid.Value)) { crList = _CostbearerOid2RateFactor[sr.CostBearer2SupportConcept.CostBearer.Oid.Value]; cr = crList.GetCostRatePeriodForDate(CostRatePeriodType.RateFactor, sr.Start.Value); if (cr?.CostRateValue != null) { betrag *= 1 + cr.CostRateValue.Value / 100; } } return betrag; } } } return null; } protected virtual void BuildStundensatzDictionaries() { _CategoryOid2Stundensatz = new Dictionary>(); _LeistungOid2Stundensatz = new Dictionary>(); _CostbearerOid2Stundensatz = new Dictionary>(); _CostbearerOid2RateFactor = new Dictionary>(); var categories = DAOFactory.GenericDAO.GetAllActive(); foreach (var cat in categories) { if (cat.AccountingInterval.HasValue && cat.AccountingInterval.Value == AccountingIntervalType.Hourly) { var hrCats = cat.CostRatePeriods.ToList(); if (hrCats.Count > 0) { _CategoryOid2Stundensatz.Add(cat.Oid.Value, MapperFactory.CostRatePeriodDC_CostRatePeriod.MapToNewDCs(hrCats)); } } } var descriptions = DAOFactory.GenericDAO.GetAllActive(); foreach (var desc in descriptions) { if (desc.AccountingInterval.HasValue && desc.AccountingInterval.Value == AccountingIntervalType.Hourly) { var hrCats = desc.CostRatePeriods.ToList(); if (hrCats.Count > 0) { _LeistungOid2Stundensatz.Add(desc.Oid.Value, MapperFactory.CostRatePeriodDC_CostRatePeriod.MapToNewDCs(hrCats)); } } } var costBearers = DAOFactory.GenericDAO.GetAllActive(); foreach (var cb in costBearers) { var hrCats = cb.CostRatePeriods.Where(c => c.CostRateType == CostRatePeriodType.HourlyRate).ToList(); if (hrCats.Count > 0) { _CostbearerOid2Stundensatz.Add(cb.Oid.Value, MapperFactory.CostRatePeriodDC_CostRatePeriod.MapToNewDCs(hrCats)); } var rfCats = cb.CostRatePeriods.Where(c => c.CostRateType == CostRatePeriodType.RateFactor).ToList(); if (rfCats.Count > 0) { _CostbearerOid2RateFactor.Add(cb.Oid.Value, MapperFactory.CostRatePeriodDC_CostRatePeriod.MapToNewDCs(rfCats)); } } } protected virtual decimal? GetSollPerDayEmployee(Customer customer, Employee employee, DateTime date, SupportConceptApprovalPeriod scap, Calculations calc) { var scapDC = MapperFactory.SupportConceptApprovalPeriodDC_SupportConceptApprovalPeriod.MapToNewDC(scap); var sollPerDay = calc.GetApprovedHoursPerDay(scapDC, new List()) * 60; if (employee == null) return sollPerDay; var sc2e = scap.SupportConceptApprovalPeriod2Employee.FirstOrDefault(x => x.Employee.Oid == employee.Oid); if (sc2e != null) return sc2e.IsAbsolut ? sc2e.Betreuungsschluessel : sollPerDay * sc2e.Betreuungsschluessel/100; else return sollPerDay; } protected virtual decimal? GetSollPerDay(Customer customer, DateTime date, SupportConceptApprovalPeriod scap, Calculations calc) { var scapDC = MapperFactory.SupportConceptApprovalPeriodDC_SupportConceptApprovalPeriod.MapToNewDC(scap); var sollPerDay = calc.GetApprovedHoursPerDay(scapDC, new List()) * 60; return sollPerDay; } // ToDo: Auslagern / generaliesieren protected static IEnumerable GetHauptbetreuer(Customer c) { foreach (Employee2Customer e2c in c.Employee2CustomerList) { foreach (ValueListEntry2Object vle2o in e2c.ValueList) { var vle = vle2o.Entry; if (vle.SystemEntryID == SystemEntryID.EmployeeRoleMainAttendant && e2c.CustomerOid == c.Oid) yield return e2c.Employee; } } } protected virtual IEnumerable GetFlexibleReportResult_Entries(IEnumerable alleRec, bool zeigeIst, bool zeigeBetrag, bool zeigeKilometer) { foreach (var serviceRecord in alleRec) { if (!serviceRecord.Start.HasValue || !serviceRecord.End.HasValue) continue; var entry = new FlexibleReportEntryDC { ServiceRecordOid = serviceRecord.Oid, EndDatum = serviceRecord.End.Value, Notice = serviceRecord.Notice, Notice2 = serviceRecord.Notice2, Notice3 = serviceRecord.Notice3, Notice4 = serviceRecord.Notice4, Notice5 = serviceRecord.Notice5, SollArbeitszeitMinuten = null, SollBetreuungszeitMinuten = null, StartDatum = serviceRecord.Start.Value, Leistung = serviceRecord.ServiceDescription.Name, Leistungskategorie = serviceRecord.ServiceDescription.ServiceCategory.Name }; if (zeigeIst || zeigeBetrag) { entry.IstArbeitszeitMinuten = serviceRecord.RoundedDuration; entry.IstBetreuungszeitMinuten = serviceRecord.RoundedDuration; if (serviceRecord.GroupEmployeeCount.HasValue && serviceRecord.GroupEmployeeCount.Value > 1) { entry.IstBetreuungszeitMinuten /= serviceRecord.GroupEmployeeCount.Value; } } if (zeigeBetrag) { entry.Stundensatz = GetStundensatz(serviceRecord); entry.Betrag = (entry.IstBetreuungszeitMinuten / 60) * entry.Stundensatz; } if (zeigeKilometer) { entry.Kilometer = (int?)serviceRecord.DistanceInMeter; entry.KilometerDecimal = serviceRecord.DistanceInMeter; } if (serviceRecord.Customer != null) { entry.CustomerOid = serviceRecord.Customer.Oid; entry.CustomerString = serviceRecord.Customer.Person.LastNameFirstName; entry.Team = serviceRecord.Customer.TeamSimpleString; } if (serviceRecord.Employee != null) { entry.EmployeeOid = serviceRecord.Employee.Oid; entry.EmployeeString = serviceRecord.Employee.Person.LastNameFirstName; } if (serviceRecord.SupportConcept != null) { entry.SupportConceptOid = serviceRecord.SupportConcept.Oid; entry.SupportConceptString = serviceRecord.SupportConcept.TimeSpanString; } if (serviceRecord.CostBearer2SupportConcept != null) { entry.Organisation = serviceRecord.CostBearer2SupportConcept.CostBearer.Organisation.Name; } yield return entry; } } protected virtual IEnumerable GetFlexibleReportResult_Dummies(IList alleHelp, DateTimeSpan filterZeitraum, Calculations calc, bool zeigeSoll) { foreach (var hilfePlan in alleHelp.Where(x => filterZeitraum.StartDate <= x.EndDate && filterZeitraum.EndDate >= x.StartDate)) { foreach (var c2s in hilfePlan.CostBearer2SupportConceptList.Where(x => filterZeitraum.StartDate <= x.EndDate && filterZeitraum.EndDate >= x.StartDate)) { foreach (var approvalPeriod in c2s.ApprovalPeriodList.Where(x => filterZeitraum.StartDate <= x.EndDate && filterZeitraum.EndDate >= x.StartDate)) { var start = filterZeitraum.StartDate > approvalPeriod.StartDate ? filterZeitraum.StartDate : approvalPeriod.StartDate.Value; var ende = filterZeitraum.EndDate < approvalPeriod.EndDate ? filterZeitraum.EndDate : approvalPeriod.EndDate.Value; var zeitraum = new DateTimeSpan(start, ende); // Wenn kein Mitarbeiter dem Bewilligungszeitraum zugewiesen ist if (approvalPeriod.SupportConceptApprovalPeriod2Employee.Count == 0) { var hauptbetreuer = GetHauptbetreuer(hilfePlan.Customer).ToList(); var soll = zeigeSoll ? GetSollPerDay(hilfePlan.Customer, start, approvalPeriod, calc) : null; // Wenn der Klient keine Hauptbetreuer hat if (hauptbetreuer.Count == 0) { yield return GetFlexibleReportDummy(hilfePlan.Customer, null, zeitraum, hilfePlan, approvalPeriod, soll, null); } // Wenn der Klient ein oder mehr Hauptbetreuer hat else { var sollAnteil = soll / hauptbetreuer.Count; foreach (var betreuer in hauptbetreuer) { yield return GetFlexibleReportDummy(hilfePlan.Customer, betreuer, zeitraum, hilfePlan, approvalPeriod, sollAnteil, null); } } } // Wenn ein oder mehr Mitarbeiter dem Bewilligungszeitraum zugewiesen ist/sind else { foreach (var s2e in approvalPeriod.SupportConceptApprovalPeriod2Employee) { var soll = zeigeSoll ? GetSollPerDayEmployee(hilfePlan.Customer, s2e.Employee, approvalPeriod.StartDate.Value, approvalPeriod, calc) : null; yield return GetFlexibleReportDummy(hilfePlan.Customer, s2e.Employee, zeitraum, hilfePlan, approvalPeriod, soll, null); } } } } } } protected virtual FlexibleReportDummyDC GetFlexibleReportDummy(Customer customer, Employee employee, DateTimeSpan timeSpan, SupportConcept supportConcept, SupportConceptApprovalPeriod approvalPeriod, decimal? sollBetreuungszeit, decimal? sollArbeitszeit) { var dummy = new FlexibleReportDummyDC { CustomerOid = customer.Oid, CustomerString = customer.Person.LastNameFirstName, SupportConceptOid = supportConcept.Oid, SupportConceptString = supportConcept.TimeSpanString, StartDate = timeSpan.StartDate.Date, EndDate = timeSpan.EndDate.Date, SollBetreuungszeit = sollBetreuungszeit, SollArbeitszeit = sollArbeitszeit }; if (employee != null) { dummy.EmployeeOid = employee.Oid; dummy.EmployeeString = employee.Person.LastNameFirstName; } if (approvalPeriod != null) { dummy.Leistungskategorie = approvalPeriod.ServiceCategory?.Name; dummy.Organisation = approvalPeriod.CostBearer2SupportConcept.CostBearer.Organisation.Name; } return dummy; } protected virtual Dictionary GetFlexibleReportResult_Customers(IList customers) { var customerDic = new Dictionary(); foreach (var customer in customers) { customerDic.Add(customer.Oid.Value, string.Format("{0}, {1}", customer.Person.LastName, customer.Person.FirstName)); } return customerDic; } protected virtual Dictionary GetFlexibleReportResult_Employees(IList employees) { var employeeDic = new Dictionary(); foreach (var employee in employees) { employeeDic.Add(employee.Oid.Value, string.Format("{0}, {1}", employee.Person.LastName, employee.Person.FirstName)); } return employeeDic; } } }