/// <summary>
            /// Get struct PriceResult from active trade agreement.
            /// Struct PriceResult contains India MaxRetailPrice. Currently there is a field �Max. retail price� in the form price/discount agreement journal
            /// (Navigation path: Main Menu > Sales and marketing > Journal > price/discount agreement journal).
            /// The field will be visible only when the logged on company is an India company. And it is optional.
            /// User can use this field to specify different MRP values on different sites and warehouses for the same item. And when the trade agreement applies to a transaction,
            /// the MRP value should flow to the MRP field of the transaction as the default value.
            /// So current change is when fetching the superset of trade agreements which could apply to all of these items and customer for the given date,
            /// also takes field MAXIMUMRETAILPRICE_IN through the stored procedures GETALLDISCOUNTTRADEAGREEMENTS/ GETALLTRADEAGREEMENTS/ GETTRADEAGREEMENTS.
            /// Then return the whole struct PriceResult  rather than PriceResult.Price.
            /// </summary>
            /// <param name="tradeAgreementRules">The trade agreement rules.</param>
            /// <param name="priceParameters">The price parameters.</param>
            /// <param name="currencyCode">The currency code.</param>
            /// <param name="itemId">The item Id.</param>
            /// <param name="defaultSalesUnit">The default sales unit.</param>
            /// <param name="salesUnit">The sales unit.</param>
            /// <param name="variantLine">The variant line.</param>
            /// <param name="unitOfMeasureConversion">The UnitOfMeasure Conversion.</param>
            /// <param name="quantity">The quantity.</param>
            /// <param name="customerId">The customer Id.</param>
            /// <param name="customerPriceGroup">The customer price group.</param>
            /// <param name="channelPriceGroupIds">The channel price group Ids.</param>
            /// <param name="salesLines">Optional sales lines.</param>
            /// <param name="priceContext">Price context.</param>
            /// <param name="activeDate">The active date.</param>
            /// <returns>The PriceResult of active trade agreement.</returns>
            internal static PriceResult GetPriceResultOfActiveTradeAgreement(
                IDictionary <string, IList <TradeAgreement> > tradeAgreementRules,
                DiscountParameters priceParameters,
                string currencyCode,
                string itemId,
                string defaultSalesUnit,
                string salesUnit,
                ProductVariant variantLine,
                UnitOfMeasureConversion unitOfMeasureConversion,
                decimal quantity,
                string customerId,
                string customerPriceGroup,
                IEnumerable <string> channelPriceGroupIds,
                IEnumerable <SalesLine> salesLines,
                PriceContext priceContext,
                DateTimeOffset activeDate)
            {
                PriceResult result;

                variantLine = variantLine ?? new ProductVariant();

                // Get basic arguments for Price evaluation
                RetailPriceArgs args = new RetailPriceArgs()
                {
                    Barcode      = string.Empty,
                    CurrencyCode = currencyCode,
                    CustomerId   = customerId,
                    Dimensions   = variantLine,
                    DefaultSalesUnitOfMeasure = defaultSalesUnit,
                    ItemId                  = itemId,
                    PriceGroups             = channelPriceGroupIds.AsReadOnly(),
                    Quantity                = quantity,
                    SalesUOM                = salesUnit,
                    UnitOfMeasureConversion = unitOfMeasureConversion,
                };

                // Get the active retail price - checks following prices brackets in order: Customer TAs, Store price group TAs, 'All' TAs.
                // First bracket to return a price 'wins'. Each bracket returns the lowest price it can find.
                result = FindPriceAgreement(tradeAgreementRules, priceParameters, args, salesLines, priceContext, activeDate);

                // Direct customer TA price would have been caught above.
                // Compare against customer price group TAs now and override if lower than previously found price (or if previously found price was 0).
                if (!string.IsNullOrEmpty(customerId) &&
                    !string.IsNullOrEmpty(customerPriceGroup) &&
                    !channelPriceGroupIds.Contains(customerPriceGroup))
                {
                    // Customer price group
                    args.PriceGroups = new ReadOnlyCollection <string>(new[] { customerPriceGroup });
                    PriceResult customerResult = FindPriceAgreement(tradeAgreementRules, priceParameters, args, salesLines, priceContext, activeDate);

                    // Pick the Customer price if either the Retail price is ZERO, or the Customer Price is non-zero AND lower
                    if ((result.Price == decimal.Zero) ||
                        ((customerResult.Price > decimal.Zero) && (customerResult.Price <= result.Price)))
                    {
                        result = customerResult;
                    }
                }

                return(result);
            }
        public static UnitOfMeasureConversion CreateUnitOfMeasureConversion(string fromUnitSymbol,
                                                                            string toUnitSymbol,
                                                                            decimal innerOffset,
                                                                            decimal outerOffset,
                                                                            int numerator,
                                                                            decimal factor,
                                                                            int denominator,
                                                                            global::Microsoft.Dynamics.DataEntities.UnitOfMeasure fromUnitOfMeasure,
                                                                            global::Microsoft.Dynamics.DataEntities.UnitOfMeasure toUnitOfMeasure)
        {
            UnitOfMeasureConversion unitOfMeasureConversion = new UnitOfMeasureConversion();

            unitOfMeasureConversion.FromUnitSymbol = fromUnitSymbol;
            unitOfMeasureConversion.ToUnitSymbol   = toUnitSymbol;
            unitOfMeasureConversion.InnerOffset    = innerOffset;
            unitOfMeasureConversion.OuterOffset    = outerOffset;
            unitOfMeasureConversion.Numerator      = numerator;
            unitOfMeasureConversion.Factor         = factor;
            unitOfMeasureConversion.Denominator    = denominator;
            if ((fromUnitOfMeasure == null))
            {
                throw new global::System.ArgumentNullException("fromUnitOfMeasure");
            }
            unitOfMeasureConversion.FromUnitOfMeasure = fromUnitOfMeasure;
            if ((toUnitOfMeasure == null))
            {
                throw new global::System.ArgumentNullException("toUnitOfMeasure");
            }
            unitOfMeasureConversion.ToUnitOfMeasure = toUnitOfMeasure;
            return(unitOfMeasureConversion);
        }
Exemplo n.º 3
0
            private static SalesLine ConstructSalesLine(string itemId, string lineId = "1")
            {
                SalesLine salesLine = new SalesLine();

                salesLine.OriginalSalesOrderUnitOfMeasure = "ea";
                salesLine.SalesOrderUnitOfMeasure         = "ea";
                salesLine.ItemId   = itemId;
                salesLine.Quantity = 1;
                salesLine.UnitOfMeasureConversion = UnitOfMeasureConversion.CreateDefaultUnitOfMeasureConversion();
                salesLine.LineId = lineId;
                return(salesLine);
            }
Exemplo n.º 4
0
        public static UnitOfMeasureConversion CreateUnitOfMeasureConversion(string fromUnitSymbol,
                                                                            string toUnitSymbol,
                                                                            decimal innerOffset,
                                                                            decimal outerOffset,
                                                                            int numerator,
                                                                            decimal factor,
                                                                            int denominator)
        {
            UnitOfMeasureConversion unitOfMeasureConversion = new UnitOfMeasureConversion();

            unitOfMeasureConversion.FromUnitSymbol = fromUnitSymbol;
            unitOfMeasureConversion.ToUnitSymbol   = toUnitSymbol;
            unitOfMeasureConversion.InnerOffset    = innerOffset;
            unitOfMeasureConversion.OuterOffset    = outerOffset;
            unitOfMeasureConversion.Numerator      = numerator;
            unitOfMeasureConversion.Factor         = factor;
            unitOfMeasureConversion.Denominator    = denominator;
            return(unitOfMeasureConversion);
        }
            private static Tuple <decimal, string> GetActiveTradeAgreementPriceAndGroup(
                IDictionary <string, IList <TradeAgreement> > tradeAgreementRules,
                DiscountParameters priceParameters,
                string currencyCode,
                string itemId,
                string defaultSalesUnit,
                string salesUnit,
                ProductVariant variantLine,
                UnitOfMeasureConversion unitOfMeasureConversion,
                decimal quantity,
                string customerId,
                string customerPriceGroup,
                IEnumerable <string> channelPriceGroupIds,
                IEnumerable <SalesLine> salesLines,
                PriceContext priceContext,
                DateTimeOffset activeDate)
            {
                PriceResult result = GetPriceResultOfActiveTradeAgreement(
                    tradeAgreementRules,
                    priceParameters,
                    currencyCode,
                    itemId,
                    defaultSalesUnit,
                    salesUnit,
                    variantLine,
                    unitOfMeasureConversion,
                    quantity,
                    customerId,
                    customerPriceGroup,
                    channelPriceGroupIds,
                    salesLines,
                    priceContext,
                    activeDate);

                return(new Tuple <decimal, string>(result.Price, result.CustPriceGroup));
            }
 private UoMConversionDto Map(UnitOfMeasureConversion entity)
 {
     return(Mapper.Map <UnitOfMeasureConversion, UoMConversionDto>(entity));
 }
Exemplo n.º 7
0
            /// <summary>
            /// Calculate the tax bases calculationBase and limitBase (which is zero for India).
            /// </summary>
            /// <param name="codes">The 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>
            /// <returns>The calculation base as Item1 and The limit base as Item2 in Tuple.</returns>
            protected override Tuple <decimal, decimal> GetBases(ReadOnlyCollection <TaxCode> codes, bool taxInStoreCurrency, bool calculateBasePrice)
            {
                const decimal LimitBase = decimal.Zero;
                decimal       calculationBase;

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

                    // 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);
                    }

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

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

                case TaxableBasisIndia.MaxRetailPrice:
                    calculationBase = this.GetItemMaxRetailPrice();
                    break;

                default:
                    calculationBase = decimal.Zero;
                    break;
                }

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

                calculationBase *= Math.Abs(this.TaxableEntity.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 = this.Formula.ParseExpression();

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

                    if (taxLine != null)
                    {
                        this.IsTaxOnTax = true;
                        if (!this.taxCodesInFormula.Contains(taxLine.TaxCode))
                        {
                            this.taxCodesInFormula.Add(taxLine.TaxCode);
                        }
                    }

                    decimal amount      = taxLine == null ? decimal.Zero : taxLine.Amount * Math.Sign(this.TaxableEntity.Quantity);
                    int     tokenNumber = index - 1;

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

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

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

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

                    default:
                        RetailLogger.Log.CrtServicesTaxCodeIndiaTaxServiceInvalidOperatorFoundInBaseCalculation(tokens[tokenNumber]);
                        break;
                    }
                }

                // Knock any abatement off of the taxable basis
                calculationBase *= (100 - this.AbatementPercent) / 100;
                return(new Tuple <decimal, decimal>(calculationBase, LimitBase));
            }
Exemplo n.º 8
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));
            }