using System; using System.Collections.Generic; using System.Linq; using System.Text; using BeWo.Data.Access; using BeWo.Data.Entities; using BeWo.Service.DCEntityMapper; using BeWo.Service.Invoicing; using BeWo.Service.Plugins; using BS.Shared; using BS.Shared.Core; using BS.Shared.DataContracts; using BS.Shared.Extensions; using BS.Shared.Services; namespace Service.Invoicing { public class SbdDefaultInvoiceCreation : InvoiceCreation { public override void SetInvoiceId(ServiceInvoice invoice) { invoice.InvoiceBase.InvoiceId = "SBD"; invoice.InvoiceBase.InvoiceTypeText = "Abrechnung Schulbegleitender Dienst"; } public override void SetInvoiceItems(ServiceInvoice invoice, ServiceInvoicePeriod serviceInvoicePeriod, SupportConceptApprovalPeriodDC supportConceptApprovalPeriod, CostBearer2SupportConcept cb2sc, DateTimeSpan invoicePeriod, List serviceRecords) { Calculations calc = PluginLoader.FindClass(_SpecificID) ?? Calculations.GetInstance(_SpecificID); List serviceRecordsInPeriod = serviceRecords.Where( i => { bool valid = i.Start.Value.InBetween(serviceInvoicePeriod.Start.Value, serviceInvoicePeriod.End.Value, true); if (valid && serviceInvoicePeriod.SupportConceptApprovalPeriod != null && serviceInvoicePeriod.SupportConceptApprovalPeriod.ServiceCategory != null) valid = serviceInvoicePeriod.SupportConceptApprovalPeriod.ServiceCategory.Oid == i.ServiceDescription.Category.ServiceCategoryOid; return valid; }).ToList(); var itemList = CreateAllInvoiceItems(cb2sc, serviceRecordsInPeriod, invoicePeriod, serviceInvoicePeriod.SupportConceptApprovalPeriod, calc); serviceInvoicePeriod.InvoiceItemList.AddRange(itemList); } public virtual IList CreateAllInvoiceItems(CostBearer2SupportConcept c2s, List serviceRecordsInPeriod, DateTimeSpan invoicePeriod, SupportConceptApprovalPeriod scap, Calculations calc) { var items = CreateSbdInvoiceItems(c2s.SupportConcept.Customer, serviceRecordsInPeriod, invoicePeriod, scap, calc); decimal hours = 0; decimal hourlyRate = 0; decimal ratefactor = 0; var crList = MapperFactory.CostRatePeriodDC_CostRatePeriod.MapToNewDCs(c2s.CostBearer.CostRatePeriods); InvoiceItem newItem = null; foreach (var item in items) { if (!item.AmountPerUnit.HasValue) { item.AmountPerUnit = GetCostRateValue(crList, CostRatePeriodType.HourlyRate, item.ItemPeriodStart.Value); } if (!item.RateFactor.HasValue) { item.RateFactor = GetCostRateValue(crList, CostRatePeriodType.RateFactor, item.ItemPeriodStart.Value); } if (newItem == null) { newItem = new InvoiceItem(); newItem.ItemPeriodStart = item.ItemPeriodStart; newItem.ItemPeriodEnd = item.ItemPeriodEnd; } hours += item.UnitCount ?? 0; hourlyRate = item.AmountPerUnit ?? 0; ratefactor = item.RateFactor ?? 0; item.AmountTotal = 0; item.GrossAmountTotal = 0; } if (newItem != null) { newItem.ItemDescription = "Betreuungseinsätze"; newItem.AmountPerUnit = hourlyRate; newItem.UnitCount = hours; newItem.AmountTotal = Math.Round(hourlyRate * hours, 2, MidpointRounding.AwayFromZero); newItem.GrossAmountTotal = newItem.AmountTotal; items.Add(newItem); if (ratefactor > 0) { var rfItem = new InvoiceItem(); rfItem.ItemPeriodStart = newItem.ItemPeriodStart; rfItem.ItemPeriodEnd = newItem.ItemPeriodEnd; rfItem.RateFactor = ratefactor; rfItem.AmountPerUnit = Math.Round(hourlyRate * (ratefactor / 100), 2, MidpointRounding.AwayFromZero); rfItem.UnitCount = hours; rfItem.AmountTotal = Math.Round((rfItem.AmountPerUnit ?? 0) * hours, 2, MidpointRounding.AwayFromZero); rfItem.GrossAmountTotal = rfItem.AmountTotal; rfItem.ItemDescription = String.Format("{0:0.##}% Zuschlag auf Betreuungszeit", ratefactor); items.Add(rfItem); } } return items; } public virtual IList CreateSbdInvoiceItems(Customer customer, List serviceRecordsInPeriod, DateTimeSpan invoicePeriod, SupportConceptApprovalPeriod scap, Calculations calc) { IList result = new List(); var stundenplanItems = ErstelleStundenplanItems(customer, invoicePeriod.StartDate, invoicePeriod.EndDate); IList srList = new List(); foreach (ServiceRecordDC iServiceRecord in serviceRecordsInPeriod) { if (iServiceRecord.ServiceDescription.Category.IsBillable) { if (!iServiceRecord.AlreadyAccounted) { var invoiceItem = CreateInvoiceItem(iServiceRecord, scap, calc); invoiceItem.ItemDescription = String.Format("{0} {1}", iServiceRecord.Employee.FirstName, iServiceRecord.Employee.LastName); srList.Add(invoiceItem); iServiceRecord.AlreadyAccounted = true; } } } Dictionary dayDict = new Dictionary(); foreach (var item in srList) { String key = String.Format("{0:dd.MM.yyyy}", item.ItemPeriodStart); if (!dayDict.ContainsKey(key)) { dayDict.Add(key, true); } result.Add(item); } foreach (var ii in stundenplanItems) { String key = String.Format("{0:dd.MM.yyyy}", ii.ItemPeriodStart); if (!dayDict.ContainsKey(key)) { ii.ItemDescription = GetHauptbetreuer(customer); result.Add(ii); } } var newList = result.Where(i => i.UnitCount.HasValue && i.UnitCount.Value > 0).OrderBy(i => i.ItemPeriodStart).ToList(); return CreateSummaryInvoiceItems(newList, invoicePeriod, scap, calc); } private string GetHauptbetreuer(Customer customer) { foreach (var e2c in customer.Employee2CustomerList) { foreach (var v2e in e2c.ValueList) { if (v2e.Entry.Type == ValueListEntryType.StaffRoleType && v2e.Entry.Value == "Hauptbetreuung") { return e2c.Employee.Person.FirstNameLastName; } } } return ""; } public virtual List ErstelleStundenplanItems(Customer customer, DateTime start, DateTime ende) { var stundenplan = GetStundenplan(customer, start, ende); var vs = PluginLoader.FindClass(); List items = new List(); while (start <= ende) { bool istSamstag = false; bool istSonntag = false; bool istFerien = false; bool istFeiertag = false; if (start.DayOfWeek == DayOfWeek.Saturday) { istSamstag = true; } if (start.DayOfWeek == DayOfWeek.Sunday) { istSonntag = true; } var ferien = vs.GetFerien(start, vs.Bundesland); if (ferien != null) { istFerien = true; } var ft = vs.GetFeiertag(start); if (ft != null) { istFeiertag = true; } if (!istSamstag && !istSonntag && !istFerien && !istFeiertag) { var subItems = ErstelleStundenplanEintraege(stundenplan, start); items.AddRange(subItems); } start = start.AddDays(1); } return items; } private static Organisation SucheSchule(Customer customer) { foreach (var c2o in customer.Customer2OrganisationList) { foreach (var v2o in c2o.ValueList) { if (v2o.Entry.Value != null && v2o.Entry.Value.Contains("Schule")) { return c2o.Organisation; } } } return null; } private static Arbeitszeit GetStundenplan(Customer customer, DateTime start, DateTime ende) { var stundenplan = SucheStundenplan(customer.Arbeitszeiten, start, ende); if (stundenplan == null) { //Kein Stundenplan hinterlegt, suche Stundenplan bei der Organisation (Schule) var org = SucheSchule(customer); if (org != null) { return SucheStundenplan(org.Arbeitszeiten, start, ende); } } return stundenplan; } private static Arbeitszeit SucheStundenplan(IList arbeitszeiten, DateTime start, DateTime ende) { if (arbeitszeiten != null && arbeitszeiten.Count > 0) { foreach (var az in arbeitszeiten) { if ((!az.GueltigVon.HasValue || az.GueltigVon <= ende) && (!az.GueltigBis.HasValue || az.GueltigBis >= start)) { return az; } } } return null; } private static List ErstelleStundenplanEintraege(Arbeitszeit arbeitszeit, DateTime date) { List result = new List(); if (arbeitszeit != null && arbeitszeit.ArbeitszeitEintraege != null && arbeitszeit.ArbeitszeitEintraege.Count > 0) { if (arbeitszeit.GueltigVon <= date && date.Date <= arbeitszeit.GueltigBis) { var day = date.DayOfWeek; foreach (var ae in arbeitszeit.ArbeitszeitEintraege) { if (SindAmGleichenWochentag(day, ae.Tag)) { String dateStr1 = String.Format("{0:dd.MM.yyyy} {1}", date, ae.UhrzeitVon); String dateStr2 = String.Format("{0:dd.MM.yyyy} {1}", date, ae.UhrzeitBis); DateTime date1; DateTime date2; if (DateTime.TryParse(dateStr1, out date1) && DateTime.TryParse(dateStr2, out date2)) { var item = new InvoiceItem(); item.ItemPeriodStart = date1; item.ItemPeriodEnd = date2; item.UnitCount = (decimal) date2.Subtract(date1).TotalHours; if (ae.Employee != null) { item.ItemDescription = ae.Employee.Person.FirstNameLastName; } else { item.ItemDescription = "Hauptbetreuer"; } result.Add(item); } } } } } return result; } private static decimal BerechneStunden(ArbeitszeitEintrag ae) { return 0; } private static 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 virtual InvoiceItem CreateInvoiceItem(ServiceRecordDC iServiceRecord, SupportConceptApprovalPeriod scap, Calculations calc) { var invoiceItem = new InvoiceItem(); BillingData bd = calc.GetBillingData(iServiceRecord); invoiceItem.AmountPerUnit = bd.AmountPerUnit; invoiceItem.UnitCount = bd.UnitCount; invoiceItem.AmountTotal = bd.AmountTotal; invoiceItem.ItemPeriodStart = bd.BillingPeriodStart; invoiceItem.ItemPeriodEnd = bd.BillingPeriodEnd; invoiceItem.RateFactor = bd.RateFactor; invoiceItem.GrossAmountTotal = bd.GrossAmountTotal; invoiceItem.AccountingInterval = bd.AccountingInterval; invoiceItem.ItemDescription = iServiceRecord.ServiceDescription.Name; //iServiceRecord.Employee + " - " + iServiceRecord.ServiceDescription.Name; invoiceItem.ServiceRecord = DAOFactory.GenericDAO.LoadByID(iServiceRecord.ServiceRecordOid.Value); if (scap != null) invoiceItem.SupportConceptApprovalPeriodOid = scap.Oid; //var crs = iServiceRecord.CostBearer.CostRatePeriods; //List costRatePeriodOids = new List(); //if (cdc != null) // costRatePeriodOids.Add(cdc.CostRatePeriodOid.Value); //cdc = crs.GetCostRatePeriodForDate(CostRatePeriodType.MinutesIntervall, iServiceRecord.Start.Value); //if (cdc != null) // costRatePeriodOids.Add(cdc.CostRatePeriodOid.Value); //cdc = crs.GetCostRatePeriodForDate(CostRatePeriodType.MinutesPerServiceUnit, iServiceRecord.Start.Value); //if (cdc != null) // costRatePeriodOids.Add(cdc.CostRatePeriodOid.Value); //cdc = crs.GetCostRatePeriodForDate(CostRatePeriodType.RateFactor, iServiceRecord.Start.Value); //if (cdc != null) // costRatePeriodOids.Add(cdc.CostRatePeriodOid.Value); //cdc = crs.GetCostRatePeriodForDate(CostRatePeriodType.ServiceTolerance, iServiceRecord.Start.Value); //if (cdc != null) // costRatePeriodOids.Add(cdc.CostRatePeriodOid.Value); //invoiceItem.CostRatePeriodList = DAOFactory.GenericDAO.LoadByIDs(costRatePeriodOids); //var rateFactor = invoiceItem.CostRatePeriodList.SingleOrDefault(i => i.CostRateType == CostRatePeriodType.RateFactor); //if (rateFactor != null && !iServiceRecord.CostBearer.IsCalculatingWithFactor) //{ // invoiceItem.RateFactor = rateFactor.CostRateValue; // invoiceItem.GrossAmountTotal = invoiceItem.AmountTotal // + (invoiceItem.AmountTotal * rateFactor.CostRateValue / 100); //} //else //{ // invoiceItem.GrossAmountTotal = invoiceItem.AmountTotal; //} return invoiceItem; } private decimal GetCostRateValue(List crList, CostRatePeriodType t, DateTime date) { var cp = crList.GetCostRatePeriodForDate(t, date); if (cp != null && cp.CostRateValue.HasValue) return cp.CostRateValue.Value; return 0; } public override void CheckMaxApprovedAmount(ServiceInvoice invoice, ServiceInvoicePeriod sip, SupportConceptApprovalPeriodDC scap, CostBearer2SupportConcept costBearer2SupportConcept, DateTimeSpan invoicePeriod, List serviceRecords) { //do nothing } public override IList CreateSummaryInvoiceItems(IList itemList, DateTimeSpan invoicePeriod, SupportConceptApprovalPeriod scap, Calculations calc) { return itemList; } } }