Files
BeWoPlaner/Service/Plugins/AccountingService.cs

874 lines
44 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using BeWo.Data.Access;
using BeWo.Data.Entities;
using BeWo.Data.Security;
using BeWo.Service.Configuration;
using BeWo.Service.Core;
using BeWo.Service.DCEntityMapper;
using BeWo.Service.Invoicing;
using BS.Shared;
using BS.Shared.Core;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Compact;
using BS.Shared.Extensions;
using BS.Shared.Models;
namespace BeWo.Service.Plugins
{
public class AccountingService : AbstractIDSpecificDefaultClass<AccountingService>
{
public virtual List<ServiceInvoiceDC> GenerateInitialServiceInvoices(long costBearerOid, long? supportConceptOid, DateTimeSpan invoicePeriod)
{
var cs = PluginLoader.FindClass<CustomerService>();
IEnumerable<CompactSupportConceptDC> supportConcepts;
// GetAllActiveSupportConceptCostbearer returns a "Flat" SupportConcept List, one for each CostBearer2SupportConcept!
if (!supportConceptOid.HasValue)
{
supportConcepts = cs.GetAllActiveSupportConceptCostbearer(false, true, 0)
.Where(i => i.CostBearerOids2CostBearerRelOids.ContainsKey(costBearerOid));
}
else
{
supportConcepts = cs.GetCompactSupportConcepts(supportConceptOid.Value, null)
.Where(i => i.CostBearerOids2CostBearerRelOids.ContainsKey(costBearerOid));
}
DateTimeSpan newSpan = null;
if (invoicePeriod != null)
{
//invoicePeriod.StartDateTime = invoicePeriod.StartDateTime.Date;
//invoicePeriod.EndDateTime = invoicePeriod.EndDateTime.Date;
newSpan = new DateTimeSpan();
newSpan.StartDateTime = invoicePeriod.StartDateTime.Date;
newSpan.EndDateTime = invoicePeriod.EndDateTime.Date.AddDays(1).AddTicks(-1);
if (!supportConceptOid.HasValue)
{
supportConcepts =
supportConcepts.Where(sc => sc.StartDate < newSpan.EndDateTime && sc.EndDate >= newSpan.StartDate);
}
}
var supportConcepts2ServiceRecords = supportConcepts.ToDictionary(
i => i,
i => MapperFactory.ServiceRecordDC_ServiceRecord.MapToNewDCs(
DAOFactory.SearchDAO.FindServiceRecordsInSpan(i.CostBearerRelOids[0], newSpan)));
var cb = DAOFactory.GenericDAO.LoadByID<CostBearer>(costBearerOid);
String tenant = PluginLoader.Tenant;
var factory = PluginLoader.FindClass<InvoiceFactory>(cb.ID);
if (factory == null)
{
factory = InvoiceFactory.GetInstance(cb.ID, tenant);
}
var creator = factory.CreateInvoiceCreator(cb.ID, tenant, supportConcepts2ServiceRecords);
var newInvoices = creator.GenerateServiceInvoices(costBearerOid, invoicePeriod, supportConcepts2ServiceRecords);
//Prüfe ob Rechnungen neu sind oder Diff vorhanden
var differenzRechnungChecks = GetNewInvoices(newInvoices, invoicePeriod?.StartDate, invoicePeriod?.EndDate);
var resultList = ErstelleNeueRechnungen(differenzRechnungChecks);
return resultList;
}
protected virtual List<ServiceInvoiceDC> ErstelleNeueRechnungen(List<DifferenzRechnungCheck> differenzRechnungChecks)
{
var rechnungen = new List<ServiceInvoiceDC>();
foreach (var item in differenzRechnungChecks)
{
if (item.VorhandeneRechungen.Count == 0 || !item.VorhandeneRechungen.Any(r => item.NeueRechnung.InvoiceBase.CustomerOid == r.InvoiceBase.CustomerOid))
{
item.NeueRechnung.InvoiceBase.NeuErstellen = true;
rechnungen.Add(item.NeueRechnung);
}
else
{
var diffRechnung = ErstelleDifferenzRechnung(item);
if (diffRechnung != null)
{
diffRechnung.InvoiceBase.NeuErstellen = false;
rechnungen.Add(diffRechnung);
}
}
}
return rechnungen;
}
protected virtual ServiceInvoiceDC ErstelleDifferenzRechnung(DifferenzRechnungCheck item)
{
ServiceInvoiceDC diffRechnung = null;
//var alterBetrag = item.VorhandeneRechungen.Sum(i => i.ClaimSum ?? 0);
var letzteRg = item.VorhandeneRechungen.OrderByDescending(r => r.ServiceInvoiceOid).FirstOrDefault();
letzteRg = item.VorhandeneRechungen.FirstOrDefault(r => item.NeueRechnung.InvoiceBase.CustomerOid == r.InvoiceBase.CustomerOid);
if (letzteRg != null)
{
if (item.NeueRechnung.ClaimSum == letzteRg.ClaimSum)
{
diffRechnung = item.NeueRechnung;
diffRechnung.InvoiceBase.NeuErstellen = false;
diffRechnung.InvoiceBase.Hinweise = String.Format("Rechnung wurde bereits erstellt");
}
else
{
diffRechnung = new ServiceInvoiceDC();
diffRechnung.OriginalZurDifferenz = item.NeueRechnung;
diffRechnung.InvoiceBase = new InvoiceBaseDC();
CopyInvoiceBaseDC(item.NeueRechnung.InvoiceBase, diffRechnung);
ServiceInvoice counterInvoice = new ServiceInvoice();
var serviceInvoice = DAOFactory.SearchDAO.GetServiceInvoiceByInvoiceBaseOid(letzteRg.InvoiceBase.InvoiceBaseOid.Value);
CopyServiceInvoice(serviceInvoice, counterInvoice);
SetzeStornoInfos(counterInvoice);
SetzeRechnungspositionenServiceInvoice(diffRechnung, counterInvoice, item);
diffRechnung.InvoiceBase.NeuErstellen = true;
// Differenzrechnung nur, wenn der Zeitraum der selbe ist, wie der der neuen Rechnung
if (letzteRg.InvoiceBase.AccountingPeriodStart == item.NeueRechnung.InvoiceBase.AccountingPeriodStart &&
letzteRg.InvoiceBase.AccountingPeriodEnd == item.NeueRechnung.InvoiceBase.AccountingPeriodEnd)
{
diffRechnung.InvoiceBase.Hinweise = String.Format("Rechnungsdifferenz zu Rechnung {0} in Höhe von {1:c}", letzteRg.InvoiceBase.InvoiceNumber, letzteRg.InvoiceBase.TotalAmount.Value);
}
else
{
diffRechnung.InvoiceBase.Hinweise = String.Format("WARNUNG: Möglcherweise keine korrekte dargestellte Differenzabrechnung!\r\n" +
"Die Differenzrechnung kann nur für den ursprünglichen Zeitraum einer Rechnung erstellt werden.\r\n" +
"Achten Sie auf identische Abrechenzeiträume, wenn Sie eine Differenzabrechnung erstellen!");
}
}
}
return diffRechnung;
}
protected virtual List<DifferenzRechnungCheck> GetNewInvoices(List<ServiceInvoiceDC> invoices, DateTime? start, DateTime? end)
{
List<DifferenzRechnungCheck> result = new List<DifferenzRechnungCheck>();
var existingInvoices = DAOFactory.SearchDAO.GetInvoiceBases(start, end, false);
foreach (var si in invoices)
{
var checkResult = new DifferenzRechnungCheck();
result.Add(checkResult);
checkResult.NeueRechnung = si;
checkResult.VorhandeneRechungen = new List<ServiceInvoiceDC>();
foreach (var i2 in existingInvoices.Where(i => i.Type == InvoiceType.Service))
{
if (si.InvoiceBase.SupportConceptCostBearerRelDc != null && si.InvoiceBase.SupportConceptCostBearerRelDc.CostBearer2SupportConceptOid == i2.CostBearer2SupportConceptOid)
{
var siAlt = DAOFactory.SearchDAO.GetServiceInvoiceByInvoiceBaseOid(i2.Oid.Value);
var siDCAlt = MapperFactory.ServiceInvoiceDC_ServiceInvoice.MapToNewDC(siAlt);
checkResult.VorhandeneRechungen.Add(siDCAlt);
}
else // Sammelrechnung
{
if (i2.SupportConceptOid == invoices[0].InvoiceBase.SupportConceptOid)
{
var siAlt = DAOFactory.SearchDAO.GetServiceInvoiceByInvoiceBaseOid(i2.Oid.Value);
var siDCAlt = MapperFactory.ServiceInvoiceDC_ServiceInvoice.MapToNewDC(siAlt);
if (siAlt.ServiceInvoicePeriodList != null && siAlt.ServiceInvoicePeriodList.Count > 0)
{
foreach (var i in invoices)
{
if (i.ServiceInvoicePeriods != null && i.ServiceInvoicePeriods.Count > 0)
{
foreach (var sip in siDCAlt.ServiceInvoicePeriods)
{
if (sip.Customer != null && i.ServiceInvoicePeriods.Any(s => s.Customer.CustomerOid == sip.Customer.CustomerOid))
{
checkResult.VorhandeneRechungen.Add(siDCAlt);
break;
}
}
}
}
}
}
}
}
}
return result;
}
public virtual List<long> UpdateServiceInvoices(List<ServiceInvoiceDC> invoices)
{
//if (!Data.Security.UserRightHelper.LoggedInUserHasRight(UserRightType.AccountingTransactionView_Create))
//{
// throw new FaultException<BeWoFault>(new BeWoFault("Du kommst hier nicht rein!", BeWoFaultType.CustomWithoutDetails));
//}
var originals = DAOFactory.GenericDAO.LoadByIDs<ServiceInvoice>(invoices.Select(i => i.ServiceInvoiceOid.Value));
MapperFactory.ServiceInvoiceDC_ServiceInvoice.MergeWithEntitys(invoices, originals);
DAOFactory.GenericDAO.Update(originals);
return originals.Select(e => e.Version.Value).ToList();
}
public virtual List<InvoiceBaseDC> GetInvoiceBases(DateTime? startDate, DateTime? endDate)
{
DateTime? end = endDate;
if (end.HasValue)
{
end = end.Value.Date.AddDays(1).AddTicks(-1);
}
var list = DAOFactory.SearchDAO.GetInvoiceBases(startDate, end);
return MapperFactory.InvoiceBaseDC_InvoiceBase.MapToNewDCs(list);
}
public virtual List<InvoiceBaseDC> GetInvoiceBases(DateTime? startDate, DateTime? endDate, bool filterByInvoiceDate)
{
DateTime? end = endDate;
if (end.HasValue)
{
end = end.Value.Date.AddDays(1).AddTicks(-1);
}
var list = DAOFactory.SearchDAO.GetInvoiceBases(startDate, end, filterByInvoiceDate);
return MapperFactory.InvoiceBaseDC_InvoiceBase.MapToNewDCs(list);
}
public virtual List<InvoiceBaseDC> GetInvoiceBases(DateTime? startDate, DateTime? endDate, long costBearerOid, String invoiceId)
{
DateTime? end = endDate;
if (end.HasValue)
{
end = end.Value.Date.AddDays(1).AddTicks(-1);
}
var list = DAOFactory.SearchDAO.GetInvoiceBases(startDate, end, costBearerOid, invoiceId);
return MapperFactory.InvoiceBaseDC_InvoiceBase.MapToNewDCs(list);
}
public virtual void DeactivateInvoiceBases(List<InvoiceBaseDC> invoices)
{
ServiceLogic.SetActivationType<InvoiceBase>(invoices.ToDictionary(i => i.InvoiceBaseOid.Value, i => i.InvoiceBaseVersion.Value), ActivationTypeId.Deleted);
}
public virtual void DeactivateServiceInvoices(List<ServiceInvoiceDC> invoices)
{
ServiceLogic.SetActivationType<ServiceInvoice>(invoices.ToDictionary(i => i.ServiceInvoiceOid.Value, i => i.ServiceInvoiceVersion.Value), ActivationTypeId.Deleted);
ServiceLogic.SetActivationType<InvoiceBase>(invoices.ToDictionary(i => i.InvoiceBase.InvoiceBaseOid.Value, i => i.InvoiceBase.InvoiceBaseVersion.Value), ActivationTypeId.Deleted);
}
public virtual void StorniereInvoiceBases(List<InvoiceBaseDC> invoices)
{
foreach (var item in invoices)
{
if (item.Type == InvoiceType.Service)
{
ErstelleStornoRechnung(item);
}
else if (item.Type == InvoiceType.Settlement)
{
ErstelleStornoSpitzabrechnung(item);
}
else
{
ErstelleStornoAllgemeineRechnung(item);
}
}
}
public virtual InvoiceBase ErstelleStornoAllgemeineRechnung(InvoiceBaseDC ibdc)
{
InvoiceBase newInvoice = new InvoiceBase();
var oldInvoice = DAOFactory.GenericDAO.LoadByID<InvoiceBase>(ibdc.InvoiceBaseOid.Value);
CopyInvoiceBase(oldInvoice, newInvoice);
SetzeStornoInfos(newInvoice);
return newInvoice;
}
public virtual ServiceInvoice ErstelleStornoRechnung(InvoiceBaseDC ibdc)
{
ServiceInvoice newInvoice = new ServiceInvoice();
var serviceInvoice = DAOFactory.SearchDAO.GetServiceInvoiceByInvoiceBaseOid(ibdc.InvoiceBaseOid.Value);
CopyServiceInvoice(serviceInvoice, newInvoice);
SetzeStornoInfos(newInvoice);
return newInvoice;
}
public virtual SettlementInvoice ErstelleStornoSpitzabrechnung(InvoiceBaseDC ibdc)
{
SettlementInvoice newInvoice = new SettlementInvoice();
newInvoice.InvoiceBase = new InvoiceBase();
var settlementInvoice = DAOFactory.SearchDAO.GetSettlementInvoiceByInvoiceBaseOid(ibdc.InvoiceBaseOid.Value);
CopySettlementInvoice(settlementInvoice, newInvoice);
SetzeStornoInfos(newInvoice);
if (newInvoice.InvoiceBase.InvoiceItems.Count == 0 && newInvoice.Claim.HasValue)
{
newInvoice.InvoiceBase.InvoiceItems.Add(new InvoiceItem
{
AmountTotal = newInvoice.Claim,
ItemPeriodStart = newInvoice.InvoiceBase.AccountingPeriodStart,
ItemPeriodEnd = newInvoice.InvoiceBase.AccountingPeriodEnd,
ItemDescription = "Spitzabrechnung"
});
}
return newInvoice;
}
public virtual ServiceInvoice ErstelleStornoRechnung(ServiceInvoiceDC sidc)
{
ServiceInvoice newInvoice = new ServiceInvoice();
var serviceInvoice = DAOFactory.GenericDAO.LoadByID<ServiceInvoice>(sidc.ServiceInvoiceOid.Value);
CopyServiceInvoice(serviceInvoice, newInvoice);
SetzeStornoInfos(newInvoice);
return newInvoice;
}
public virtual void SaveStornoRechnung(InvoiceBase originalInvoice, ServiceInvoice stornoInvoice)
{
DAOFactory.GenericDAO.Insert(stornoInvoice);
originalInvoice.StornoInvoiceBaseOid = stornoInvoice.Oid;
DAOFactory.GenericDAO.Update(originalInvoice);
}
public virtual void SetzeStornoInfos(InvoiceBase newInvoice)
{
foreach (var ii in newInvoice.InvoiceItems)
{
if (ii.AmountTotal.HasValue)
{
ii.AmountTotal *= -1;
}
if (ii.GrossAmountTotal.HasValue)
{
ii.GrossAmountTotal *= -1;
}
}
}
public virtual void SetzeStornoInfos(SettlementInvoice newInvoice)
{
if (newInvoice.Claim.HasValue)
newInvoice.Claim *= -1;
if (newInvoice.AmountBillableTotal.HasValue)
newInvoice.AmountBillableTotal *= -1;
if (newInvoice.AmountTotalAdvancedPaidWithNewHourlyRate.HasValue)
newInvoice.AmountTotalAdvancedPaidWithNewHourlyRate *= -1;
if (newInvoice.AmountTotalAdvancedPaidWithOldHourlyRate.HasValue)
newInvoice.AmountTotalAdvancedPaidWithOldHourlyRate *= -1;
if (newInvoice.AmountWithRateFactor.HasValue)
newInvoice.AmountWithRateFactor *= -1;
if (newInvoice.AmountRateFactor.HasValue)
newInvoice.AmountRateFactor *= -1;
// FLS-Felder negieren, damit isDefaultSpitzabrechnung-Pfad negative Positionen berechnet
if (newInvoice.ApprovedFLSWithActualHourlyRate.HasValue)
newInvoice.ApprovedFLSWithActualHourlyRate *= -1;
if (newInvoice.ApprovedFLSWithOldHourlyRate.HasValue)
newInvoice.ApprovedFLSWithOldHourlyRate *= -1;
// XMLData aktualisieren: Claim (wird vom Mapper als TotalAmount verwendet) und
// ApprovedFLSWithHourlyRate3 (nur bei DifferentHourlyRateCount == 3 vorhanden) negieren
if (newInvoice.InvoiceBase != null && !string.IsNullOrEmpty(newInvoice.InvoiceBase.XMLData))
{
var xmlDC = BS.Shared.Core.Utils.XMLDeserializeFromString<SettlementDC>(newInvoice.InvoiceBase.XMLData);
if (xmlDC != null)
{
bool xmlChanged = false;
if (xmlDC.Claim != 0)
{
xmlDC.Claim *= -1;
xmlChanged = true;
}
if (xmlDC.ApprovedFLSWithHourlyRate3 != 0)
{
xmlDC.ApprovedFLSWithHourlyRate3 *= -1;
xmlChanged = true;
}
if (xmlChanged)
newInvoice.InvoiceBase.XMLData = BS.Shared.Core.Utils.XMLSerializeToString(xmlDC);
}
}
SetzeStornoInfos(newInvoice.InvoiceBase);
}
public virtual void SetzeStornoInfos(ServiceInvoice newInvoice)
{
foreach (var sip in newInvoice.ServiceInvoicePeriodList)
{
sip.HoursNotBillableAbsence = 0;
sip.HoursNotBillableNotApproved = 0;
if (sip.Claim.HasValue)
{
sip.Claim *= -1;
}
foreach (var ii in sip.InvoiceItemList)
{
if (ii.AmountTotal.HasValue)
{
ii.AmountTotal *= -1;
}
if (ii.GrossAmountTotal.HasValue)
{
ii.GrossAmountTotal *= -1;
}
}
}
}
public void CopyServiceInvoice(ServiceInvoice existingInvoice, ServiceInvoice copyInvoice)
{
copyInvoice.AmountAdvancePayments = existingInvoice.AmountAdvancePayments;
copyInvoice.AmountEquityContribution = existingInvoice.AmountEquityContribution;
copyInvoice.ServiceUnitOid = existingInvoice.ServiceUnitOid;
CopyInvoiceBase(existingInvoice.InvoiceBase, copyInvoice.InvoiceBase);
foreach (var sip in existingInvoice.ServiceInvoicePeriodList)
{
var copySip = new ServiceInvoicePeriod();
copyInvoice.ServiceInvoicePeriodList.Add(copySip);
CopyServiceInvoicePeriod(sip, copySip);
}
}
public void CopySettlementInvoice(SettlementInvoice existing, SettlementInvoice copy)
{
copy.AmountAdvancedPayments = existing.AmountAdvancedPayments;
copy.AmountBillableTotal = existing.AmountBillableTotal;
copy.AmountRateFactor = existing.AmountRateFactor;
copy.AmountTotalAdvancedPaidWithNewHourlyRate = existing.AmountTotalAdvancedPaidWithNewHourlyRate;
copy.AmountTotalAdvancedPaidWithOldHourlyRate = existing.AmountTotalAdvancedPaidWithOldHourlyRate;
copy.AmountWithRateFactor = existing.AmountWithRateFactor;
copy.ApprovalNoticeDate = existing.ApprovalNoticeDate;
copy.ApprovedFLS = existing.ApprovedFLS;
copy.ApprovedFLSWithActualHourlyRate = existing.ApprovedFLSWithActualHourlyRate;
copy.ApprovedFLSWithOldHourlyRate = existing.ApprovedFLSWithOldHourlyRate;
copy.Claim = existing.Claim;
copy.ErrorNotice = existing.ErrorNotice;
copy.HourlyRateNew = existing.HourlyRateNew;
copy.HourlyRateNewStartDate = existing.HourlyRateNewStartDate;
copy.HourlyRateOld = existing.HourlyRateOld;
copy.HourlyRateOldEndDate = existing.HourlyRateOldEndDate;
copy.RecordedBillableFLSBrutto = existing.RecordedBillableFLSBrutto;
copy.RecordedBillableFLSNetto = existing.RecordedBillableFLSNetto;
copy.RecordedBillableFLSNotBillableCustomerAbsent = existing.RecordedBillableFLSNotBillableCustomerAbsent;
copy.RecordedBillableFLSNotBillableOutOfApprovedSpan = existing.RecordedBillableFLSNotBillableOutOfApprovedSpan;
CopyInvoiceBase(existing.InvoiceBase, copy.InvoiceBase);
}
public void CopyInvoiceBase(InvoiceBase existing, InvoiceBase copy)
{
copy.AccountingPeriodEnd = existing.AccountingPeriodEnd;
copy.AccountingPeriodStart = existing.AccountingPeriodStart;
copy.CostBearer2SupportConcept = existing.CostBearer2SupportConcept;
copy.CreatorFirstName = existing.CreatorFirstName;
copy.CreatorLastName = existing.CreatorLastName;
copy.CustomerReferenceNumber = existing.CustomerReferenceNumber;
copy.DueDate = existing.DueDate;
copy.DunningLetterCount = existing.DunningLetterCount;
copy.InvoiceDate = existing.InvoiceDate;
copy.InvoiceId = existing.InvoiceId;
copy.InvoiceNumber = existing.InvoiceNumber;
copy.InvoiceTitle = existing.InvoiceTitle;
copy.InvoiceTypeText = existing.InvoiceTypeText;
copy.IsPaid = existing.IsPaid;
copy.IsPrinted = existing.IsPrinted;
copy.RecipientCostBearerOid = existing.RecipientCostBearerOid;
copy.RecipientCustomerOid = existing.RecipientCustomerOid;
copy.RecipientDivision = existing.RecipientDivision;
copy.RecipientOrganisation = existing.RecipientOrganisation;
copy.RecipientOrganisationOid = existing.RecipientOrganisationOid;
copy.RecipientPersonFirstName = existing.RecipientPersonFirstName;
copy.RecipientPersonLastName = existing.RecipientPersonLastName;
copy.RecipientPersonOid = existing.RecipientPersonOid;
copy.SenderDivision = existing.SenderDivision;
copy.SenderFirstName = existing.SenderFirstName;
copy.SenderLastName = existing.SenderLastName;
copy.SenderOrganisation = existing.SenderOrganisation;
copy.SupportConceptOid = existing.SupportConceptOid;
copy.Type = existing.Type;
copy.XMLData = existing.XMLData;
foreach (var ii in existing.InvoiceItems)
{
var copyItem = new InvoiceItem();
copy.InvoiceItems.Add(copyItem);
CopyInvoiceItem(ii, copyItem);
}
if (existing.RecipientAddress != null)
{
copy.RecipientAddress = CreateCopyAddress(existing.RecipientAddress);
}
if (existing.RecipientContacts != null)
{
copy.RecipientContacts = new List<Contact>();
foreach (var existingContact in existing.RecipientContacts)
{
copy.RecipientContacts.Add(CreateCopyContact(existingContact));
}
}
if (existing.SenderAddress != null)
{
copy.SenderAddress = existing.SenderAddress;
}
if (existing.SenderContacts != null)
{
copy.SenderContacts = new List<Contact>();
foreach (var existingContact in existing.SenderContacts)
{
copy.SenderContacts.Add(CreateCopyContact(existingContact));
}
}
}
public void CopyInvoiceBaseDC(InvoiceBaseDC orgRechnung, ServiceInvoiceDC diffRechnung)
{
diffRechnung.InvoiceBase.DiffErstellen = true;
diffRechnung.InvoiceBase.AccountingPeriodStart = orgRechnung.AccountingPeriodStart;
diffRechnung.InvoiceBase.AccountingPeriodEnd = orgRechnung.AccountingPeriodEnd;
diffRechnung.InvoiceBase.CustomerLastName = orgRechnung.CustomerLastName;
diffRechnung.InvoiceBase.CustomerFirstName = orgRechnung.CustomerFirstName;
diffRechnung.InvoiceBase.CustomerReferenceNumber = orgRechnung.CustomerReferenceNumber;
diffRechnung.InvoiceBase.InvoiceBaseOid = orgRechnung.InvoiceBaseOid;
diffRechnung.InvoiceBase.InvoiceDate = orgRechnung.InvoiceDate;
diffRechnung.InvoiceBase.InvoiceId = orgRechnung.InvoiceId;
diffRechnung.InvoiceBase.InvoiceNumber = orgRechnung.InvoiceNumber;
diffRechnung.InvoiceBase.InvoiceTitle = orgRechnung.InvoiceTitle;
diffRechnung.InvoiceBase.InvoiceTypeText = orgRechnung.InvoiceTypeText;
diffRechnung.InvoiceBase.RecipientAddressLine1 = orgRechnung.RecipientAddressLine1;
diffRechnung.InvoiceBase.RecipientAddressOid = orgRechnung.RecipientAddressOid;
diffRechnung.InvoiceBase.RecipientAddressVersion = orgRechnung.RecipientAddressVersion;
diffRechnung.InvoiceBase.RecipientContactInformations = orgRechnung.RecipientContactInformations;
diffRechnung.InvoiceBase.RecipientCostBearerOid = orgRechnung.RecipientCostBearerOid;
diffRechnung.InvoiceBase.RecipientCustomerOid = orgRechnung.RecipientCustomerOid;
diffRechnung.InvoiceBase.RecipientDivision = orgRechnung.RecipientDivision;
diffRechnung.InvoiceBase.RecipientOrganisation = orgRechnung.RecipientOrganisation;
diffRechnung.InvoiceBase.RecipientOrganisationOid = orgRechnung.RecipientOrganisationOid;
diffRechnung.InvoiceBase.RecipientPersonFirstName = orgRechnung.RecipientPersonFirstName;
diffRechnung.InvoiceBase.RecipientPersonLastName = orgRechnung.RecipientPersonLastName;
diffRechnung.InvoiceBase.RecipientPersonOid = orgRechnung.RecipientPersonOid;
diffRechnung.InvoiceBase.RecipientPostCode = orgRechnung.RecipientPostCode;
diffRechnung.InvoiceBase.RecipientSalutationAddressField = orgRechnung.RecipientSalutationAddressField;
diffRechnung.InvoiceBase.RecipientStreet = orgRechnung.RecipientStreet;
diffRechnung.InvoiceBase.RecipientTown = orgRechnung.RecipientTown;
diffRechnung.InvoiceBase.SenderAddressOid = orgRechnung.SenderAddressOid;
diffRechnung.InvoiceBase.SenderAddressVersion = orgRechnung.SenderAddressVersion;
diffRechnung.InvoiceBase.SenderContactInformations = orgRechnung.SenderContactInformations;
diffRechnung.InvoiceBase.SenderDivision = orgRechnung.SenderDivision;
diffRechnung.InvoiceBase.SenderFirstName = orgRechnung.SenderFirstName;
diffRechnung.InvoiceBase.SenderLastName = orgRechnung.SenderLastName;
diffRechnung.InvoiceBase.SenderOrganisation = orgRechnung.SenderOrganisation;
diffRechnung.InvoiceBase.SenderPostCode = orgRechnung.SenderPostCode;
diffRechnung.InvoiceBase.SenderStreet = orgRechnung.SenderStreet;
diffRechnung.InvoiceBase.SenderTown = orgRechnung.SenderTown;
diffRechnung.InvoiceBase.SupportConceptCostBearerRelDc = orgRechnung.SupportConceptCostBearerRelDc;
diffRechnung.InvoiceBase.SupportConceptOid = orgRechnung.SupportConceptOid;
diffRechnung.InvoiceBase.TotalAmount = orgRechnung.TotalAmount;
diffRechnung.InvoiceBase.Type = orgRechnung.Type;
}
public Contact CreateCopyContact(Contact existingContact)
{
Contact newContact = new Contact();
newContact.Value = existingContact.Value;
newContact.Type = existingContact.Type;
return newContact;
}
public Address CreateCopyAddress(Address address)
{
Address newAddress = new Address();
newAddress.AddressLine1 = address.AddressLine1;
newAddress.AddressLine2 = address.AddressLine2;
newAddress.Country = address.Country;
newAddress.PostalCode = address.PostalCode;
newAddress.State = address.State;
newAddress.Street = address.Street;
newAddress.Town = address.Town;
return newAddress;
}
public void CopyServiceInvoicePeriod(ServiceInvoicePeriod existingSip, ServiceInvoicePeriod copySip)
{
copySip.AccountingInterval = existingSip.AccountingInterval;
copySip.ApprovedAmountDefaultHourlyRate = existingSip.ApprovedAmountDefaultHourlyRate;
copySip.ApprovedBE = existingSip.ApprovedBE;
copySip.ApprovedFixedAmount = existingSip.ApprovedFixedAmount;
copySip.ApprovedHours = existingSip.ApprovedHours;
copySip.Claim = existingSip.Claim;
copySip.End = existingSip.End;
copySip.HoursNotBillableAbsence = existingSip.HoursNotBillableAbsence;
copySip.HoursNotBillableNotApproved = existingSip.HoursNotBillableNotApproved;
copySip.ServiceUnitName = existingSip.ServiceUnitName;
copySip.Start = existingSip.Start;
copySip.Notice = existingSip.Notice;
copySip.Customer = existingSip.Customer;
copySip.SupportConceptApprovalPeriod = existingSip.SupportConceptApprovalPeriod;
foreach (var ii in existingSip.InvoiceItemList)
{
var copyItem = new InvoiceItem();
copySip.InvoiceItemList.Add(copyItem);
CopyInvoiceItem(ii, copyItem);
}
}
public void CopyInvoiceItem(InvoiceItem existingItem, InvoiceItem copyItem)
{
copyItem.AccountingInterval = existingItem.AccountingInterval;
copyItem.AmountPerUnit = existingItem.AmountPerUnit;
copyItem.AmountTotal = existingItem.AmountTotal;
copyItem.ApprovalUnit = existingItem.AccountingInterval;
copyItem.ApprovedPerUnit = existingItem.ApprovedPerUnit;
copyItem.GrossAmountTotal = existingItem.GrossAmountTotal;
copyItem.ItemDescription = existingItem.ItemDescription;
copyItem.ItemPeriodEnd = existingItem.ItemPeriodEnd;
copyItem.ItemPeriodStart = existingItem.ItemPeriodStart;
copyItem.MaxApprovedAmount = existingItem.MaxApprovedAmount;
copyItem.MaxApprovedUnitCount = existingItem.MaxApprovedUnitCount;
copyItem.RateFactor = existingItem.RateFactor;
copyItem.ReceivedAmount = existingItem.ReceivedAmount;
copyItem.SupportConceptApprovalPeriodOid = existingItem.SupportConceptApprovalPeriodOid;
copyItem.UnitCount = existingItem.UnitCount;
copyItem.UnitDescription = existingItem.UnitDescription;
copyItem.Notice = existingItem.Notice;
copyItem.ServiceRecord = existingItem.ServiceRecord;
}
public virtual void SetzeRechnungspositionenServiceInvoice(ServiceInvoiceDC diffRechnung, ServiceInvoice counterInvoice, DifferenzRechnungCheck item)
{
var siDCAlt = MapperFactory.ServiceInvoiceDC_ServiceInvoice.MapToNewDC(counterInvoice);
if (siDCAlt.ServiceInvoicePeriods != null && siDCAlt.ServiceInvoicePeriods.Count > 0)
{
diffRechnung.ServiceInvoicePeriods = siDCAlt.ServiceInvoicePeriods;
}
if (item.NeueRechnung.ServiceInvoicePeriods != null && item.NeueRechnung.ServiceInvoicePeriods.Count > 0)
{
if (diffRechnung.ServiceInvoicePeriods == null)
{
diffRechnung.ServiceInvoicePeriods = item.NeueRechnung.ServiceInvoicePeriods;
}
else
{
foreach (var NewSip in item.NeueRechnung.ServiceInvoicePeriods)
{
if (NewSip.InvoiceItems != null && NewSip.InvoiceItems.Count > 0)
{
if (NewSip.Customer != null && diffRechnung.ServiceInvoicePeriods.Any(s => s.Customer.CustomerOid == NewSip.Customer.CustomerOid) &&
NewSip.SupportConceptApprovalPeriod != null && NewSip.SupportConceptApprovalPeriod.SupportConceptApprovalPeriodOid.HasValue
&& diffRechnung.ServiceInvoicePeriods.Any(s => s.SupportConceptApprovalPeriod != null && s.SupportConceptApprovalPeriod.SupportConceptApprovalPeriodOid.HasValue
&& s.SupportConceptApprovalPeriod.SupportConceptApprovalPeriodOid.Value == NewSip.SupportConceptApprovalPeriod.SupportConceptApprovalPeriodOid.Value))
{
var ip = diffRechnung.ServiceInvoicePeriods.Where(s => s.SupportConceptApprovalPeriod != null && s.SupportConceptApprovalPeriod.SupportConceptApprovalPeriodOid.Value == NewSip.SupportConceptApprovalPeriod.SupportConceptApprovalPeriodOid.Value).First();
if (ip.InvoiceItems != null && ip.InvoiceItems.Count > 0)
{
ip.Claim += NewSip.Claim;
foreach (var ii in NewSip.InvoiceItems)
{
ip.InvoiceItems.Add(ii);
}
// Bei Rechnungspositionen mit negativem Betrag auf alte Rechnung verweisen
foreach (var iitem in ip.InvoiceItems)
{
if (iitem.AmountTotal < 0)
{
var vorhandeneRechnung = item.VorhandeneRechungen.FirstOrDefault(r => r.InvoiceBase != null && r.InvoiceBase.CustomerOid == ip.Customer.CustomerOid);
if (vorhandeneRechnung != null)
iitem.ItemDescription += string.Format(" (am {0:dd.MM.yyyy} in Rechnung {1} berechnet)", vorhandeneRechnung.InvoiceBase.InvoiceDate, vorhandeneRechnung.InvoiceBase.InvoiceNumber);
}
}
}
}
else
{
diffRechnung.ServiceInvoicePeriods.Add(NewSip);
}
}
}
}
}
}
public virtual Settlement2DC ErstelleDifferenzSpitzabrechnung(Settlement2DC neueRechnung, Settlement2DC letzteRechnung)
{
neueRechnung.Claim = neueRechnung.Claim - letzteRechnung.Claim;
var differenzItems = new List<InvoiceItemDC>();
// Exaktieselbe Erkennung wie SettlementReport.cs für isDefaultSpitzabrechnung:
// genau 1 Item mit Bezeichnung "Spitzabrechnung"/"Spitzabrechung", GrossAmountTotal==null, RateFactor==null
bool letzteIstOldWay = letzteRechnung.InvoiceItems == null
|| (letzteRechnung.InvoiceItems.Count == 1 && (letzteRechnung.InvoiceItems[0].ItemDescription == "Spitzabrechnung" || letzteRechnung.InvoiceItems[0].ItemDescription == "Spitzabrechung")
&& letzteRechnung.InvoiceItems[0].GrossAmountTotal == null && letzteRechnung.InvoiceItems[0].RateFactor == null);
if (letzteIstOldWay)
{
// Storno der alten Gesamtsumme als einzelne explizite Position
differenzItems.Add(new InvoiceItemDC
{
AmountTotal = -(letzteRechnung.Claim ?? 0),
GrossAmountTotal = -(letzteRechnung.Claim ?? 0),
ItemPeriodStart = letzteRechnung.AccountingPeriodStart,
ItemPeriodEnd = letzteRechnung.AccountingPeriodEnd,
ItemDescription = "Storno"
});
// Neue Rechnung als Old-Way mit expliziten Items (isDefaultSpitzabrechnung = false im Report)
bool neueHatExpliziteItems = neueRechnung.InvoiceItems != null && neueRechnung.InvoiceItems.Any(ii => ii.GrossAmountTotal != null);
if (neueHatExpliziteItems)
differenzItems.AddRange(neueRechnung.InvoiceItems);
else
differenzItems.AddRange(ErstelleExpliziteSpitzabrechnungsItems(neueRechnung));
// Claim aus den tatsächlichen Items berechnen (Storno + neue Items),
// da bei old-way Rechnungen neueRechnung.Claim null sein kann
neueRechnung.Claim = differenzItems.Sum(i => i.AmountTotal ?? 0m);
}
else
{
// Normalfall: Items der alten Rechnung negieren (SettlementReport2 → SettlementReport2)
if (letzteRechnung.InvoiceItems != null)
{
foreach (var item in letzteRechnung.InvoiceItems)
{
differenzItems.Add(new InvoiceItemDC
{
AmountTotal = -(item.AmountTotal ?? 0),
GrossAmountTotal = item.GrossAmountTotal.HasValue ? -item.GrossAmountTotal : null,
AmountPerUnit = item.AmountPerUnit,
ApprovedPerUnit = item.ApprovedPerUnit,
ItemPeriodStart = item.ItemPeriodStart,
ItemPeriodEnd = item.ItemPeriodEnd,
UnitDescription = item.UnitDescription,
UnitCount = item.UnitCount,
RateFactor = item.RateFactor,
ItemDescription = item.ItemDescription + " (Storno)"
});
}
}
if (neueRechnung.InvoiceItems != null)
differenzItems.AddRange(neueRechnung.InvoiceItems);
}
neueRechnung.InvoiceItems = differenzItems;
neueRechnung.Notice = string.Format("Differenzrechnung zu Rechnung {0} vom {1:dd.MM.yyyy}", letzteRechnung.InvoiceNumber, letzteRechnung.InvoiceDate);
return neueRechnung;
}
private IList<InvoiceItemDC> ErstelleExpliziteSpitzabrechnungsItems(Settlement2DC dc)
{
decimal fact = 1;
if (dc.RateFactor != null && dc.RateFactor.Value > 0)
{
fact = (100 + dc.RateFactor.Value) / 100;
}
decimal? rateFactor = fact != 1 ? fact : (decimal?)null;
var items = new List<InvoiceItemDC>();
// Periode mit drittem Stundensatz (nur bei DifferentHourlyRateCount >= 3)
if (dc.DifferentHourlyRateCount >= 3)
{
items.Add(new InvoiceItemDC
{
ItemPeriodStart = dc.AccountingPeriodStart,
ItemPeriodEnd = dc.HourlyRateEndDate3,
UnitCount = dc.ApprovedFLSWithHourlyRate3,
AmountPerUnit = dc.HourlyRate3,
RateFactor = rateFactor,
GrossAmountTotal = dc.ApprovedFLSWithHourlyRate3 * fact * dc.HourlyRate3,
AmountTotal = dc.ApprovedFLSWithHourlyRate3 * fact * dc.HourlyRate3
});
}
// Periode mit altem Stundensatz (bei DifferentHourlyRateCount >= 2)
if (dc.DifferentHourlyRateCount >= 2)
{
items.Add(new InvoiceItemDC
{
ItemPeriodStart = dc.DifferentHourlyRateCount >= 3 ? dc.HourlyRateOldStartDate : dc.AccountingPeriodStart,
ItemPeriodEnd = dc.HourlyRateOldEndDate,
UnitCount = dc.ApprovedFLSWithOldHourlyRate,
AmountPerUnit = dc.HourlyRateOld,
RateFactor = rateFactor,
GrossAmountTotal = dc.ApprovedFLSWithOldHourlyRate * fact * (dc.HourlyRateOld ?? 0),
AmountTotal = dc.ApprovedFLSWithOldHourlyRate * fact * (dc.HourlyRateOld ?? 0)
});
}
// Periode mit aktuellem Stundensatz (immer vorhanden)
items.Add(new InvoiceItemDC
{
ItemPeriodStart = dc.DifferentHourlyRateCount >= 2 ? dc.HourlyRateNewStartDate : dc.AccountingPeriodStart,
ItemPeriodEnd = dc.AccountingPeriodEnd,
UnitCount = dc.ApprovedFLSWithActualHourlyRate,
AmountPerUnit = dc.HourlyRateNew,
RateFactor = rateFactor,
GrossAmountTotal = dc.ApprovedFLSWithActualHourlyRate * fact * (dc.HourlyRateNew ?? 0),
AmountTotal = dc.ApprovedFLSWithActualHourlyRate * fact * (dc.HourlyRateNew ?? 0)
});
return items;
}
public virtual AddressInformation GetAddressInformation(long? customer_oid = null)
{
var user = UserRightHelper.GetLoggedInUser().Employee;
var mandator = AppSettings.GetMandatorEntity();
return new AddressInformation()
{
IKLeistungserbringer = mandator.IKLeistungserbringer,
Fax = user.Person.Contacts.FirstOrDefault(x => x.Type == ContactType.business_Fax)?.Value.ToNullIfEmpty(),
Mail = user.Person.Contacts.FirstOrDefault(x => x.Type == ContactType.business_Mail)?.Value.ToNullIfEmpty(),
Phone = user.Person.Contacts.FirstOrDefault(x => x.Type == ContactType.business_Phone)?.Value.ToNullIfEmpty(),
OrganisationName = mandator.Name,
PostCode = mandator.PostalCode,
Street = mandator.Street,
Town = mandator.Town,
Website = mandator.Website
};
}
}
public class DifferenzRechnungCheck
{
public ServiceInvoiceDC NeueRechnung { get; set; }
public IList<ServiceInvoiceDC> VorhandeneRechungen { get; set; }
}
}