예제 #1
0
        /// <summary>
        /// Get the bases for tax calculations
        /// </summary>
        /// <param name="codes">The collection of tax codes.</param>
        /// <param name="taxInStoreCurrency">if set to <c>true</c> [tax in store currency].</param>
        /// <param name="calculateBasePrice">if set to <c>true</c> [Calculate the base price].</param>
        /// <param name="calculationBase">The calculation base.</param>
        /// <param name="limitBase">The limit base.</param>
        protected virtual void GetBases(ReadOnlyCollection <TaxCode> codes,
                                        bool taxInStoreCurrency,
                                        bool calculateBasePrice,
                                        out decimal calculationBase,
                                        out decimal limitBase)
        {
            decimal basePrice = decimal.Zero;

            if (calculateBasePrice)
            {
                basePrice = this.TaxIncludedInPrice ?
                            Provider.GetBasePriceForTaxIncluded(this.LineItem, codes) :
                            LineItem.NetAmountPerUnit;
            }

            //1. Get initial value for the Calculation Base
            switch (this.TaxBase)
            {
            case TaxBase.PercentPerTax:

                // Base is the amount of the other tax
                switch (this.TaxLimitBase)
                {
                case TaxLimitBase.InvoiceWithoutVat:
                case TaxLimitBase.InvoiceWithVat:
                    calculationBase = Math.Abs(this.CalculateTaxOnTax(this.LineItem.RetailTransaction));
                    break;

                case TaxLimitBase.UnitWithoutVat:
                case TaxLimitBase.UnitWithVat:
                    // if this tax's Limit is per-unit, then we need to convert the existing tax amounts from per-line to per-unit
                    decimal quantity = (this.LineItem.Quantity == decimal.Zero) ? decimal.One : this.LineItem.Quantity;
                    calculationBase = Math.Abs(this.CalculateTaxOnTax()) / Math.Abs(quantity);
                    break;

                default:
                    calculationBase = Math.Abs(this.CalculateTaxOnTax());
                    break;
                }
                break;

            case TaxBase.PercentPerGross:

                // Base is the price + other taxes
                calculationBase = basePrice;

                // If the Limit base is NOT per-unit, then we need to factor in the line quanity
                if (TaxLimitBase != TaxLimitBase.UnitWithoutVat && TaxLimitBase != TaxLimitBase.UnitWithVat)
                {
                    calculationBase *= Math.Abs(this.LineItem.Quantity);
                }

                if (!string.IsNullOrEmpty(this.TaxOnTax))
                {
                    // Base is the Price + the amount of a single other tax
                    calculationBase += Math.Abs(this.CalculateTaxOnTax());
                }
                else
                {
                    // Base is the Price + all other taxes
                    calculationBase += Math.Abs(TaxCode.SumAllTaxAmounts(this.LineItem));
                }

                break;

            case TaxBase.AmountByUnit:
                calculationBase = AmountPerUnitCalculationBase;
                break;

            case TaxBase.PercentPerNet:
            case TaxBase.PercentGrossOnNet:
            default:

                // Base is the Price
                calculationBase = basePrice;

                // If the Limit base is NOT per-unit, then we need to factor in the line quanity
                if (TaxLimitBase != TaxLimitBase.UnitWithoutVat && TaxLimitBase != TaxLimitBase.UnitWithVat)
                {
                    calculationBase *= Math.Abs(this.LineItem.Quantity);
                }

                break;
            }

            //3. Set Limit Base
            if (this.TaxBase == TaxBase.AmountByUnit)
            {
                // Base for limits/intervals is base-quantity * price
                limitBase = calculationBase * basePrice;

                // Convert limit base to Tax currency, if different
                if (!taxInStoreCurrency)
                {
                    limitBase = TaxService.Tax.InternalApplication.Services.Currency.CurrencyToCurrency(
                        ApplicationSettings.Terminal.StoreCurrency,
                        this.Currency,
                        limitBase);
                }

                // If the tax is calculated in a different UOM, then convert if possible
                // this is only applicable for lineItem taxes.
                BaseSaleItem saleLineItem = this.LineItem as BaseSaleItem;

                if (saleLineItem != null &&
                    !string.Equals(this.Unit, this.LineItem.SalesOrderUnitOfMeasure, StringComparison.OrdinalIgnoreCase))
                {
                    UnitOfMeasureData uomData = new UnitOfMeasureData(
                        ApplicationSettings.Database.LocalConnection,
                        ApplicationSettings.Database.DATAAREAID,
                        ApplicationSettings.Terminal.StorePrimaryId,
                        TaxService.Tax.InternalApplication);
                    UnitQtyConversion uomConversion = uomData.GetUOMFactor(this.LineItem.SalesOrderUnitOfMeasure, this.Unit, saleLineItem);
                    calculationBase *= uomConversion.GetFactorForQty(this.LineItem.Quantity);
                }
            }
            else
            {
                // Convert base to Tax currency, if different
                if (!taxInStoreCurrency)
                {
                    calculationBase = TaxService.Tax.InternalApplication.Services.Currency.CurrencyToCurrency(
                        ApplicationSettings.Terminal.StoreCurrency,
                        this.Currency,
                        calculationBase);
                }

                // Base for limits/intervals is same for Calculations
                limitBase = calculationBase;
            }
        }
예제 #2
0
        /// <summary>
        /// Calculate the tax bases calculationBase and limitBase (which is zero for India).
        /// </summary>
        /// <param name="basePrice">The base price.</param>
        /// <param name="taxInStoreCurrency">if set to <c>true</c> [tax in store currency].</param>
        /// <param name="calculateBasePrice">if set to <c>true</c> [Calculate the base price].</param>
        /// <param name="calculationBase">The calculation base.</param>
        /// <param name="limitBase">The limit base.</param>
        protected override void GetBases(ReadOnlyCollection <TaxCode> codes, bool taxInStoreCurrency, bool calculateBasePrice, out decimal calculationBase, out decimal limitBase)
        {
            limitBase = decimal.Zero;

            // For amount by unit calculation base is just the quantity.
            if (this.TaxBase == TaxBase.AmountByUnit)
            {
                calculationBase = LineItem.Quantity;

                // If the tax is calculated in a different UOM, then convert if possible
                // this is only applicable for lineItem taxes.
                BaseSaleItem saleLineItem = this.LineItem as BaseSaleItem;

                if (saleLineItem != null &&
                    !string.Equals(this.Unit, this.LineItem.SalesOrderUnitOfMeasure, StringComparison.OrdinalIgnoreCase))
                {
                    UnitOfMeasureData uomData = new UnitOfMeasureData(
                        ApplicationSettings.Database.LocalConnection,
                        ApplicationSettings.Database.DATAAREAID,
                        ApplicationSettings.Terminal.StorePrimaryId,
                        TaxService.Tax.InternalApplication);
                    UnitQtyConversion uomConversion = uomData.GetUOMFactor(this.LineItem.SalesOrderUnitOfMeasure, this.Unit, saleLineItem);
                    calculationBase *= uomConversion.GetFactorForQty(this.LineItem.Quantity);
                }
                return;
            }

            // Determine the starting calculation base (includes the line price or not)
            switch (Formula.TaxableBasis)
            {
            case TaxableBases.LineAmount:
                calculationBase = this.LineItem.NetAmountWithAllInclusiveTaxPerUnit;
                break;

            case TaxableBases.MRP:
                calculationBase = GetMRP();
                break;

            default:
                calculationBase = decimal.Zero;
                break;
            }

            if (this.TaxIncludedInPrice)
            {
                calculationBase = GetBasePriceForTaxIncluded(calculationBase, codes, Formula);
            }

            calculationBase *= Math.Abs(this.LineItem.Quantity);

            // Calculation expression is of the form: +[BCD]+[CVD]+[E-CESS_CVD]+[PE-C_CVD]+[SHE-C_CVD]
            // where the brackets are replaced with the delimiter char(164)
            // and BCD, CVD ... are tax codes.
            // The operator may be + - / *.
            string[] tokens = Formula.ParseExpression();

            for (int index = 1; index < tokens.Length; index += 2)
            {
                ITaxItem taxItem = (from line in this.LineItem.TaxLines
                                    where line.TaxCode == tokens[index]
                                    select line).FirstOrDefault();

                if (taxItem != null)
                {
                    this.IsTaxOnTax = true;
                    this.TaxCodesInFormula.Add(taxItem.TaxCode);
                }

                decimal amount = taxItem == null ? decimal.Zero : taxItem.Amount * Math.Sign(this.LineItem.Quantity);

                switch (tokens[index - 1])
                {
                case "+":
                    calculationBase += amount;
                    break;

                case "-":
                    calculationBase -= amount;
                    break;

                case "*":
                    calculationBase *= amount;
                    break;

                case "/":
                    calculationBase = (amount == decimal.Zero ? calculationBase : calculationBase /= amount);
                    break;

                default:
                    NetTracer.Error("GetBases(): Invalid operator in formula. tokens[{0}]: {1}", index - 1, tokens[index - 1]);
                    System.Diagnostics.Debug.Fail("Invalid operator in formula");
                    break;
                }
            }

            // Knock any abatement off of the taxable basis
            calculationBase *= (100 - AbatementPercent) / 100;
        }