Files
BeWoPlaner/Service/Invoicing/InvoiceCreation.cs
2026-06-18 11:05:29 +02:00

1015 lines
48 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using BeWo.Data;
using BeWo.Data.Access;
using BeWo.Data.Entities;
using BeWo.Data.Security;
using BeWo.Service.DCEntityMapper;
using BeWo.Service.Plugins;
using BeWo.Service.ServiceImplementations;
using BS.Shared;
using BS.Shared.Core;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Compact;
using BS.Shared.Extensions;
using BS.Shared.Services;
namespace BeWo.Service.Invoicing
{
public class InvoiceCreation : AbstractIDSpecificDefaultClass<InvoiceCreation>
{
public virtual List<ServiceInvoiceDC> GenerateServiceInvoices(long costBearerOid,
DateTimeSpan invoicePeriod,
Dictionary<CompactSupportConceptDC, List<ServiceRecordDC>> supportConcepts2ServiceRecords)
{
return GenerateServiceInvoices(costBearerOid, invoicePeriod, supportConcepts2ServiceRecords, false);
}
public virtual List<ServiceInvoiceDC> GenerateServiceInvoices(long costBearerOid,
DateTimeSpan invoicePeriod,
Dictionary<CompactSupportConceptDC, List<ServiceRecordDC>> supportConcepts2ServiceRecords, bool splitInvoices)
{
var costBearer = DAOFactory.GenericDAO.LoadByID<CostBearer>(costBearerOid);
var invoiceList = new List<ServiceInvoice>();
var invoiceCounter = 0;
ServiceInvoice invoice;
if (costBearer.IsSingleInvoicePerCustomer)
{
invoice = CreateCollectiveBilling(costBearer, invoicePeriod, supportConcepts2ServiceRecords);
if (invoice != null)
{
invoiceList.Add(invoice);
}
}
else
{
foreach (var iSupportConcept2ServiceRecords in supportConcepts2ServiceRecords)
{
invoice = CreateSingleInvoice(invoiceCounter, costBearer, invoicePeriod, iSupportConcept2ServiceRecords.Key, iSupportConcept2ServiceRecords.Value);
if (invoice != null)
{
if (splitInvoices && invoice.ServiceInvoicePeriodList.Count > 1
&& !invoice.ServiceInvoicePeriodList.Any(s => s.Start == invoicePeriod.StartDate && s.End == invoicePeriod.EndDate))
{
foreach (var sip in invoice.ServiceInvoicePeriodList)
{
DateTimeSpan invPeriod = invoicePeriod;
invPeriod.StartDate = sip.Start.Value;
invPeriod.EndDate = sip.End.Value;
var partInvoice = CreateSingleInvoice(invoiceCounter, costBearer, invPeriod, iSupportConcept2ServiceRecords.Key, iSupportConcept2ServiceRecords.Value);
partInvoice.ServiceInvoicePeriodList.Add(sip);
invoiceList.Add(partInvoice);
invoiceCounter++;
}
}
else
{
invoiceList.Add(invoice);
invoiceCounter++;
}
}
}
}
var result = invoiceList.Select(item => MapperFactory.ServiceInvoiceDC_ServiceInvoice.MapToNewDC(item)).ToList();
return result.Count > 1 ? result.OrderBy(i => i.InvoiceBase.CustomerLastName).ToList() : result;
}
public virtual void SetInvoiceId(ServiceInvoice invoice)
{
//invoice.InvoiceBase.InvoiceId = "Id";
//invoice.InvoiceBase.InvoiceTypeText = "Text in Rechnungsübersicht";
}
public virtual ServiceInvoice CreateSingleInvoice(int invoiceCounter, CostBearer costBearer, DateTimeSpan invoicePeriod, CompactSupportConceptDC supportConcept, List<ServiceRecordDC> serviceRecords)
{
if (supportConcept.IsApproved)
{
var invoice = new ServiceInvoice();
var supportConceptList = new List<CompactSupportConceptDC> {supportConcept};
SetSenderInformation(invoice);
SetInvoiceBaseData(invoiceCounter, invoice, costBearer, invoicePeriod, supportConceptList);
SetSingleInvoiceBaseData(invoiceCounter, invoice, costBearer, invoicePeriod, supportConcept);
SetRecipientInformation(invoice, costBearer);
SetServiceInvoicePeriods(invoice, invoice.InvoiceBase.CostBearer2SupportConcept, invoicePeriod,
serviceRecords);
SetServiceInvoicePeriodAmounts(invoice);
// Spitzabrechnung
if (invoicePeriod == null)
{
SetAmountAdvancePayments(invoice);
SetAmountEquityContribution(invoice);
}
return invoice;
}
return null;
}
public virtual ServiceInvoice CreateCollectiveBilling(CostBearer costBearer, DateTimeSpan invoicePeriod, Dictionary<CompactSupportConceptDC, List<ServiceRecordDC>> supportConcepts2ServiceRecords)
{
var invoice = new ServiceInvoice();
var newDict = new Dictionary<CompactSupportConceptDC, List<ServiceRecordDC>>();
foreach (var sc2sr in supportConcepts2ServiceRecords)
{
if (sc2sr.Key.IsApproved)
{
newDict.Add(sc2sr.Key, sc2sr.Value);
}
}
SetRecipientInformation(invoice, costBearer);
SetSenderInformation(invoice);
SetInvoiceBaseData(0, invoice, costBearer, invoicePeriod, newDict.Keys.ToList());
SetCollectiveBillingBaseData(0, invoice, costBearer, invoicePeriod, newDict);
SetCollectiveBillingServiceInvoicePeriods(invoice, invoicePeriod, newDict);
SetServiceInvoicePeriodAmounts(invoice);
// Spitzabrechnung
if (invoicePeriod == null)
{
SetAmountAdvancePayments(invoice);
}
return invoice;
}
public virtual void SetServiceInvoicePeriodAmounts(ServiceInvoice invoice)
{
foreach (ServiceInvoicePeriod iPeriod in invoice.ServiceInvoicePeriodList)
{
//Dictionary<decimal, decimal> rate2UnitCount = new Dictionary<decimal, decimal>();
iPeriod.Claim = 0;
if (iPeriod.ApprovedFixedAmount.HasValue && iPeriod.ApprovedFixedAmount.Value != 0)
iPeriod.Claim = iPeriod.ApprovedFixedAmount;
else
{
foreach (InvoiceItem item in iPeriod.InvoiceItemList)
{
//if (item.UnitCount.HasValue && item.AmountPerUnit.HasValue)
//{
// if (!rate2UnitCount.ContainsKey(item.AmountPerUnit.Value))
// rate2UnitCount.Add(item.AmountPerUnit.Value, item.UnitCount.Value);
// else
// rate2UnitCount[item.AmountPerUnit.Value] += item.UnitCount.Value;
//}
if (item.GrossAmountTotal.HasValue)
iPeriod.Claim += item.GrossAmountTotal;
}
//foreach (decimal rate in rate2UnitCount.Keys)
//{
// decimal unitCount = rate2UnitCount[rate];
// iPeriod.Claim += rate * Math.Round(unitCount, 2, MidpointRounding.AwayFromZero);
//}
}
iPeriod.Claim = Math.Round(iPeriod.Claim.Value, 2, MidpointRounding.AwayFromZero);
//iPeriod.Claim = iPeriod.InvoiceItemList.Sum(i => i.GrossAmountTotal);
//invoice.InvoiceBase.InvoiceItems.AddRange(iPeriod.InvoiceItemList);
}
}
public virtual void SetAmountAdvancePayments(ServiceInvoice invoice)
{
decimal payments = 0;
var processedBookings = new Dictionary<long, bool>();
foreach (ServiceInvoicePeriod period in invoice.ServiceInvoicePeriodList)
{
if (period.SupportConceptApprovalPeriod != null)
{
IList<AccountingTransaction> bookingList = period.SupportConceptApprovalPeriod.CostBearer2SupportConcept.AccountingTransactions;
bookingList = bookingList.Where(i => i.GueltigkeitsDatum.HasValue
&& i.GueltigkeitsDatum.Value.InBetween(period.Start.Value, period.End.Value, true)).ToList();
foreach (AccountingTransaction item in bookingList)
{
if (!processedBookings.ContainsKey(item.Oid.Value))
{
payments += item.Amount;
processedBookings.Add(item.Oid.Value, true);
}
}
}
}
invoice.AmountAdvancePayments = payments;
}
public virtual void SetAmountEquityContribution(ServiceInvoice invoice)
{
decimal equity = 0;
IList<InvoiceBase> EquityInvoiceList =
DAOFactory.SearchDAO.GetInvoiceBaseByTypeAndSupportConceptOid(InvoiceType.CustomerEquity, invoice.InvoiceBase.SupportConceptOid.Value);
EquityInvoiceList = EquityInvoiceList.Where(i => i.InvoiceDate.HasValue &&
i.InvoiceDate.Value.InBetween(invoice.InvoiceBase.AccountingPeriodStart.Value, invoice.InvoiceBase.AccountingPeriodEnd.Value, true)).ToList();
foreach (InvoiceBase iEquityInvoice in EquityInvoiceList)
{
foreach (InvoiceItem item in iEquityInvoice.InvoiceItems)
{
if (item.AmountTotal != null)
{
equity += item.AmountTotal.Value;
}
}
}
invoice.AmountEquityContribution = equity;
}
public virtual void SetInvoiceBaseData(int invoiceCounter, ServiceInvoice invoice, CostBearer costBearer, DateTimeSpan invoicePeriod, IList<CompactSupportConceptDC> supportConceptList)
{
DateTime start = DateTime.MaxValue;
DateTime end = DateTime.MinValue;
if (invoicePeriod != null)
{
start = invoicePeriod.StartDateTime;
end = invoicePeriod.EndDateTime;
}
else
{
foreach (CompactSupportConceptDC iSupportConcept in supportConceptList)
{
if (iSupportConcept.CostBearerList != null && iSupportConcept.CostBearerList.Count > 0)
{
DateTime? dt = iSupportConcept.CostBearerList[0].ApprovedStartDate;
if (dt.HasValue && dt < start)
start = dt.Value;
dt = iSupportConcept.CostBearerList[0].ApprovedEndDate;
if (dt.HasValue && dt > end)
end = dt.Value;
}
}
}
invoice.InvoiceBase.AccountingPeriodStart = start;
invoice.InvoiceBase.AccountingPeriodEnd = end;
invoice.InvoiceBase.InvoiceDate = DateTime.Now;
invoice.InvoiceBase.Type = InvoiceType.Service;
invoice.InvoiceBase.DueDate = DateTime.Now.AddDays(14);
SetInvoiceId(invoice);
if (String.IsNullOrEmpty(invoice.InvoiceBase.InvoiceNumber))
{
var inc = PluginLoader.FindClass<InvoiceNumberGenerator>();
invoice.InvoiceBase.InvoiceNumber = inc.GetNextInvoiceNumber(invoiceCounter, invoice.InvoiceBase);
}
if (costBearer.CostRatePeriods != null)
{
List<CostRatePeriodDC> crpList = MapperFactory.CostRatePeriodDC_CostRatePeriod.MapToNewDCs(costBearer.CostRatePeriods);
CostRatePeriodDC crp = crpList.GetCostRatePeriodForDate(CostRatePeriodType.MinutesPerServiceUnit, DateTime.Now);
if (crp != null)
invoice.ServiceUnitOid = crp.CostRatePeriodOid;
}
}
public virtual void SetSingleInvoiceBaseData(int invoiceCounter, ServiceInvoice invoice, CostBearer costBearer, DateTimeSpan invoicePeriod, CompactSupportConceptDC supportConcept)
{
//Nur SingleInvoice und nicht Collective
invoice.InvoiceBase.SupportConceptOid = supportConcept.SupportConceptOid;
invoice.InvoiceBase.CostBearer2SupportConcept =
DAOFactory.GenericDAO.LoadByID<CostBearer2SupportConcept>(supportConcept.CostBearerRelOids[0]);
if (supportConcept.CustomerReferenceNumbers.Count > 0)
{
invoice.InvoiceBase.CustomerReferenceNumber = supportConcept.CustomerReferenceNumbers[0];
}
Person p = invoice.InvoiceBase.CostBearer2SupportConcept.SupportConcept.Customer.Person;
DateTimeSpan span = invoice.InvoiceBase.CostBearer2SupportConcept.GetApprovedSpan();
if (span == null)
{
span = invoice.InvoiceBase.CostBearer2SupportConcept.GetRequestedSpan();
}
if (span != null)
{
invoice.InvoiceBase.InvoiceTitle = String.Format("{0}, {1}, {2:dd.MM.yyy}-{3:dd.MM.yy}", p.LastName,
p.FirstName, span.StartDate, span.EndDate);
}
}
public virtual 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();
if (serviceRecordsInPeriod.Count > 0)
{
//var approvalPeriodDC = DAOFactory.GenericDAO
// .LoadByID<SupportConceptApprovalPeriod>(serviceInvoicePeriod.SupportConceptApprovalPeriodOid.Value)
// .MapToNewDC();
//Dictionary<DateTimeSpan, decimal> span2HoursTest = cb2sc.SupportConcept.Customer.GetAbsencesTimesNotBillableWholeWeeks();
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 virtual bool ShouldCreateFixedAmounts(ServiceInvoicePeriod serviceInvoicePeriod, SupportConceptApprovalPeriodDC supportConceptApprovalPeriod, CostBearer2SupportConcept cb2sc)
{
if (serviceInvoicePeriod.ApprovedFixedAmount.HasValue)
return true;
if (supportConceptApprovalPeriod.ServiceCategory != null)
{
List<CostRatePeriodDC> crList = supportConceptApprovalPeriod.ServiceCategory.CostRatePeriods;
AccountingIntervalType? ai = supportConceptApprovalPeriod.ServiceCategory.AccountingInterval;
if (ai.HasValue && crList.Count(c => c.CostRateValue.HasValue) > 0)
{
return ai.Value != AccountingIntervalType.Hourly;
}
}
return false;
}
public virtual void CreateFixedAmounts(ServiceInvoicePeriod serviceInvoicePeriod, SupportConceptApprovalPeriodDC supportConceptApprovalPeriod, CostBearer2SupportConcept cb2sc)
{
var calc = PluginLoader.FindClass<Calculations>(_SpecificID) ?? Calculations.GetInstance(_SpecificID);
var data = calc.GetFixedBillingData(supportConceptApprovalPeriod, serviceInvoicePeriod.Start, serviceInvoicePeriod.End);
foreach (var billingData in data)
{
serviceInvoicePeriod.InvoiceItemList.Add(new InvoiceItem
{
AmountTotal = billingData.AmountTotal,
GrossAmountTotal = billingData.GrossAmountTotal,
ItemPeriodStart = billingData.BillingPeriodStart,
ItemPeriodEnd = billingData.BillingPeriodEnd,
AccountingInterval = billingData.AccountingInterval,
AmountPerUnit = billingData.AmountPerUnit,
UnitCount = billingData.UnitCount
});
}
}
public virtual void SetRecipientInformation(ServiceInvoice serviceInvoice, CostBearer costBearer)
{
if (costBearer.Organisation.Name.ToLower().Trim() == "selbstzahler")
{
serviceInvoice.InvoiceBase.RecipientDivision = costBearer.Organisation.Name2;
serviceInvoice.InvoiceBase.RecipientOrganisationOid = costBearer.Organisation.Oid;
serviceInvoice.InvoiceBase.RecipientOrganisation = costBearer.Organisation.Name;
serviceInvoice.InvoiceBase.RecipientContacts = costBearer.Organisation.Contacts.Select(i => i.CopyToNew()).ToList();
serviceInvoice.InvoiceBase.RecipientCostBearerOid = costBearer.Oid;
if (serviceInvoice.InvoiceBase.CostBearer2SupportConcept != null)
{
var cust = serviceInvoice.InvoiceBase.CostBearer2SupportConcept.SupportConcept.Customer;
if (cust.Person.InvoiceAddress != null)
{
serviceInvoice.InvoiceBase.RecipientAddress = cust.Person.InvoiceAddress.CopyToNew();
}
else if (cust.Person.Address != null)
{
serviceInvoice.InvoiceBase.RecipientAddress = cust.Person.Address.CopyToNew();
}
if (cust.Person.InvoiceAddress != null && cust.Person.InvoiceAddress.AddressLine1 != null) // Anderer Rechnungsempfänger z.B. Vormund
{
serviceInvoice.InvoiceBase.RecipientPersonFirstName = cust.Person.InvoiceAddress.AddressLine1;
serviceInvoice.InvoiceBase.RecipientPersonLastName = "";
}
else
{
serviceInvoice.InvoiceBase.RecipientPersonFirstName = cust.Person.FirstName;
serviceInvoice.InvoiceBase.RecipientPersonLastName = cust.Person.LastName;
}
serviceInvoice.InvoiceBase.RecipientPersonOid = cust.Person.Oid;
return;
}
if (costBearer.Organisation.InvoiceAddress != null)
{
serviceInvoice.InvoiceBase.RecipientAddress = costBearer.Organisation.InvoiceAddress.CopyToNew();
}
else if (costBearer.Organisation.Address != null)
{
serviceInvoice.InvoiceBase.RecipientAddress = costBearer.Organisation.Address.CopyToNew();
}
}
else
{
if (costBearer.Organisation.InvoiceAddress != null)
{
serviceInvoice.InvoiceBase.RecipientAddress = costBearer.Organisation.InvoiceAddress.CopyToNew();
}
else if (costBearer.Organisation.Address != null)
{
serviceInvoice.InvoiceBase.RecipientAddress = costBearer.Organisation.Address.CopyToNew();
}
serviceInvoice.InvoiceBase.RecipientDivision = costBearer.Organisation.Name2;
serviceInvoice.InvoiceBase.RecipientOrganisationOid = costBearer.Organisation.Oid;
serviceInvoice.InvoiceBase.RecipientOrganisation = costBearer.Organisation.Name;
serviceInvoice.InvoiceBase.RecipientContacts = costBearer.Organisation.Contacts.Select(i => i.CopyToNew()).ToList();
serviceInvoice.InvoiceBase.RecipientCostBearerOid = costBearer.Oid;
//serviceInvoice.InvoiceBase. = c2s.CostBearer.Organisation.Contacts.FirstOrDefault(f => f.Type.Equals(ContactType.business_POBox)) != null ? c2s.CostBearer.Organisation.Contacts.FirstOrDefault(f => f.Type.Equals(ContactType.business_POBox)).Value : String.Empty;
if (serviceInvoice.InvoiceBase.CostBearer2SupportConcept != null &&
serviceInvoice.InvoiceBase.CostBearer2SupportConcept.CostBearerContactPerson != null)
{
serviceInvoice.InvoiceBase.RecipientPersonFirstName = serviceInvoice.InvoiceBase.CostBearer2SupportConcept.CostBearerContactPerson.FirstName;
serviceInvoice.InvoiceBase.RecipientPersonLastName = serviceInvoice.InvoiceBase.CostBearer2SupportConcept.CostBearerContactPerson.LastName;
serviceInvoice.InvoiceBase.RecipientPersonOid = serviceInvoice.InvoiceBase.CostBearer2SupportConcept.CostBearerContactPerson.Oid;
}
}
}
public virtual void SetSenderInformation(ServiceInvoice serviceInvoice)
{
if (UserRightHelper.GetLoggedInUser() != null)
{
var lLoggedInEmployee = UserRightHelper.GetLoggedInUser().Employee;
var mandator = new OperationsServiceImp().GetMandator2(false);
if (lLoggedInEmployee != null)
{
serviceInvoice.InvoiceBase.CreatorFirstName = serviceInvoice.InvoiceBase.SenderFirstName =
lLoggedInEmployee.Person.FirstName;
serviceInvoice.InvoiceBase.CreatorLastName = serviceInvoice.InvoiceBase.SenderLastName =
lLoggedInEmployee.Person.LastName;
serviceInvoice.InvoiceBase.SenderContacts =
lLoggedInEmployee.Person.Contacts.Select(i => i.CopyToNew()).ToList();
serviceInvoice.InvoiceBase.SenderAddress = new Address
{
Street = mandator.Street,
PostalCode = mandator.PostalCode,
Town = mandator.Town,
State = mandator.State
};
}
}
}
public virtual void SetServiceInvoicePeriods(ServiceInvoice invoice, CostBearer2SupportConcept costBearer2SupportConcept, DateTimeSpan invoicePeriod, List<ServiceRecordDC> serviceRecords)
{
var invoiceAccountingPeriodSpan = new DateTimeSpan
{
StartDateTime = invoice.InvoiceBase.AccountingPeriodStart.Value,
EndDateTime = invoice.InvoiceBase.AccountingPeriodEnd.Value
};
foreach (SupportConceptApprovalPeriod iPeriod in costBearer2SupportConcept.ApprovalPeriodList)
{
SupportConceptApprovalPeriodDC approvalPeriodDC = MapperFactory.SupportConceptApprovalPeriodDC_SupportConceptApprovalPeriod.MapToNewDC(iPeriod);
if (approvalPeriodDC.Span.EndDateTime < invoiceAccountingPeriodSpan.StartDateTime || approvalPeriodDC.Span.StartDateTime > invoiceAccountingPeriodSpan.EndDate)
{
continue;
}
ServiceInvoicePeriod serviceInvoicePeriod = CreateServiceInvoicePeriod(approvalPeriodDC, invoiceAccountingPeriodSpan);
serviceInvoicePeriod.SupportConceptApprovalPeriod = iPeriod;
serviceInvoicePeriod.Customer = costBearer2SupportConcept.SupportConcept.Customer;
CostBearer costBearer = costBearer2SupportConcept.CostBearer;
List<CostRatePeriodDC> costRates = MapperFactory.CostRatePeriodDC_CostRatePeriod.MapToNewDCs(costBearer.CostRatePeriods);
CostRatePeriodDC serviceUnit = costRates.GetCostRatePeriodForDate(CostRatePeriodType.MinutesPerServiceUnit, DateTime.Now);
serviceInvoicePeriod.ServiceUnitName = serviceUnit.UnitName;
Calculations calc = PluginLoader.FindClass<Calculations>(_SpecificID) ?? Calculations.GetInstance(_SpecificID);
decimal amountPerUnit;
decimal unitCount;
serviceInvoicePeriod.ApprovedFixedAmount = calc.GetApprovedFixedAmountForPeriod(approvalPeriodDC, serviceInvoicePeriod.Start.Value, serviceInvoicePeriod.End.Value, out amountPerUnit, out unitCount);
if (!serviceInvoicePeriod.ApprovedFixedAmount.HasValue)
{
serviceInvoicePeriod.ApprovedHours = calc.GetApprovedHoursForPeriod(approvalPeriodDC,
costRates,
serviceInvoicePeriod.Start.Value,
serviceInvoicePeriod.End.Value);
if (serviceInvoicePeriod.ApprovedHours.HasValue)
serviceInvoicePeriod.ApprovedBE = serviceUnit.GetHoursInBE(serviceInvoicePeriod.ApprovedHours.Value);
serviceInvoicePeriod.ApprovedAmountDefaultHourlyRate = calc.GetApprovedAmountDefaultHourlyRateForPeriod(approvalPeriodDC,
costRates,
serviceInvoicePeriod.Start,
serviceInvoicePeriod.End);
}
SetInvoiceItems(invoice, serviceInvoicePeriod, approvalPeriodDC, costBearer2SupportConcept, invoicePeriod, serviceRecords);
CheckMaxApprovedAmount(invoice, serviceInvoicePeriod, approvalPeriodDC, costBearer2SupportConcept, invoicePeriod, serviceRecords);
if (serviceInvoicePeriod.InvoiceItemList.Count > 0)
invoice.ServiceInvoicePeriodList.Add(serviceInvoicePeriod);
}
}
public virtual void CheckMaxApprovedAmount(ServiceInvoice invoice, ServiceInvoicePeriod sip, SupportConceptApprovalPeriodDC scap, CostBearer2SupportConcept costBearer2SupportConcept, DateTimeSpan invoicePeriod, List<ServiceRecordDC> serviceRecords)
{
if (sip.ApprovedHours.HasValue && !scap.IsApprovedBEShifting)
{
//Prüfen ob der abzurechnende Zeitraum kleiner als das Bewilligungsintervall ist
if (scap.ApprovedBEInterval.HasValue)
{
var days = invoicePeriod.GetTimeSpan().Days + 1;
switch (scap.ApprovedBEInterval.Value)
{
case SupportConceptApprovalInterval.Quarterly:
if (days < 89) //CB: Machen wir es mal nicht zu kompliziert, wenn man weniger als 89 Tage abrechnet, gehen wir davon aus, dass nicht das gesamte Quartal abgerechnet wird
{
return; // Mach nix. TODO: Gesamtstunden prüfen und dann nur das abrechnen, was noch offen ist. Wer das macht bekommt ein Fleißsternchen:-)
}
break;
case SupportConceptApprovalInterval.HalfYearly:
if (days < 178) //CB: Siehe oben
{
return; // Mach nix. TODO: Gesamtstunden prüfen und dann nur das abrechnen, was noch offen ist. Wer das macht bekommt ein Fleißsternchen:-)
}
break;
case SupportConceptApprovalInterval.Yearly:
if (days < 365) //CB: Siehe oben
{
return; // Mach nix. TODO: Gesamtstunden prüfen und dann nur das abrechnen, was noch offen ist. Wer das macht bekommt ein Fleißsternchen:-)
}
break;
default:
break;
}
}
decimal totalHours = 0;
foreach (var ii in sip.InvoiceItemList.Where(ii => ii.UnitCount.HasValue))
{
if (totalHours + ii.UnitCount.Value > sip.ApprovedHours)
{
ii.UnitCount = Math.Round(sip.ApprovedHours.Value - totalHours, 2, MidpointRounding.AwayFromZero);
if (ii.AmountPerUnit.HasValue)
{
ii.AmountTotal = ii.AmountPerUnit.Value*ii.UnitCount;
ii.GrossAmountTotal = ii.AmountTotal;
}
if (ii.RateFactor.HasValue)
{
ii.AmountTotal *= (ii.RateFactor + 100) / 100;
ii.GrossAmountTotal *= (ii.RateFactor + 100) / 100;
}
totalHours = sip.ApprovedHours.Value;
}
else
{
totalHours += ii.UnitCount.Value;
}
}
}
}
public virtual ServiceInvoicePeriod CreateServiceInvoicePeriod(SupportConceptApprovalPeriodDC approvalPeriodDC, DateTimeSpan invoiceAccountingPeriodSpan)
{
var sip = new ServiceInvoicePeriod
{
Start = approvalPeriodDC.Span.StartDateTime > invoiceAccountingPeriodSpan.StartDateTime
? approvalPeriodDC.Span.StartDateTime
: invoiceAccountingPeriodSpan.StartDateTime,
End = approvalPeriodDC.Span.EndDateTime < invoiceAccountingPeriodSpan.EndDateTime
? approvalPeriodDC.Span.EndDateTime
: invoiceAccountingPeriodSpan.EndDateTime,
};
return sip;
}
public virtual void SetCollectiveBillingBaseData(int invoiceCounter, ServiceInvoice invoice, CostBearer costBearer, DateTimeSpan invoicePeriod, Dictionary<CompactSupportConceptDC, List<ServiceRecordDC>> supportConcepts2ServiceRecords)
{
invoice.InvoiceBase.InvoiceTitle = "Rechnung über Betreuungleistungen";
}
public virtual void SetCollectiveBillingServiceInvoicePeriods(ServiceInvoice invoice, DateTimeSpan invoicePeriod, Dictionary<CompactSupportConceptDC, List<ServiceRecordDC>> supportConcepts2ServiceRecords)
{
foreach (var supportConcepts2ServiceRecord in supportConcepts2ServiceRecords)
{
var c2s = DAOFactory.GenericDAO.LoadByID<CostBearer2SupportConcept>(
supportConcepts2ServiceRecord.Key.CostBearerRelOids[0]);
SetServiceInvoicePeriods(invoice, c2s, invoicePeriod, supportConcepts2ServiceRecord.Value);
}
}
public virtual IList<InvoiceItem> CreateInvoiceItems(List<ServiceRecordDC> serviceRecordsInPeriod, DateTimeSpan invoicePeriod, SupportConceptApprovalPeriod scap, Calculations calc)
{
var list = new List<InvoiceItem>();
foreach (ServiceRecordDC iServiceRecord in serviceRecordsInPeriod)
{
if (iServiceRecord.ServiceDescription.Category.IsBillable)
{
if (!iServiceRecord.AlreadyAccounted)
{
InvoiceItem invoiceItem = CreateInvoiceItem(iServiceRecord, scap, calc);
if (invoiceItem != null)
{
list.Add(invoiceItem);
}
iServiceRecord.AlreadyAccounted = true;
}
}
}
return CreateSummaryInvoiceItems(list, invoicePeriod, scap, calc);
}
public virtual IList<InvoiceItem> CreateSummaryInvoiceItems(IList<InvoiceItem> itemList, DateTimeSpan invoicePeriod, SupportConceptApprovalPeriod scap, Calculations calc)
{
return CreateSummaryInvoiceItems(itemList, invoicePeriod, scap, calc, false);
}
public virtual IList<InvoiceItem> CreateSummaryInvoiceItems(IList<InvoiceItem> itemList,
DateTimeSpan invoicePeriod, SupportConceptApprovalPeriod scap, Calculations calc, bool summaryPerMonth)
{
return CreateSummaryInvoiceItems(itemList, invoicePeriod, scap, calc, summaryPerMonth, false);
}
public virtual IList<InvoiceItem> CreateSummaryInvoiceItems(IList<InvoiceItem> itemList,
DateTimeSpan invoicePeriod, SupportConceptApprovalPeriod scap, Calculations calc, bool summaryPerMonth, bool addRateFactorToUnitCount)
{
//Fasse InvoiceItems mit gleichem Stundensatz zusammen:
var newlist = new List<InvoiceItem>();
var rateToItem = new Dictionary<String, InvoiceItem>();
foreach (InvoiceItem iitem in itemList)
{
InvoiceItem item;
var key = GetSummaryItemKey(scap, iitem, summaryPerMonth);
if (rateToItem.ContainsKey(key))
{
item = rateToItem[key];
}
else
{
item = new InvoiceItem();
newlist.Add(item);
item.AmountPerUnit = iitem.AmountPerUnit;
if (invoicePeriod != null)
{
item.ItemPeriodStart = invoicePeriod.StartDate;
item.ItemPeriodEnd = invoicePeriod.EndDate;
}
else
{
item.ItemPeriodStart = scap.StartDate;
item.ItemPeriodEnd = scap.EndDate;
}
if (summaryPerMonth && iitem.ItemPeriodStart.HasValue)
{
DateTime start = new DateTime(iitem.ItemPeriodStart.Value.Year, iitem.ItemPeriodStart.Value.Month, 1);
DateTime end = start.AddMonths(1).AddDays(-1);
if (item.ItemPeriodStart < start)
{
item.ItemPeriodStart = start;
}
if (item.ItemPeriodEnd > end)
{
item.ItemPeriodEnd = end;
}
}
item.RateFactor = iitem.RateFactor;
item.AccountingInterval = iitem.AccountingInterval;
item.ItemDescription = iitem.ItemDescription;
item.UnitDescription = iitem.UnitDescription;
item.SupportConceptApprovalPeriodOid = scap.Oid;
rateToItem[key] = item;
}
if (!item.UnitCount.HasValue)
{
item.UnitCount = 0;
}
item.UnitCount += iitem.UnitCount ?? 0;
}
BerechneSummaryItemsSummen(newlist, addRateFactorToUnitCount);
return newlist;
}
public virtual string GetSummaryItemKey(SupportConceptApprovalPeriod scap, InvoiceItem iitem, bool summaryPerMonth)
{
String key = String.Format("{0:0.0000}_{1}", iitem.AmountPerUnit, iitem.RateFactor);
if (summaryPerMonth)
{
key = String.Format("{0:0.0000}_{1}_{2:yyyyMM}", iitem.AmountPerUnit, iitem.RateFactor, iitem.ItemPeriodStart);
}
return key;
}
public virtual void BerechneSummaryItemsSummen(List<InvoiceItem> newlist, bool addRateFactorToUnitCount)
{
foreach (InvoiceItem invoiceItem in newlist)
{
if (!invoiceItem.AmountPerUnit.HasValue)
{
invoiceItem.AmountPerUnit = 0;
}
invoiceItem.AmountPerUnit = Math.Round(invoiceItem.AmountPerUnit.Value, 2, MidpointRounding.AwayFromZero);
if (!invoiceItem.UnitCount.HasValue)
{
invoiceItem.UnitCount = 0;
}
if (addRateFactorToUnitCount && invoiceItem.RateFactor.HasValue)
{
invoiceItem.UnitCount = (invoiceItem.UnitCount ?? 0) * ((invoiceItem.RateFactor + 100) / 100);
}
invoiceItem.UnitCount = Math.Round(invoiceItem.UnitCount.Value, 2, MidpointRounding.AwayFromZero);
invoiceItem.AmountTotal = invoiceItem.AmountPerUnit * invoiceItem.UnitCount;
invoiceItem.AmountTotal = Math.Round(invoiceItem.AmountTotal.Value, 2, MidpointRounding.AwayFromZero);
invoiceItem.GrossAmountTotal = invoiceItem.AmountTotal;
if (!addRateFactorToUnitCount && invoiceItem.RateFactor.HasValue)
{
invoiceItem.GrossAmountTotal *= ((invoiceItem.RateFactor + 100) / 100);
}
}
}
public virtual IList<InvoiceItem> CreateInvoiceItemsForEachServiceRecord(List<ServiceRecordDC> serviceRecordsInPeriod, SupportConceptApprovalPeriod scap, Calculations calc)
{
var list = new List<InvoiceItem>();
foreach (ServiceRecordDC iServiceRecord in serviceRecordsInPeriod)
{
if (iServiceRecord.ServiceDescription.Category.IsBillable)
{
if (!iServiceRecord.AlreadyAccounted)
{
InvoiceItem invoiceItem = CreateInvoiceItem(iServiceRecord, scap, calc);
list.Add(invoiceItem);
iServiceRecord.AlreadyAccounted = true;
}
}
}
return list;
}
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;
if (iServiceRecord.ServiceDescription.Name.ToLower().Contains("fehlkontakt") || (iServiceRecord.ServiceDescription.ProzentAbrechnung.HasValue && iServiceRecord.ServiceDescription.ProzentAbrechnung.Value < 100))
{
invoiceItem.RateFactor = null;
invoiceItem.GrossAmountTotal = invoiceItem.AmountTotal;
}
//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;
}
public virtual decimal GetPreis(String preisBezeichnung, DateTime datum)
{
var preise = DAOFactory.GenericDAO.GetAllActive<Preis>();
var preis = preise.Where(p => p.Name.Contains(preisBezeichnung)).FirstOrDefault();
if (preis != null)
{
var crlist = MapperFactory.CostRatePeriodDC_CostRatePeriod.MapToNewDCs(preis.CostRatePeriods);
var cr = crlist.GetCostRatePeriodForDate(CostRatePeriodType.AmountOfMoney, datum);
if (cr != null && cr.CostRateValue.HasValue)
{
return cr.CostRateValue.Value;
}
}
return 0;
}
// public virtual void RemoveOrCropInvoiceItemsNotBillable(ServiceInvoicePeriod iPeriod)
// {
// this.RemoveOrCropInvoiceItemsNotBillableDueToAbsenceTimes(iPeriod);
// this.RemoveOrCropInvoiceItemsNotBillableDueToMoreThanApproved(iPeriod);
// }
// public virtual void RemoveOrCropInvoiceItemsNotBillableDueToAbsenceTimes(ServiceInvoicePeriod iPeriod)
// {
// if (iPeriod.ApprovedFixedAmount.HasValue)
// {
// return;
// }
// var absenceTimes = DAOFactory.GenericDAO.LoadByID<SupportConceptApprovalPeriod>(iPeriod.SupportConceptApprovalPeriodOid.Value)
// .CostBearer2SupportConcept.SupportConcept.Customer.GetAbsencesTimesNotBillableWholeWeeks();
// foreach (var iInvoiceItem in iPeriod.InvoiceItemList.ToList())
// {
// var absenceWeek = absenceTimes.SingleOrDefault(i => iInvoiceItem.ItemPeriodStart.Value.InBetween(i.Key)).Key;
// if (absenceWeek != null)
// {
// if (absenceTimes[absenceWeek] == 0)
// {
// iPeriod.InvoiceItemList.Remove(iInvoiceItem);
// iPeriod.HoursNotBillableAbsence += iInvoiceItem.UnitCount.Value;
// }
// else
// {
// var minutes = iInvoiceItem.UnitCount.Value * 60m;
// if (absenceTimes[absenceWeek] - minutes >= 0)
// {
// absenceTimes[absenceWeek] -= minutes;
// }
// else
// {
// iPeriod.HoursNotBillableAbsence += (minutes - absenceTimes[absenceWeek]) / 60;
// iInvoiceItem.UnitCount = absenceTimes[absenceWeek] / 60m;
// iInvoiceItem.ItemPeriodEnd = iInvoiceItem.ItemPeriodStart.Value.AddHours(Convert.ToDouble(iInvoiceItem.UnitCount));
// iInvoiceItem.AmountTotal = iInvoiceItem.AmountPerUnit * iInvoiceItem.UnitCount;
// if (iInvoiceItem.RateFactor != null)
// {
// iInvoiceItem.GrossAmountTotal = iInvoiceItem.AmountTotal + (iInvoiceItem.AmountTotal * iInvoiceItem.RateFactor.Value / 100);
// }
// else
// {
// iInvoiceItem.GrossAmountTotal = iInvoiceItem.AmountTotal;
// }
// absenceTimes[absenceWeek] = 0;
// }
// }
// }
// }
// }
// public virtual void RemoveOrCropInvoiceItemsNotBillableDueToMoreThanApproved(ServiceInvoicePeriod iPeriod)
// {
// if (iPeriod.ApprovedFixedAmount.HasValue)
// {
// return;
// }
// var approvedAmountCounter = iPeriod.ApprovedAmountDefaultHourlyRate;
// foreach (var iInvoiceItem in iPeriod.InvoiceItemList.ToList())
// {
// if (approvedAmountCounter - iInvoiceItem.GrossAmountTotal >= 0)
// {
// approvedAmountCounter -= iInvoiceItem.GrossAmountTotal;
// }
// else if (approvedAmountCounter == 0)
// {
// iPeriod.InvoiceItemList.Remove(iInvoiceItem);
// iPeriod.HoursNotBillableNotApproved += iInvoiceItem.UnitCount.Value;
// }
// else
// {
// iInvoiceItem.GrossAmountTotal = approvedAmountCounter;
// if (iInvoiceItem.RateFactor != null)
// {
// iInvoiceItem.AmountTotal = (iInvoiceItem.GrossAmountTotal / (100 + iInvoiceItem.RateFactor.Value)) * 100;
// }
// else
// {
// iInvoiceItem.AmountTotal = iInvoiceItem.GrossAmountTotal;
// }
// var oldUnitCount = iInvoiceItem.UnitCount.Value;
// iInvoiceItem.UnitCount = iInvoiceItem.AmountTotal / iInvoiceItem.AmountPerUnit;
// iPeriod.HoursNotBillableNotApproved += oldUnitCount - iInvoiceItem.UnitCount.Value;
// iInvoiceItem.ItemPeriodEnd = iInvoiceItem.ItemPeriodStart.Value.AddHours(Convert.ToDouble(iInvoiceItem.UnitCount));
// approvedAmountCounter = 0;
// }
// }
// }
}
}