示例#1
0
            /// <summary>
            /// Calculates the tax for the last item.
            /// </summary>
            /// <param name="request">The request.</param>
            /// <returns>The response.</returns>
            private static CalculateTaxServiceResponse CalculateTax(CalculateTaxServiceRequest request)
            {
                ThrowIf.Null(request, "request");

                TaxHelpers.SetSalesTaxGroup(request.RequestContext, request.Transaction);
                SalesTaxOverrideHelper.CalculateTaxOverrides(request.RequestContext, request.Transaction);

                // Consider active (non-void) lines for tax.
                // Need to recalculate tax on return-by-receipt lines because we cannot reconstruct tax lines from return transaction lines alone.
                // A few key information like IsExempt, IsTaxInclusive, TaxCode are not available on return transaction line.
                foreach (var saleItem in request.Transaction.ActiveSalesLines)
                {
                    saleItem.TaxRatePercent = 0;
                    saleItem.TaxLines.Clear();
                }

                var totaler = new SalesTransactionTotaler(request.Transaction);

                totaler.CalculateTotals(request.RequestContext);

                ClearChargeTaxLines(request.Transaction);

                TaxContext taxContext = new TaxContext(request.RequestContext);

                TaxCodeProvider defaultProvider = GetTaxProvider(request.RequestContext, taxContext);

                defaultProvider.CalculateTax(request.RequestContext, request.Transaction);

                return(new CalculateTaxServiceResponse(request.Transaction));
            }
示例#2
0
        /// <summary>
        /// Load all registered TaxCodeProviders
        /// </summary>
        protected void LoadProviders()
        {
            ITaxProvider defaultProvider;

            NetTracer.Information("Tax.LoadProviders(): Functions.CountryRegion: {0}", Functions.CountryRegion);

            //Add default provider
            switch (Functions.CountryRegion)
            {
            case SupportedCountryRegion.IN:
                defaultProvider = new TaxCodeProviderIndia(Application);
                break;

            case SupportedCountryRegion.BR:
                defaultProvider = new TaxCodeProviderBrazil(Application);
                break;

            default:
                defaultProvider = new TaxCodeProvider(Application);
                break;
            }

            //Load providers from config file
            Providers = ProviderLoader.Load(defaultProvider);
        }
示例#3
0
            /// <summary>
            /// Get the tax code provider.
            /// </summary>
            /// <param name="context">The request context.</param>
            /// <param name="taxContext">Tax context.</param>
            /// <returns>The tax code provider.</returns>
            private static TaxCodeProvider GetTaxProvider(RequestContext context, TaxContext taxContext)
            {
                TaxCodeProvider taxCodeProvider;

                switch (context.GetChannelConfiguration().CountryRegionISOCode)
                {
                case CountryRegionISOCode.IN:
                    taxCodeProvider = new TaxCodeProviderIndia(taxContext);
                    break;

                default:
                    taxCodeProvider = new TaxCodeProvider(taxContext);
                    break;
                }

                return(taxCodeProvider);
            }
            /// <summary>
            /// Sorts the specified tax codes by priority.
            /// </summary>
            /// <param name="codes">The tax codes.</param>
            /// <returns>An ordered collection of tax codes.</returns>
            protected override ReadOnlyCollection <TaxCode> SortCodes(Dictionary <string, TaxCode> codes)
            {
                if (codes == null)
                {
                    throw new ArgumentNullException("codes");
                }

                // Return codes to be processed in the following order:
                // Non-India codes
                // India codes ordered by Id
                return(new ReadOnlyCollection <TaxCode>(
                           codes.Values.OrderBy(code =>
                {
                    TaxCodeIndia codeIndia = code as TaxCodeIndia;
                    if (codeIndia != null)
                    {
                        return codeIndia.Formula.Id + MaxPriorityTaxCode + 1;
                    }
                    else
                    {
                        return TaxCodeProvider.TaxCodePriority(code);
                    }
                }).ToList()));
            }
示例#5
0
            /// <summary>
            /// Gets 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 amount is in the store's currency.</param>
            /// <param name="calculateBasePrice">If set to <c>true</c>, calculate the base price.</param>
            /// <returns>The calculation base and The limit base in <see cref="Tuple">Tuple</see>.</returns>
            protected virtual Tuple <decimal, decimal> GetBases(
                ReadOnlyCollection <TaxCode> codes,
                bool taxInStoreCurrency,
                bool calculateBasePrice)
            {
                decimal calculationBase;
                decimal limitBase;
                decimal basePrice = decimal.Zero;

                if (calculateBasePrice)
                {
                    basePrice = this.TaxIncludedInPrice ?
                                TaxCodeProvider.GetBasePriceForTaxIncluded(this.TaxableEntity, codes, this.TaxContext) :
                                this.TaxableEntity.NetAmountPerUnit + GetApplicableDutyTaxes(this.TaxableEntity, codes);
                }

                // 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.Transaction));
                        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.TaxableEntity.Quantity == decimal.Zero) ? decimal.One : this.TaxableEntity.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.TaxableEntity.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.TaxableEntity));
                    }

                    break;

                case TaxBase.AmountByUnit:
                    calculationBase = this.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.TaxableEntity.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 = this.TaxContext.TaxCurrencyOperations.ConvertCurrency(this.TaxContext.ChannelCurrency, this.Currency, limitBase);
                    }

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

                    if (salesLine != null && !string.Equals(this.Unit, this.TaxableEntity.SalesOrderUnitOfMeasure, StringComparison.OrdinalIgnoreCase))
                    {
                        ItemUnitConversion conversion = new ItemUnitConversion
                        {
                            FromUnitOfMeasure = this.TaxableEntity.SalesOrderUnitOfMeasure,
                            ToUnitOfMeasure   = this.Unit,
                            ItemId            = this.TaxableEntity.ItemId
                        };

                        var conversions = new List <ItemUnitConversion>();
                        conversions.Add(conversion);

                        var getUomConvertionDataRequest   = new GetUnitOfMeasureConversionDataRequest(conversions, QueryResultSettings.SingleRecord);
                        UnitOfMeasureConversion converter = this.RequestContext.Runtime
                                                            .Execute <GetUnitOfMeasureConversionDataResponse>(getUomConvertionDataRequest, this.RequestContext).UnitConversions.SingleOrDefault();

                        calculationBase *= converter.GetFactorForQuantity(this.TaxableEntity.Quantity);
                    }
                }
                else
                {
                    // Convert base to Tax currency, if different
                    if (!taxInStoreCurrency)
                    {
                        calculationBase = this.TaxContext.TaxCurrencyOperations.ConvertCurrency(this.TaxContext.ChannelCurrency, this.Currency, calculationBase);
                    }

                    // Base for limits/intervals is same for Calculations
                    limitBase = calculationBase;
                }

                return(new Tuple <decimal, decimal>(calculationBase, limitBase));
            }