448 lines
17 KiB
C#
448 lines
17 KiB
C#
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<ServiceRecordDC> serviceRecords)
|
|
{
|
|
Calculations calc = PluginLoader.FindClass<Calculations>(_SpecificID) ?? Calculations.GetInstance(_SpecificID);
|
|
|
|
|
|
List<ServiceRecordDC> 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<InvoiceItem> CreateAllInvoiceItems(CostBearer2SupportConcept c2s, List<ServiceRecordDC> 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<InvoiceItem> CreateSbdInvoiceItems(Customer customer, List<ServiceRecordDC> serviceRecordsInPeriod, DateTimeSpan invoicePeriod, SupportConceptApprovalPeriod scap, Calculations calc)
|
|
{
|
|
IList<InvoiceItem> result = new List<InvoiceItem>();
|
|
|
|
var stundenplanItems = ErstelleStundenplanItems(customer, invoicePeriod.StartDate, invoicePeriod.EndDate);
|
|
|
|
IList<InvoiceItem> srList = new List<InvoiceItem>();
|
|
|
|
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<String, bool> dayDict = new Dictionary<String, bool>();
|
|
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<InvoiceItem> ErstelleStundenplanItems(Customer customer, DateTime start, DateTime ende)
|
|
{
|
|
var stundenplan = GetStundenplan(customer, start, ende);
|
|
var vs = PluginLoader.FindClass<VacationService>();
|
|
|
|
List<InvoiceItem> items = new List<InvoiceItem>();
|
|
|
|
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<Arbeitszeit> 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<InvoiceItem> ErstelleStundenplanEintraege(Arbeitszeit arbeitszeit, DateTime date)
|
|
{
|
|
List<InvoiceItem> result = new List<InvoiceItem>();
|
|
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;
|
|
}
|
|
#pragma warning disable CS0114 // Rethrow to preserve stack details
|
|
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<ServiceRecord>(iServiceRecord.ServiceRecordOid.Value);
|
|
if (scap != null)
|
|
invoiceItem.SupportConceptApprovalPeriodOid = scap.Oid;
|
|
|
|
//var crs = iServiceRecord.CostBearer.CostRatePeriods;
|
|
|
|
//List<long> costRatePeriodOids = new List<long>();
|
|
|
|
//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<CostRatePeriod>(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;
|
|
}
|
|
#pragma warning restore CS0114 // Rethrow to preserve stack details
|
|
|
|
public decimal GetCostRateValue(List<CostRatePeriodDC> 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<ServiceRecordDC> serviceRecords)
|
|
{
|
|
//do nothing
|
|
}
|
|
|
|
public override IList<InvoiceItem> CreateSummaryInvoiceItems(IList<InvoiceItem> itemList, DateTimeSpan invoicePeriod, SupportConceptApprovalPeriod scap,
|
|
Calculations calc)
|
|
{
|
|
return itemList;
|
|
}
|
|
}
|
|
}
|