protected virtual IPurchasable SelectFromProductsDirectlyRelatedToPurchaseEntity(OrganizationServiceContext serviceContext, Entity purchaseEntity, string requiredProductsRelationship, Entity purchaseMetadata, IEnumerable <IPurchasableItemOptions> options)
        {
            TraceMethodInfo("Start: purchaseEntity={0}:{1}, requiredProductsRelationship={2}", purchaseEntity.LogicalName, purchaseEntity.Id, requiredProductsRelationship);

            var requiredProducts = purchaseEntity.GetRelatedEntities(serviceContext, requiredProductsRelationship);

            var optionalProductsRelationship = purchaseMetadata.GetAttributeValue <string>(PurchaseMetadataAttributes.OptionalProductsRelationship);

            var optionalProducts = string.IsNullOrEmpty(optionalProductsRelationship)
                                ? Enumerable.Empty <Entity>()
                                : purchaseEntity.GetRelatedEntities(serviceContext, optionalProductsRelationship);

            var requiredLineItems = requiredProducts.Select(e => new LineItem(e, null, 1, false, e.GetAttributeValue <string>("description"), null, 1));
            var optionalLineItems = optionalProducts.Select(e => new LineItem(e, null, 0, true, e.GetAttributeValue <string>("description"), null, 2));

            var lineItems = requiredLineItems.Union(optionalLineItems);

            var quote = QuoteFunctions.CreateQuote(lineItems, purchaseEntity.ToEntityReference(), serviceContext, Dependencies.GetServiceContextForWrite(), Dependencies.GetPortalUser(),
                                                   Dependencies.GetPriceList(), WebFormSession.AnonymousIdentification, Target, purchaseMetadata);

            var purchasable = quote == null
                                ? null
                                : SelectFromQuote(quote, purchaseMetadata, options);

            TraceMethodInfo("End");

            return(purchasable);
        }
        protected virtual string GetQuoteName(Entity purchaseMetadata)
        {
            var serviceContext = Dependencies.GetServiceContextForWrite();

            var webForm = serviceContext.CreateQuery("adx_webform")
                          .Where(e => e.GetAttributeValue <Guid>("adx_webformid") == WebForm.Id)
                          .Select(e => new { Name = e.GetAttributeValue <string>("adx_name") })
                          .ToArray()
                          .FirstOrDefault();

            return(QuoteFunctions.GetQuoteName(serviceContext, purchaseMetadata, webForm.Name));
        }
        protected virtual EntityReference GetQuoteCustomer(Entity purchaseMetadata)
        {
            var user = Dependencies.GetPortalUser();

            if (user != null)
            {
                return(user);
            }

            var visitorId = WebFormSession.AnonymousIdentification;

            if (string.IsNullOrEmpty(visitorId))
            {
                throw new InvalidOperationException("Unable to create anonymous quote customer record.");
            }

            return(QuoteFunctions.GetQuoteCustomer(Dependencies.GetServiceContext(), null, visitorId));
        }
        protected virtual IPurchasable SelectFromProduct(Entity product, Entity purchaseMetadata, IEnumerable <IPurchasableItemOptions> options)
        {
            TraceMethodInfo("Start: product={0}:{1}", product.LogicalName, product.Id);

            var lineItems = new[]
            {
                new LineItem(product, null, 1, false, product.GetAttributeValue <string>("description"), null, 1)
            };

            var quote = QuoteFunctions.CreateQuote(lineItems, Target, Dependencies.GetServiceContext(), Dependencies.GetServiceContextForWrite(), Dependencies.GetPortalUser(),
                                                   Dependencies.GetPriceList(), WebFormSession.AnonymousIdentification, Target, purchaseMetadata);

            var purchasable = quote == null
                                ? null
                                : SelectFromQuote(quote, purchaseMetadata, options);

            TraceMethodInfo("End");

            return(purchasable);
        }
        protected virtual IPurchasable SelectFromLineItemEntities(OrganizationServiceContext serviceContext, Entity purchaseEntity, string lineItemRelationship,
                                                                  Entity purchaseMetadata, IEnumerable <IPurchasableItemOptions> options)
        {
            TraceMethodInfo("Start: purchaseEntity={0}:{1}, lineItemRelationship={2}", purchaseEntity.LogicalName, purchaseEntity.Id, lineItemRelationship);

            var productAttribute = purchaseMetadata.GetAttributeValue <string>(PurchaseMetadataAttributes.LineItemProduct);

            if (string.IsNullOrEmpty(productAttribute))
            {
                TraceMethodError("Unable to retrieve products from line item entities. {0} not defined in web form step metadata. Returning null.", PurchaseMetadataAttributes.LineItemProduct);

                return(null);
            }

            var descriptionAttribute  = purchaseMetadata.GetAttributeValue <string>(PurchaseMetadataAttributes.LineItemDescription);
            var instructionsAttribute = purchaseMetadata.GetAttributeValue <string>(PurchaseMetadataAttributes.LineItemInstructions);
            var orderAttribute        = purchaseMetadata.GetAttributeValue <string>(PurchaseMetadataAttributes.LineItemOrder);
            var requiredAttribute     = purchaseMetadata.GetAttributeValue <string>(PurchaseMetadataAttributes.LineItemRequired);
            var quantityAttribute     = purchaseMetadata.GetAttributeValue <string>(PurchaseMetadataAttributes.LineItemQuantity);
            var uomAttribute          = purchaseMetadata.GetAttributeValue <string>(PurchaseMetadataAttributes.LineItemUom);

            var entities = purchaseEntity.GetRelatedEntities(serviceContext, lineItemRelationship).ToArray();

            if (!entities.Any())
            {
                TraceMethodError("Unable to retrieve any line item entities. Returning null.");

                return(null);
            }

            var productIds = entities
                             .Select(e => e.GetAttributeValue <EntityReference>(productAttribute))
                             .Where(product => product != null)
                             .Select(product => product.Id)
                             .ToArray();

            if (!productIds.Any())
            {
                TraceMethodError("Unable to retrieve any products from line item entities. Returning null.");

                return(null);
            }

            var products = serviceContext.CreateQuery("product")
                           .WhereIn(e => e.GetAttributeValue <Guid>("productid"), productIds)
                           .ToDictionary(e => e.Id, e => e);

            var lineItems = entities
                            .Select(e => LineItem.GetLineItemFromLineItemEntity(e, productAttribute, descriptionAttribute, instructionsAttribute, orderAttribute, requiredAttribute, quantityAttribute, uomAttribute, products))
                            .Where(lineItem => lineItem != null);

            var quote = QuoteFunctions.CreateQuote(lineItems, purchaseEntity.ToEntityReference(), serviceContext, Dependencies.GetServiceContextForWrite(), Dependencies.GetPortalUser(),
                                                   Dependencies.GetPriceList(), WebFormSession.AnonymousIdentification, Target, purchaseMetadata);

            var purchasable = quote == null
                                ? null
                                : SelectFromQuote(quote, purchaseMetadata, options);

            TraceMethodInfo("End");

            return(purchasable);
        }
 protected virtual EntityReference CreateQuote(IEnumerable <LineItem> lineItems, Entity purchaseMetadata, EntityReference purchaseEntity)
 {
     return(QuoteFunctions.CreateQuote(lineItems, purchaseEntity, Dependencies.GetServiceContext(), Dependencies.GetServiceContextForWrite(),
                                       Dependencies.GetPortalUser(), Dependencies.GetPriceList(), WebFormSession.AnonymousIdentification, Target, purchaseMetadata));
 }
        private static IPurchasableItem GetPurchasableItemFromQuoteProduct(OrganizationServiceContext serviceContext, Entity quoteProduct, IDictionary <Guid, Entity> products)
        {
            var productReference = quoteProduct.GetAttributeValue <EntityReference>("productid");

            if (productReference == null)
            {
                return(null);
            }

            Entity product;

            if (!products.TryGetValue(productReference.Id, out product))
            {
                return(null);
            }

            serviceContext.LoadProperty(quoteProduct, new Relationship("adx_discount_quotedetail"));

            var discounts = quoteProduct.GetRelatedEntities <Entity>(new Relationship("adx_discount_quotedetail"))
                            .Select(e => new Discount(e.Id, e.GetAttributeValue <string>("adx_code"), e.GetAttributeValue <string>("adx_name"),
                                                      e.GetAttributeValue <OptionSetValue>("adx_scope") == null ? 0 : e.GetAttributeValue <OptionSetValue>("adx_scope").Value,
                                                      e.GetAttributeValue <OptionSetValue>("adx_type") == null ? 0 : e.GetAttributeValue <OptionSetValue>("adx_type").Value,
                                                      e.GetAttributeValue <OptionSetValue>("adx_type") == null ? 0 : (e.GetAttributeValue <OptionSetValue>("adx_type").Value == (int)DiscountType.Amount) ? QuoteFunctions.GetDecimalFromMoney(e, "adx_amount") : e.GetAttributeValue <decimal?>("adx_percentage") ?? 0))
                            .ToArray();

            return(new PurchaseableItem(
                       quoteProduct,
                       product.GetAttributeValue <string>("name"),
                       productReference,
                       discounts,
                       product.GetAttributeValue <decimal?>("stockweight").GetValueOrDefault(0) > 0));
        }
        public IPurchasable Select(IEnumerable <IPurchasableItemOptions> options)
        {
            Update(options);

            var serviceContext = Dependencies.GetServiceContext();

            var quote = serviceContext.CreateQuery("quote")
                        .FirstOrDefault(e => e.GetAttributeValue <Guid>("quoteid") == Quote.Id);

            if (quote == null)
            {
                return(null);
            }

            var quoteProducts = serviceContext.CreateQuery("quotedetail")
                                .Where(e => e.GetAttributeValue <EntityReference>("quoteid") == quote.ToEntityReference())
                                .ToArray();

            var productIds = quoteProducts
                             .Select(e => e.GetAttributeValue <EntityReference>("productid"))
                             .Where(product => product != null)
                             .Select(product => product.Id);

            var products = serviceContext.CreateQuery("product")
                           .WhereIn(e => e.GetAttributeValue <Guid>("productid"), productIds)
                           .ToDictionary(e => e.Id, e => e);

            var items = quoteProducts
                        .Select(e => GetPurchasableItemFromQuoteProduct(serviceContext, e, products))
                        .Where(e => e != null)
                        .OrderBy(e => e.IsOptional)
                        .ThenBy(e => e.LineItemNumber)
                        .ThenBy(e => e.Name);

            serviceContext.LoadProperty(quote, new Relationship("adx_discount_quote"));

            var discounts = quote.GetRelatedEntities <Entity>(new Relationship("adx_discount_quote"))
                            .Select(e => new Discount(e.Id, e.GetAttributeValue <string>("adx_code"), e.GetAttributeValue <string>("adx_name"),
                                                      e.GetAttributeValue <OptionSetValue>("adx_scope") == null ? 0 : e.GetAttributeValue <OptionSetValue>("adx_scope").Value,
                                                      e.GetAttributeValue <OptionSetValue>("adx_type") == null ? 0 : e.GetAttributeValue <OptionSetValue>("adx_type").Value,
                                                      e.GetAttributeValue <OptionSetValue>("adx_type") == null ? 0 : (e.GetAttributeValue <OptionSetValue>("adx_type").Value == (int)DiscountType.Amount) ? QuoteFunctions.GetDecimalFromMoney(e, "adx_amount") : e.GetAttributeValue <decimal?>("adx_percentage") ?? 0))
                            .ToArray();

            return(new Purchasable(quote, items, discounts, RequiresShipping));
        }