private static List <PriceComponent> GetPriceComponents(this WorkEffort @this, Part part) { var priceComponents = new List <PriceComponent>(); var extent = new PriceComponents(@this.Strategy.Session).Extent(); foreach (PriceComponent priceComponent in extent) { if (priceComponent.ExistPart && priceComponent.Part.Equals(part) && priceComponent.FromDate <= @this.ActualStart && (!priceComponent.ExistThroughDate || priceComponent.ThroughDate >= @this.ActualStart)) { priceComponents.Add(priceComponent); } } // Discounts and surcharges can be specified without product or product feature, these need te be added to collection of pricecomponents extent = new PriceComponents(@this.Strategy.Session).Extent(); foreach (PriceComponent priceComponent in extent) { if (!priceComponent.ExistProduct && !priceComponent.ExistPart && !priceComponent.ExistProductFeature && priceComponent.FromDate <= @this.ActualStart && (!priceComponent.ExistThroughDate || priceComponent.ThroughDate >= @this.ActualStart)) { priceComponents.Add(priceComponent); } } return(priceComponents); }
private static List <PriceComponent> GetPriceComponents(Product product, DateTime date) { // TODO: Code duplication ? var priceComponents = new List <PriceComponent>(); var session = product.Strategy.Session; var extent = new PriceComponents(session).Extent(); foreach (PriceComponent priceComponent in extent) { if (priceComponent.ExistProduct && priceComponent.Product.Equals(product) && !priceComponent.ExistProductFeature && priceComponent.FromDate <= date && (!priceComponent.ExistThroughDate || priceComponent.ThroughDate >= date)) { priceComponents.Add(priceComponent); } } if (priceComponents.Count == 0 && product.ExistProductWhereVariant) { extent = new PriceComponents(session).Extent(); foreach (PriceComponent priceComponent in extent) { if (priceComponent.ExistProduct && priceComponent.Product.Equals(product.ProductWhereVariant) && !priceComponent.ExistProductFeature && priceComponent.FromDate <= date && (!priceComponent.ExistThroughDate || priceComponent.ThroughDate >= date)) { priceComponents.Add(priceComponent); } } } // Discounts and surcharges can be specified without product or product feature, these need te be added to collection of pricecomponents extent = new PriceComponents(session).Extent(); foreach (PriceComponent priceComponent in extent) { if (!priceComponent.ExistProduct && !priceComponent.ExistProductFeature && priceComponent.FromDate <= date && (!priceComponent.ExistThroughDate || priceComponent.ThroughDate >= date)) { priceComponents.Add(priceComponent); } } return(priceComponents); }
public void BaseCalculateSellingPrice(WorkEffortPurchaseOrderItemAssignmentCalculateSellingPrice method) { if (!method.Result.HasValue) { if (this.AssignedUnitSellingPrice.HasValue) { this.UnitSellingPrice = this.AssignedUnitSellingPrice.Value; } else { var part = this.PurchaseOrderItem.Part; var currentPriceComponents = new PriceComponents(this.Strategy.Session).CurrentPriceComponents(this.Assignment.ScheduledStart); var currentPartPriceComponents = part.GetPriceComponents(currentPriceComponents); var price = currentPartPriceComponents.OfType <BasePrice>().Max(v => v.Price); this.UnitSellingPrice = price ?? 0M; } method.Result = true; } }
public void BaseOnDerive(ObjectOnDerive method) { var derivation = method.Derivation; var session = this.Session(); this.ValidQuoteItems = this.QuoteItems.Where(v => v.IsValid).ToArray(); var currentPriceComponents = new PriceComponents(session).CurrentPriceComponents(this.IssueDate); var quantityOrderedByProduct = this.ValidQuoteItems .Where(v => v.ExistProduct) .GroupBy(v => v.Product) .ToDictionary(v => v.Key, v => v.Sum(w => w.Quantity)); // First run to calculate price foreach (QuoteItem quoteItem in this.ValidQuoteItems) { decimal quantityOrdered = 0; if (quoteItem.ExistProduct) { quantityOrderedByProduct.TryGetValue(quoteItem.Product, out quantityOrdered); } foreach (QuoteItem featureItem in quoteItem.QuotedWithFeatures) { featureItem.Quantity = quoteItem.Quantity; this.CalculatePrices(derivation, featureItem, currentPriceComponents, quantityOrdered, 0); } this.CalculatePrices(derivation, quoteItem, currentPriceComponents, quantityOrdered, 0); } var totalBasePriceByProduct = this.QuoteItems .Where(v => v.ExistProduct) .GroupBy(v => v.Product) .ToDictionary(v => v.Key, v => v.Sum(w => w.TotalBasePrice)); // Second run to calculate price (because of order value break) foreach (QuoteItem quoteItem in this.ValidQuoteItems) { decimal quantityOrdered = 0; decimal totalBasePrice = 0; if (quoteItem.ExistProduct) { quantityOrderedByProduct.TryGetValue(quoteItem.Product, out quantityOrdered); totalBasePriceByProduct.TryGetValue(quoteItem.Product, out totalBasePrice); } foreach (QuoteItem featureItem in quoteItem.QuotedWithFeatures) { this.CalculatePrices(derivation, featureItem, currentPriceComponents, quantityOrdered, totalBasePrice); } this.CalculatePrices(derivation, quoteItem, currentPriceComponents, quantityOrdered, totalBasePrice); } // SalesOrderItem Derivations and Validations foreach (QuoteItem quoteItem in this.ValidQuoteItems) { var isSubTotalItem = quoteItem.ExistInvoiceItemType && (quoteItem.InvoiceItemType.IsProductItem || quoteItem.InvoiceItemType.IsPartItem); if (isSubTotalItem) { if (quoteItem.Quantity == 0) { derivation.Validation.AddError(quoteItem, M.QuoteItem.Quantity, "Quantity is Required"); } } else { if (quoteItem.UnitPrice == 0) { derivation.Validation.AddError(quoteItem, M.QuoteItem.UnitPrice, "Price is Required"); } } } // Calculate Totals if (this.ExistQuoteItems) { this.TotalBasePrice = 0; this.TotalDiscount = 0; this.TotalSurcharge = 0; this.TotalExVat = 0; this.TotalFee = 0; this.TotalShippingAndHandling = 0; this.TotalVat = 0; this.TotalIncVat = 0; this.TotalListPrice = 0; foreach (QuoteItem quoteItem in this.ValidQuoteItems) { if (!quoteItem.ExistQuoteItemWhereQuotedWithFeature) { this.TotalBasePrice += quoteItem.TotalBasePrice; this.TotalDiscount += quoteItem.TotalDiscount; this.TotalSurcharge += quoteItem.TotalSurcharge; this.TotalExVat += quoteItem.TotalExVat; this.TotalVat += quoteItem.TotalVat; this.TotalIncVat += quoteItem.TotalIncVat; this.TotalListPrice += quoteItem.TotalExVat; } } if (this.ExistDiscountAdjustment) { var discount = this.DiscountAdjustment.Percentage.HasValue ? Math.Round(this.TotalExVat * this.DiscountAdjustment.Percentage.Value / 100, 2) : this.DiscountAdjustment.Amount ?? 0; this.TotalDiscount += discount; this.TotalExVat -= discount; if (this.ExistVatRegime) { var vat = Math.Round(discount * this.VatRegime.VatRate.Rate / 100, 2); this.TotalVat -= vat; this.TotalIncVat -= discount + vat; } } if (this.ExistSurchargeAdjustment) { var surcharge = this.SurchargeAdjustment.Percentage.HasValue ? Math.Round(this.TotalExVat * this.SurchargeAdjustment.Percentage.Value / 100, 2) : this.SurchargeAdjustment.Amount ?? 0; this.TotalSurcharge += surcharge; this.TotalExVat += surcharge; if (this.ExistVatRegime) { var vat = Math.Round(surcharge * this.VatRegime.VatRate.Rate / 100, 2); this.TotalVat += vat; this.TotalIncVat += surcharge + vat; } } if (this.ExistFee) { var fee = this.Fee.Percentage.HasValue ? Math.Round(this.TotalExVat * this.Fee.Percentage.Value / 100, 2) : this.Fee.Amount ?? 0; this.TotalFee += fee; this.TotalExVat += fee; if (this.Fee.ExistVatRate) { var vat1 = Math.Round(fee * this.Fee.VatRate.Rate / 100, 2); this.TotalVat += vat1; this.TotalIncVat += fee + vat1; } } if (this.ExistShippingAndHandlingCharge) { var shipping = this.ShippingAndHandlingCharge.Percentage.HasValue ? Math.Round(this.TotalExVat * this.ShippingAndHandlingCharge.Percentage.Value / 100, 2) : this.ShippingAndHandlingCharge.Amount ?? 0; this.TotalShippingAndHandling += shipping; this.TotalExVat += shipping; if (this.ShippingAndHandlingCharge.ExistVatRate) { var vat2 = Math.Round(shipping * this.ShippingAndHandlingCharge.VatRate.Rate / 100, 2); this.TotalVat += vat2; this.TotalIncVat += shipping + vat2; } } //// Only take into account items for which there is data at the item level. //// Skip negative sales. decimal totalUnitBasePrice = 0; decimal totalListPrice = 0; foreach (QuoteItem item1 in this.ValidQuoteItems) { if (item1.TotalExVat > 0) { totalUnitBasePrice += item1.UnitBasePrice; totalListPrice += item1.UnitPrice; } } } this.DeriveWorkflow(); this.Sync(this.Strategy.Session); this.ResetPrintDocument(); }
public void CalculatePrices( IDerivation derivation, QuoteItem quoteItem, PriceComponent[] currentPriceComponents, decimal quantityOrdered, decimal totalBasePrice) { var quoteItemDeriveRoles = (QuoteItemDerivedRoles)quoteItem; var currentGenericOrProductOrFeaturePriceComponents = Array.Empty <PriceComponent>(); if (quoteItem.ExistProduct) { currentGenericOrProductOrFeaturePriceComponents = quoteItem.Product.GetPriceComponents(currentPriceComponents); } else if (quoteItem.ExistProductFeature) { currentGenericOrProductOrFeaturePriceComponents = quoteItem.ProductFeature.GetPriceComponents(quoteItem.QuoteItemWhereQuotedWithFeature.Product, currentPriceComponents); } var priceComponents = currentGenericOrProductOrFeaturePriceComponents.Where( v => PriceComponents.BaseIsApplicable( new PriceComponents.IsApplicable { PriceComponent = v, Customer = this.Receiver, Product = quoteItem.Product, QuantityOrdered = quantityOrdered, ValueOrdered = totalBasePrice, })).ToArray(); var unitBasePrice = priceComponents.OfType <BasePrice>().Min(v => v.Price); if (!unitBasePrice.HasValue) { unitBasePrice = 0; } // Calculate Unit Price (with Discounts and Surcharges) if (quoteItem.AssignedUnitPrice.HasValue) { quoteItemDeriveRoles.UnitBasePrice = unitBasePrice ?? quoteItem.AssignedUnitPrice.Value; quoteItemDeriveRoles.UnitDiscount = 0; quoteItemDeriveRoles.UnitSurcharge = 0; quoteItemDeriveRoles.UnitPrice = quoteItem.AssignedUnitPrice.Value; } else { quoteItemDeriveRoles.UnitBasePrice = unitBasePrice.Value; quoteItemDeriveRoles.UnitDiscount = priceComponents.OfType <DiscountComponent>().Sum( v => v.Percentage.HasValue ? Math.Round(quoteItem.UnitBasePrice * v.Percentage.Value / 100, 2) : v.Price ?? 0); quoteItemDeriveRoles.UnitSurcharge = priceComponents.OfType <SurchargeComponent>().Sum( v => v.Percentage.HasValue ? Math.Round(quoteItem.UnitBasePrice * v.Percentage.Value / 100, 2) : v.Price ?? 0); quoteItemDeriveRoles.UnitPrice = quoteItem.UnitBasePrice - quoteItem.UnitDiscount + quoteItem.UnitSurcharge; if (quoteItem.ExistDiscountAdjustment) { quoteItemDeriveRoles.UnitDiscount += quoteItem.DiscountAdjustment.Percentage.HasValue ? Math.Round(quoteItem.UnitPrice * quoteItem.DiscountAdjustment.Percentage.Value / 100, 2) : quoteItem.DiscountAdjustment.Amount ?? 0; } if (quoteItem.ExistSurchargeAdjustment) { quoteItemDeriveRoles.UnitSurcharge += quoteItem.SurchargeAdjustment.Percentage.HasValue ? Math.Round(quoteItem.UnitPrice * quoteItem.SurchargeAdjustment.Percentage.Value / 100, 2) : quoteItem.SurchargeAdjustment.Amount ?? 0; } quoteItemDeriveRoles.UnitPrice = quoteItem.UnitBasePrice - quoteItem.UnitDiscount + quoteItem.UnitSurcharge; } foreach (QuoteItem featureItem in quoteItem.QuotedWithFeatures) { quoteItemDeriveRoles.UnitBasePrice += featureItem.UnitBasePrice; quoteItemDeriveRoles.UnitPrice += featureItem.UnitPrice; quoteItemDeriveRoles.UnitDiscount += featureItem.UnitDiscount; quoteItemDeriveRoles.UnitSurcharge += featureItem.UnitSurcharge; } quoteItemDeriveRoles.UnitVat = quoteItem.ExistVatRate ? Math.Round(quoteItem.UnitPrice * quoteItem.VatRate.Rate / 100, 2) : 0; // Calculate Totals quoteItemDeriveRoles.TotalBasePrice = quoteItem.UnitBasePrice * quoteItem.Quantity; quoteItemDeriveRoles.TotalDiscount = quoteItem.UnitDiscount * quoteItem.Quantity; quoteItemDeriveRoles.TotalSurcharge = quoteItem.UnitSurcharge * quoteItem.Quantity; quoteItemDeriveRoles.TotalPriceAdjustment = quoteItem.TotalSurcharge - quoteItem.TotalDiscount; if (quoteItem.TotalBasePrice > 0) { quoteItemDeriveRoles.TotalDiscountAsPercentage = Math.Round(quoteItem.TotalDiscount / quoteItem.TotalBasePrice * 100, 2); quoteItemDeriveRoles.TotalSurchargeAsPercentage = Math.Round(quoteItem.TotalSurcharge / quoteItem.TotalBasePrice * 100, 2); } else { quoteItemDeriveRoles.TotalDiscountAsPercentage = 0; quoteItemDeriveRoles.TotalSurchargeAsPercentage = 0; } quoteItemDeriveRoles.TotalExVat = quoteItem.UnitPrice * quoteItem.Quantity; quoteItemDeriveRoles.TotalVat = quoteItem.UnitVat * quoteItem.Quantity; quoteItemDeriveRoles.TotalIncVat = quoteItem.TotalExVat + quoteItem.TotalVat; }
public void BaseOnDerive(ObjectOnDerive method) { var derivation = method.Derivation; var session = this.Session(); this.ValidQuoteItems = this.QuoteItems.Where(v => v.IsValid).ToArray(); var currentPriceComponents = new PriceComponents(session).CurrentPriceComponents(this.IssueDate); var quantityOrderedByProduct = this.ValidQuoteItems .Where(v => v.ExistProduct) .GroupBy(v => v.Product) .ToDictionary(v => v.Key, v => v.Sum(w => w.Quantity)); // First run to calculate price foreach (QuoteItem quoteItem in this.ValidQuoteItems) { decimal quantityOrdered = 0; if (quoteItem.ExistProduct) { quantityOrderedByProduct.TryGetValue(quoteItem.Product, out quantityOrdered); } foreach (QuoteItem featureItem in quoteItem.QuotedWithFeatures) { featureItem.Quantity = quoteItem.Quantity; this.CalculatePrices(derivation, featureItem, currentPriceComponents, quantityOrdered, 0); } this.CalculatePrices(derivation, quoteItem, currentPriceComponents, quantityOrdered, 0); } var totalBasePriceByProduct = this.QuoteItems .Where(v => v.ExistProduct) .GroupBy(v => v.Product) .ToDictionary(v => v.Key, v => v.Sum(w => w.TotalBasePrice)); // Second run to calculate price (because of order value break) foreach (QuoteItem quoteItem in this.ValidQuoteItems) { decimal quantityOrdered = 0; decimal totalBasePrice = 0; if (quoteItem.ExistProduct) { quantityOrderedByProduct.TryGetValue(quoteItem.Product, out quantityOrdered); totalBasePriceByProduct.TryGetValue(quoteItem.Product, out totalBasePrice); } foreach (QuoteItem featureItem in quoteItem.QuotedWithFeatures) { this.CalculatePrices(derivation, featureItem, currentPriceComponents, quantityOrdered, totalBasePrice); } this.CalculatePrices(derivation, quoteItem, currentPriceComponents, quantityOrdered, totalBasePrice); } // SalesOrderItem Derivations and Validations foreach (QuoteItem quoteItem in this.ValidQuoteItems) { var isSubTotalItem = quoteItem.ExistInvoiceItemType && (quoteItem.InvoiceItemType.IsProductItem || quoteItem.InvoiceItemType.IsPartItem); if (isSubTotalItem) { if (quoteItem.Quantity == 0) { derivation.Validation.AddError(quoteItem, M.QuoteItem.Quantity, "Quantity is Required"); } } else { if (quoteItem.UnitPrice == 0) { derivation.Validation.AddError(quoteItem, M.QuoteItem.UnitPrice, "Price is Required"); } } } // Calculate Totals this.TotalBasePrice = 0; this.TotalDiscount = 0; this.TotalSurcharge = 0; this.TotalExVat = 0; this.TotalFee = 0; this.TotalShippingAndHandling = 0; this.TotalExtraCharge = 0; this.TotalVat = 0; this.TotalIrpf = 0; this.TotalIncVat = 0; this.TotalListPrice = 0; this.GrandTotal = 0; foreach (QuoteItem quoteItem in this.ValidQuoteItems) { if (!quoteItem.ExistQuoteItemWhereQuotedWithFeature) { this.TotalBasePrice += quoteItem.TotalBasePrice; this.TotalDiscount += quoteItem.TotalDiscount; this.TotalSurcharge += quoteItem.TotalSurcharge; this.TotalExVat += quoteItem.TotalExVat; this.TotalVat += quoteItem.TotalVat; this.TotalIrpf += quoteItem.TotalIrpf; this.TotalIncVat += quoteItem.TotalIncVat; this.TotalListPrice += quoteItem.TotalExVat; this.GrandTotal += quoteItem.GrandTotal; } } var discount = 0M; var discountVat = 0M; var discountIrpf = 0M; var surcharge = 0M; var surchargeVat = 0M; var surchargeIrpf = 0M; var fee = 0M; var feeVat = 0M; var feeIrpf = 0M; var shipping = 0M; var shippingVat = 0M; var shippingIrpf = 0M; var miscellaneous = 0M; var miscellaneousVat = 0M; var miscellaneousIrpf = 0M; if (this.ExistIssueDate) { this.DerivedVatRate = this.DerivedVatRegime?.VatRates.First(v => v.FromDate <= this.IssueDate && (!v.ExistThroughDate || v.ThroughDate >= this.IssueDate)); this.DerivedIrpfRate = this.DerivedIrpfRegime?.IrpfRates.First(v => v.FromDate <= this.IssueDate && (!v.ExistThroughDate || v.ThroughDate >= this.IssueDate)); } foreach (OrderAdjustment orderAdjustment in this.OrderAdjustments) { if (orderAdjustment.GetType().Name.Equals(typeof(DiscountAdjustment).Name)) { discount = orderAdjustment.Percentage.HasValue ? this.TotalExVat * orderAdjustment.Percentage.Value / 100 : orderAdjustment.Amount ?? 0; this.TotalDiscount += discount; if (this.ExistDerivedVatRegime) { discountVat = discount * this.DerivedVatRate.Rate / 100; } if (this.ExistDerivedIrpfRegime) { discountIrpf = discount * this.DerivedIrpfRate.Rate / 100; } } if (orderAdjustment.GetType().Name.Equals(typeof(SurchargeAdjustment).Name)) { surcharge = orderAdjustment.Percentage.HasValue ? this.TotalExVat * orderAdjustment.Percentage.Value / 100 : orderAdjustment.Amount ?? 0; this.TotalSurcharge += surcharge; if (this.ExistDerivedVatRegime) { surchargeVat = surcharge * this.DerivedVatRate.Rate / 100; } if (this.ExistDerivedIrpfRegime) { surchargeIrpf = surcharge * this.DerivedIrpfRate.Rate / 100; } } if (orderAdjustment.GetType().Name.Equals(typeof(Fee).Name)) { fee = orderAdjustment.Percentage.HasValue ? this.TotalExVat * orderAdjustment.Percentage.Value / 100 : orderAdjustment.Amount ?? 0; this.TotalFee += fee; if (this.ExistDerivedVatRegime) { feeVat = fee * this.DerivedVatRate.Rate / 100; } if (this.ExistDerivedIrpfRegime) { feeIrpf = fee * this.DerivedIrpfRate.Rate / 100; } } if (orderAdjustment.GetType().Name.Equals(typeof(ShippingAndHandlingCharge).Name)) { shipping = orderAdjustment.Percentage.HasValue ? this.TotalExVat * orderAdjustment.Percentage.Value / 100 : orderAdjustment.Amount ?? 0; this.TotalShippingAndHandling += shipping; if (this.ExistDerivedVatRegime) { shippingVat = shipping * this.DerivedVatRate.Rate / 100; } if (this.ExistDerivedIrpfRegime) { shippingIrpf = shipping * this.DerivedIrpfRate.Rate / 100; } } if (orderAdjustment.GetType().Name.Equals(typeof(MiscellaneousCharge).Name)) { miscellaneous = orderAdjustment.Percentage.HasValue ? this.TotalExVat * orderAdjustment.Percentage.Value / 100 : orderAdjustment.Amount ?? 0; this.TotalExtraCharge += miscellaneous; if (this.ExistDerivedVatRegime) { miscellaneousVat = miscellaneous * this.DerivedVatRate.Rate / 100; } if (this.ExistDerivedIrpfRegime) { miscellaneousIrpf = miscellaneous * this.DerivedIrpfRate.Rate / 100; } } } var totalExtraCharge = fee + shipping + miscellaneous; var totalExVat = this.TotalExVat - discount + surcharge + fee + shipping + miscellaneous; var totalVat = this.TotalVat - discountVat + surchargeVat + feeVat + shippingVat + miscellaneousVat; var totalIncVat = this.TotalIncVat - discount - discountVat + surcharge + surchargeVat + fee + feeVat + shipping + shippingVat + miscellaneous + miscellaneousVat; var totalIrpf = this.TotalIrpf + discountIrpf - surchargeIrpf - feeIrpf - shippingIrpf - miscellaneousIrpf; var grandTotal = totalIncVat - totalIrpf; if (this.ExistIssueDate && this.ExistDerivedCurrency && this.ExistIssuer) { this.TotalBasePriceInPreferredCurrency = Rounder.RoundDecimal(Currencies.ConvertCurrency(this.TotalBasePrice, this.IssueDate, this.DerivedCurrency, this.Issuer.PreferredCurrency), 2); this.TotalDiscountInPreferredCurrency = Rounder.RoundDecimal(Currencies.ConvertCurrency(this.TotalDiscount, this.IssueDate, this.DerivedCurrency, this.Issuer.PreferredCurrency), 2); this.TotalSurchargeInPreferredCurrency = Rounder.RoundDecimal(Currencies.ConvertCurrency(this.TotalSurcharge, this.IssueDate, this.DerivedCurrency, this.Issuer.PreferredCurrency), 2); this.TotalExtraChargeInPreferredCurrency = Rounder.RoundDecimal(Currencies.ConvertCurrency(totalExtraCharge, this.IssueDate, this.DerivedCurrency, this.Issuer.PreferredCurrency), 2); this.TotalFeeInPreferredCurrency = Rounder.RoundDecimal(Currencies.ConvertCurrency(this.TotalFee, this.IssueDate, this.DerivedCurrency, this.Issuer.PreferredCurrency), 2); this.TotalShippingAndHandlingInPreferredCurrency = Rounder.RoundDecimal(Currencies.ConvertCurrency(this.TotalShippingAndHandling, this.IssueDate, this.DerivedCurrency, this.Issuer.PreferredCurrency), 2); this.TotalExVatInPreferredCurrency = Rounder.RoundDecimal(Currencies.ConvertCurrency(totalExVat, this.IssueDate, this.DerivedCurrency, this.Issuer.PreferredCurrency), 2); this.TotalVatInPreferredCurrency = Rounder.RoundDecimal(Currencies.ConvertCurrency(totalVat, this.IssueDate, this.DerivedCurrency, this.Issuer.PreferredCurrency), 2); this.TotalIncVatInPreferredCurrency = Rounder.RoundDecimal(Currencies.ConvertCurrency(totalIncVat, this.IssueDate, this.DerivedCurrency, this.Issuer.PreferredCurrency), 2); this.TotalIrpfInPreferredCurrency = Rounder.RoundDecimal(Currencies.ConvertCurrency(totalIrpf, this.IssueDate, this.DerivedCurrency, this.Issuer.PreferredCurrency), 2); this.GrandTotalInPreferredCurrency = Rounder.RoundDecimal(Currencies.ConvertCurrency(grandTotal, this.IssueDate, this.DerivedCurrency, this.Issuer.PreferredCurrency), 2); } this.TotalBasePrice = Rounder.RoundDecimal(this.TotalBasePrice, 2); this.TotalDiscount = Rounder.RoundDecimal(this.TotalDiscount, 2); this.TotalSurcharge = Rounder.RoundDecimal(this.TotalSurcharge, 2); this.TotalExtraCharge = Rounder.RoundDecimal(totalExtraCharge, 2); this.TotalFee = Rounder.RoundDecimal(this.TotalFee, 2); this.TotalShippingAndHandling = Rounder.RoundDecimal(this.TotalShippingAndHandling, 2); this.TotalExVat = Rounder.RoundDecimal(totalExVat, 2); this.TotalVat = Rounder.RoundDecimal(totalVat, 2); this.TotalIncVat = Rounder.RoundDecimal(totalIncVat, 2); this.TotalIrpf = Rounder.RoundDecimal(totalIrpf, 2); this.GrandTotal = Rounder.RoundDecimal(grandTotal, 2); //// Only take into account items for which there is data at the item level. //// Skip negative sales. decimal totalUnitBasePrice = 0; decimal totalListPrice = 0; foreach (QuoteItem item1 in this.ValidQuoteItems) { if (item1.TotalExVat > 0) { totalUnitBasePrice += item1.UnitBasePrice; totalListPrice += item1.UnitPrice; } } this.TotalListPriceInPreferredCurrency = Rounder.RoundDecimal(Currencies.ConvertCurrency(TotalListPrice, this.IssueDate, this.DerivedCurrency, this.Issuer.PreferredCurrency), 2); this.TotalListPrice = Rounder.RoundDecimal(this.TotalListPrice, 2); this.DeriveWorkflow(); this.Sync(this.Strategy.Session); this.ResetPrintDocument(); }
private IEnumerable <PriceComponent> GetPriceComponents() { var priceComponents = new List <PriceComponent>(); if (priceComponents.Count == 0) { var extent = new PriceComponents(this.strategy.Session).Extent(); if (this.ExistProduct) { foreach (PriceComponent priceComponent in extent) { if (priceComponent.ExistProduct && priceComponent.Product.Equals(this.Product) && !priceComponent.ExistProductFeature && priceComponent.FromDate <= this.SalesInvoiceWhereSalesInvoiceItem.InvoiceDate && (!priceComponent.ExistThroughDate || priceComponent.ThroughDate >= this.SalesInvoiceWhereSalesInvoiceItem.InvoiceDate)) { priceComponents.Add(priceComponent); } } if (priceComponents.Count == 0 && this.Product.ExistProductWhereVariant) { extent = new PriceComponents(this.strategy.Session).Extent(); foreach (PriceComponent priceComponent in extent) { if (priceComponent.ExistProduct && priceComponent.Product.Equals(this.Product.ProductWhereVariant) && !priceComponent.ExistProductFeature && priceComponent.FromDate <= this.SalesInvoiceWhereSalesInvoiceItem.InvoiceDate && (!priceComponent.ExistThroughDate || priceComponent.ThroughDate >= this.SalesInvoiceWhereSalesInvoiceItem.InvoiceDate)) { priceComponents.Add(priceComponent); } } } } if (this.ExistProductFeature) { foreach (PriceComponent priceComponent in extent) { if (priceComponent.ExistProductFeature && priceComponent.ProductFeature.Equals(this.ProductFeature) && !priceComponent.ExistProduct && priceComponent.FromDate <= this.SalesInvoiceWhereSalesInvoiceItem.InvoiceDate && (!priceComponent.ExistThroughDate || priceComponent.ThroughDate >= this.SalesInvoiceWhereSalesInvoiceItem.InvoiceDate)) { priceComponents.Add(priceComponent); } } } // Discounts and surcharges can be specified without product or product feature, these need te be added to collection of pricecomponents extent = new PriceComponents(this.strategy.Session).Extent(); foreach (PriceComponent priceComponent in extent) { if (!priceComponent.ExistProduct && !priceComponent.ExistProductFeature && priceComponent.FromDate <= this.SalesInvoiceWhereSalesInvoiceItem.InvoiceDate && (!priceComponent.ExistThroughDate || priceComponent.ThroughDate >= this.SalesInvoiceWhereSalesInvoiceItem.InvoiceDate)) { priceComponents.Add(priceComponent); } } } return(priceComponents); }
public void AppsOnDerivePrices(IDerivation derivation, decimal quantityInvoiced, decimal totalBasePrice) { this.UnitBasePrice = 0; this.UnitDiscount = 0; this.UnitSurcharge = 0; this.CalculatedUnitPrice = 0; decimal discountAdjustmentAmount = 0; decimal surchargeAdjustmentAmount = 0; var internalOrganisation = this.Strategy.Session.GetSingleton(); var customer = this.SalesInvoiceWhereSalesInvoiceItem.BillToCustomer; var salesInvoice = this.SalesInvoiceWhereSalesInvoiceItem; var baseprices = new PriceComponent[0]; if (this.ExistProduct && this.Product.ExistBasePrices) { baseprices = this.Product.BasePrices; } if (this.ExistProductFeature && this.ProductFeature.ExistBasePrices) { baseprices = this.ProductFeature.BasePrices; } foreach (BasePrice priceComponent in baseprices) { if (priceComponent.FromDate <= this.SalesInvoiceWhereSalesInvoiceItem.InvoiceDate && (!priceComponent.ExistThroughDate || priceComponent.ThroughDate >= this.SalesInvoiceWhereSalesInvoiceItem.InvoiceDate)) { if (priceComponent.Strategy.Class.Equals(M.BasePrice.ObjectType)) { if (PriceComponents.AppsIsEligible(new PriceComponents.IsEligibleParams { PriceComponent = priceComponent, Customer = customer, Product = this.Product, SalesInvoice = salesInvoice, QuantityOrdered = quantityInvoiced, ValueOrdered = totalBasePrice })) { if (priceComponent.ExistPrice) { if (priceComponent.Price.HasValue && (this.UnitBasePrice == 0 || priceComponent.Price < this.UnitBasePrice)) { this.UnitBasePrice = priceComponent.Price.Value; this.RemoveCurrentPriceComponents(); this.AddCurrentPriceComponent(priceComponent); } } } } } } if (!this.ExistActualUnitPrice) { var priceComponents = this.GetPriceComponents(); var revenueBreakDiscount = 0M; var revenueBreakSurcharge = 0M; foreach (var priceComponent in priceComponents) { if (priceComponent.Strategy.Class.Equals(M.DiscountComponent.ObjectType) || priceComponent.Strategy.Class.Equals(M.SurchargeComponent.ObjectType)) { if (PriceComponents.AppsIsEligible(new PriceComponents.IsEligibleParams { PriceComponent = priceComponent, Customer = customer, Product = this.Product, SalesInvoice = salesInvoice, QuantityOrdered = quantityInvoiced, ValueOrdered = totalBasePrice, })) { this.AddCurrentPriceComponent(priceComponent); revenueBreakDiscount = this.SetUnitDiscount(priceComponent, revenueBreakDiscount); revenueBreakSurcharge = this.SetUnitSurcharge(priceComponent, revenueBreakSurcharge); } } } var adjustmentBase = this.UnitBasePrice - this.UnitDiscount + this.UnitSurcharge; if (this.ExistDiscountAdjustment) { if (this.DiscountAdjustment.Percentage.HasValue) { discountAdjustmentAmount = Math.Round((adjustmentBase * this.DiscountAdjustment.Percentage.Value) / 100, 2); } else { discountAdjustmentAmount = this.DiscountAdjustment.Amount.HasValue ? this.DiscountAdjustment.Amount.Value : 0; } this.UnitDiscount += discountAdjustmentAmount; } if (this.ExistSurchargeAdjustment) { if (this.SurchargeAdjustment.Percentage.HasValue) { surchargeAdjustmentAmount = Math.Round((adjustmentBase * this.SurchargeAdjustment.Percentage.Value) / 100, 2); } else { surchargeAdjustmentAmount = this.SurchargeAdjustment.Amount.HasValue ? this.SurchargeAdjustment.Amount.Value : 0; } this.UnitSurcharge += surchargeAdjustmentAmount; } } var price = this.ActualUnitPrice.HasValue ? this.ActualUnitPrice.Value : this.UnitBasePrice; decimal vat = 0; if (this.ExistDerivedVatRate) { var vatRate = this.DerivedVatRate.Rate; var vatBase = price - this.UnitDiscount + this.UnitSurcharge; vat = Math.Round((vatBase * vatRate) / 100, 2); } this.UnitVat = vat; this.TotalBasePrice = price * this.Quantity; this.TotalDiscount = this.UnitDiscount * this.Quantity; this.TotalSurcharge = this.UnitSurcharge * this.Quantity; this.TotalInvoiceAdjustment = (0 - discountAdjustmentAmount + surchargeAdjustmentAmount) * this.Quantity; if (this.TotalBasePrice > 0) { this.TotalDiscountAsPercentage = Math.Round((this.TotalDiscount / this.TotalBasePrice) * 100, 2); this.TotalSurchargeAsPercentage = Math.Round((this.TotalSurcharge / this.TotalBasePrice) * 100, 2); } if (this.ActualUnitPrice.HasValue) { this.CalculatedUnitPrice = this.ActualUnitPrice.Value; } else { this.CalculatedUnitPrice = this.UnitBasePrice - this.UnitDiscount + this.UnitSurcharge; } this.TotalVat = this.UnitVat * this.Quantity; this.TotalExVat = this.CalculatedUnitPrice * this.Quantity; this.TotalIncVat = this.TotalExVat + this.TotalVat; var toCurrency = this.SalesInvoiceWhereSalesInvoiceItem.Currency; var fromCurrency = this.SalesInvoiceWhereSalesInvoiceItem.BilledFrom.PreferredCurrency; if (fromCurrency.Equals(toCurrency)) { this.TotalBasePriceCustomerCurrency = this.TotalBasePrice; this.TotalDiscountCustomerCurrency = this.TotalDiscount; this.TotalSurchargeCustomerCurrency = this.TotalSurcharge; this.TotalExVatCustomerCurrency = this.TotalExVat; this.TotalVatCustomerCurrency = this.TotalVat; this.TotalIncVatCustomerCurrency = this.TotalIncVat; } else { this.TotalBasePriceCustomerCurrency = Currencies.ConvertCurrency(this.TotalBasePrice, fromCurrency, toCurrency); this.TotalDiscountCustomerCurrency = Currencies.ConvertCurrency(this.TotalDiscount, fromCurrency, toCurrency); this.TotalSurchargeCustomerCurrency = Currencies.ConvertCurrency(this.TotalSurcharge, fromCurrency, toCurrency); this.TotalExVatCustomerCurrency = Currencies.ConvertCurrency(this.TotalExVat, fromCurrency, toCurrency); this.TotalVatCustomerCurrency = Currencies.ConvertCurrency(this.TotalVat, fromCurrency, toCurrency); this.TotalIncVatCustomerCurrency = Currencies.ConvertCurrency(this.TotalIncVat, fromCurrency, toCurrency); } this.AppsOnDeriveMarkupAndProfitMargin(derivation); }
private void CalculatePrice(IDerivation derivation, SalesOrder salesOrder, bool useValueOrdered = false) { var sameProductItems = salesOrder.SalesOrderItems .Where(v => v.IsValid && v.ExistProduct && v.Product.Equals(this.Product)) .ToArray(); var quantityOrdered = sameProductItems.Sum(w => w.QuantityOrdered); var valueOrdered = useValueOrdered ? sameProductItems.Sum(w => w.TotalBasePrice) : 0; var orderPriceComponents = new PriceComponents(this.Session()).CurrentPriceComponents(salesOrder.OrderDate); var orderItemPriceComponents = Array.Empty <PriceComponent>(); if (this.ExistProduct) { orderItemPriceComponents = this.Product.GetPriceComponents(orderPriceComponents); } else if (this.ExistProductFeature) { orderItemPriceComponents = this.ProductFeature.GetPriceComponents(this.SalesOrderItemWhereOrderedWithFeature.Product, orderPriceComponents); } var priceComponents = orderItemPriceComponents.Where( v => PriceComponents.BaseIsApplicable( new PriceComponents.IsApplicable { PriceComponent = v, Customer = salesOrder.BillToCustomer, Product = this.Product, SalesOrder = salesOrder, QuantityOrdered = quantityOrdered, ValueOrdered = valueOrdered, })).ToArray(); var unitBasePrice = priceComponents.OfType <BasePrice>().Min(v => v.Price); // Calculate Unit Price (with Discounts and Surcharges) if (this.AssignedUnitPrice.HasValue) { this.UnitBasePrice = unitBasePrice ?? this.AssignedUnitPrice.Value; this.UnitDiscount = 0; this.UnitSurcharge = 0; this.UnitPrice = this.AssignedUnitPrice.Value; } else { if (!unitBasePrice.HasValue) { derivation.Validation.AddError(this, M.SalesOrderItem.UnitBasePrice, "No BasePrice with a Price"); return; } this.UnitBasePrice = unitBasePrice.Value; this.UnitDiscount = priceComponents.OfType <DiscountComponent>().Sum( v => v.Percentage.HasValue ? Math.Round(this.UnitBasePrice * v.Percentage.Value / 100, 2) : v.Price ?? 0); this.UnitSurcharge = priceComponents.OfType <SurchargeComponent>().Sum( v => v.Percentage.HasValue ? Math.Round(this.UnitBasePrice * v.Percentage.Value / 100, 2) : v.Price ?? 0); this.UnitPrice = this.UnitBasePrice - this.UnitDiscount + this.UnitSurcharge; foreach (OrderAdjustment orderAdjustment in this.DiscountAdjustments) { this.UnitDiscount += orderAdjustment.Percentage.HasValue ? Math.Round(this.UnitPrice * orderAdjustment.Percentage.Value / 100, 2) : orderAdjustment.Amount ?? 0; } foreach (OrderAdjustment orderAdjustment in this.SurchargeAdjustments) { this.UnitSurcharge += orderAdjustment.Percentage.HasValue ? Math.Round(this.UnitPrice * orderAdjustment.Percentage.Value / 100, 2) : orderAdjustment.Amount ?? 0; } this.UnitPrice = this.UnitBasePrice - this.UnitDiscount + this.UnitSurcharge; } foreach (SalesOrderItem featureItem in this.OrderedWithFeatures) { this.UnitBasePrice += featureItem.UnitBasePrice; this.UnitPrice += featureItem.UnitPrice; this.UnitDiscount += featureItem.UnitDiscount; this.UnitSurcharge += featureItem.UnitSurcharge; } this.UnitVat = this.ExistVatRate ? this.UnitPrice * this.VatRate.Rate / 100 : 0; this.UnitIrpf = this.ExistIrpfRate ? this.UnitPrice * this.IrpfRate.Rate / 100 : 0; // Calculate Totals this.TotalBasePrice = this.UnitBasePrice * this.QuantityOrdered; this.TotalDiscount = this.UnitDiscount * this.QuantityOrdered; this.TotalSurcharge = this.UnitSurcharge * this.QuantityOrdered; this.TotalOrderAdjustment = this.TotalSurcharge - this.TotalDiscount; if (this.TotalBasePrice > 0) { this.TotalDiscountAsPercentage = Math.Round(this.TotalDiscount / this.TotalBasePrice * 100, 2); this.TotalSurchargeAsPercentage = Math.Round(this.TotalSurcharge / this.TotalBasePrice * 100, 2); } else { this.TotalDiscountAsPercentage = 0; this.TotalSurchargeAsPercentage = 0; } this.TotalExVat = this.UnitPrice * this.QuantityOrdered; this.TotalVat = Math.Round(this.UnitVat * this.QuantityOrdered, 2); this.TotalIncVat = this.TotalExVat + this.TotalVat; this.TotalIrpf = Math.Round(this.UnitIrpf * this.QuantityOrdered, 2); this.GrandTotal = this.TotalIncVat - this.TotalIrpf; }
private static decimal BaseCatalogPrice( SalesOrder salesOrder, SalesInvoice salesInvoice, Product product, DateTime date) { var productBasePrice = 0M; var productDiscount = 0M; var productSurcharge = 0M; var baseprices = new PriceComponent[0]; if (product.ExistBasePrices) { baseprices = product.BasePrices; } var party = salesOrder != null ? salesOrder.ShipToCustomer : salesInvoice?.BillToCustomer; foreach (BasePrice priceComponent in baseprices) { if (priceComponent.FromDate <= date && (!priceComponent.ExistThroughDate || priceComponent.ThroughDate >= date)) { if (PriceComponents.BaseIsApplicable(new PriceComponents.IsApplicable { PriceComponent = priceComponent, Customer = party, Product = product, SalesOrder = salesOrder, SalesInvoice = salesInvoice, })) { if (priceComponent.ExistPrice) { if (productBasePrice == 0 || priceComponent.Price < productBasePrice) { productBasePrice = priceComponent.Price ?? 0; } } } } } var currentPriceComponents = new PriceComponents(product.Strategy.Session).CurrentPriceComponents(date); var priceComponents = product.GetPriceComponents(currentPriceComponents); foreach (var priceComponent in priceComponents) { if (priceComponent.Strategy.Class.Equals(M.DiscountComponent.ObjectType) || priceComponent.Strategy.Class.Equals(M.SurchargeComponent.ObjectType)) { if (PriceComponents.BaseIsApplicable(new PriceComponents.IsApplicable { PriceComponent = priceComponent, Customer = party, Product = product, SalesOrder = salesOrder, SalesInvoice = salesInvoice, })) { if (priceComponent.Strategy.Class.Equals(M.DiscountComponent.ObjectType)) { var discountComponent = (DiscountComponent)priceComponent; decimal discount; if (discountComponent.Price.HasValue) { discount = discountComponent.Price.Value; productDiscount += discount; } else { var percentage = discountComponent.Percentage ?? 0; discount = Rounder.RoundDecimal(productBasePrice * percentage / 100, 2); productDiscount += discount; } } if (priceComponent.Strategy.Class.Equals(M.SurchargeComponent.ObjectType)) { var surchargeComponent = (SurchargeComponent)priceComponent; decimal surcharge; if (surchargeComponent.Price.HasValue) { surcharge = surchargeComponent.Price.Value; productSurcharge += surcharge; } else { var percentage = surchargeComponent.Percentage ?? 0; surcharge = Rounder.RoundDecimal(productBasePrice * percentage / 100, 2); productSurcharge += surcharge; } } } } } return(productBasePrice - productDiscount + productSurcharge); }
public void CalculatePrices( IDerivation derivation, SalesInvoiceItem salesInvoiceItem, PriceComponent[] currentPriceComponents, decimal quantityOrdered, decimal totalBasePrice) { var salesInvoiceItemDerivedRoles = (SalesInvoiceItemDerivedRoles)salesInvoiceItem; var currentGenericOrProductOrFeaturePriceComponents = new List <PriceComponent>(); if (salesInvoiceItem.ExistProduct) { currentGenericOrProductOrFeaturePriceComponents.AddRange(salesInvoiceItem.Product.GetPriceComponents(currentPriceComponents)); } foreach (ProductFeature productFeature in salesInvoiceItem.ProductFeatures) { currentGenericOrProductOrFeaturePriceComponents.AddRange(productFeature.GetPriceComponents(salesInvoiceItem.Product, currentPriceComponents)); } var priceComponents = currentGenericOrProductOrFeaturePriceComponents.Where( v => PriceComponents.BaseIsApplicable( new PriceComponents.IsApplicable { PriceComponent = v, Customer = this.BillToCustomer, Product = salesInvoiceItem.Product, SalesInvoice = this, QuantityOrdered = quantityOrdered, ValueOrdered = totalBasePrice, })).ToArray(); var unitBasePrice = priceComponents.OfType <BasePrice>().Min(v => v.Price); // Calculate Unit Price (with Discounts and Surcharges) if (salesInvoiceItem.AssignedUnitPrice.HasValue) { salesInvoiceItemDerivedRoles.UnitBasePrice = unitBasePrice ?? salesInvoiceItem.AssignedUnitPrice.Value; salesInvoiceItemDerivedRoles.UnitDiscount = 0; salesInvoiceItemDerivedRoles.UnitSurcharge = 0; salesInvoiceItemDerivedRoles.UnitPrice = salesInvoiceItem.AssignedUnitPrice.Value; } else { if (!unitBasePrice.HasValue) { derivation.Validation.AddError(salesInvoiceItem, M.SalesOrderItem.UnitBasePrice, "No BasePrice with a Price"); return; } salesInvoiceItemDerivedRoles.UnitBasePrice = unitBasePrice.Value; salesInvoiceItemDerivedRoles.UnitDiscount = priceComponents.OfType <DiscountComponent>().Sum( v => v.Percentage.HasValue ? Math.Round(salesInvoiceItem.UnitBasePrice * v.Percentage.Value / 100, 2) : v.Price ?? 0); salesInvoiceItemDerivedRoles.UnitSurcharge = priceComponents.OfType <SurchargeComponent>().Sum( v => v.Percentage.HasValue ? Math.Round(salesInvoiceItem.UnitBasePrice * v.Percentage.Value / 100, 2) : v.Price ?? 0); salesInvoiceItemDerivedRoles.UnitPrice = salesInvoiceItem.UnitBasePrice - salesInvoiceItem.UnitDiscount + salesInvoiceItem.UnitSurcharge; if (salesInvoiceItem.ExistDiscountAdjustment) { salesInvoiceItemDerivedRoles.UnitDiscount += salesInvoiceItem.DiscountAdjustment.Percentage.HasValue ? Math.Round(salesInvoiceItem.UnitPrice * salesInvoiceItem.DiscountAdjustment.Percentage.Value / 100, 2) : salesInvoiceItem.DiscountAdjustment.Amount ?? 0; } if (salesInvoiceItem.ExistSurchargeAdjustment) { salesInvoiceItemDerivedRoles.UnitSurcharge += salesInvoiceItem.SurchargeAdjustment.Percentage.HasValue ? Math.Round(salesInvoiceItem.UnitPrice * salesInvoiceItem.SurchargeAdjustment.Percentage.Value / 100, 2) : salesInvoiceItem.SurchargeAdjustment.Amount ?? 0; } salesInvoiceItemDerivedRoles.UnitPrice = salesInvoiceItem.UnitBasePrice - salesInvoiceItem.UnitDiscount + salesInvoiceItem.UnitSurcharge; } salesInvoiceItemDerivedRoles.UnitVat = salesInvoiceItem.ExistVatRate ? Math.Round(salesInvoiceItem.UnitPrice * salesInvoiceItem.VatRate.Rate / 100, 2) : 0; // Calculate Totals salesInvoiceItemDerivedRoles.TotalBasePrice = salesInvoiceItem.UnitBasePrice * salesInvoiceItem.Quantity; salesInvoiceItemDerivedRoles.TotalDiscount = salesInvoiceItem.UnitDiscount * salesInvoiceItem.Quantity; salesInvoiceItemDerivedRoles.TotalSurcharge = salesInvoiceItem.UnitSurcharge * salesInvoiceItem.Quantity; if (salesInvoiceItem.TotalBasePrice > 0) { salesInvoiceItemDerivedRoles.TotalDiscountAsPercentage = Math.Round(salesInvoiceItem.TotalDiscount / salesInvoiceItem.TotalBasePrice * 100, 2); salesInvoiceItemDerivedRoles.TotalSurchargeAsPercentage = Math.Round(salesInvoiceItem.TotalSurcharge / salesInvoiceItem.TotalBasePrice * 100, 2); } else { salesInvoiceItemDerivedRoles.TotalDiscountAsPercentage = 0; salesInvoiceItemDerivedRoles.TotalSurchargeAsPercentage = 0; } salesInvoiceItemDerivedRoles.TotalExVat = salesInvoiceItem.UnitPrice * salesInvoiceItem.Quantity; salesInvoiceItemDerivedRoles.TotalVat = salesInvoiceItem.UnitVat * salesInvoiceItem.Quantity; salesInvoiceItemDerivedRoles.TotalIncVat = salesInvoiceItem.TotalExVat + salesInvoiceItem.TotalVat; }
public void BaseOnDerive(ObjectOnDerive method) { var derivation = method.Derivation; var session = this.Session(); var internalOrganisations = new Organisations(session).InternalOrganisations(); if (!this.ExistBilledFrom && internalOrganisations.Count() == 1) { this.BilledFrom = internalOrganisations.First(); } if (!this.ExistStore && this.ExistBilledFrom) { var stores = new Stores(session).Extent(); stores.Filter.AddEquals(M.Store.InternalOrganisation, this.BilledFrom); this.Store = stores.FirstOrDefault(); } if (!this.ExistInvoiceNumber && this.ExistStore) { this.InvoiceNumber = this.Store.NextTemporaryInvoiceNumber(); } if (!this.ExistBilledFromContactMechanism && this.ExistBilledFrom) { this.BilledFromContactMechanism = this.BilledFrom.ExistBillingAddress ? this.BilledFrom.BillingAddress : this.BilledFrom.GeneralCorrespondence; } if (!this.ExistBillToContactMechanism && this.ExistBillToCustomer) { this.BillToContactMechanism = this.BillToCustomer.BillingAddress; } if (!this.ExistBillToEndCustomerContactMechanism && this.ExistBillToEndCustomer) { this.BillToEndCustomerContactMechanism = this.BillToEndCustomer.BillingAddress; } if (!this.ExistShipToEndCustomerAddress && this.ExistShipToEndCustomer) { this.ShipToEndCustomerAddress = this.ShipToEndCustomer.ShippingAddress; } if (!this.ExistShipToAddress && this.ExistShipToCustomer) { this.ShipToAddress = this.ShipToCustomer.ShippingAddress; } if (!this.ExistCurrency && this.ExistBilledFrom) { if (this.ExistBillToCustomer && (this.BillToCustomer.ExistPreferredCurrency || this.BillToCustomer.ExistLocale)) { this.Currency = this.BillToCustomer.ExistPreferredCurrency ? this.BillToCustomer.PreferredCurrency : this.BillToCustomer.Locale.Country.Currency; } else { this.Currency = this.BilledFrom.ExistPreferredCurrency ? this.BilledFrom.PreferredCurrency : session.GetSingleton().DefaultLocale.Country.Currency; } } this.VatRegime = this.VatRegime ?? this.BillToCustomer?.VatRegime; this.IsRepeating = this.ExistRepeatingSalesInvoiceWhereSource; foreach (SalesInvoiceItem salesInvoiceItem in this.SalesInvoiceItems) { foreach (OrderItemBilling orderItemBilling in salesInvoiceItem.OrderItemBillingsWhereInvoiceItem) { if (orderItemBilling.OrderItem is SalesOrderItem salesOrderItem && !this.SalesOrders.Contains(salesOrderItem.SalesOrderWhereSalesOrderItem)) { this.AddSalesOrder(salesOrderItem.SalesOrderWhereSalesOrderItem); } } foreach (WorkEffortBilling workEffortBilling in salesInvoiceItem.WorkEffortBillingsWhereInvoiceItem) { if (!this.WorkEfforts.Contains(workEffortBilling.WorkEffort)) { this.AddWorkEffort(workEffortBilling.WorkEffort); } } foreach (TimeEntryBilling timeEntryBilling in salesInvoiceItem.TimeEntryBillingsWhereInvoiceItem) { if (!this.WorkEfforts.Contains(timeEntryBilling.TimeEntry.WorkEffort)) { this.AddWorkEffort(timeEntryBilling.TimeEntry.WorkEffort); } } } this.IsRepeatingInvoice = this.ExistRepeatingSalesInvoiceWhereSource && (!this.RepeatingSalesInvoiceWhereSource.ExistFinalExecutionDate || this.RepeatingSalesInvoiceWhereSource.FinalExecutionDate.Value.Date >= this.Strategy.Session.Now().Date); this.SalesInvoiceItems = this.SalesInvoiceItems.ToArray(); if (this.ExistBillToCustomer && this.BillToCustomer.ExistLocale) { this.Locale = this.BillToCustomer.Locale; } else { this.Locale = session.GetSingleton().DefaultLocale; } if (this.ExistSalesTerms) { foreach (AgreementTerm term in this.SalesTerms) { if (term.TermType.Equals(new InvoiceTermTypes(session).PaymentNetDays)) { if (int.TryParse(term.TermValue, out var netDays)) { this.PaymentDays = netDays; } } } } else if (this.BillToCustomer?.PaymentNetDays().HasValue == true) { this.PaymentDays = this.BillToCustomer.PaymentNetDays().Value; } else if (this.ExistStore && this.Store.ExistPaymentNetDays) { this.PaymentDays = this.Store.PaymentNetDays; } if (!this.ExistPaymentDays) { this.PaymentDays = 0; } if (this.ExistInvoiceDate) { this.DueDate = this.InvoiceDate.AddDays(this.PaymentNetDays); } var validInvoiceItems = this.SalesInvoiceItems.Where(v => v.IsValid).ToArray(); this.ValidInvoiceItems = validInvoiceItems; var currentPriceComponents = new PriceComponents(this.Strategy.Session).CurrentPriceComponents(this.InvoiceDate); var quantityByProduct = validInvoiceItems .Where(v => v.ExistProduct) .GroupBy(v => v.Product) .ToDictionary(v => v.Key, v => v.Sum(w => w.Quantity)); // First run to calculate price foreach (var salesInvoiceItem in validInvoiceItems) { decimal quantityOrdered = 0; if (salesInvoiceItem.ExistProduct) { quantityByProduct.TryGetValue(salesInvoiceItem.Product, out quantityOrdered); } this.CalculatePrices(derivation, salesInvoiceItem, currentPriceComponents, quantityOrdered, 0); } var totalBasePriceByProduct = validInvoiceItems .Where(v => v.ExistProduct) .GroupBy(v => v.Product) .ToDictionary(v => v.Key, v => v.Sum(w => w.TotalBasePrice)); // Second run to calculate price (because of order value break) foreach (var salesInvoiceItem in validInvoiceItems) { decimal quantityOrdered = 0; decimal totalBasePrice = 0; if (salesInvoiceItem.ExistProduct) { quantityByProduct.TryGetValue(salesInvoiceItem.Product, out quantityOrdered); totalBasePriceByProduct.TryGetValue(salesInvoiceItem.Product, out totalBasePrice); } this.CalculatePrices(derivation, salesInvoiceItem, currentPriceComponents, quantityOrdered, totalBasePrice); } // Calculate Totals if (this.ExistSalesInvoiceItems) { this.TotalBasePrice = 0; this.TotalDiscount = 0; this.TotalSurcharge = 0; this.TotalExVat = 0; this.TotalFee = 0; this.TotalShippingAndHandling = 0; this.TotalVat = 0; this.TotalIncVat = 0; this.TotalListPrice = 0; foreach (var item in validInvoiceItems) { this.TotalBasePrice += item.TotalBasePrice; this.TotalDiscount += item.TotalDiscount; this.TotalSurcharge += item.TotalSurcharge; this.TotalExVat += item.TotalExVat; this.TotalVat += item.TotalVat; this.TotalIncVat += item.TotalIncVat; this.TotalListPrice += item.UnitPrice; } if (this.ExistDiscountAdjustment) { var discount = this.DiscountAdjustment.Percentage.HasValue ? Math.Round(this.TotalExVat * this.DiscountAdjustment.Percentage.Value / 100, 2) : this.DiscountAdjustment.Amount ?? 0; this.TotalDiscount += discount; this.TotalExVat -= discount; if (this.ExistVatRegime) { var vat = Math.Round(discount * this.VatRegime.VatRate.Rate / 100, 2); this.TotalVat -= vat; this.TotalIncVat -= discount + vat; } } if (this.ExistSurchargeAdjustment) { var surcharge = this.SurchargeAdjustment.Percentage.HasValue ? Math.Round(this.TotalExVat * this.SurchargeAdjustment.Percentage.Value / 100, 2) : this.SurchargeAdjustment.Amount ?? 0; this.TotalSurcharge += surcharge; this.TotalExVat += surcharge; if (this.ExistVatRegime) { var vat = Math.Round(surcharge * this.VatRegime.VatRate.Rate / 100, 2); this.TotalVat += vat; this.TotalIncVat += surcharge + vat; } } if (this.ExistFee) { var fee = this.Fee.Percentage.HasValue ? Math.Round(this.TotalExVat * this.Fee.Percentage.Value / 100, 2) : this.Fee.Amount ?? 0; this.TotalFee += fee; this.TotalExVat += fee; if (this.Fee.ExistVatRate) { var vat1 = Math.Round(fee * this.Fee.VatRate.Rate / 100, 2); this.TotalVat += vat1; this.TotalIncVat += fee + vat1; } } if (this.ExistShippingAndHandlingCharge) { var shipping = this.ShippingAndHandlingCharge.Percentage.HasValue ? Math.Round(this.TotalExVat * this.ShippingAndHandlingCharge.Percentage.Value / 100, 2) : this.ShippingAndHandlingCharge.Amount ?? 0; this.TotalShippingAndHandling += shipping; this.TotalExVat += shipping; if (this.ShippingAndHandlingCharge.ExistVatRate) { var vat2 = Math.Round(shipping * this.ShippingAndHandlingCharge.VatRate.Rate / 100, 2); this.TotalVat += vat2; this.TotalIncVat += shipping + vat2; } } //// Only take into account items for which there is data at the item level. //// Skip negative sales. decimal totalUnitBasePrice = 0; decimal totalListPrice = 0; foreach (var item1 in validInvoiceItems) { if (item1.TotalExVat > 0) { totalUnitBasePrice += item1.UnitBasePrice; totalListPrice += item1.UnitPrice; } } } var salesInvoiceItemStates = new SalesInvoiceItemStates(derivation.Session); var salesInvoiceStates = new SalesInvoiceStates(derivation.Session); foreach (var invoiceItem in validInvoiceItems) { if (!invoiceItem.SalesInvoiceItemState.Equals(salesInvoiceItemStates.ReadyForPosting)) { if (invoiceItem.AmountPaid == 0) { invoiceItem.SalesInvoiceItemState = salesInvoiceItemStates.NotPaid; } else if (invoiceItem.ExistAmountPaid && invoiceItem.AmountPaid > 0 && invoiceItem.AmountPaid >= invoiceItem.TotalIncVat) { invoiceItem.SalesInvoiceItemState = salesInvoiceItemStates.Paid; } else { invoiceItem.SalesInvoiceItemState = salesInvoiceItemStates.PartiallyPaid; } } } if (validInvoiceItems.Any() && !this.SalesInvoiceState.Equals(salesInvoiceStates.ReadyForPosting)) { if (this.SalesInvoiceItems.All(v => v.SalesInvoiceItemState.IsPaid)) { this.SalesInvoiceState = salesInvoiceStates.Paid; } else if (this.SalesInvoiceItems.All(v => v.SalesInvoiceItemState.IsNotPaid)) { this.SalesInvoiceState = salesInvoiceStates.NotPaid; } else { this.SalesInvoiceState = salesInvoiceStates.PartiallyPaid; } } this.AmountPaid = this.AdvancePayment; this.AmountPaid += this.PaymentApplicationsWhereInvoice.Sum(v => v.AmountApplied); //// Perhaps payments are recorded at the item level. if (this.AmountPaid == 0) { this.AmountPaid = this.InvoiceItems.Sum(v => v.AmountPaid); } // If receipts are not matched at invoice level if (this.AmountPaid > 0) { if (this.AmountPaid >= this.TotalIncVat) { this.SalesInvoiceState = salesInvoiceStates.Paid; } else { this.SalesInvoiceState = salesInvoiceStates.PartiallyPaid; } foreach (var invoiceItem in validInvoiceItems) { if (!invoiceItem.SalesInvoiceItemState.Equals(salesInvoiceItemStates.CancelledByInvoice) && !invoiceItem.SalesInvoiceItemState.Equals(salesInvoiceItemStates.WrittenOff)) { if (this.AmountPaid >= this.TotalIncVat) { invoiceItem.SalesInvoiceItemState = salesInvoiceItemStates.Paid; } else { invoiceItem.SalesInvoiceItemState = salesInvoiceItemStates.PartiallyPaid; } } } } if (this.ExistVatRegime && this.VatRegime.ExistVatClause) { this.DerivedVatClause = this.VatRegime.VatClause; } else { if (Equals(this.VatRegime, new VatRegimes(session).ServiceB2B)) { this.DerivedVatClause = new VatClauses(session).ServiceB2B; } else if (Equals(this.VatRegime, new VatRegimes(session).IntraCommunautair)) { this.DerivedVatClause = new VatClauses(session).Intracommunautair; } } this.DerivedVatClause = this.ExistAssignedVatClause ? this.AssignedVatClause : this.DerivedVatClause; this.BaseOnDeriveCustomers(derivation); if (this.ExistBillToCustomer && !this.BillToCustomer.BaseIsActiveCustomer(this.BilledFrom, this.InvoiceDate)) { derivation.Validation.AddError(this, M.SalesInvoice.BillToCustomer, ErrorMessages.PartyIsNotACustomer); } if (this.ExistShipToCustomer && !this.ShipToCustomer.BaseIsActiveCustomer(this.BilledFrom, this.InvoiceDate)) { derivation.Validation.AddError(this, M.SalesInvoice.ShipToCustomer, ErrorMessages.PartyIsNotACustomer); } this.PreviousBillToCustomer = this.BillToCustomer; this.PreviousShipToCustomer = this.ShipToCustomer; // this.BaseOnDeriveRevenues(derivation); var singleton = this.Session().GetSingleton(); this.AddSecurityToken(new SecurityTokens(this.Session()).DefaultSecurityToken); this.Sync(this.Session()); this.ResetPrintDocument(); }
private static decimal AppsCatalogPrice( SalesOrder salesOrder, SalesInvoice salesInvoice, Product product, DateTime date) { var productBasePrice = 0M; var productDiscount = 0M; var productSurcharge = 0M; var baseprices = new PriceComponent[0]; if (product.ExistBasePrices) { baseprices = product.BasePrices; } var party = salesOrder != null ? salesOrder.ShipToCustomer : salesInvoice != null ? salesInvoice.BillToCustomer : null; foreach (BasePrice priceComponent in baseprices) { if (priceComponent.FromDate <= date && (!priceComponent.ExistThroughDate || priceComponent.ThroughDate >= date)) { if (PriceComponents.AppsIsEligible(new PriceComponents.IsEligibleParams { PriceComponent = priceComponent, Customer = party, Product = product, SalesOrder = salesOrder, SalesInvoice = salesInvoice, })) { if (priceComponent.ExistPrice) { if (productBasePrice == 0 || priceComponent.Price < productBasePrice) { productBasePrice = priceComponent.Price ?? 0; } } } } } var priceComponents = GetPriceComponents(product, date); var revenueBreakDiscount = 0M; var revenueBreakSurcharge = 0M; foreach (var priceComponent in priceComponents) { if (priceComponent.Strategy.Class.Equals(M.DiscountComponent.ObjectType) || priceComponent.Strategy.Class.Equals(M.SurchargeComponent.ObjectType)) { if (PriceComponents.AppsIsEligible(new PriceComponents.IsEligibleParams { PriceComponent = priceComponent, Customer = party, Product = product, SalesOrder = salesOrder, SalesInvoice = salesInvoice, })) { if (priceComponent.Strategy.Class.Equals(M.DiscountComponent.ObjectType)) { var discountComponent = (DiscountComponent)priceComponent; decimal discount; if (discountComponent.Price.HasValue) { discount = discountComponent.Price.Value; productDiscount += discount; } else { var percentage = discountComponent.Percentage.HasValue ? discountComponent.Percentage.Value : 0; discount = Math.Round((productBasePrice * percentage) / 100, 2); productDiscount += discount; } } if (priceComponent.Strategy.Class.Equals(M.SurchargeComponent.ObjectType)) { var surchargeComponent = (SurchargeComponent)priceComponent; decimal surcharge; if (surchargeComponent.Price.HasValue) { surcharge = surchargeComponent.Price.Value; productSurcharge += surcharge; } else { var percentage = surchargeComponent.Percentage.HasValue ? surchargeComponent.Percentage.Value : 0; surcharge = Math.Round((productBasePrice * percentage) / 100, 2); productSurcharge += surcharge; } } } } } return(productBasePrice - productDiscount + productSurcharge); }