Files

332 lines
12 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Windows.Forms;
using BeWo.Data.Access;
using BeWo.Data.Entities;
using BeWo.Service.DCEntityMapper;
using BeWo.Service.Invoicing;
using BeWo.Service.Plugins;
using BeWo.Service.ServiceContracts;
using BS.Shared;
using BS.Shared.Core;
using BS.Shared.DataContracts;
using BS.Shared.Extensions;
using BS.Shared.Services;
using DevExpress.Data.Helpers;
using Service.Invoicing;
namespace AWOMuensterlandRecklinghausen.Invoicing
{
public class CustomInvoiceCreation : SbdDefaultInvoiceCreation
{
public override void SetInvoiceId(ServiceInvoice invoice)
{
if (invoice.InvoiceBase.AccountingPeriodStart > new DateTime(2024, 03, 31)) //neues Rechnungsformular
{
invoice.InvoiceBase.InvoiceId = "SBD2024";
}
else
{
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);
if (ShouldCreateFixedAmounts(serviceInvoicePeriod, supportConceptApprovalPeriod, cb2sc))
{
CreateFixedAmounts(serviceInvoicePeriod, supportConceptApprovalPeriod, cb2sc);
}
else
{
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 override IList<InvoiceItem> CreateSbdInvoiceItems(Customer customer, List<ServiceRecordDC> serviceRecordsInPeriod, DateTimeSpan invoicePeriod, SupportConceptApprovalPeriod scap, Calculations calc)
{
IList<InvoiceItem> result = new List<InvoiceItem>();
var ccSchule = GetCostCenterSchule(customer); //Kostenstellen setzen sich zusammen aus: Schule (3Stellen) und Qualifikation MA 3 Stellen
string ccEmp; //GetHauptbetreuer(customer, true);
Dictionary<long, string> emp2Value = new Dictionary<long, string>();
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);
if (invoiceItem.ItemDescription.ToLower().Contains("pool"))
{
ccEmp = "510"; //Bei Pool ist die Qualifikation MA hinfällig -> immer 510
}
else
{
long empOid = iServiceRecord.Employee.EmployeeOid;
if (emp2Value.ContainsKey(iServiceRecord.Employee.EmployeeOid))
{
ccEmp = emp2Value[empOid];
}
else
{
var emp = DAOFactory.GenericDAO.GetByID<Employee>(empOid);
if (emp == null)
{
ccEmp = "312500".Substring(3, 3);
emp2Value.Add(0, ccEmp);
}
else
{
if (emp.TaxNumber == null || emp.TaxNumber == "")
{
//throw new FaultException<BeWoFault>(new BeWoFault(String.Format("Bei Mitarbeiter*in {0} wurde keine Kostenstelle hinterlegt", emp.Person.FirstNameLastName), BeWoFaultType.CustomWithoutDetails));
emp.TaxNumber = "312500";
}
ccEmp = emp.TaxNumber.Substring(3, 3);
emp2Value.Add(empOid, ccEmp);
}
}
}
//Sonderfälle -> wenn MA mit anderer Quali vertritt, teilweise weiter Ursprungskostenstelle:
if (ccEmp == "560") //FK vertritt bei ENFK
{
if (invoiceItem.ItemDescription.ToLower().Contains("enfk"))
{
ccEmp = "550";
}
}
if (ccEmp == "550") //ENFK vertritt bei FSJ
{
if (invoiceItem.ItemDescription.ToLower().Contains("fsj"))
{
ccEmp = "540";
}
}
invoiceItem.UnitDescription = String.Format("{0}{1}", ccSchule, ccEmp);
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);
}
var newList = result.Where(i => i.UnitCount.HasValue && i.UnitCount.Value > 0).OrderBy(i => i.ItemPeriodStart).ToList();
return newList;
}
private IList<InvoiceItem> CreateRateFactorInvoiceItems(IList<InvoiceItem> basisList, DateTimeSpan invoicePeriod, SupportConceptApprovalPeriod scap, Calculations calc)
{
IList<InvoiceItem> newList = new List<InvoiceItem>();
var rfItem = new InvoiceItem();
decimal hours = 0;
decimal hourlyRate = 0;
decimal ratefactor = 0;
foreach (var item in basisList)
{
newList.Add(item);
if (item.RateFactor != null && item.RateFactor > 0)
{
rfItem = new InvoiceItem();
rfItem.ItemPeriodStart = item.ItemPeriodStart;
rfItem.ItemPeriodEnd = item.ItemPeriodEnd;
rfItem.RateFactor = item.RateFactor;
hours = item.UnitCount ?? 0;
hourlyRate = item.AmountPerUnit ?? 0;
ratefactor = item.RateFactor ?? 0;
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);
newList.Add(rfItem);
}
}
return newList;
}
public override 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;
bool pausenabzug = CheckPausenabzug(c2s.SupportConcept);
var crList = MapperFactory.CostRatePeriodDC_CostRatePeriod.MapToNewDCs(c2s.CostBearer.CostRatePeriods);
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);
}
item.ItemPeriodStart = item.ItemPeriodStart;
item.ItemPeriodEnd = item.ItemPeriodEnd;
if (pausenabzug && item.ServiceRecord.GroupOid != null && item.ServiceRecord.GroupRoundedDuration > 360) //Brummel - die ist in Minuten
{
item.UnitCount = (decimal?)((item.ServiceRecord.GroupRoundedDuration - 30) / item.ServiceRecord.GroupPersonCount / 60);
}
if (item.ServiceRecord.GroupOid == null && pausenabzug && item.UnitCount > 6)
{
item.UnitCount -= (decimal)0.5;
//hours = item.UnitCount ?? 0;
}
if (item.ServiceRecord.Notice != null && item.ServiceRecord.Notice.StartsWith("KF-Pauschale"))
{
item.UnitCount = 10;
item.ItemDescription = "Klassenfahrt-Pauschale";
}
item.UnitCount = Math.Round(item.UnitCount ?? 0, 2, MidpointRounding.AwayFromZero);
hours = item.UnitCount ?? 0;
hourlyRate = item.AmountPerUnit ?? 0;
ratefactor = item.RateFactor ?? 0;
item.AmountTotal = Math.Round(hourlyRate * hours, 2, MidpointRounding.AwayFromZero);
item.GrossAmountTotal = item.AmountTotal;
}
var basisList = CreateSummaryInvoiceItems(items, invoicePeriod, scap, calc);
return CreateRateFactorInvoiceItems(basisList, invoicePeriod, scap, calc);
}
public override IList<InvoiceItem> CreateSummaryInvoiceItems(IList<InvoiceItem> itemList, DateTimeSpan invoicePeriod, SupportConceptApprovalPeriod scap, Calculations calc)
{
return CreateSummaryInvoiceItems(itemList, invoicePeriod, scap, calc, true);
}
public override IList<InvoiceItem> CreateSummaryInvoiceItems(IList<InvoiceItem> itemList,
DateTimeSpan invoicePeriod, SupportConceptApprovalPeriod scap, Calculations calc, bool summaryPerMonth)
{
return CreateSummaryInvoiceItems(itemList, invoicePeriod, scap, calc, summaryPerMonth, true);
}
public override string GetSummaryItemKey(SupportConceptApprovalPeriod scap, InvoiceItem iitem, bool summaryPerMonth)
{
String key = String.Format("{0}_{1}_{2}", iitem.AmountPerUnit, iitem.ItemDescription, iitem.UnitDescription);
if (summaryPerMonth)
{
key = String.Format("{0}_{1}_{2}_{3:yyyyMM}", iitem.AmountPerUnit, iitem.ItemDescription, iitem.UnitDescription, iitem.ItemPeriodStart);
}
return key;
}
private string GetHauptbetreuer(Customer customer, bool costcenter)
{
foreach (var e2c in customer.Employee2CustomerList)
{
foreach (var v2e in e2c.ValueList)
{
if (v2e.Entry.Type == ValueListEntryType.StaffRoleType && v2e.Entry.Value == "Hauptbetreuung")
{
if (costcenter && e2c.Employee.TaxNumber.Length > 0)
{
return e2c.Employee.TaxNumber.Substring(3, 3);
}
else
{
return e2c.Employee.Person.FirstNameLastName;
}
}
}
}
//throw new FaultException<BeWoFault>(new BeWoFault(String.Format("Es wurde keine Hauptbetreuung für {0} gefunden.", customer.Person.FirstNameLastName), BeWoFaultType.CustomWithoutDetails));
return "";
}
private 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;
}
private string GetCostCenterSchule(Customer c)
{
foreach (var c2o in c.Customer2OrganisationList)
{
foreach (var v2e in c2o.ValueList)
{
if (v2e.Entry.Type == ValueListEntryType.EnvironmentOrganisationType && v2e.Entry.Value.ToLower().Contains("schule"))
{
if (c2o.Organisation.DebitorNumber != null)
{
return c2o.Organisation.DebitorNumber.Trim();
}
else
{
return "300";
}
}
}
}
//throw new FaultException<BeWoFault>(new BeWoFault(String.Format("Es wurde keine Schule für { 0 } gefunden.", c.Person.FirstNameLastName), BeWoFaultType.CustomWithoutDetails));
return "300";
}
private bool CheckPausenabzug(SupportConcept sc)
{
var vv = sc.VarFieldValueList.FirstOrDefault(v => v.VarFieldDefOid.Value == 90);
if (vv != null)
{
var varFieldValue = BS.Shared.Core.Utils.XMLDeserializeFromString(vv.SerializedValue, Type.GetType(vv.TypeName));
if (varFieldValue != null && varFieldValue.ToString().ToLower() == "true")
{
return true;
}
}
return false;
}
}
}