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 { public virtual List GenerateInitialServiceInvoices(long costBearerOid, long? supportConceptOid, DateTimeSpan invoicePeriod) { var cs = PluginLoader.FindClass(); IEnumerable 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(costBearerOid); String tenant = PluginLoader.Tenant; var factory = PluginLoader.FindClass(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 ErstelleNeueRechnungen(List differenzRechnungChecks) { var rechnungen = new List(); 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; diffRechnung.InvoiceBase.Hinweise = String.Format("Rechnungsdifferenz zu Rechnung {0} in Höhe von {1:c}", letzteRg.InvoiceBase.InvoiceNumber, letzteRg.InvoiceBase.TotalAmount.Value); } } return diffRechnung; } protected virtual List GetNewInvoices(List invoices, DateTime? start, DateTime? end) { List result = new List(); 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(); 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 UpdateServiceInvoices(List invoices) { //if (!Data.Security.UserRightHelper.LoggedInUserHasRight(UserRightType.AccountingTransactionView_Create)) //{ // throw new FaultException(new BeWoFault("Du kommst hier nicht rein!", BeWoFaultType.CustomWithoutDetails)); //} var originals = DAOFactory.GenericDAO.LoadByIDs(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 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 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 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 invoices) { ServiceLogic.SetActivationType(invoices.ToDictionary(i => i.InvoiceBaseOid.Value, i => i.InvoiceBaseVersion.Value), ActivationTypeId.Deleted); } public virtual void DeactivateServiceInvoices(List invoices) { ServiceLogic.SetActivationType(invoices.ToDictionary(i => i.ServiceInvoiceOid.Value, i => i.ServiceInvoiceVersion.Value), ActivationTypeId.Deleted); ServiceLogic.SetActivationType(invoices.ToDictionary(i => i.InvoiceBase.InvoiceBaseOid.Value, i => i.InvoiceBase.InvoiceBaseVersion.Value), ActivationTypeId.Deleted); } public virtual void StorniereInvoiceBases(List 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(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(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(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(); 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(); 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(); // 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 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(); // 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 VorhandeneRechungen { get; set; } } }