/// <summary> /// Executes the workflow to retrieve an item. /// </summary> /// <param name="request">The request.</param> /// <returns>The response.</returns> protected override GetItemByIdResponse Process(GetItemByIdRequest request) { ThrowIf.Null(request, "request"); List <Item> items = new List <Item>(); if (request.ItemIds.Any()) { var getItemsRequest = new GetItemsDataRequest(request.ItemIds) { QueryResultSettings = new QueryResultSettings(request.ColumnSet, PagingInfo.AllRecords) }; var getItemsResponse = request.RequestContext.Runtime.Execute <GetItemsDataResponse>(getItemsRequest, request.RequestContext); items.AddRange(getItemsResponse.Items); } if (request.ProductIds.Any()) { GetItemsDataRequest dataRequest = new GetItemsDataRequest(request.ProductIds) { QueryResultSettings = request.QueryResultSettings }; GetItemsDataResponse dataResponse = this.Context.Runtime.Execute <GetItemsDataResponse>(dataRequest, this.Context); items.AddRange(dataResponse.Items); } var response = new GetItemByIdResponse(items.AsPagedResult()); return(response); }
/// <summary> /// Calculates the price charges. /// </summary> /// <param name="salesLine">The sales line.</param> /// <param name="request">The request.</param> /// <returns> /// The miscellaneous charge line. /// </returns> private static Microsoft.Dynamics.Commerce.Runtime.DataModel.ChargeLine CalculatePriceCharges(SalesLine salesLine, GetChargesServiceRequest request) { // hook up with caching when it is in. var getItemsRequest = new GetItemsDataRequest(new string[] { salesLine.ItemId }); getItemsRequest.QueryResultSettings = new QueryResultSettings(new ColumnSet("ItemId", "AllocateMarkup", "PriceQty", "Markup"), PagingInfo.AllRecords); var getItemsResponse = request.RequestContext.Execute <GetItemsDataResponse>(getItemsRequest); Item itemDetails = getItemsResponse.Items.SingleOrDefault(); if (itemDetails != null && itemDetails.Markup != 0) { // there is a price charge associated with the item. decimal amount; // check type price charge if (itemDetails.AllocateMarkup) { // Per Unit markup if (!itemDetails.PriceQuantity.HasValue || itemDetails.PriceQuantity.Value == 0M) { throw new DataValidationException( DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_ValueOutOfRange, string.Format("Price quantity is set to 0 for item {0}", itemDetails.ItemId)); } amount = itemDetails.Markup / itemDetails.PriceQuantity.Value; } else { // per line markup amount = itemDetails.Markup; } // there is a price charge associated with this item. need to update the price accordingly. var priceCharge = new Microsoft.Dynamics.Commerce.Runtime.DataModel.ChargeLine { CalculatedAmount = amount, ChargeCode = string.Empty, ItemTaxGroupId = salesLine.ItemTaxGroupId, SalesTaxGroupId = salesLine.SalesTaxGroupId, ChargeType = ChargeType.PriceCharge, ModuleType = ChargeModule.Sales, }; return(priceCharge); } return(null); }
/// <summary> /// Retrieves the item data for the items in the cart. /// </summary> /// <param name="context">The request context.</param> /// <param name="salesLines">The sales lines for which to retrieve item information.</param> /// <returns>The cart items.</returns> private static IEnumerable <Item> GetItemsForSalesLines(RequestContext context, IEnumerable <SalesLine> salesLines) { IEnumerable <string> itemIds = salesLines.Where(l => l.IsProductLine).Select(l => l.ItemId); IEnumerable <Item> items = null; if (itemIds.Any()) { var getItemsRequest = new GetItemsDataRequest(itemIds); getItemsRequest.QueryResultSettings = new QueryResultSettings(new ColumnSet("ITEMID", "ITEMTAXGROUPID", "PRODUCT"), PagingInfo.AllRecords); var getItemsResponse = context.Runtime.Execute <GetItemsDataResponse>(getItemsRequest, context); items = getItemsResponse.Items; } else { items = new Collection <Item>(); } return(items); }
private static GetItemsDataResponse GetItems(GetItemsDataRequest request) { QueryResultSettings settings = request.QueryResultSettings ?? QueryResultSettings.AllRecords; ReadOnlyCollection <Item> items; if (!request.ItemIds.IsNullOrEmpty()) { items = GetItems(request.RequestContext, request.ItemIds, settings); } else if (!request.ProductIds.IsNullOrEmpty()) { items = GetItems(request.RequestContext, request.ProductIds, settings); } else { items = new ReadOnlyCollection <Item>(new List <Item>()); } return(new GetItemsDataResponse(items)); }
/// <summary> /// Given all relevant transaction/line info, this will calculate the charges /// which should be put on the given sales line. /// </summary> /// <param name="context">The request context.</param> /// <param name="customerId">The customer account number to use for searching.</param> /// <param name="customerGroup">The customer charge group id to use for searching.</param> /// <param name="deliveryMode">The delivery mode code to use for searching.</param> /// <param name="deliveryModeGroup">The delivery mode charge group id to use for searching.</param> /// <param name="line">The sales line that would get the charge. Null if not applying to sales line.</param> /// <param name="transaction">The sales transaction that will have this charge.</param> /// <returns>Collection of charges which apply to this line.</returns> private static IEnumerable <ChargeLine> CalculateLineCharges(RequestContext context, string customerId, string customerGroup, string deliveryMode, string deliveryModeGroup, SalesLine line, SalesTransaction transaction) { GetSalesParametersDataRequest getSalesParametersDataRequest = new GetSalesParametersDataRequest(QueryResultSettings.SingleRecord); var salesParameters = context.Execute <SingleEntityDataServiceResponse <SalesParameters> >(getSalesParametersDataRequest).Entity; // return empty if we're not calculating line charges if (!salesParameters.UseLineCharges) { return(new Collection <ChargeLine>()); } var getItemsRequest = new GetItemsDataRequest(new string[] { line.ItemId }); getItemsRequest.QueryResultSettings = new QueryResultSettings(new ColumnSet("ITEMID", "MARKUPGROUPID"), PagingInfo.AllRecords); var getItemsResponse = context.Execute <GetItemsDataResponse>(getItemsRequest); Item item = getItemsResponse.Items.SingleOrDefault(); if (item == null) { return(new Collection <ChargeLine>()); } // generate all applicable combinations of account, item, and delivery type for line auto-charges // we'll iterate through these below to create the header filters for finding auto-charge configurations var allCombinations = GetAllLineChargeCombinations(); var processorArgs = new ChargeProcessorArguments { CombinationsToTry = allCombinations, ChargeType = ChargeLevel.Line, CustomerId = customerId, CustomerChargeGroup = customerGroup, ItemId = item.ItemId, ItemChargeGroup = item.ChargeGroup, DeliveryModeId = deliveryMode, DeliveryModeChargeGroup = deliveryModeGroup, }; return(ApplyAutoCharges(context, transaction, processorArgs)); }
/// <summary> /// Initializes a new instance of the <see cref="GetItemsProcedure"/> class. /// </summary> /// <param name="request">The data request.</param> public GetItemsProcedure(GetItemsDataRequest request) { this.request = request; }
private static GetItemsDataResponse GetItems(GetItemsDataRequest request) { var getItemsByItemIdsProcedure = new GetItemsProcedure(request); return(getItemsByItemIdsProcedure.Execute()); }
/// <summary> /// Updates the sales transaction with the threshold promotion if applicable. /// </summary> /// <param name="existingTransaction">Existing transaction.</param> /// <param name="tempSalesTransaction">Copy of existing transaction.</param> /// <param name="context">The request context.</param> /// <param name="salesLineIndex">The sales line under consideration.</param> /// <param name="cartPromotionLines">The object with the cart promotion lines.</param> /// <param name="thresholdDiscount">The threshold discount line under consideration.</param> /// <param name="tiers">The tiers for the threshold discount.</param> private static void GetThresholdDiscounts( SalesTransaction existingTransaction, SalesTransaction tempSalesTransaction, RequestContext context, int salesLineIndex, Collection <string> cartPromotionLines, DiscountLine thresholdDiscount, IEnumerable <ThresholdDiscountTier> tiers) { // Find all the sales lines with the same offer. List <SalesLine> salesLinesWithOffer = tempSalesTransaction.SalesLines.Where(j => j.DiscountLines.Any(k => k.OfferId.Equals(thresholdDiscount.OfferId))).ToList(); decimal totalAmount = salesLinesWithOffer.Select(j => j.GrossAmount).Sum(); decimal currentQuantity = tempSalesTransaction.SalesLines[salesLineIndex].Quantity; // Find the minimum threshold amount required to hit a discount among all the tiers for this offer. IEnumerable <ThresholdDiscountTier> tiersForCurrentAmtOffer = tiers.Where(j => j.OfferId.Equals(thresholdDiscount.OfferId) && j.AmountThreshold > totalAmount).OrderBy(l => l.AmountThreshold); ThresholdDiscountTier tier = tiersForCurrentAmtOffer.Any() ? tiersForCurrentAmtOffer.First() : null; if (tier != null) { // Add that amount difference to the first item that has this offer in the cart by increasing its quantity and see if this discount applies after applying concurrency rules. existingTransaction.SalesLines[salesLineIndex].Quantity = Math.Ceiling(tempSalesTransaction.SalesLines[salesLineIndex].Quantity * (tier.AmountThreshold - totalAmount + tempSalesTransaction.SalesLines[salesLineIndex].GrossAmount) / (tempSalesTransaction.SalesLines[salesLineIndex].GrossAmount / tempSalesTransaction.SalesLines[salesLineIndex].Quantity)); CartWorkflowHelper.Calculate(context, existingTransaction, CalculationModes.All); DiscountLine isApplied = existingTransaction.SalesLines[salesLineIndex].DiscountLines.Where(j => j.OfferId.Equals(thresholdDiscount.OfferId)).SingleOrDefault(); if (isApplied != null) { var getItemsRequest = new GetItemsDataRequest(salesLinesWithOffer.Select(j => j.ItemId)) { QueryResultSettings = new QueryResultSettings(new ColumnSet("NAME"), PagingInfo.AllRecords) }; var getItemsResponse = context.Runtime.Execute <GetItemsDataResponse>(getItemsRequest, context); ReadOnlyCollection <Item> items = getItemsResponse.Items; StringBuilder buffer = new StringBuilder(); foreach (Item item in items.ToList()) { buffer.Append(item.Name).Append(", "); } buffer.Remove(buffer.Length - 2, 1); if (tier.DiscountMethod == ThresholdDiscountMethod.AmountOff) { thresholdDiscount.OfferName = string.Format(CultureInfo.CurrentUICulture, Resources.ThresholdDiscountPricePromotion, buffer, Math.Round(tier.AmountThreshold, 2), Math.Round(tier.DiscountValue, 2)); } else { thresholdDiscount.OfferName = string.Format(CultureInfo.CurrentUICulture, Resources.ThresholdDiscountPercentagePromotion, buffer, Math.Round(tier.AmountThreshold, 2), Math.Round(tier.DiscountValue, 2)); } cartPromotionLines.Add(thresholdDiscount.OfferName); } } existingTransaction.SalesLines[salesLineIndex].Quantity = currentQuantity; CartWorkflowHelper.Calculate(context, existingTransaction, CalculationModes.All); foreach (SalesLine salesLineWithOffer in salesLinesWithOffer) { salesLineWithOffer.DiscountLines.Remove(salesLineWithOffer.DiscountLines.Where(k => k.OfferId == thresholdDiscount.OfferId).SingleOrDefault()); } }
/// <summary> /// Executes the workflow for a get nearby stores with availability. /// </summary> /// <param name="request">The request.</param> /// <returns>The response.</returns> protected override GetStoreProductAvailabilityResponse Process(GetStoreProductAvailabilityRequest request) { ThrowIf.Null(request, "request"); string variantId = request.VariantId; if (request.Items == null || !request.Items.Any()) { if (string.IsNullOrWhiteSpace(request.ItemId) && string.IsNullOrWhiteSpace(request.Barcode)) { throw new DataValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_ItemIdBarcodeMissing, "Please specify either an item id or a barcode."); } List <string> itemIds = new List <string>(1); if (!string.IsNullOrWhiteSpace(request.Barcode)) { GetProductBarcodeDataRequest dataRequest = new GetProductBarcodeDataRequest(request.Barcode) { QueryResultSettings = new QueryResultSettings(new ColumnSet("ITEMID"), PagingInfo.AllRecords) }; ItemBarcode itemBarcode = this.Context.Runtime.Execute <GetProductBarcodeDataResponse>(dataRequest, this.Context).Barcode; if (itemBarcode == null) { throw new DataValidationException( DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_BarcodeNotFound, string.Format("The specified barcode ({0}) was not found.", request.Barcode)); } itemIds.Add(itemBarcode.ItemId); variantId = itemBarcode.VariantId; } else { itemIds.Add(request.ItemId); } var getItemsRequest = new GetItemsDataRequest(itemIds) { QueryResultSettings = new QueryResultSettings(new ColumnSet("INVENTUNITID"), PagingInfo.AllRecords) }; var getItemsResponse = request.RequestContext.Runtime.Execute <GetItemsDataResponse>(getItemsRequest, request.RequestContext); ReadOnlyCollection <Item> items = getItemsResponse.Items; if (items == null || items.Count == 0) { throw new DataValidationException( DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_ObjectNotFound, string.Format("No items were found for the specified item identifiers ({0}).", string.Join(", ", itemIds))); } if (items.Count > 1) { throw new DataValidationException( DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_DuplicateObject, string.Format("More than one item was found for the specified item identifiers ({0}).", string.Join(", ", itemIds))); } var getStoresRequest = new GetStoresDataRequest(this.Context.GetPrincipal().ChannelId, request.SearchArea, QueryResultSettings.AllRecords); ReadOnlyCollection <OrgUnitLocation> storeLocations = this.Context.Execute <EntityDataServiceResponse <OrgUnitLocation> >(getStoresRequest).PagedEntityCollection.Results; var productAvailabilityRequest = new Services.GetStoreAvailabilityServiceRequest(items[0].ItemId, variantId ?? string.Empty); var productAvailabilityResponse = this.Context.Execute <Services.GetStoreAvailabilityServiceResponse>(productAvailabilityRequest); var storeAvailabilities = GetStoreAvailabilities(productAvailabilityResponse.ItemsAvailability, storeLocations, items[0].InventoryUnitOfMeasure); return(new GetStoreProductAvailabilityResponse(storeAvailabilities.AsPagedResult())); } else { ThrowIf.Null(request.Items, "request.Items"); var getStoresRequest = new GetStoresDataRequest(this.Context.GetPrincipal().ChannelId, request.SearchArea, QueryResultSettings.AllRecords); ReadOnlyCollection <OrgUnitLocation> storeLocations = this.Context.Execute <EntityDataServiceResponse <OrgUnitLocation> >(getStoresRequest).PagedEntityCollection.Results; var storeAvailabilities = ChannelAvailabilityHelper.GetChannelAvailabiltiy(this.Context, storeLocations, request.Items); return(new GetStoreProductAvailabilityResponse(storeAvailabilities.AsPagedResult())); } }