using System; using System.Collections.Generic; using System.Linq; using BeWo.Data; using BeWo.Data.Access; using BeWo.Data.Entities; 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 { public virtual List GenerateServiceInvoices(long costBearerOid, DateTimeSpan invoicePeriod, Dictionary> supportConcepts2ServiceRecords) { var costBearer = DAOFactory.GenericDAO.LoadByID(costBearerOid); var invoiceList = new List(); var invoiceCounter = 0; ServiceInvoice invoice; if (costBearer.IsSingleInvoicePerCustomer) { invoice = CreateCollectiveBilling(costBearer, invoicePeriod, supportConcepts2ServiceRecords); invoiceList.Add(invoice); } else { foreach (var iSupportConcept2ServiceRecords in supportConcepts2ServiceRecords) { invoice = CreateSingleInvoice(invoiceCounter, costBearer, invoicePeriod, iSupportConcept2ServiceRecords.Key, iSupportConcept2ServiceRecords.Value); 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) { //override } public virtual ServiceInvoice CreateSingleInvoice(int invoiceCounter, CostBearer costBearer, DateTimeSpan invoicePeriod, CompactSupportConceptDC supportConcept, List serviceRecords) { var invoice = new ServiceInvoice(); var supportConceptList = new List {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; } private ServiceInvoice CreateCollectiveBilling(CostBearer costBearer, DateTimeSpan invoicePeriod, Dictionary> supportConcepts2ServiceRecords) { var invoice = new ServiceInvoice(); SetRecipientInformation(invoice, costBearer); SetSenderInformation(invoice); SetInvoiceBaseData(0, invoice, costBearer, invoicePeriod, supportConcepts2ServiceRecords.Keys.ToList()); SetCollectiveBillingBaseData(0, invoice, costBearer, invoicePeriod, supportConcepts2ServiceRecords); SetCollectiveBillingServiceInvoicePeriods(invoice, invoicePeriod, supportConcepts2ServiceRecords); SetServiceInvoicePeriodAmounts(invoice); // Spitzabrechnung if (invoicePeriod == null) { SetAmountAdvancePayments(invoice); } return invoice; } public virtual void SetServiceInvoicePeriodAmounts(ServiceInvoice invoice) { foreach (ServiceInvoicePeriod iPeriod in invoice.ServiceInvoicePeriodList) { //Dictionary rate2UnitCount = new Dictionary(); 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(); foreach (ServiceInvoicePeriod period in invoice.ServiceInvoicePeriodList) { if (period.SupportConceptApprovalPeriod != null) { IList 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 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 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(); invoice.InvoiceBase.InvoiceNumber = inc.GetNextInvoiceNumber(invoiceCounter, invoice.InvoiceBase); } if (costBearer.CostRatePeriods != null) { List 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(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(); 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 serviceRecords) { Calculations calc = PluginLoader.FindClass(_SpecificID) ?? Calculations.GetInstance(_SpecificID); if (ShouldCreateFixedAmounts(serviceInvoicePeriod, supportConceptApprovalPeriod, cb2sc)) { CreateFixedAmounts(serviceInvoicePeriod, supportConceptApprovalPeriod, cb2sc); } else { List 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(serviceInvoicePeriod.SupportConceptApprovalPeriodOid.Value) // .MapToNewDC(); serviceInvoicePeriod.HoursNotBillableAbsence += calc.GetHoursNotBillableDueToAbsenceTimes(supportConceptApprovalPeriod, cb2sc.CostBearer.CostRatePeriods.MapToNewDCs(), serviceRecordsInPeriod, cb2sc.SupportConcept.Customer.GetAbsencesTimesNotBillableWholeWeeks(), true, true); serviceInvoicePeriod.HoursNotBillableNotApproved += calc.GetHoursNotBillableDueToMoreThanApproved(supportConceptApprovalPeriod, cb2sc.CostBearer.CostRatePeriods.MapToNewDCs(), serviceRecordsInPeriod, true, true); var itemList = CreateInvoiceItems(serviceRecordsInPeriod, invoicePeriod, serviceInvoicePeriod.SupportConceptApprovalPeriod, calc); serviceInvoicePeriod.InvoiceItemList.AddRange(itemList); } } } private static bool ShouldCreateFixedAmounts(ServiceInvoicePeriod serviceInvoicePeriod, SupportConceptApprovalPeriodDC supportConceptApprovalPeriod, CostBearer2SupportConcept cb2sc) { if (serviceInvoicePeriod.ApprovedFixedAmount.HasValue) return true; if (supportConceptApprovalPeriod.ServiceCategory != null) { List 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(_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.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 = ""; 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; } } public virtual void SetSenderInformation(ServiceInvoice serviceInvoice) { var lLoggedInEmployee = LoggedInUserOperationContextExt.Current.User.Employee; var mandator = new OperationsServiceImp().GetMandator(); 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 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 costRates = MapperFactory.CostRatePeriodDC_CostRatePeriod.MapToNewDCs(costBearer.CostRatePeriods); CostRatePeriodDC serviceUnit = costRates.GetCostRatePeriodForDate(CostRatePeriodType.MinutesPerServiceUnit, DateTime.Now); serviceInvoicePeriod.ServiceUnitName = serviceUnit.UnitName; Calculations calc = PluginLoader.FindClass(_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 serviceRecords) { if (sip.ApprovedHours.HasValue && !scap.IsApprovedBEShifting) { decimal totalHours = 0; foreach (var ii in sip.InvoiceItemList.Where(ii => ii.UnitCount.HasValue)) { if (totalHours + ii.UnitCount.Value > sip.ApprovedHours) { ii.UnitCount = sip.ApprovedHours.Value - totalHours; if (ii.AmountPerUnit.HasValue) { ii.AmountTotal = ii.AmountPerUnit.Value*ii.UnitCount; ii.GrossAmountTotal = ii.AmountTotal; } 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> supportConcepts2ServiceRecords) { invoice.InvoiceBase.InvoiceTitle = "Rechnung über Betreuungleistungen"; } private void SetCollectiveBillingServiceInvoicePeriods(ServiceInvoice invoice, DateTimeSpan invoicePeriod, Dictionary> supportConcepts2ServiceRecords) { foreach (var supportConcepts2ServiceRecord in supportConcepts2ServiceRecords) { var c2s = DAOFactory.GenericDAO.LoadByID( supportConcepts2ServiceRecord.Key.CostBearerRelOids[0]); SetServiceInvoicePeriods(invoice, c2s, invoicePeriod, supportConcepts2ServiceRecord.Value); } } public virtual IList CreateInvoiceItems(List serviceRecordsInPeriod, DateTimeSpan invoicePeriod, SupportConceptApprovalPeriod scap, Calculations calc) { var list = new List(); 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 CreateSummaryInvoiceItems(IList itemList, DateTimeSpan invoicePeriod, SupportConceptApprovalPeriod scap, Calculations calc) { return CreateSummaryInvoiceItems(itemList, invoicePeriod, scap, calc, false); } public virtual IList CreateSummaryInvoiceItems(IList itemList, DateTimeSpan invoicePeriod, SupportConceptApprovalPeriod scap, Calculations calc, bool summaryPerMonth) { //Fasse InvoiceItems mit gleichem Stundensatz zusammen: var newlist = new List(); var rateToItem = new Dictionary(); foreach (InvoiceItem iitem in itemList) { InvoiceItem item; String key = String.Format("{0}_{1}", iitem.AmountPerUnit, iitem.RateFactor); if (summaryPerMonth) { key = String.Format("{0}_{1}_{2:yyyyMM}", iitem.AmountPerUnit, iitem.RateFactor, iitem.ItemPeriodStart); } 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.SupportConceptApprovalPeriodOid = scap.Oid; rateToItem[key] = item; } if (!item.UnitCount.HasValue) { item.UnitCount = 0; } item.UnitCount += iitem.UnitCount ?? 0; } foreach (InvoiceItem invoiceItem in newlist) { if (invoiceItem.AmountPerUnit.HasValue) { invoiceItem.AmountPerUnit = Math.Round(invoiceItem.AmountPerUnit.Value, 2, MidpointRounding.AwayFromZero); } else { invoiceItem.AmountPerUnit = 0; } if (invoiceItem.UnitCount.HasValue) { invoiceItem.UnitCount = Math.Round(invoiceItem.UnitCount.Value, 2, MidpointRounding.AwayFromZero); } else { invoiceItem.UnitCount = 0; } invoiceItem.AmountTotal = invoiceItem.AmountPerUnit * invoiceItem.UnitCount; invoiceItem.AmountTotal = Math.Round(invoiceItem.AmountTotal.Value, 2, MidpointRounding.AwayFromZero); if (invoiceItem.RateFactor.HasValue) { invoiceItem.GrossAmountTotal = invoiceItem.AmountTotal * ((invoiceItem.RateFactor + 100) / 100); } else { invoiceItem.GrossAmountTotal = invoiceItem.AmountTotal; } } return newlist; } public virtual IList CreateInvoiceItemsForEachServiceRecord(List serviceRecordsInPeriod, SupportConceptApprovalPeriod scap, Calculations calc) { var list = new List(); 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(iServiceRecord.ServiceRecordOid.Value); if (scap != null) invoiceItem.SupportConceptApprovalPeriodOid = scap.Oid; //var crs = iServiceRecord.CostBearer.CostRatePeriods; //List costRatePeriodOids = new List(); //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(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 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(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; // } // } // } } }