Files
BeWoPlaner/ReportImp/SBBMainzReports/Invoicing/CustomInvoiceCreationQA.cs

248 lines
12 KiB
C#

using BeWo.Data.Access;
using BeWo.Data.Entities;
using BeWo.Data.Models.XRechnung;
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;
using DevExpress.Data.Helpers;
using DevExpress.DataProcessing.InMemoryDataProcessor;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SBBMainzReports.Invoicing
{
public class CustomInvoiceCreationQA : InvoiceCreation
{
// Bei QA werden werden pauschal die bewilligten Stunden pro Woche abgerechnet
// nur wenn ein Kontingent bewilligt wurde, wird es nach Zeiterfassung abgerechnet
bool bienen_ = false;
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();
if (cb2sc.CustomerReferenceNumber != null && cb2sc.CustomerReferenceNumber.Trim().ToLower().EndsWith("b") || (cb2sc.AuswahlBezeichnung != null && cb2sc.AuswahlBezeichnung.Trim().ToLower().Contains("bienen")))
{
bienen_ = true;
}
if (ShouldCreateFixedAmounts(serviceInvoicePeriod, supportConceptApprovalPeriod, cb2sc))
{
CreateFixedAmounts(serviceInvoicePeriod, supportConceptApprovalPeriod, cb2sc);
// Erweiterung um Wegepauschale
if (serviceRecordsInPeriod.Count > 0 && !bienen_)
{
InvoiceItem wg = null;
wg = CreateWegepauschale(serviceRecordsInPeriod, invoicePeriod, serviceInvoicePeriod.SupportConceptApprovalPeriod);
if (wg != null)
{
serviceInvoicePeriod.InvoiceItemList.Add(wg);
}
}
}
else
{
if (serviceRecordsInPeriod.Count > 0)
{
var absenceTimes = MapperFactory.AbsenceTimeDC_AbsenceTime.MapToNewDCs(cb2sc.SupportConcept.Customer.AbsenceTimes);
Dictionary<DateTimeSpan, decimal> span2Hours = calc.GetAbsencesTimesNotBillable(absenceTimes);
serviceInvoicePeriod.HoursNotBillableAbsence +=
calc.GetHoursNotBillableDueToAbsenceTimes(supportConceptApprovalPeriod,
cb2sc.CostBearer.CostRatePeriods.MapToNewDCs(),
serviceRecordsInPeriod,
span2Hours,
true, true);
if (!supportConceptApprovalPeriod.IsApprovedBEShifting)
{
serviceInvoicePeriod.HoursNotBillableNotApproved +=
calc.GetHoursNotBillableDueToMoreThanApproved(supportConceptApprovalPeriod,
cb2sc.CostBearer.CostRatePeriods.MapToNewDCs(),
serviceRecordsInPeriod,
true, true);
}
var itemList = CreateInvoiceItems(serviceRecordsInPeriod, invoicePeriod, serviceInvoicePeriod.SupportConceptApprovalPeriod, calc);
serviceInvoicePeriod.InvoiceItemList.AddRange(itemList);
}
}
}
public override bool ShouldCreateFixedAmounts(ServiceInvoicePeriod serviceInvoicePeriod, SupportConceptApprovalPeriodDC scap, CostBearer2SupportConcept cb2sc)
{
if (scap.ApprovedBEInterval.Value == SupportConceptApprovalInterval.Weekly && scap.ApprovedBEInterval.HasValue && scap.ApprovedBEPerInterval.HasValue)
{
return true;
}
if (scap.Notice != null && scap.Notice.ToLower().StartsWith("kontingent") && scap.ApprovedBETotal.HasValue)
{
List<CostRatePeriodDC> crList = scap.ServiceCategory.CostRatePeriods;
AccountingIntervalType? ai = scap.ServiceCategory.AccountingInterval;
if (ai.HasValue && crList.Count(c => c.CostRateValue.HasValue) > 0)
{
return ai.Value != AccountingIntervalType.Hourly;
}
}
return true;
}
public override void CreateFixedAmounts(ServiceInvoicePeriod serviceInvoicePeriod, SupportConceptApprovalPeriodDC supportConceptApprovalPeriod, CostBearer2SupportConcept cb2sc)
{
var calc = PluginLoader.FindClass<Calculations>(_SpecificID) ?? Calculations.GetInstance(_SpecificID);
var scap = supportConceptApprovalPeriod;
var crList = scap.ServiceCategory.CostRatePeriods;
var cr = crList.GetCostRatePeriodForDate(BS.Shared.CostRatePeriodType.AmountOfMoney, serviceInvoicePeriod.Start.Value);
if (cr != null && cr.CostRateValue.HasValue)
{
decimal? hourlyRate = cr.CostRateValue.Value;
decimal weeklyFactor = 4.33m;
// Anteilige Berechnung nur in dem Monat, in dem der HP tatsächlich beginnt bzw. endet -
// in allen anderen (vollen) Monaten wird der volle Monatsfaktor berechnet
if (scap.StartDate.HasValue && scap.StartDate.Value.Day > 7 && serviceInvoicePeriod.Start.HasValue
&& scap.StartDate.Value.Year == serviceInvoicePeriod.Start.Value.Year && scap.StartDate.Value.Month == serviceInvoicePeriod.Start.Value.Month)
{
int startDay = scap.StartDate.Value.Day;
if (startDay <= 14)
{
weeklyFactor = Math.Min(weeklyFactor, 3m);
}
else if (startDay <= 21)
{
weeklyFactor = Math.Min(weeklyFactor, 2m);
}
else
{
weeklyFactor = Math.Min(weeklyFactor, 1m);
}
}
if (scap.EndDate.HasValue && scap.EndDate.Value.Day < 22 && serviceInvoicePeriod.End.HasValue
&& scap.EndDate.Value.Year == serviceInvoicePeriod.End.Value.Year && scap.EndDate.Value.Month == serviceInvoicePeriod.End.Value.Month)
{
int endDay = scap.EndDate.Value.Day;
if (endDay >= 15)
{
weeklyFactor = Math.Min(weeklyFactor, 3m);
}
else if (endDay >= 8)
{
weeklyFactor = Math.Min(weeklyFactor, 2m);
}
else
{
weeklyFactor = Math.Min(weeklyFactor, 1m);
}
}
decimal approvedHours = 0;
decimal approvedHoursMonth = 0;
if (scap.ApprovedBEInterval.HasValue && scap.ApprovedBEInterval.Value == SupportConceptApprovalInterval.Weekly && scap.ApprovedBEPerInterval.HasValue)
{
approvedHours = scap.ApprovedBEPerInterval.Value;
approvedHoursMonth = weeklyFactor * scap.ApprovedBEPerInterval.Value;
}
decimal amount = approvedHoursMonth * hourlyRate.Value;
serviceInvoicePeriod.InvoiceItemList.Add(new InvoiceItem
{
AmountTotal = amount,
GrossAmountTotal = amount,
ItemPeriodStart = serviceInvoicePeriod.Start,
ItemPeriodEnd = serviceInvoicePeriod.End,
AmountPerUnit = hourlyRate.Value,
ItemDescription = "Fachleistungseinheiten/Woche",
UnitDescription = "QA/Woche",
UnitCount = approvedHours,
Notice = approvedHoursMonth.ToString("n2")
});
}
}
public override IList<InvoiceItem> CreateInvoiceItems(List<ServiceRecordDC> serviceRecordsInPeriod, DateTimeSpan invoicePeriod, SupportConceptApprovalPeriod scap,
BS.Shared.Services.Calculations calc)
{
var list = base.CreateInvoiceItems(serviceRecordsInPeriod, invoicePeriod, scap, calc);
InvoiceItem wg = null;
if (list.Count > 0 && !bienen_)
{
wg = CreateWegepauschale(serviceRecordsInPeriod, invoicePeriod, scap);
if (wg != null)
{
list.Add(wg);
}
}
return list;
}
private InvoiceItem CreateWegepauschale(List<ServiceRecordDC> serviceRecordsInPeriod, DateTimeSpan invoicePeriod, SupportConceptApprovalPeriod scap)
{
decimal wegepauschale = 17.35m;
wegepauschale = base.GetPreis("Wegepauschale", invoicePeriod.StartDate);
int countWege = 0;
//Anzahl der Zeiterfassungseinträge, die nicht im Büro stattfinden
countWege = serviceRecordsInPeriod.Where(r => r.ServiceDescription.CategoryName.Contains("QA") && !r.ServiceDescription.Name.Contains("Büro")).Count();
if (countWege > 0)
{
decimal anzahlWege = countWege;
var invoiceItem = new InvoiceItem();
invoiceItem.AmountPerUnit = wegepauschale;
invoiceItem.UnitCount = anzahlWege;
invoiceItem.AmountTotal = anzahlWege * wegepauschale;
invoiceItem.ItemPeriodStart = invoicePeriod.StartDate;
invoiceItem.ItemPeriodEnd = invoicePeriod.EndDate;
invoiceItem.RateFactor = null;
invoiceItem.GrossAmountTotal = invoiceItem.AmountTotal;
invoiceItem.ItemDescription = "Wegepauschale/Anzahl";
if (scap != null)
{
invoiceItem.SupportConceptApprovalPeriodOid = scap.Oid;
}
return invoiceItem;
}
return null;
}
public override void SetRecipientInformation(ServiceInvoice serviceInvoice, CostBearer costBearer)
{
base.SetRecipientInformation(serviceInvoice, costBearer);
if (serviceInvoice.InvoiceBase.CostBearer2SupportConcept != null)
{
var refNumber = serviceInvoice.InvoiceBase.CostBearer2SupportConcept.CustomerReferenceNumber;
if (!string.IsNullOrEmpty(refNumber))
{
var parts = refNumber.Split('.');
if (parts.Length == 3 && parts[0].Trim() == "50" && int.TryParse(parts[1].Trim(), out _))
{
string sachgebiet = parts[1].Trim();
string suffix = $"Sachgebiet {sachgebiet}";
if (string.IsNullOrEmpty(serviceInvoice.InvoiceBase.RecipientDivision))
serviceInvoice.InvoiceBase.RecipientDivision = suffix;
else if (!serviceInvoice.InvoiceBase.RecipientDivision.EndsWith(suffix))
serviceInvoice.InvoiceBase.RecipientDivision += $" {suffix}";
}
}
}
}
}
}