Example #1
0
        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();
        }
Example #2
0
        public void BaseOnDeriveInvoiceTotals()
        {
            this.TotalBasePrice   = 0;
            this.TotalDiscount    = 0;
            this.TotalSurcharge   = 0;
            this.TotalVat         = 0;
            this.TotalExVat       = 0;
            this.TotalIncVat      = 0;
            this.TotalIrpf        = 0;
            this.TotalExtraCharge = 0;
            this.GrandTotal       = 0;

            foreach (PurchaseInvoiceItem item in this.PurchaseInvoiceItems)
            {
                this.TotalBasePrice += item.TotalBasePrice;
                this.TotalSurcharge += item.TotalSurcharge;
                this.TotalIrpf      += item.TotalIrpf;
                this.TotalVat       += item.TotalVat;
                this.TotalExVat     += item.TotalExVat;
                this.TotalIncVat    += item.TotalIncVat;
                this.GrandTotal     += item.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;

            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.ExistInvoiceDate && this.ExistDerivedCurrency && this.ExistBilledTo)
            {
                this.TotalBasePriceInPreferredCurrency           = Rounder.RoundDecimal(Currencies.ConvertCurrency(this.TotalBasePrice, this.InvoiceDate, this.DerivedCurrency, this.BilledTo.PreferredCurrency), 2);
                this.TotalDiscountInPreferredCurrency            = Rounder.RoundDecimal(Currencies.ConvertCurrency(this.TotalDiscount, this.InvoiceDate, this.DerivedCurrency, this.BilledTo.PreferredCurrency), 2);
                this.TotalSurchargeInPreferredCurrency           = Rounder.RoundDecimal(Currencies.ConvertCurrency(this.TotalSurcharge, this.InvoiceDate, this.DerivedCurrency, this.BilledTo.PreferredCurrency), 2);
                this.TotalExtraChargeInPreferredCurrency         = Rounder.RoundDecimal(Currencies.ConvertCurrency(totalExtraCharge, this.InvoiceDate, this.DerivedCurrency, this.BilledTo.PreferredCurrency), 2);
                this.TotalFeeInPreferredCurrency                 = Rounder.RoundDecimal(Currencies.ConvertCurrency(this.TotalFee, this.InvoiceDate, this.DerivedCurrency, this.BilledTo.PreferredCurrency), 2);
                this.TotalShippingAndHandlingInPreferredCurrency = Rounder.RoundDecimal(Currencies.ConvertCurrency(this.TotalShippingAndHandling, this.InvoiceDate, this.DerivedCurrency, this.BilledTo.PreferredCurrency), 2);
                this.TotalExVatInPreferredCurrency               = Rounder.RoundDecimal(Currencies.ConvertCurrency(totalExVat, this.InvoiceDate, this.DerivedCurrency, this.BilledTo.PreferredCurrency), 2);
                this.TotalVatInPreferredCurrency                 = Rounder.RoundDecimal(Currencies.ConvertCurrency(totalVat, this.InvoiceDate, this.DerivedCurrency, this.BilledTo.PreferredCurrency), 2);
                this.TotalIncVatInPreferredCurrency              = Rounder.RoundDecimal(Currencies.ConvertCurrency(totalIncVat, this.InvoiceDate, this.DerivedCurrency, this.BilledTo.PreferredCurrency), 2);
                this.TotalIrpfInPreferredCurrency                = Rounder.RoundDecimal(Currencies.ConvertCurrency(totalIrpf, this.InvoiceDate, this.DerivedCurrency, this.BilledTo.PreferredCurrency), 2);
                this.GrandTotalInPreferredCurrency               = Rounder.RoundDecimal(Currencies.ConvertCurrency(grandTotal, this.InvoiceDate, this.DerivedCurrency, this.BilledTo.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);
        }
Example #3
0
        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);
        }
Example #4
0
        public void BaseOnDerive(ObjectOnDerive method)
        {
            var derivation = method.Derivation;

            if (!this.ExistOrderNumber)
            {
                var year = this.OrderDate.Year;
                this.OrderNumber = this.OrderedBy.NextPurchaseOrderNumber(year);

                var fiscalYearInternalOrganisationSequenceNumbers = this.OrderedBy?.FiscalYearsInternalOrganisationSequenceNumbers.FirstOrDefault(v => v.FiscalYear == year);
                var prefix = this.OrderedBy.InvoiceSequence.IsEnforcedSequence ? this.OrderedBy?.PurchaseOrderNumberPrefix : fiscalYearInternalOrganisationSequenceNumbers.PurchaseOrderNumberPrefix;
                this.SortableOrderNumber = this.Session().GetSingleton().SortableNumber(prefix, this.OrderNumber, year.ToString());
            }

            if (this.TakenViaSupplier is Organisation supplier)
            {
                if (!this.OrderedBy.ActiveSuppliers.Contains(supplier))
                {
                    derivation.Validation.AddError(this, this.Meta.TakenViaSupplier, ErrorMessages.PartyIsNotASupplier);
                }
            }

            if (this.TakenViaSubcontractor is Organisation subcontractor)
            {
                if (!this.OrderedBy.ActiveSubContractors.Contains(subcontractor))
                {
                    derivation.Validation.AddError(this, this.Meta.TakenViaSubcontractor, ErrorMessages.PartyIsNotASubcontractor);
                }
            }

            if (this.PurchaseOrderState.IsCreated)
            {
                this.DerivedLocale                   = this.Locale ?? this.OrderedBy?.Locale;
                this.DerivedCurrency                 = this.AssignedCurrency ?? this.OrderedBy?.PreferredCurrency;
                this.DerivedVatRegime                = this.AssignedVatRegime;
                this.DerivedIrpfRegime               = this.AssignedIrpfRegime;
                this.DerivedShipToAddress            = this.AssignedShipToAddress ?? this.OrderedBy?.ShippingAddress;
                this.DerivedBillToContactMechanism   = this.AssignedBillToContactMechanism ?? this.OrderedBy?.BillingAddress ?? this.OrderedBy?.GeneralCorrespondence;
                this.DerivedTakenViaContactMechanism = this.AssignedTakenViaContactMechanism ?? this.TakenViaSupplier?.OrderAddress;
            }

            derivation.Validation.AssertExistsAtMostOne(this, this.Meta.TakenViaSupplier, this.Meta.TakenViaSubcontractor);
            derivation.Validation.AssertAtLeastOne(this, this.Meta.TakenViaSupplier, this.Meta.TakenViaSubcontractor);

            if (this.ExistOrderDate &&
                this.ExistOrderedBy &&
                this.DerivedCurrency != this.OrderedBy.PreferredCurrency)
            {
                var exchangeRate = this.DerivedCurrency.ExchangeRatesWhereFromCurrency.Where(v => v.ValidFrom.Date <= this.OrderDate.Date && v.ToCurrency.Equals(this.OrderedBy.PreferredCurrency)).OrderByDescending(v => v.ValidFrom).FirstOrDefault();

                if (exchangeRate == null)
                {
                    exchangeRate = this.OrderedBy.PreferredCurrency.ExchangeRatesWhereFromCurrency.Where(v => v.ValidFrom.Date <= this.OrderDate.Date && v.ToCurrency.Equals(this.DerivedCurrency)).OrderByDescending(v => v.ValidFrom).FirstOrDefault();
                }

                if (exchangeRate == null)
                {
                    derivation.Validation.AddError(this, M.Quote.AssignedCurrency, ErrorMessages.CurrencyNotAllowed);
                }
            }

            var validOrderItems = this.PurchaseOrderItems.Where(v => v.IsValid).ToArray();

            this.ValidOrderItems = validOrderItems;

            var purchaseOrderShipmentStates = new PurchaseOrderShipmentStates(this.Strategy.Session);
            var purchaseOrderPaymentStates  = new PurchaseOrderPaymentStates(this.Strategy.Session);
            var purchaseOrderItemStates     = new PurchaseOrderItemStates(derivation.Session);

            // PurchaseOrder Shipment State
            if (validOrderItems.Any())
            {
                if (validOrderItems.Any(v => v.IsReceivable))
                {
                    if (validOrderItems.Where(v => v.IsReceivable).All(v => v.PurchaseOrderItemShipmentState.IsReceived))
                    {
                        this.PurchaseOrderShipmentState = purchaseOrderShipmentStates.Received;
                    }
                    else if (validOrderItems.Where(v => v.IsReceivable).All(v => v.PurchaseOrderItemShipmentState.IsNotReceived))
                    {
                        this.PurchaseOrderShipmentState = purchaseOrderShipmentStates.NotReceived;
                    }
                    else
                    {
                        this.PurchaseOrderShipmentState = purchaseOrderShipmentStates.PartiallyReceived;
                    }
                }
                else
                {
                    this.PurchaseOrderShipmentState = purchaseOrderShipmentStates.Na;
                }

                // PurchaseOrder Payment State
                if (validOrderItems.All(v => v.PurchaseOrderItemPaymentState.IsPaid))
                {
                    this.PurchaseOrderPaymentState = purchaseOrderPaymentStates.Paid;
                }
                else if (validOrderItems.All(v => v.PurchaseOrderItemPaymentState.IsNotPaid))
                {
                    this.PurchaseOrderPaymentState = purchaseOrderPaymentStates.NotPaid;
                }
                else
                {
                    this.PurchaseOrderPaymentState = purchaseOrderPaymentStates.PartiallyPaid;
                }

                // PurchaseOrder OrderState
                if (this.PurchaseOrderState.IsSent &&
                    (this.PurchaseOrderShipmentState.IsReceived || this.PurchaseOrderShipmentState.IsNa))
                {
                    this.PurchaseOrderState = new PurchaseOrderStates(this.Strategy.Session).Completed;
                }

                if (this.PurchaseOrderState.IsCompleted && this.PurchaseOrderPaymentState.IsPaid)
                {
                    this.PurchaseOrderState = new PurchaseOrderStates(this.Strategy.Session).Finished;
                }
            }

            // Derive Totals
            var quantityOrderedByPart = new Dictionary <Part, decimal>();
            var totalBasePriceByPart  = new Dictionary <Part, decimal>();

            foreach (PurchaseOrderItem item in this.ValidOrderItems)
            {
                if (item.ExistPart)
                {
                    if (!quantityOrderedByPart.ContainsKey(item.Part))
                    {
                        quantityOrderedByPart.Add(item.Part, item.QuantityOrdered);
                        totalBasePriceByPart.Add(item.Part, item.TotalBasePrice);
                    }
                    else
                    {
                        quantityOrderedByPart[item.Part] += item.QuantityOrdered;
                        totalBasePriceByPart[item.Part]  += item.TotalBasePrice;
                    }
                }
            }

            this.TotalBasePrice   = 0;
            this.TotalDiscount    = 0;
            this.TotalSurcharge   = 0;
            this.TotalVat         = 0;
            this.TotalIrpf        = 0;
            this.TotalExVat       = 0;
            this.TotalExtraCharge = 0;
            this.TotalIncVat      = 0;
            this.GrandTotal       = 0;
            this.TotalShippingAndHandlingInPreferredCurrency = 0;
            this.TotalFeeInPreferredCurrency         = 0;
            this.TotalExtraChargeInPreferredCurrency = 0;
            this.TotalListPriceInPreferredCurrency   = 0;

            foreach (PurchaseOrderItem orderItem in this.ValidOrderItems)
            {
                this.TotalBasePrice += orderItem.TotalBasePrice;
                this.TotalDiscount  += orderItem.TotalDiscount;
                this.TotalSurcharge += orderItem.TotalSurcharge;
                this.TotalVat       += orderItem.TotalVat;
                this.TotalIrpf      += orderItem.TotalIrpf;
                this.TotalExVat     += orderItem.TotalExVat;
                this.TotalIncVat    += orderItem.TotalIncVat;
                this.GrandTotal     += orderItem.GrandTotal;
            }

            if (this.ExistOrderDate && this.ExistDerivedCurrency && this.ExistOrderedBy)
            {
                this.TotalBasePriceInPreferredCurrency = Rounder.RoundDecimal(Currencies.ConvertCurrency(this.TotalBasePrice, this.OrderDate, this.DerivedCurrency, this.OrderedBy.PreferredCurrency), 2);
                this.TotalDiscountInPreferredCurrency  = Rounder.RoundDecimal(Currencies.ConvertCurrency(this.TotalDiscount, this.OrderDate, this.DerivedCurrency, this.OrderedBy.PreferredCurrency), 2);
                this.TotalSurchargeInPreferredCurrency = Rounder.RoundDecimal(Currencies.ConvertCurrency(this.TotalSurcharge, this.OrderDate, this.DerivedCurrency, this.OrderedBy.PreferredCurrency), 2);
                this.TotalExVatInPreferredCurrency     = Rounder.RoundDecimal(Currencies.ConvertCurrency(this.TotalExVat, this.OrderDate, this.DerivedCurrency, this.OrderedBy.PreferredCurrency), 2);
                this.TotalVatInPreferredCurrency       = Rounder.RoundDecimal(Currencies.ConvertCurrency(this.TotalVat, this.OrderDate, this.DerivedCurrency, this.OrderedBy.PreferredCurrency), 2);
                this.TotalIncVatInPreferredCurrency    = Rounder.RoundDecimal(Currencies.ConvertCurrency(this.TotalIncVat, this.OrderDate, this.DerivedCurrency, this.OrderedBy.PreferredCurrency), 2);
                this.TotalIrpfInPreferredCurrency      = Rounder.RoundDecimal(Currencies.ConvertCurrency(this.TotalIrpf, this.OrderDate, this.DerivedCurrency, this.OrderedBy.PreferredCurrency), 2);
                this.GrandTotalInPreferredCurrency     = Rounder.RoundDecimal(Currencies.ConvertCurrency(this.GrandTotal, this.OrderDate, this.DerivedCurrency, this.OrderedBy.PreferredCurrency), 2);
            }

            this.TotalBasePrice = Rounder.RoundDecimal(this.TotalBasePrice, 2);
            this.TotalDiscount  = Rounder.RoundDecimal(this.TotalDiscount, 2);
            this.TotalSurcharge = Rounder.RoundDecimal(this.TotalSurcharge, 2);
            this.TotalVat       = Rounder.RoundDecimal(this.TotalVat, 2);
            this.TotalIrpf      = Rounder.RoundDecimal(this.TotalIrpf, 2);
            this.TotalExVat     = Rounder.RoundDecimal(this.TotalExVat, 2);
            this.TotalIncVat    = Rounder.RoundDecimal(this.TotalIncVat, 2);
            this.GrandTotal     = Rounder.RoundDecimal(this.GrandTotal, 2);

            this.PreviousTakenViaSupplier = this.TakenViaSupplier;

            // Derive Workflow
            this.WorkItemDescription = $"PurchaseOrder: {this.OrderNumber} [{this.TakenViaSupplier?.PartyName}]";
            var openTasks = this.TasksWhereWorkItem.Where(v => !v.ExistDateClosed).ToArray();

            if (this.PurchaseOrderState.IsAwaitingApprovalLevel1)
            {
                if (!openTasks.OfType <PurchaseOrderApprovalLevel1>().Any())
                {
                    new PurchaseOrderApprovalLevel1Builder(this.Session()).WithPurchaseOrder(this).Build();
                }
            }

            if (this.PurchaseOrderState.IsAwaitingApprovalLevel2)
            {
                if (!openTasks.OfType <PurchaseOrderApprovalLevel2>().Any())
                {
                    new PurchaseOrderApprovalLevel2Builder(this.Session()).WithPurchaseOrder(this).Build();
                }
            }

            this.Sync(derivation, validOrderItems);

            this.ResetPrintDocument();
        }