public ProductAssociationType(IDataLoaderContextAccessor dataLoader, IMediator mediator)
        {
            Name        = "ProductAssociation";
            Description = "product association.";

            Field(d => d.Type);
            Field(d => d.Priority);
            Field("Quantity", x => x.Quantity, nullable: true, type: typeof(IntGraphType));
            Field(d => d.AssociatedObjectId);
            Field(d => d.AssociatedObjectType);

            var productField = new FieldType
            {
                Name     = "product",
                Type     = GraphTypeExtenstionHelper.GetActualType <ProductType>(),
                Resolver = new AsyncFieldResolver <ProductAssociation, object>(async context =>
                {
                    var loader = dataLoader.Context.GetOrAddBatchLoader <string, ExpProduct>("associatedProductLoader", (ids) => LoadProductsAsync(mediator, ids));

                    // IMPORTANT: In order to avoid deadlocking on the loader we use the following construct (next 2 lines):
                    var loadHandle = loader.LoadAsync(context.Source.AssociatedObjectId);
                    return(await loadHandle);
                })
            };

            AddField(productField);
        }
        public void Build(ISchema schema)
        {
            _ = schema.Query.AddField(new FieldType
            {
                Name      = "menus",
                Arguments = new QueryArguments(
                    new QueryArgument <NonNullGraphType <StringGraphType> > {
                    Name = "storeId"
                },
                    new QueryArgument <StringGraphType> {
                    Name = "cultureName"
                },
                    new QueryArgument <StringGraphType> {
                    Name = "keyword"
                }
                    ),
                Type     = GraphTypeExtenstionHelper.GetActualType <ListGraphType <MenuLinkListType> >(),
                Resolver = new AsyncFieldResolver <object>(async context =>
                {
                    var result = await _mediator.Send(new GetMenusQuery
                    {
                        StoreId     = context.GetArgument <string>("storeId"),
                        CultureName = context.GetArgument <string>("cultureName"),
                        Keyword     = context.GetArgument <string>("keyword"),
                    });

                    return(result.Menus);
                })
            });
        }
        public ProductRecommendationType(
            IMediator mediator,
            IDataLoaderContextAccessor dataLoader)
        {
            Name        = "ProductRecommendation";
            Description = "Product recommendation object";

            Field(d => d.ProductId).Description("The unique ID of the product.");
            Field(d => d.Scenario).Description("The recommendation scenario name.");
            Field(d => d.Score).Description("The recommendation relevance score.");

            var productField = new FieldType
            {
                Name     = "product",
                Type     = GraphTypeExtenstionHelper.GetActualType <ProductType>(),
                Resolver = new FuncFieldResolver <ProductRecommendation, IDataLoaderResult <ExpProduct> >(context =>
                {
                    var includeFields = context.SubFields.Values.GetAllNodesPaths().ToArray();
                    var loader        = dataLoader.Context.GetOrAddBatchLoader <string, ExpProduct>($"recommendedProducts", (ids) => LoadProductsAsync(mediator, context, ids, includeFields));

                    return(loader.LoadAsync(context.Source.ProductId));
                })
            };

            AddField(productField);
        }
        public GiftItemType(IMediator mediator, IDataLoaderContextAccessor dataLoader, IDynamicPropertyResolverService dynamicPropertyResolverService)
        {
            Field(x => x.PromotionId).Description("Promotion ID");
            Field(x => x.Quantity).Description("Number of gifts in the reward");
            Field(x => x.ProductId, true).Description("Product ID");
            Field(x => x.CategoryId, true).Description("Product category ID");
            Field(x => x.ImageUrl, true).Description("Value of reward image absolute URL");
            Field(x => x.Name).Description("Name of the reward");
            Field(x => x.MeasureUnit, true).Description("Measurement unit");
            Field(x => x.LineItemId, true).Description("Line item ID in case there is a gift in the cart. If there is no gift, it stays null");

            AddField(new FieldType
            {
                Name        = "id",
                Description = "Artificial ID for this value object",
                Type        = GraphTypeExtenstionHelper.GetActualType <NonNullGraphType <StringGraphType> >(),
                Resolver    = new FuncFieldResolver <GiftItem, string>(context =>
                {
                    // CacheKey as Id. CacheKey is determined by the values returned form GetEqualityComponents().
                    return(context.Source.GetCacheKey());
                })
            });

            AddField(new FieldType
            {
                Name     = "product",
                Type     = GraphTypeExtenstionHelper.GetActualType <ProductType>(),
                Resolver = new FuncFieldResolver <GiftItem, IDataLoaderResult <ExpProduct> >(context =>
                {
                    if (context.Source.ProductId.IsNullOrEmpty())
                    {
                        return(default);
        public ProductRecommendationType(
            IMediator mediator,
            IDataLoaderContextAccessor dataLoader)
        {
            Name        = "ProductRecommendation";
            Description = "Product recommendation object";

            Field(d => d.ProductId).Description("The unique ID of the product.");
            Field(d => d.Scenario).Description("The recommendation scenario name.");
            Field(d => d.Score).Description("The recommendation relevance score.");


            var productField = new FieldType
            {
                Name     = "product",
                Type     = GraphTypeExtenstionHelper.GetActualType <ProductType>(),
                Resolver = new AsyncFieldResolver <ProductRecommendation, object>(async context =>
                {
                    var includeFields = context.SubFields.Values.GetAllNodesPaths().Select(x => x.TrimStart("items.")).ToArray();
                    var loader        = dataLoader.Context.GetOrAddBatchLoader <string, ExpProduct>($"recommendedProducts", (ids) => LoadProductsAsync(mediator, new LoadProductRequest {
                        Ids = ids.ToArray(), IncludeFields = includeFields.ToArray()
                    }));

                    // IMPORTANT: In order to avoid deadlocking on the loader we use the following construct (next 2 lines):
                    var loadHandle = loader.LoadAsync(context.Source.ProductId);
                    return(await loadHandle);
                })
            };

            AddField(productField);
        }
        public OrganizationType(IMediator mediator)
        {
            Name        = "Organization";
            Description = "Organization info";
            //this.AuthorizeWith(CustomerModule.Core.ModuleConstants.Security.Permissions.Read);

            Field(x => x.Organization.Id).Description("Description");
            Field(x => x.Organization.Description, true).Description("Description");
            Field(x => x.Organization.BusinessCategory, true).Description("Business category");
            Field(x => x.Organization.OwnerId, true).Description("Owner id");
            Field(x => x.Organization.ParentId, true).Description("Parent id");
            Field(x => x.Organization.Name, true).Description("Name");
            Field(x => x.Organization.MemberType).Description("Member type");
            Field(x => x.Organization.OuterId, true).Description("Outer id");
            Field <NonNullGraphType <ListGraphType <MemberAddressType> > >("addresses", resolve: x => x.Source.Organization.Addresses);
            Field(x => x.Organization.Phones, true);
            Field(x => x.Organization.Emails, true);
            Field(x => x.Organization.Groups, true);
            Field(x => x.Organization.SeoObjectType).Description("SEO object type");

            // TODO:
            //DynamicProperties
            //    SeoInfos

            var connectionBuilder = GraphTypeExtenstionHelper.CreateConnection <ContactType, OrganizationAggregate>()
                                    .Name("contacts")
                                    .Argument <StringGraphType>("searchPhrase", "Free text search")
                                    .Unidirectional()
                                    .PageSize(20);

            connectionBuilder.ResolveAsync(async context => await ResolveConnectionAsync(mediator, context));
            AddField(connectionBuilder.FieldType);
        }
        public void Build(ISchema schema)
        {
            #region countries query

#pragma warning disable S125 // Sections of code should not be commented out

            /*
             * query {
             *       countries
             * }
             */
#pragma warning restore S125 // Sections of code should not be commented out

            #endregion

            _ = schema.Query.AddField(new FieldType
            {
                Name     = "countries",
                Type     = GraphTypeExtenstionHelper.GetActualType <ListGraphType <CountryType> >(),
                Resolver = new AsyncFieldResolver <object>(async context =>
                {
                    var result = await _mediator.Send(new GetCountriesQuery());

                    return(result.Countries);
                })
            });

            #region regions query

#pragma warning disable S125 // Sections of code should not be commented out

            /*
             * query {
             *       regions(countryId: "country code")
             * }
             */
#pragma warning restore S125 // Sections of code should not be commented out

            #endregion

            _ = schema.Query.AddField(new FieldType
            {
                Name      = "regions",
                Arguments = new QueryArguments(new QueryArgument <NonNullGraphType <StringGraphType> > {
                    Name = "countryId"
                }),
                Type     = GraphTypeExtenstionHelper.GetActualType <ListGraphType <CountryRegionType> >(),
                Resolver = new AsyncFieldResolver <object>(async context =>
                {
                    var result = await _mediator.Send(new GetRegionsQuery
                    {
                        CountryId = context.GetArgument <string>("countryId"),
                    });

                    return(result.Regions);
                })
            });

#pragma warning disable S125 // Sections of code should not be commented out
        }
Пример #8
0
        public ProductAssociationType(IDataLoaderContextAccessor dataLoader, IMediator mediator)
        {
            Name        = "ProductAssociation";
            Description = "product association.";

            Field(d => d.Type, nullable: true);
            Field(d => d.Priority, nullable: true);
            Field("Quantity", x => x.Quantity, nullable: true, type: typeof(IntGraphType));
            Field(d => d.AssociatedObjectId, nullable: true);
            Field(d => d.AssociatedObjectType, nullable: true);
            Field <ListGraphType <StringGraphType> >("tags", resolve: context => context.Source.Tags?.ToList() ?? new List <string>());

            var productField = new FieldType
            {
                Name     = "product",
                Type     = GraphTypeExtenstionHelper.GetActualType <ProductType>(),
                Resolver = new FuncFieldResolver <ProductAssociation, IDataLoaderResult <ExpProduct> >(context =>
                {
                    var loader = dataLoader.Context.GetOrAddBatchLoader <string, ExpProduct>("associatedProductLoader", (ids) => LoadProductsAsync(mediator, ids, context));
                    return(loader.LoadAsync(context.Source.AssociatedObjectId));
                })
            };

            AddField(productField);
        }
        public ContactType(IOrganizationAggregateRepository organizationAggregateRepository)
        {
            _organizationAggregateRepository = organizationAggregateRepository;

            //this.AuthorizeWith(CustomerModule.Core.ModuleConstants.Security.Permissions.Read);

            Field(x => x.Contact.FirstName);
            Field(x => x.Contact.LastName);
            Field <DateGraphType>("birthDate", resolve: context => context.Source.Contact.BirthDate);
            Field(x => x.Contact.FullName);
            Field(x => x.Contact.Id);
            Field(x => x.Contact.MemberType);
            Field(x => x.Contact.MiddleName, true);
            Field(x => x.Contact.Name, true);
            Field(x => x.Contact.OuterId, true);
            Field <ListGraphType <MemberAddressType> >("addresses", resolve: context => context.Source.Contact.Addresses);
            Field <ListGraphType <UserType> >("securityAccounts", resolve: context => context.Source.Contact.SecurityAccounts);
            //TODO: remove later
            Field <StringGraphType>("organizationId", resolve: context => context.Source.Contact.Organizations?.FirstOrDefault());
            Field("organizationsIds", x => x.Contact.Organizations);
            Field("phones", x => x.Contact.Phones);


            AddField(new FieldType
            {
                Name        = "Organizations",
                Description = "All contact's organizations",
                Type        = GraphTypeExtenstionHelper.GetActualType <ListGraphType <OrganizationType> >(),
                Resolver    = new AsyncFieldResolver <ContactAggregate, IEnumerable <OrganizationAggregate> >(async context =>
                {
                    if (context.Source.Contact.Organizations.IsNullOrEmpty())
                    {
                        return(default);
Пример #10
0
        public void GetComplexType_HasOverriddenType_OverriddenTypeReturned()
        {
            // Arrange
            AbstractTypeFactory <IGraphType> .OverrideType <FooType, FooTypeExtended>();

            // Act
            var targetType = GraphTypeExtenstionHelper.GetActualComplexType <FooType>();

            // Assert
            targetType.Name.Should().Be(nameof(FooTypeExtended));
        }
Пример #11
0
        public void GetComplexTypeThreeLevels_HasOverriddenType_OverriddenTypeReturned()
        {
            // Arrange
            AbstractTypeFactory <IGraphType> .OverrideType <FooType, FooTypeExtended>();

            // Act
            var targetType = GraphTypeExtenstionHelper.GetActualComplexType <FooComplex2 <FooComplex <FooType> > >();

            // Assert
            typeof(FooComplex2 <FooComplex <FooType> >).GenericTypeArguments[0].GenericTypeArguments.Should().OnlyContain(x => x.Name.EqualsInvariant(nameof(FooType)));
            targetType.GenericTypeArguments[0].GenericTypeArguments.Should().OnlyContain(x => x.Name.EqualsInvariant(nameof(FooTypeExtended)));
        }
        public void Build(ISchema schema)
        {
            var connectionBuilder = GraphTypeExtenstionHelper.CreateConnection <ProductRecommendationType, object>()
                                    .Name("recommendations")
                                    .Argument <StringGraphType>("scenario", "The recommendation scenario")
                                    .Argument <StringGraphType>("itemId", "The context product id")
                                    .Argument <StringGraphType>("userId", "The context user id")
                                    .Unidirectional()
                                    .PageSize(20);

            connectionBuilder.ResolveAsync(async context =>
            {
                return(await ResolveConnectionAsync(context));
            });
            schema.Query.AddField(connectionBuilder.FieldType);
        }
Пример #13
0
        public CatalogDiscountType(IMediator mediator, IDataLoaderContextAccessor dataLoader)
        {
            var promotion = new EventStreamFieldType
            {
                Name      = "promotion",
                Type      = GraphTypeExtenstionHelper.GetActualType <PromotionType>(),
                Arguments = new QueryArguments(),
                Resolver  = new FuncFieldResolver <Discount, IDataLoaderResult <Promotion> >(context =>
                {
                    var loader = dataLoader.Context.GetOrAddBatchLoader <string, Promotion>("promotionsLoader", (ids) => LoadPromotionsAsync(mediator, ids));
                    return(loader.LoadAsync(context.Source.PromotionId));
                })
            };

            AddField(promotion);
        }
Пример #14
0
        public void Build(ISchema schema)
        {
            var dynamicPropertyField = new FieldType
            {
                Name      = "dynamicProperty",
                Arguments = new QueryArguments(
                    new QueryArgument <NonNullGraphType <StringGraphType> > {
                    Name = "idOrName", Description = "Id or name of the dynamic property"
                },
                    new QueryArgument <StringGraphType> {
                    Name = "cultureName", Description = "Culture name (\"en-US\")"
                },
                    new QueryArgument <StringGraphType> {
                    Name = "objectType", Description = "Object type of the dynamic property"
                }
                    ),
                Type     = GraphTypeExtenstionHelper.GetActualType <DynamicPropertyType>(),
                Resolver = new AsyncFieldResolver <object>(async context =>
                {
                    context.CopyArgumentsToUserContext();

                    var query        = context.GetDynamicPropertiesQuery <GetDynamicPropertyQuery>();
                    query.IdOrName   = context.GetArgument <string>("idOrName");
                    query.ObjectType = context.GetArgument <string>("objectType");

                    var response = await _mediator.Send(query);

                    return(response.DynamicProperty);
                })
            };

            schema.Query.AddField(dynamicPropertyField);

            var dynamicPropertiesConnectionBuilder = GraphTypeExtenstionHelper.CreateConnection <DynamicPropertyType, object>()
                                                     .Name("dynamicProperties")
                                                     .Argument <StringGraphType>("cultureName", "The culture name (\"en-US\")")
                                                     .Argument <StringGraphType>("filter", "This parameter applies a filter to the query results")
                                                     .Argument <StringGraphType>("sort", "The sort expression")
                                                     .Argument <StringGraphType>("objectType", "Object type of the dynamic property")
                                                     .PageSize(20);

            dynamicPropertiesConnectionBuilder.ResolveAsync(async context => await ResolveDynamicPropertiesConnectionAsync(_mediator, context));

            schema.Query.AddField(dynamicPropertiesConnectionBuilder.FieldType);
        }
Пример #15
0
        public void Build(ISchema schema)
        {
            var connectionBuilder = GraphTypeExtenstionHelper.CreateConnection <ProductRecommendationType, object>()
                                    .Name("recommendations")
                                    .Argument <StringGraphType>("scenario", "The recommendation scenario")
                                    .Argument <StringGraphType>("itemId", "The context product id")
                                    .Argument <StringGraphType>("userId", "The context user id")
                                    .Argument <StringGraphType>("storeId", "the store id")
                                    .PageSize(20);

            connectionBuilder.ResolveAsync(async context =>
            {
                //PT-1606:  Need to check what there is no any alternative way to access to the original request arguments in sub selection
                context.CopyArgumentsToUserContext();
                return(await ResolveConnectionAsync(context));
            });
            schema.Query.AddField(connectionBuilder.FieldType);
        }
        public void Build(ISchema schema)
        {
            var productField = new FieldType
            {
                Name      = "product",
                Arguments = new QueryArguments(new QueryArgument <NonNullGraphType <StringGraphType> > {
                    Name = "id", Description = "id of the product"
                }),
                Type     = GraphTypeExtenstionHelper.GetActualType <ProductType>(),
                Resolver = new AsyncFieldResolver <object>(async context =>
                {
                    var loader = _dataLoader.Context.GetOrAddBatchLoader <string, ExpProduct>("productsLoader", (ids) => LoadProductsAsync(_mediator, ids, context.SubFields.Values.GetAllNodesPaths()));
                    return(await loader.LoadAsync(context.GetArgument <string>("id")));
                })
            };

            schema.Query.AddField(productField);

            //var productsConnectionBuilder = ConnectionBuilder.Create<ProductType, EdgeType<ProductType>, ProductsConnectonType<ProductType>, object>()
            var productsConnectionBuilder = GraphTypeExtenstionHelper.CreateConnection <ProductType, EdgeType <ProductType>, ProductsConnectonType <ProductType>, object>()
                                            .Name("products")
                                            .Argument <StringGraphType>("query", "The query parameter performs the full-text search")
                                            .Argument <StringGraphType>("filter", "This parameter applies a filter to the query results")
                                            .Argument <BooleanGraphType>("fuzzy", "When the fuzzy query parameter is set to true the search endpoint will also return products that contain slight differences to the search text.")
                                            .Argument <StringGraphType>("facet", "Facets calculate statistical counts to aid in faceted navigation.")
                                            .Argument <StringGraphType>("sort", "The sort expression")
                                            .Unidirectional()
                                            .PageSize(20);

            productsConnectionBuilder.ResolveAsync(async context =>
            {
                return(await ResolveConnectionAsync(_mediator, context));
            });


            schema.Query.AddField(productsConnectionBuilder.FieldType);
        }
Пример #17
0
        public UserType(IContactAggregateRepository contactAggregateRepository)
        {
            Field(x => x.AccessFailedCount);
            Field(x => x.CreatedBy, true);
            Field(x => x.CreatedDate, true);
            Field(x => x.Email, true);
            Field(x => x.EmailConfirmed);
            Field(x => x.Id);
            Field(x => x.IsAdministrator);
            Field(x => x.LockoutEnabled);
            Field <DateTimeGraphType>("lockoutEnd", resolve: x => x.Source.LockoutEnd);
            Field(x => x.MemberId, true);
            Field(x => x.ModifiedBy, true);
            Field(x => x.ModifiedDate, true);
            Field(x => x.NormalizedEmail, true);
            Field(x => x.NormalizedUserName, true);
            Field(x => x.PasswordExpired);
            Field(x => x.PhoneNumber, true);
            Field(x => x.PhoneNumberConfirmed);
            Field(x => x.PhotoUrl, true);
            Field <ListGraphType <RoleType> >("roles", resolve: x => x.Source.Roles);
            Field <ListGraphType <StringGraphType> >("permissions", resolve: x => x.Source.Roles?.SelectMany(r => r.Permissions?.Select(p => p.Name)));
            Field(x => x.SecurityStamp);
            Field(x => x.StoreId, true);
            Field(x => x.TwoFactorEnabled);
            Field(x => x.UserName);
            Field(x => x.UserType, true);

            AddField(new FieldType
            {
                Name        = "Contact",
                Description = "The associated contact info",
                Type        = GraphTypeExtenstionHelper.GetActualType <ContactType>(),
                Resolver    = new AsyncFieldResolver <ApplicationUser, ContactAggregate>(context =>
                                                                                         contactAggregateRepository.GetContactByIdAsync(context.Source.MemberId))
            });
        }
Пример #18
0
 public FieldType ExtendableField <TGraphType>(
     string name,
     string description       = null,
     QueryArguments arguments = null,
     Func <IResolveFieldContext <TSourceType>, object> resolve = null,
     string deprecationReason = null)
     where TGraphType : IGraphType
 {
     return(AddField(new FieldType
     {
         Name = name,
         Description = description,
         DeprecationReason = deprecationReason,
         Type = GraphTypeExtenstionHelper.GetActualComplexType <TGraphType>(),
         Arguments = arguments,
         Resolver = resolve != null
             ? new FuncFieldResolver <TSourceType, object>(context =>
         {
             context.CopyArgumentsToUserContext();
             return resolve(context);
         })
             : null
     }));
 }
Пример #19
0
        public CartType(ICartAvailMethodsService cartAvailMethods)
        {
            Field(x => x.Cart.Id, nullable: true).Description("Shopping cart Id");
            Field(x => x.Cart.Name, nullable: false).Description("Shopping cart name");
            Field(x => x.Cart.Status, nullable: true).Description("Shopping cart status");
            Field(x => x.Cart.StoreId, nullable: true).Description("Shopping cart store id");
            Field(x => x.Cart.ChannelId, nullable: true).Description("Shopping cart channel id");
            Field <BooleanGraphType>("hasPhysicalProducts", resolve: context => AbstractTypeFactory <CartHasPhysicalProductsSpecification> .TryCreateInstance().IsSatisfiedBy(context.Source.Cart));
            Field(x => x.Cart.IsAnonymous, nullable: true).Description("Sign that shopping cart is anonymous");
            //Field(x => x.Customer, nullable: true).Description("Shopping cart user"); //todo: add resolver
            Field(x => x.Cart.CustomerId, nullable: true).Description("Shopping cart user id");
            Field(x => x.Cart.CustomerName, nullable: true).Description("Shopping cart user name");
            Field(x => x.Cart.OrganizationId, nullable: true).Description("Shopping cart organization id");
            Field(x => x.Cart.IsRecuring, nullable: true).Description("Sign that shopping cart is recurring");
            Field(x => x.Cart.Comment, nullable: true).Description("Shopping cart text comment");

            // Characteristics
            Field(x => x.Cart.VolumetricWeight, nullable: true).Description("Shopping cart value of volumetric weight");
            Field(x => x.Cart.WeightUnit, nullable: true).Description("Shopping cart value of weight unit");
            Field(x => x.Cart.Weight, nullable: true).Description("Shopping cart value of shopping cart weight");
            //TODO:
            //Field(x => x.MeasureUnit, nullable: true).Description("Shopping cart value of measurement unit");
            //Field(x => x.Height, nullable: true).Description("Shopping cart value of height");
            //Field(x => x.Length, nullable: true).Description("Shopping cart value of length");
            //Field(x => x.Width, nullable: true).Description("Shopping cart value of width");

            // Money
            Field <MoneyType>("total", resolve: context => context.Source.Cart.Total.ToMoney(context.Source.Currency));
            Field <MoneyType>("subTotal", resolve: context => context.Source.Cart.SubTotal.ToMoney(context.Source.Currency));
            Field <MoneyType>("subTotalWithTax", resolve: context => context.Source.Cart.SubTotalWithTax.ToMoney(context.Source.Currency));
            Field <MoneyType>("extendedPriceTotal", resolve: context => context.Source.Cart.Items.Sum(i => i.ExtendedPrice).ToMoney(context.Source.Currency));
            Field <MoneyType>("extendedPriceTotalWithTax", resolve: context => context.Source.Cart.Items.Sum(i => i.ExtendedPriceWithTax).ToMoney(context.Source.Currency));
            Field <CurrencyType>("currency", resolve: context => context.Source.Currency);
            Field <MoneyType>("taxTotal", resolve: context => context.Source.Cart.TaxTotal.ToMoney(context.Source.Currency));
            Field(x => x.Cart.TaxPercentRate, nullable: true).Description("Tax percent rate");
            Field(x => x.Cart.TaxType, nullable: true).Description("Shipping tax type");
            Field <ListGraphType <TaxDetailType> >("taxDetails", resolve: context => context.Source.Cart.TaxDetails);

            // Shipping
            Field <MoneyType>("shippingPrice", resolve: context => context.Source.Cart.ShippingTotal.ToMoney(context.Source.Currency));
            Field <MoneyType>("shippingPriceWithTax", resolve: context => context.Source.Cart.ShippingTotalWithTax.ToMoney(context.Source.Currency));
            Field <MoneyType>("shippingTotal", resolve: context => context.Source.Cart.ShippingTotal.ToMoney(context.Source.Currency));
            Field <MoneyType>("shippingTotalWithTax", resolve: context => context.Source.Cart.ShippingTotalWithTax.ToMoney(context.Source.Currency));
            //Field<ListGraphType<ShipmentType>>("shipments", resolve: context => context.Source.Cart.Shipments);
            //TODO: By this registration we support the schema types extensions. Need to move this code into extensions and replace everywhere to this version.
            var cartShipmentsField = new FieldType
            {
                Name     = "shipments",
                Type     = typeof(ListGraphType <>).MakeGenericType(GraphTypeExtenstionHelper.GetActualType <ShipmentType>()),
                Resolver = new FuncFieldResolver <CartAggregate, object>(context => context.Source.Cart.Shipments)
            };

            AddField(cartShipmentsField);

            FieldAsync <ListGraphType <ShippingMethodType> >("availableShippingMethods", resolve: async context =>
            {
                var rates = await cartAvailMethods.GetAvailableShippingRatesAsync(context.Source);
                //store the pair ShippingMethodType and cart aggregate in the user context for future usage in the ShippingMethodType fields resolvers
                if (rates != null)
                {
                    rates.Apply(x => context.UserContext[x.GetCacheKey()] = context.Source);
                }
                return(rates);
            });

            // Payment
            Field <MoneyType>("paymentPrice", resolve: context => context.Source.Cart.PaymentTotal.ToMoney(context.Source.Currency));
            Field <MoneyType>("paymentPriceWithTax", resolve: context => context.Source.Cart.PaymentTotalWithTax.ToMoney(context.Source.Currency));
            Field <MoneyType>("paymentTotal", resolve: context => context.Source.Cart.PaymentTotal.ToMoney(context.Source.Currency));
            Field <MoneyType>("paymentTotalWithTax", resolve: context => context.Source.Cart.PaymentTotalWithTax.ToMoney(context.Source.Currency));
            Field <ListGraphType <PaymentType> >("payments", resolve: context => context.Source.Cart.Payments);
            FieldAsync <ListGraphType <PaymentMethodType> >("availablePaymentMethods", resolve: async context =>
            {
                var methods = await cartAvailMethods.GetAvailablePaymentMethodsAsync(context.Source);
                //store the pair ShippingMethodType and cart aggregate in the user context for future usage in the ShippingMethodType fields resolvers
                if (methods != null)
                {
                    methods.Apply(x => context.UserContext[x.Id] = context.Source);
                }
                return(methods);
            });
            //TODO:
            //Field<ListGraphType<PaymentPlanType>>("paymentPlan", resolve: context => context.Source.PaymentPlan);

            // Extended money
            //TODO:
            //Field<MoneyType>("extendedPriceTotal", resolve: context => context.Source.ExtendedPriceTotal);
            //Field<MoneyType>("extendedPriceTotalWithTax", resolve: context => context.Source.ExtendedPriceTotalWithTax);

            // Handling totals
            Field <MoneyType>("handlingTotal", resolve: context => context.Source.Cart.HandlingTotal.ToMoney(context.Source.Currency));
            Field <MoneyType>("handlingTotalWithTax", resolve: context => context.Source.Cart.HandlingTotalWithTax.ToMoney(context.Source.Currency));

            // Discounts
            Field <MoneyType>("discountTotal", resolve: context => context.Source.Cart.DiscountTotal.ToMoney(context.Source.Currency));
            Field <MoneyType>("discountTotalWithTax", resolve: context => context.Source.Cart.DiscountTotalWithTax.ToMoney(context.Source.Currency));
            Field <ListGraphType <DiscountType> >("discounts", resolve: context => context.Source.Cart.Discounts);

            // Addresses
            Field <ListGraphType <AddressType> >("addresses", resolve: context => context.Source.Cart.Addresses);

            // Items
            Field <ListGraphType <LineItemType> >("items", resolve: context => context.Source.Cart.Items);

            Field <IntGraphType>("itemsCount", "Count of different items", resolve: context => context.Source.Cart.Items.Count);
            Field <IntGraphType>("itemsQuantity", "Quantity of items", resolve: context => context.Source.Cart.Items.Sum(x => x.Quantity));
            //TODO:
            //Field<LineItemType>("recentlyAddedItem", resolve: context => context.Source.Cart.RecentlyAddedItem);

            // Coupons
            Field <ListGraphType <CouponType> >("coupons", resolve: context => context.Source.Coupons);

            // Other
            //Field<ListGraphType<DynamicPropertyType>>("dynamicProperties", resolve: context => context.Source.DynamicProperties); //todo add dynamic properties
            //TODO:
            Field(x => x.IsValid, nullable: true).Description("Is cart valid");
            Field <ListGraphType <ValidationErrorType> >("validationErrors", resolve: context => context.Source.ValidationErrors.OfType <CartValidationError>());
            Field(x => x.Cart.Type, nullable: true).Description("Shopping cart type");
        }
        /// <summary>
        /// XDigitalCatalog schema builder
        /// </summary>
        /// <remarks>
        /// IMPORTANT!
        /// We can't use the fluent syntax for new types registration provided by dotnet graphql here,
        /// because we have the strict requirement for underlying types extensions and must use
        /// GraphTypeExtenstionHelper to resolve the effective type on execution time
        /// </remarks>
        public void Build(ISchema schema)
        {
            var productField = new FieldType
            {
                Name      = "product",
                Arguments = new QueryArguments(
                    new QueryArgument <NonNullGraphType <StringGraphType> > {
                    Name = "id", Description = "id of the product"
                },
                    new QueryArgument <NonNullGraphType <StringGraphType> > {
                    Name = "storeId", Description = "Store Id"
                },
                    new QueryArgument <StringGraphType> {
                    Name = "userId", Description = "User Id"
                },
                    new QueryArgument <StringGraphType> {
                    Name = "currencyCode", Description = "Currency code (\"USD\")"
                },
                    new QueryArgument <StringGraphType> {
                    Name = "cultureName", Description = "Culture name (\"en-US\")"
                }
                    ),
                Type     = GraphTypeExtenstionHelper.GetActualType <ProductType>(),
                Resolver = new AsyncFieldResolver <object, IDataLoaderResult <ExpProduct> >(async context =>
                {
                    //PT-1606:  Need to check what there is no any alternative way to access to the original request arguments in sub selection
                    context.CopyArgumentsToUserContext();

                    var store = await _storeService.GetByIdAsync(context.GetArgument <string>("storeId"));
                    context.UserContext["store"] = store;

                    var cultureName = context.GetArgument <string>("cultureName");

                    var allCurrencies = await _currencyService.GetAllCurrenciesAsync();
                    //Store all currencies in the user context for future resolve in the schema types
                    context.SetCurrencies(allCurrencies, cultureName);

                    var loader = _dataLoader.Context.GetOrAddBatchLoader <string, ExpProduct>("productsLoader", (ids) => LoadProductsAsync(_mediator, ids, context));
                    return(loader.LoadAsync(context.GetArgument <string>("id")));
                })
            };

            schema.Query.AddField(productField);

            var productsConnectionBuilder = GraphTypeExtenstionHelper.CreateConnection <ProductType, EdgeType <ProductType>, ProductsConnectonType <ProductType>, object>()
                                            .Name("products")
                                            .Argument <NonNullGraphType <StringGraphType> >("storeId", "The store id where products are searched")
                                            .Argument <StringGraphType>("userId", "The customer id for search result impersonalization")
                                            .Argument <StringGraphType>("currencyCode", "The currency for which all prices data will be returned")
                                            .Argument <StringGraphType>("cultureName", "The culture name for cart context product")
                                            .Argument <StringGraphType>("query", "The query parameter performs the full-text search")
                                            .Argument <StringGraphType>("filter", "This parameter applies a filter to the query results")
                                            .Argument <BooleanGraphType>("fuzzy", "When the fuzzy query parameter is set to true the search endpoint will also return products that contain slight differences to the search text.")
                                            .Argument <IntGraphType>("fuzzyLevel", "The fuzziness level is quantified in terms of the Damerau-Levenshtein distance, this distance being the number of operations needed to transform one word into another.")
                                            .Argument <StringGraphType>("facet", "Facets calculate statistical counts to aid in faceted navigation.")
                                            .Argument <StringGraphType>("sort", "The sort expression")
                                            .Argument <ListGraphType <StringGraphType> >("productIds", "Product Ids")
                                            .PageSize(20);

            productsConnectionBuilder.ResolveAsync(async context =>
            {
                //PT-1606:  Need to check what there is no any alternative way to access to the original request arguments in sub selection
                context.CopyArgumentsToUserContext();

                var cultureName = context.GetArgument <string>("cultureName");
                var store       = await _storeService.GetByIdAsync(context.GetArgument <string>("storeId"));
                context.UserContext["store"]   = store;
                context.UserContext["catalog"] = store.Catalog;

                var allCurrencies = await _currencyService.GetAllCurrenciesAsync();
                //Store all currencies in the user context for future resolve in the schema types
                context.SetCurrencies(allCurrencies, cultureName);

                return(await ResolveProductsConnectionAsync(_mediator, context));
            });

            schema.Query.AddField(productsConnectionBuilder.FieldType);

            var categoryField = new FieldType
            {
                Name      = "category",
                Arguments = new QueryArguments(
                    new QueryArgument <NonNullGraphType <StringGraphType> > {
                    Name = "id", Description = "id of the product"
                },
                    new QueryArgument <NonNullGraphType <StringGraphType> > {
                    Name = "storeId", Description = "Store Id"
                },
                    new QueryArgument <StringGraphType> {
                    Name = "userId", Description = "User Id"
                },
                    new QueryArgument <StringGraphType> {
                    Name = "currencyCode", Description = "Currency code (\"USD\")"
                },
                    new QueryArgument <StringGraphType> {
                    Name = "cultureName", Description = "Culture name (\"en-US\")"
                }
                    ),
                Type     = GraphTypeExtenstionHelper.GetActualType <CategoryType>(),
                Resolver = new AsyncFieldResolver <ExpCategory, IDataLoaderResult <ExpCategory> >(async context =>
                {
                    var store = await _storeService.GetByIdAsync(context.GetArgument <string>("storeId"));
                    context.UserContext["store"] = store;

                    //PT-1606:  Need to check what there is no any alternative way to access to the original request arguments in sub selection
                    context.CopyArgumentsToUserContext();

                    var loader = _dataLoader.Context.GetOrAddBatchLoader <string, ExpCategory>("categoriesLoader", (ids) => LoadCategoriesAsync(_mediator, ids, context));
                    return(loader.LoadAsync(context.GetArgument <string>("id")));
                })
            };

            schema.Query.AddField(categoryField);

            var categoriesConnectionBuilder = GraphTypeExtenstionHelper.CreateConnection <CategoryType, object>()
                                              .Name("categories")
                                              .Argument <StringGraphType>("storeId", "The store id where category are searched")
                                              .Argument <StringGraphType>("cultureName", "The language for which all localized category data will be returned")
                                              .Argument <StringGraphType>("userId", "The customer id for search result impersonalization")
                                              .Argument <StringGraphType>("currencyCode", "The currency for which all prices data will be returned")
                                              .Argument <StringGraphType>("query", "The query parameter performs the full-text search")
                                              .Argument <StringGraphType>("filter", "This parameter applies a filter to the query results")
                                              .Argument <BooleanGraphType>("fuzzy", "When the fuzzy query parameter is set to true the search endpoint will also return Categorys that contain slight differences to the search text.")
                                              .Argument <IntGraphType>("fuzzyLevel", "The fuzziness level is quantified in terms of the Damerau-Levenshtein distance, this distance being the number of operations needed to transform one word into another.")
                                              .Argument <StringGraphType>("facet", "Facets calculate statistical counts to aid in faceted navigation.")
                                              .Argument <StringGraphType>("sort", "The sort expression")
                                              .Argument <ListGraphType <StringGraphType> >("categoryIds", "Category Ids")
                                              .PageSize(20);

            categoriesConnectionBuilder.ResolveAsync(async context =>
            {
                var store = await _storeService.GetByIdAsync(context.GetArgument <string>("storeId"));
                context.UserContext["store"] = store;

                //PT-1606:  Need to check what there is no any alternative way to access to the original request arguments in sub selection
                context.CopyArgumentsToUserContext();
                return(await ResolveCategoriesConnectionAsync(_mediator, context));
            });

            schema.Query.AddField(categoriesConnectionBuilder.FieldType);

            var propertiesConnectionBuilder = GraphTypeExtenstionHelper.CreateConnection <PropertyType, object>()
                                              .Name("properties")
                                              .Argument <NonNullGraphType <StringGraphType> >("storeId", "The store id to get binded catalog")
                                              .Argument <ListGraphType <PropertyTypeEnum> >("types", "The owner types (Catalog, Category, Product, Variation)")
                                              .Argument <StringGraphType>("filter", "This parameter applies a filter to the query results")
                                              .Argument <StringGraphType>("cultureName", "The language for which all localized property dictionary items will be returned")
                                              .PageSize(20);

            propertiesConnectionBuilder.ResolveAsync(async context =>
            {
                var store = await _storeService.GetByIdAsync(context.GetArgument <string>("storeId"));
                context.UserContext["catalog"] = store.Catalog;

                //PT-1606:  Need to check what there is no any alternative way to access to the original request arguments in sub selection
                context.CopyArgumentsToUserContext();
                return(await ResolvePropertiesConnectionAsync(_mediator, context));
            });

            schema.Query.AddField(propertiesConnectionBuilder.FieldType);

            var propertyField = new FieldType
            {
                Name      = "property",
                Arguments = new QueryArguments(
                    new QueryArgument <NonNullGraphType <StringGraphType> > {
                    Name = "id", Description = "id of the property"
                },
                    new QueryArgument <StringGraphType> {
                    Name = "cultureName", Description = "The language for which all localized property dictionary items will be returned"
                }
                    ),
                Type     = GraphTypeExtenstionHelper.GetActualType <PropertyType>(),
                Resolver = new AsyncFieldResolver <PropertyType, IDataLoaderResult <Property> >(context =>
                {
                    //PT-1606:  Need to check what there is no any alternative way to access to the original request arguments in sub selection
                    context.CopyArgumentsToUserContext();
                    var loader = _dataLoader.Context.GetOrAddBatchLoader <string, Property>("propertiesLoader", (ids) => LoadPropertiesAsync(_mediator, ids));
                    return(Task.FromResult(loader.LoadAsync(context.GetArgument <string>("id"))));
                })
            };

            schema.Query.AddField(propertyField);
        }
Пример #21
0
        public void Build(ISchema schema)
        {
            ValueConverter.Register <ExpOrderAddress, Optional <ExpOrderAddress> >(x => new Optional <ExpOrderAddress>(x));

            _ = schema.Query.AddField(new FieldType
            {
                Name      = "order",
                Arguments = AbstractTypeFactory <OrderQueryArguments> .TryCreateInstance(),
                Type      = GraphTypeExtenstionHelper.GetActualType <CustomerOrderType>(),
                Resolver  = new AsyncFieldResolver <object>(async context =>
                {
                    var request = context.ExtractQuery <GetOrderQuery>();

                    context.CopyArgumentsToUserContext();
                    var orderAggregate = await _mediator.Send(request);

                    var authorizationResult = await _authorizationService.AuthorizeAsync(context.GetCurrentPrincipal(), orderAggregate.Order, new CanAccessOrderAuthorizationRequirement());

                    if (!authorizationResult.Succeeded)
                    {
                        throw new AuthorizationError($"Access denied");
                    }

                    var allCurrencies = await _currencyService.GetAllCurrenciesAsync();
                    //Store all currencies in the user context for future resolve in the schema types
                    context.SetCurrencies(allCurrencies, request.CultureName);

                    //store order aggregate in the user context for future usage in the graph types resolvers
                    context.SetExpandedObjectGraph(orderAggregate);

                    return(orderAggregate);
                })
            });

            var orderConnectionBuilder = GraphTypeExtenstionHelper
                                         .CreateConnection <CustomerOrderType, object>()
                                         .Name("orders")
                                         .PageSize(20)
                                         .Arguments();

            orderConnectionBuilder.ResolveAsync(async context => await ResolveOrdersConnectionAsync(_mediator, context));
            schema.Query.AddField(orderConnectionBuilder.FieldType);

            var paymentsConnectionBuilder = GraphTypeExtenstionHelper
                                            .CreateConnection <PaymentInType, object>()
                                            .Name("payments")
                                            .PageSize(20)
                                            .Arguments();

            paymentsConnectionBuilder.ResolveAsync(async context => await ResolvePaymentsConnectionAsync(_mediator, context));
            schema.Query.AddField(paymentsConnectionBuilder.FieldType);

            _ = schema.Mutation.AddField(FieldBuilder.Create <object, CustomerOrderAggregate>(GraphTypeExtenstionHelper.GetActualType <CustomerOrderType>())
                                         .Name("createOrderFromCart")
                                         .Argument(GraphTypeExtenstionHelper.GetActualComplexType <NonNullGraphType <InputCreateOrderFromCartType> >(), _commandName)
                                         .ResolveAsync(async context =>
            {
                var type     = GenericTypeHelper.GetActualType <CreateOrderFromCartCommand>();
                var response = (CustomerOrderAggregate)await _mediator.Send(context.GetArgument(type, _commandName));
                context.SetExpandedObjectGraph(response);
                return(response);
            })
                                         .FieldType);

            _ = schema.Mutation.AddField(FieldBuilder.Create <object, bool>(typeof(BooleanGraphType))
                                         .Name("changeOrderStatus")
                                         .Argument(GraphTypeExtenstionHelper.GetActualComplexType <NonNullGraphType <InputChangeOrderStatusType> >(), _commandName)
                                         .ResolveAsync(async context =>
            {
                var type    = GenericTypeHelper.GetActualType <ChangeOrderStatusCommand>();
                var command = (ChangeOrderStatusCommand)context.GetArgument(type, _commandName);
                await CheckAuthAsync(context, command.OrderId);

                return(await _mediator.Send(command));
            })
                                         .FieldType);

            _ = schema.Mutation.AddField(FieldBuilder.Create <object, ProcessPaymentRequestResult>(typeof(ProcessPaymentRequestResultType))
                                         .Name("processOrderPayment")
                                         .Argument(GraphTypeExtenstionHelper.GetActualComplexType <NonNullGraphType <InputProcessOrderPaymentType> >(), _commandName)
                                         .ResolveAsync(async context =>
            {
                var type    = GenericTypeHelper.GetActualType <ProcessOrderPaymentCommand>();
                var command = (ProcessOrderPaymentCommand)context.GetArgument(type, _commandName);
                await CheckAuthAsync(context, command.OrderId);

                return(await _mediator.Send(command));
            })
                                         .DeprecationReason("Obsolete. Use 'initializePayment' mutation")
                                         .FieldType);

            _ = schema.Mutation.AddField(FieldBuilder.Create <object, InitializePaymentResult>(typeof(InitializePaymentResultType))
                                         .Name("initializePayment")
                                         .Argument(GraphTypeExtenstionHelper.GetActualComplexType <NonNullGraphType <InputInitializePaymentType> >(), _commandName)
                                         .ResolveAsync(async context =>
            {
                var type = GenericTypeHelper.GetActualType <InitializePaymentCommand>();

                var command = (InitializePaymentCommand)context.GetArgument(type, _commandName);
                await CheckAuthAsync(context, command.OrderId);

                return(await _mediator.Send(command));
            })
                                         .FieldType);

            _ = schema.Mutation.AddField(FieldBuilder.Create <object, AuthorizePaymentResult>(typeof(AuthorizePaymentResultType))
                                         .Name("authorizePayment")
                                         .Argument(GraphTypeExtenstionHelper.GetActualComplexType <NonNullGraphType <InputAuthorizePaymentType> >(), _commandName)
                                         .ResolveAsync(async context =>
            {
                var type = GenericTypeHelper.GetActualType <AuthorizePaymentCommand>();

                var command = (AuthorizePaymentCommand)context.GetArgument(type, _commandName);
                await CheckAuthAsync(context, command.OrderId);

                return(await _mediator.Send(command));
            })
                                         .FieldType);


            _ = schema.Mutation.AddField(FieldBuilder.Create <CustomerOrderAggregate, CustomerOrderAggregate>(GraphTypeExtenstionHelper.GetActualType <CustomerOrderType>())
                                         .Name("updateOrderDynamicProperties")
                                         .Argument(GraphTypeExtenstionHelper.GetActualComplexType <NonNullGraphType <InputUpdateOrderDynamicPropertiesType> >(), _commandName)
                                         .ResolveAsync(async context =>
            {
                var type    = GenericTypeHelper.GetActualType <UpdateOrderDynamicPropertiesCommand>();
                var command = (UpdateOrderDynamicPropertiesCommand)context.GetArgument(type, _commandName);
                await CheckAuthAsync(context, command.OrderId);

                return(await _mediator.Send(command));
            })
                                         .FieldType);

            _ = schema.Mutation.AddField(FieldBuilder.Create <CustomerOrderAggregate, CustomerOrderAggregate>(GraphTypeExtenstionHelper.GetActualType <CustomerOrderType>())
                                         .Name("updateOrderItemDynamicProperties")
                                         .Argument(GraphTypeExtenstionHelper.GetActualComplexType <NonNullGraphType <InputUpdateOrderItemDynamicPropertiesType> >(), _commandName)
                                         .ResolveAsync(async context =>
            {
                var type    = GenericTypeHelper.GetActualType <UpdateOrderItemDynamicPropertiesCommand>();
                var command = (UpdateOrderItemDynamicPropertiesCommand)context.GetArgument(type, _commandName);
                await CheckAuthAsync(context, command.OrderId);

                return(await _mediator.Send(command));
            })
                                         .FieldType);

            _ = schema.Mutation.AddField(FieldBuilder.Create <CustomerOrderAggregate, CustomerOrderAggregate>(GraphTypeExtenstionHelper.GetActualType <CustomerOrderType>())
                                         .Name("updateOrderPaymentDynamicProperties")
                                         .Argument(GraphTypeExtenstionHelper.GetActualComplexType <NonNullGraphType <InputUpdateOrderPaymentDynamicPropertiesType> >(), _commandName)
                                         .ResolveAsync(async context =>
            {
                var type    = GenericTypeHelper.GetActualType <UpdateOrderPaymentDynamicPropertiesCommand>();
                var command = (UpdateOrderPaymentDynamicPropertiesCommand)context.GetArgument(type, _commandName);
                await CheckAuthAsync(context, command.OrderId);

                return(await _mediator.Send(command));
            })
                                         .FieldType);

            _ = schema.Mutation.AddField(FieldBuilder.Create <CustomerOrderAggregate, CustomerOrderAggregate>(GraphTypeExtenstionHelper.GetActualType <CustomerOrderType>())
                                         .Name("updateOrderShipmentDynamicProperties")
                                         .Argument(GraphTypeExtenstionHelper.GetActualComplexType <NonNullGraphType <InputUpdateOrderShipmentDynamicPropertiesType> >(), _commandName)
                                         .ResolveAsync(async context =>
            {
                var type    = GenericTypeHelper.GetActualType <UpdateOrderShipmentDynamicPropertiesCommand>();
                var command = (UpdateOrderShipmentDynamicPropertiesCommand)context.GetArgument(type, _commandName);
                await CheckAuthAsync(context, command.OrderId);

                return(await _mediator.Send(command));
            })
                                         .FieldType);

            _ = schema.Mutation.AddField(FieldBuilder.Create <CustomerOrderAggregate, CustomerOrderAggregate>(GraphTypeExtenstionHelper.GetActualType <CustomerOrderType>())
                                         .Name("addOrUpdateOrderPayment")
                                         .Argument(GraphTypeExtenstionHelper.GetActualComplexType <NonNullGraphType <InputAddOrUpdateOrderPaymentType> >(), _commandName)
                                         .ResolveAsync(async context =>
            {
                var type    = GenericTypeHelper.GetActualType <AddOrUpdateOrderPaymentCommand>();
                var command = (AddOrUpdateOrderPaymentCommand)context.GetArgument(type, _commandName);
                await CheckAuthAsync(context, command.OrderId);

                var response = await _mediator.Send(command);

                context.SetExpandedObjectGraph(response);

                return(response);
            })
                                         .FieldType);
        }
        public void Build(ISchema schema)
        {
            schema.Query.AddField(new FieldType
            {
                Name     = "me",
                Type     = GraphTypeExtenstionHelper.GetActualType <UserType>(),
                Resolver = new AsyncFieldResolver <object>(async context =>
                {
                    var userName = ((GraphQLUserContext)context.UserContext).User?.Identity.Name;
                    if (!string.IsNullOrEmpty(userName))
                    {
                        var result = await _mediator.Send(new GetUserQuery
                        {
                            UserName = userName
                        });
                        return(result);
                    }
                    return(AnonymousUser.Instance);
                })
            });

            //Queries

            #region organization query

            /* organization query with contacts connection filtering:
             * {
             * organization(id: "689a72757c754bef97cde51afc663430"){
             *   id contacts(first:10, after: "0", searchPhrase: null){
             *    totalCount items {id firstName}
             *  }
             * }
             * }
             */

            #endregion
            schema.Query.AddField(new FieldType
            {
                Name      = "organization",
                Arguments = new QueryArguments(
                    new QueryArgument <NonNullGraphType <StringGraphType> > {
                    Name = "id"
                },
                    new QueryArgument <StringGraphType> {
                    Name = "userId"
                }
                    ),
                Type     = GraphTypeExtenstionHelper.GetActualType <OrganizationType>(),
                Resolver = new AsyncFieldResolver <object>(async context =>
                {
                    var organizationId        = context.GetArgument <string>("id");
                    var query                 = new GetOrganizationByIdQuery(organizationId);
                    var organizationAggregate = await _mediator.Send(query);

                    await CheckAuthAsync(context.GetCurrentUserId(), organizationAggregate);
                    //store organization aggregate in the user context for future usage in the graph types resolvers
                    context.UserContext.Add("organizationAggregate", organizationAggregate);

                    return(organizationAggregate);
                })
            });

            #region contact query
            /// <example>
#pragma warning disable S125 // Sections of code should not be commented out

            /*
             *           {
             *            contact(id: "51311ae5-371c-453b-9394-e6d352f1cea7"){
             *                firstName memberType organizationIds organizations { id businessCategory description emails groups memberType name outerId ownerId parentId phones seoObjectType }
             *                addresses { line1 phone }
             *           }
             *          }
             */
#pragma warning restore S125 // Sections of code should not be commented out
            /// </example>

            #endregion
            schema.Query.AddField(new FieldType
            {
                Name      = "contact",
                Arguments = new QueryArguments(
                    new QueryArgument <NonNullGraphType <StringGraphType> > {
                    Name = "id"
                },
                    new QueryArgument <StringGraphType> {
                    Name = "userId"
                }
                    ),
                Type     = GraphTypeExtenstionHelper.GetActualType <ContactType>(),
                Resolver = new AsyncFieldResolver <object>(async context =>
                {
                    var query            = new GetContactByIdQuery(context.GetArgument <string>("id"));
                    var contactAggregate = await _mediator.Send(query);
                    await CheckAuthAsync(context.GetCurrentUserId(), contactAggregate);
                    //store organization aggregate in the user context for future usage in the graph types resolvers
                    context.UserContext.Add("contactAggregate", contactAggregate);

                    return(contactAggregate);
                })
            });

            #region updateAddressMutation

            /// sample code for updating addresses:
#pragma warning disable S125 // Sections of code should not be commented out

            /*
             *          mutation updateAddresses($command: InputUpdateContactAddressType!){
             *          contact: updateAddresses(command: $command)
             *            {
             *              firstName lastName
             *              addresses { key city countryCode countryName email firstName  lastName line1 line2 middleName name phone postalCode regionId regionName zip }
             *            }
             *          }
             *          query variables:
             *          {
             *              "command": {
             *                "contactId": "acc3b262-a21e-45f9-a612-b4b1530d27ef",
             *                "addresses": [{"addressType": "Shipping", "name": "string", "countryCode": "string", "countryName": "string", "city": "string", "postalCode": "string", "line1": "string", "regionId": "string", "regionName": "string", "firstName": "string", "lastName": "string", "phone": "string", "email": "string", "regionId": "string"
             *                  }]
             *              }
             *          }
             */
#pragma warning restore S125 // Sections of code should not be commented out

            #endregion
            _ = schema.Mutation.AddField(FieldBuilder.Create <ContactAggregate, ContactAggregate>(typeof(ContactType))
                                         .Name("updateAddresses")
                                         .Argument <NonNullGraphType <InputUpdateContactAddressType> >(_commandName)
                                         .ResolveAsync(async context =>
            {
                var command = context.GetArgument <UpdateContactAddressesCommand>(_commandName);
                await CheckAuthAsync(context.GetCurrentUserId(), command);
                return(await _mediator.Send(command));
            })
                                         .FieldType);


            _ = schema.Mutation.AddField(FieldBuilder.Create <OrganizationAggregate, OrganizationAggregate>(typeof(OrganizationType))
                                         .Name("updateOrganization")
                                         .Argument <NonNullGraphType <InputUpdateOrganizationType> >(_commandName)
                                         .ResolveAsync(async context =>
            {
                var command = context.GetArgument <UpdateOrganizationCommand>(_commandName);
                await CheckAuthAsync(context.GetCurrentUserId(), command, CustomerModule.Core.ModuleConstants.Security.Permissions.Update);
                return(await _mediator.Send(command));
            })
                                         .FieldType);

            _ = schema.Mutation.AddField(FieldBuilder.Create <OrganizationAggregate, OrganizationAggregate>(typeof(OrganizationType))
                                         .Name("createOrganization")
                                         .Argument <NonNullGraphType <InputCreateOrganizationType> >(_commandName)
                                         .ResolveAsync(async context =>
            {
                var command = context.GetArgument <CreateOrganizationCommand>(_commandName);
                await CheckAuthAsync(context.GetCurrentUserId(), command);
                return(await _mediator.Send(command));
            })
                                         .FieldType);

            _ = schema.Mutation.AddField(FieldBuilder.Create <ContactAggregate, ContactAggregate>(typeof(ContactType))
                                         .Name("createContact")
                                         .Argument <NonNullGraphType <InputCreateContactType> >(_commandName)
                                         .ResolveAsync(async context =>
            {
                var command = context.GetArgument <CreateContactCommand>(_commandName);
                await CheckAuthAsync(context.GetCurrentUserId(), command);

                return(await _mediator.Send(command));
            })
                                         .FieldType);

            _ = schema.Mutation.AddField(FieldBuilder.Create <ContactAggregate, ContactAggregate>(typeof(ContactType))
                                         .Name("updateContact")
                                         .Argument <NonNullGraphType <InputUpdateContactType> >(_commandName)
                                         .ResolveAsync(async context =>
            {
                var command = context.GetArgument <UpdateContactCommand>(_commandName);
                await CheckAuthAsync(context.GetCurrentUserId(), command);
                return(await _mediator.Send(command));
            })
                                         .FieldType);

            _ = schema.Mutation.AddField(FieldBuilder.Create <ContactAggregate, bool>(typeof(BooleanGraphType))
                                         .Name("deleteContact")
                                         .Argument <NonNullGraphType <InputDeleteContactType> >(_commandName)
                                         .ResolveAsync(async context =>
            {
                var command = context.GetArgument <DeleteContactCommand>(_commandName);
                await CheckAuthAsync(context.GetCurrentUserId(), command, CustomerModule.Core.ModuleConstants.Security.Permissions.Delete);
                return(await _mediator.Send(command));
            })
                                         .FieldType);

            _ = schema.Mutation.AddField(FieldBuilder.Create <object, IdentityResult>(typeof(IdentityResultType))
                                         .Name("updatePersonalData")
                                         .Argument <NonNullGraphType <InputUpdatePersonalDataType> >(_commandName)
                                         .ResolveAsync(async context =>
            {
                var command = context.GetArgument <UpdatePersonalDataCommand>(_commandName);
                await CheckAuthAsync(context.GetCurrentUserId(), command);
                return(await _mediator.Send(command));
            })
                                         .FieldType);

            // Security API fields

            #region user query

#pragma warning disable S125 // Sections of code should not be commented out

            /*
             *              {
             *                  user(id: "1eb2fa8ac6574541afdb525833dadb46"){
             *                  userName isAdministrator roles { name } userType memberId storeId
             *                  }
             *              }
             */
#pragma warning restore S125 // Sections of code should not be commented out

            #endregion
            _ = schema.Query.AddField(new FieldType
            {
                Name      = "user",
                Arguments = new QueryArguments(
                    new QueryArgument <StringGraphType> {
                    Name = "id"
                },
                    new QueryArgument <StringGraphType> {
                    Name = "userName"
                },
                    new QueryArgument <StringGraphType> {
                    Name = "email"
                },
                    new QueryArgument <StringGraphType> {
                    Name = "loginProvider"
                },
                    new QueryArgument <StringGraphType> {
                    Name = "providerKey"
                }),
                Type     = GraphTypeExtenstionHelper.GetActualType <UserType>(),
                Resolver = new AsyncFieldResolver <object>(async context =>
                {
                    var user = await _mediator.Send(new GetUserQuery(
                                                        id: context.GetArgument <string>("id"),
                                                        userName: context.GetArgument <string>("userName"),
                                                        email: context.GetArgument <string>("email"),
                                                        loginProvider: context.GetArgument <string>("loginProvider"),
                                                        providerKey: context.GetArgument <string>("providerKey")));

                    await CheckAuthAsync(context.GetCurrentUserId(), user);

                    return(user);
                })
            });

            #region role query

#pragma warning disable S125 // Sections of code should not be commented out

            /*
             *           {
             *            getRole(roleName: "Use api"){
             *             permissions
             *            }
             *          }
             */
#pragma warning restore S125 // Sections of code should not be commented out

            #endregion
            _ = schema.Query.AddField(new FieldType
            {
                Name      = "role",
                Arguments = new QueryArguments(
                    new QueryArgument <NonNullGraphType <StringGraphType> > {
                    Name = "roleName"
                }
                    ),
                Type     = GraphTypeExtenstionHelper.GetActualType <RoleType>(),
                Resolver = new AsyncFieldResolver <object>(async context =>
                {
                    var result = await _mediator.Send(new GetRoleQuery(context.GetArgument <string>("roleName")));

                    return(result);
                })
            });

            #region create user

#pragma warning disable S125 // Sections of code should not be commented out

            /*
             * mutation ($command: InputCreateUserType!){
             *  createUser(command: $command){ succeeded errors { code }}
             * }
             * Query variables:
             * {
             *  "command": {
             *  "createdBy": "eXp1", "email": "*****@*****.**", "password":"******", "userName": "******", "userType": "Customer"
             *  }
             * }
             */
#pragma warning restore S125 // Sections of code should not be commented out

            #endregion
            _ = schema.Mutation.AddField(FieldBuilder.Create <object, IdentityResult>(typeof(IdentityResultType))
                                         .Name("createUser")
                                         .Argument <NonNullGraphType <InputCreateUserType> >(_commandName)
                                         .ResolveAsync(async context =>
            {
                var command = context.GetArgument <CreateUserCommand>(_commandName);
                await CheckAuthAsync(context.GetCurrentUserId(), command);
                return(await _mediator.Send(command));
            })
                                         .FieldType);

            #region update user

#pragma warning disable S125 // Sections of code should not be commented out

            /*
             *           mutation ($command: InputUpdateUserType!){
             *            updateUser(command: $command){ succeeded errors { description } }
             *          }
             *          Query variables:
             *          {
             *           "command":{
             *            "isAdministrator": false,
             *            "userType": "Customer",
             *            "roles": [],
             *            "id": "b5d28a83-c296-4212-b89e-046fca3866be",
             *            "userName": "******",
             *            "email": "*****@*****.**"
             *              }
             *          }
             */
#pragma warning restore S125 // Sections of code should not be commented out

            #endregion
            _ = schema.Mutation.AddField(FieldBuilder.Create <object, IdentityResult>(typeof(IdentityResultType))
                                         .Name("updateUser")
                                         .Argument <NonNullGraphType <InputUpdateUserType> >(_commandName)
                                         .ResolveAsync(async context =>
            {
                var command = context.GetArgument <UpdateUserCommand>(_commandName);
                await CheckAuthAsync(context.GetCurrentUserId(), command);
                return(await _mediator.Send(command));
            })
                                         .FieldType);

            #region delete user

#pragma warning disable S125 // Sections of code should not be commented out

            /*
             * mutation ($command: InputDeleteUserType!){
             * deleteUser(command: $command){ succeeded errors { description } }
             * }
             * Query variables:
             * {
             * "command": {
             *  "userNames": ["admin",  "*****@*****.**"]
             * }
             * }
             */
#pragma warning restore S125 // Sections of code should not be commented out

            #endregion
            _ = schema.Mutation.AddField(FieldBuilder.Create <object, IdentityResult>(typeof(IdentityResultType))
                                         .Name("deleteUsers")
                                         .Argument <NonNullGraphType <InputDeleteUserType> >(_commandName)
                                         .ResolveAsync(async context =>
            {
                var command = context.GetArgument <DeleteUserCommand>(_commandName);
                await CheckAuthAsync(context.GetCurrentUserId(), command, PlatformConstants.Security.Permissions.SecurityDelete);
                return(await _mediator.Send(command));
            })
                                         .FieldType);

            #region update role query

#pragma warning disable S125 // Sections of code should not be commented out

            /*
             *           mutation ($command: InputUpdateRoleType!){
             *            updateRole(command: $command){ succeeded errors { description } }
             *          }
             *          Query variables:
             *          {
             *           "command":{
             *           "id": "graphtest",  "name": "graphtest", "permissions": [
             *              { "name": "order:read", "assignedScopes": [{"scope": "{{userId}}", "type": "OnlyOrderResponsibleScope" }] }
             *            ]
             *           }
             *          }
             */
#pragma warning restore S125 // Sections of code should not be commented out

            #endregion
            _ = schema.Mutation.AddField(FieldBuilder.Create <object, IdentityResult>(typeof(IdentityResultType))
                                         .Name("updateRole")
                                         .Argument <NonNullGraphType <InputUpdateRoleType> >(_commandName)
                                         .ResolveAsync(async context =>
            {
                var command = context.GetArgument <UpdateRoleCommand>(_commandName);
                await CheckAuthAsync(context.GetCurrentUserId(), command, PlatformConstants.Security.Permissions.SecurityUpdate);

                return(await _mediator.Send(command));
            })
                                         .FieldType);
        }
Пример #23
0
        /// <example>
        ///{
        ///    product(id: "f1b26974b7634abaa0900e575a99476f")
        ///    {
        ///        id
        ///        code
        ///        category{ id code name hasParent slug }
        ///        name
        ///        metaTitle
        ///        metaDescription
        ///        metaKeywords
        ///        brandName
        ///        slug
        ///        imgSrc
        ///        productType
        ///        masterVariation {
        ///        images{ id url name }
        ///        assets{ id size url }
        ///        prices(cultureName: "en-us"){
        ///            list { amount }
        ///            currency
        ///        }
        ///        availabilityData{
        ///            availableQuantity
        ///            inventories{
        ///                inStockQuantity
        ///                fulfillmentCenterId
        ///                fulfillmentCenterName
        ///                allowPreorder
        ///                allowBackorder
        ///            }
        ///        }
        ///        properties{ id name valueType value valueId }
        ///    }
        ///}
        /// </example>
        public ProductType(IMediator mediator, IDataLoaderContextAccessor dataLoader)
        {
            Name        = "Product";
            Description = "Products are the sellable goods in an e-commerce project.";

            Field(d => d.IndexedProduct.Id).Description("The unique ID of the product.");
            Field(d => d.IndexedProduct.Code, nullable: false).Description("The product SKU.");
            Field <StringGraphType>("catalogId",
                                    "The unique ID of the catalog",
                                    resolve: context => context.Source.IndexedProduct.CatalogId);
            Field(d => d.IndexedProduct.ProductType, nullable: true).Description("The type of product");
            Field(d => d.IndexedProduct.MinQuantity, nullable: true).Description("Min. quantity");
            Field(d => d.IndexedProduct.MaxQuantity, nullable: true).Description("Max. quantity");

            FieldAsync <StringGraphType>("outline", resolve: async context =>
            {
                var outlines = context.Source.IndexedProduct.Outlines;
                if (outlines.IsNullOrEmpty())
                {
                    return(null);
                }

                var loadRelatedCatalogOutlineQuery      = context.GetCatalogQuery <LoadRelatedCatalogOutlineQuery>();
                loadRelatedCatalogOutlineQuery.Outlines = outlines;

                var response = await mediator.Send(loadRelatedCatalogOutlineQuery);
                return(response.Outline);
            }, description: @"All parent categories ids relative to the requested catalog and concatenated with \ . E.g. (1/21/344)");

            FieldAsync <StringGraphType>("slug", resolve: async context =>
            {
                var outlines = context.Source.IndexedProduct.Outlines;
                if (outlines.IsNullOrEmpty())
                {
                    return(null);
                }

                var loadRelatedSlugPathQuery      = context.GetCatalogQuery <LoadRelatedSlugPathQuery>();
                loadRelatedSlugPathQuery.Outlines = outlines;

                var response = await mediator.Send(loadRelatedSlugPathQuery);
                return(response.Slug);
            }, description: "Request related slug for product");

            Field(d => d.IndexedProduct.Name, nullable: false).Description("The name of the product.");

            Field <SeoInfoType>("seoInfo", resolve: context =>
            {
                var source      = context.Source;
                var storeId     = context.GetArgumentOrValue <string>("storeId");
                var cultureName = context.GetArgumentOrValue <string>("cultureName");

                SeoInfo seoInfo = null;

                if (!source.IndexedProduct.SeoInfos.IsNullOrEmpty())
                {
                    seoInfo = source.IndexedProduct.SeoInfos.GetBestMatchingSeoInfo(storeId, cultureName);
                }

                return(seoInfo ?? GetFallbackSeoInfo(source, cultureName));
            }, description: "Request related SEO info");

            Field <ListGraphType <DescriptionType> >("descriptions",
                                                     arguments: new QueryArguments(new QueryArgument <StringGraphType> {
                Name = "type"
            }),
                                                     resolve: context =>
            {
                var reviews     = context.Source.IndexedProduct.Reviews;
                var cultureName = context.GetArgumentOrValue <string>("cultureName");
                var type        = context.GetArgumentOrValue <string>("type");
                if (cultureName != null)
                {
                    reviews = reviews.Where(x => string.IsNullOrEmpty(x.LanguageCode) || x.LanguageCode.EqualsInvariant(cultureName)).ToList();
                }
                if (type != null)
                {
                    reviews = reviews.Where(x => x.ReviewType?.EqualsInvariant(type) ?? true).ToList();
                }
                return(reviews);
            });

            Field <DescriptionType>("description",
                                    arguments: new QueryArguments(new QueryArgument <StringGraphType> {
                Name = "type"
            }),
                                    resolve: context =>
            {
                var reviews     = context.Source.IndexedProduct.Reviews;
                var type        = context.GetArgumentOrValue <string>("type");
                var cultureName = context.GetArgumentOrValue <string>("cultureName");

                if (!reviews.IsNullOrEmpty())
                {
                    return(reviews.Where(x => x.ReviewType.EqualsInvariant(type ?? "FullReview")).FirstBestMatchForLanguage(cultureName) as EditorialReview
                           ?? reviews.FirstBestMatchForLanguage(cultureName) as EditorialReview);
                }

                return(null);
            });

            FieldAsync <CategoryType>(
                "category",
                resolve: async context =>
            {
                var categoryId = context.Source.IndexedProduct.CategoryId;

                var loadCategoryQuery           = context.GetCatalogQuery <LoadCategoryQuery>();
                loadCategoryQuery.ObjectIds     = new[] { categoryId };
                loadCategoryQuery.IncludeFields = context.SubFields.Values.GetAllNodesPaths();

                var responce = await mediator.Send(loadCategoryQuery);

                return(responce.Categories.FirstOrDefault());
            });

            Field <StringGraphType>(
                "imgSrc",
                description: "The product main image URL.",
                resolve: context => context.Source.IndexedProduct.ImgSrc);

            Field(d => d.IndexedProduct.OuterId, nullable: true).Description("The outer identifier");

            Field <StringGraphType>(
                "brandName",
                description: "Get brandName for product.",
                resolve: context =>
            {
                var brandName = context.Source.IndexedProduct.Properties
                                ?.FirstOrDefault(x => x.Name.EqualsInvariant("Brand"))
                                ?.Values
                                ?.FirstOrDefault(x => x.Value != null)
                                ?.Value;

                return(brandName?.ToString());
            });

            FieldAsync <VariationType>(
                "masterVariation",
                resolve: async context =>
            {
                if (string.IsNullOrEmpty(context.Source.IndexedProduct.MainProductId))
                {
                    return(null);
                }

                var query           = context.GetCatalogQuery <LoadProductsQuery>();
                query.ObjectIds     = new[] { context.Source.IndexedProduct.MainProductId };
                query.IncludeFields = context.SubFields.Values.GetAllNodesPaths();

                var response = await mediator.Send(query);

                return(response.Products.Select(expProduct => new ExpVariation(expProduct)).FirstOrDefault());
            });

            FieldAsync <ListGraphType <VariationType> >(
                "variations",
                resolve: async context =>
            {
                var productIds = context.Source.IndexedVariationIds.ToArray();
                if (productIds.IsNullOrEmpty())
                {
                    return(new List <ExpVariation>());
                }

                var query           = context.GetCatalogQuery <LoadProductsQuery>();
                query.ObjectIds     = context.Source.IndexedVariationIds.ToArray();
                query.IncludeFields = context.SubFields.Values.GetAllNodesPaths();

                var response = await mediator.Send(query);

                return(response.Products.Select(expProduct => new ExpVariation(expProduct)));
            });

            Field <BooleanGraphType>(
                "hasVariations",
                resolve: context =>
            {
                var result = context.Source.IndexedVariationIds?.Any() ?? false;
                return(result);
            });

            Field(
                GraphTypeExtenstionHelper.GetActualType <AvailabilityDataType>(),
                "availabilityData",
                "Product availability data",
                resolve: context => new ExpAvailabilityData
            {
                AvailableQuantity = context.Source.AvailableQuantity,
                InventoryAll      = context.Source.AllInventories,
                IsBuyable         = context.Source.IsBuyable,
                IsAvailable       = context.Source.IsAvailable,
                IsInStock         = context.Source.IsInStock,
                IsActive          = context.Source.IndexedProduct.IsActive ?? false,
                IsTrackInventory  = context.Source.IndexedProduct.TrackInventory ?? false,
            });

            Field <ListGraphType <ImageType> >(
                "images",
                "Product images",
                resolve: context =>
            {
                var images = context.Source.IndexedProduct.Images;

                return(context.GetValue <string>("cultureName") switch
                {
                    // Get images with null or current cultureName value if cultureName is passed
                    string languageCode => images.Where(x => string.IsNullOrEmpty(x.LanguageCode) || x.LanguageCode.EqualsInvariant(languageCode)).ToList(),

                    // CultureName is null
                    _ => images
                });
        public OrderLineItemType(IMediator mediator, IDataLoaderContextAccessor dataLoader, IDynamicPropertyResolverService dynamicPropertyResolverService)
        {
            Field(x => x.Id);
            Field(x => x.ProductType, true);
            Field(x => x.Name);
            Field(x => x.Comment, true);
            Field(x => x.ImageUrl, true);
            Field(x => x.IsGift, true);
            Field(x => x.ShippingMethodCode, true);
            Field(x => x.FulfillmentLocationCode, true);
            Field(x => x.FulfillmentCenterId, true);
            Field(x => x.FulfillmentCenterName, true);
            Field(x => x.OuterId, true);
            Field(x => x.WeightUnit, true);
            Field(x => x.Weight, true);
            Field(x => x.MeasureUnit, true);
            Field(x => x.Height, true);
            Field(x => x.Length, true);
            Field(x => x.Width, true);
            Field(x => x.IsCancelled);
            Field(x => x.CancelledDate, true);
            Field(x => x.CancelReason, true);
            Field(x => x.ObjectType);

            Field(x => x.CategoryId, true);
            Field(x => x.CatalogId);

            Field(x => x.Sku);
            Field(x => x.PriceId, true);
            Field <MoneyType>(nameof(LineItem.Price).ToCamelCase(), resolve: context => new Money(context.Source.Price, context.GetOrderCurrency()));
            Field <MoneyType>(nameof(LineItem.PriceWithTax).ToCamelCase(), resolve: context => new Money(context.Source.PriceWithTax, context.GetOrderCurrency()));
            Field(x => x.TaxType, true);
            Field(x => x.TaxPercentRate);
            Field(x => x.ReserveQuantity);
            Field(x => x.Quantity);
            Field(x => x.ProductId);

            Field <CurrencyType>(nameof(LineItem.Currency).ToCamelCase(), resolve: context => context.GetOrderCurrency());
            Field <MoneyType>(nameof(LineItem.DiscountAmount).ToCamelCase(), resolve: context => new Money(context.Source.DiscountAmount, context.GetOrderCurrency()));
            Field <MoneyType>(nameof(LineItem.DiscountAmountWithTax).ToCamelCase(), resolve: context => new Money(context.Source.DiscountAmountWithTax, context.GetOrderCurrency()));
            Field <MoneyType>(nameof(LineItem.DiscountTotal).ToCamelCase(), resolve: context => new Money(context.Source.DiscountTotal, context.GetOrderCurrency()));
            Field <MoneyType>(nameof(LineItem.DiscountTotalWithTax).ToCamelCase(), resolve: context => new Money(context.Source.DiscountTotalWithTax, context.GetOrderCurrency()));
            Field <MoneyType>(nameof(LineItem.ExtendedPrice).ToCamelCase(), resolve: context => new Money(context.Source.ExtendedPrice, context.GetOrderCurrency()));
            Field <MoneyType>(nameof(LineItem.ExtendedPriceWithTax).ToCamelCase(), resolve: context => new Money(context.Source.ExtendedPriceWithTax, context.GetOrderCurrency()));
            Field <MoneyType>(nameof(LineItem.PlacedPrice).ToCamelCase(), resolve: context => new Money(context.Source.PlacedPrice, context.GetOrderCurrency()));
            Field <MoneyType>(nameof(LineItem.PlacedPriceWithTax).ToCamelCase(), resolve: context => new Money(context.Source.PlacedPriceWithTax, context.GetOrderCurrency()));
            Field <MoneyType>(nameof(LineItem.TaxTotal).ToCamelCase(), resolve: context => new Money(context.Source.TaxTotal, context.GetOrderCurrency()));
            Field <NonNullGraphType <ListGraphType <OrderTaxDetailType> > >(nameof(LineItem.TaxDetails), resolve: x => x.Source.TaxDetails);
            Field <NonNullGraphType <ListGraphType <OrderDiscountType> > >(nameof(LineItem.Discounts), resolve: x => x.Source.Discounts);

            var productField = new FieldType
            {
                Name     = "product",
                Type     = GraphTypeExtenstionHelper.GetActualType <ProductType>(),
                Resolver = new FuncFieldResolver <LineItem, IDataLoaderResult <ExpProduct> >(context =>
                {
                    var includeFields = context.SubFields.Values.GetAllNodesPaths();
                    var loader        = dataLoader.Context.GetOrAddBatchLoader <string, ExpProduct>("order_lineItems_products", async(ids) =>
                    {
                        //Get currencies and store only from one order.
                        //We intentionally ignore the case when there are ma be the orders with the different currencies and stores in the resulting set
                        var order   = context.GetValueForSource <CustomerOrderAggregate>().Order;
                        var request = new LoadProductsQuery
                        {
                            StoreId       = order.StoreId,
                            CurrencyCode  = order.Currency,
                            ObjectIds     = ids.ToArray(),
                            IncludeFields = includeFields.ToArray()
                        };
                        if (!context.UserContext.ContainsKey("storeId"))
                        {
                            context.UserContext.Add("storeId", order.StoreId);
                        }

                        var response = await mediator.Send(request);

                        return(response.Products.ToDictionary(x => x.Id));
                    });

                    return(loader.LoadAsync(context.Source.ProductId));
                })
            };

            AddField(productField);

            ExtendableField <ListGraphType <DynamicPropertyValueType> >(
                "dynamicProperties",
                "Customer order Line item dynamic property values",
                QueryArgumentPresets.GetArgumentForDynamicProperties(),
                context => dynamicPropertyResolverService.LoadDynamicPropertyValues(context.Source, context.GetArgumentOrValue <string>("cultureName")));
        }
        public CustomerOrderType()
        {
            Field(x => x.Order.Id);
            Field(x => x.Order.OperationType);
            Field(x => x.Order.ParentOperationId, true);
            Field(x => x.Order.Number);
            Field(x => x.Order.IsApproved);
            Field(x => x.Order.Status, true);
            Field(x => x.Order.Comment, true);
            Field(x => x.Order.OuterId, true);
            Field(x => x.Order.IsCancelled);
            Field(x => x.Order.CancelledDate, true);
            Field(x => x.Order.CancelReason, true);
            Field(x => x.Order.ObjectType);
            Field(x => x.Order.CustomerId);
            Field(x => x.Order.CustomerName, true);
            Field(x => x.Order.ChannelId, true);
            Field(x => x.Order.StoreId);
            Field(x => x.Order.StoreName, true);
            Field(x => x.Order.OrganizationId, true);
            Field(x => x.Order.OrganizationName, true);
            Field(x => x.Order.EmployeeId, true);
            Field(x => x.Order.EmployeeName, true);
            Field(x => x.Order.ShoppingCartId, true);
            Field(x => x.Order.IsPrototype);
            Field(x => x.Order.SubscriptionNumber, true);
            Field(x => x.Order.SubscriptionId, true);
            Field(x => x.Order.Fee);
            Field(x => x.Order.FeeWithTax);
            Field(x => x.Order.FeeTotal);
            Field(x => x.Order.FeeTotalWithTax);
            Field(x => x.Order.TaxType, true);

            Field(x => x.Order.TaxPercentRate);
            Field(x => x.Order.LanguageCode, true);
            Field(x => x.Order.CreatedDate);
            Field(x => x.Order.CreatedBy, true);
            Field(x => x.Order.ModifiedDate, true);
            Field(x => x.Order.ModifiedBy, true);

            Field <CurrencyType>(nameof(CustomerOrder.Currency).ToCamelCase(), resolve: context => context.Source.Currency);
            Field <MoneyType>(nameof(CustomerOrder.Total).ToCamelCase(), resolve: context => new Money(context.Source.Order.Total, context.Source.Currency));
            Field <MoneyType>(nameof(CustomerOrder.TaxTotal).ToCamelCase(), resolve: context => new Money(context.Source.Order.TaxTotal, context.Source.Currency));
            Field <MoneyType>(nameof(CustomerOrder.DiscountAmount).ToCamelCase(), resolve: context => new Money(context.Source.Order.DiscountAmount, context.Source.Currency));
            Field <MoneyType>(nameof(CustomerOrder.SubTotal).ToCamelCase(), resolve: context => new Money(context.Source.Order.SubTotal, context.Source.Currency));
            Field <MoneyType>(nameof(CustomerOrder.SubTotalWithTax).ToCamelCase(), resolve: context => new Money(context.Source.Order.SubTotalWithTax, context.Source.Currency));
            Field <MoneyType>(nameof(CustomerOrder.SubTotalDiscount).ToCamelCase(), resolve: context => new Money(context.Source.Order.SubTotalDiscount, context.Source.Currency));
            Field <MoneyType>(nameof(CustomerOrder.SubTotalDiscountWithTax).ToCamelCase(), resolve: context => new Money(context.Source.Order.SubTotalDiscountWithTax, context.Source.Currency));
            Field <MoneyType>(nameof(CustomerOrder.SubTotalTaxTotal).ToCamelCase(), resolve: context => new Money(context.Source.Order.SubTotalTaxTotal, context.Source.Currency));
            Field <MoneyType>(nameof(CustomerOrder.ShippingTotal).ToCamelCase(), resolve: context => new Money(context.Source.Order.ShippingTotal, context.Source.Currency));
            Field <MoneyType>(nameof(CustomerOrder.ShippingTotalWithTax).ToCamelCase(), resolve: context => new Money(context.Source.Order.ShippingTotalWithTax, context.Source.Currency));
            Field <MoneyType>(nameof(CustomerOrder.ShippingSubTotal).ToCamelCase(), resolve: context => new Money(context.Source.Order.ShippingSubTotal, context.Source.Currency));
            Field <MoneyType>(nameof(CustomerOrder.ShippingSubTotalWithTax).ToCamelCase(), resolve: context => new Money(context.Source.Order.ShippingSubTotalWithTax, context.Source.Currency));
            Field <MoneyType>(nameof(CustomerOrder.ShippingDiscountTotal).ToCamelCase(), resolve: context => new Money(context.Source.Order.ShippingDiscountTotal, context.Source.Currency));
            Field <MoneyType>(nameof(CustomerOrder.ShippingDiscountTotalWithTax).ToCamelCase(), resolve: context => new Money(context.Source.Order.ShippingDiscountTotalWithTax, context.Source.Currency));
            Field <MoneyType>(nameof(CustomerOrder.ShippingTaxTotal).ToCamelCase(), resolve: context => new Money(context.Source.Order.ShippingTaxTotal, context.Source.Currency));
            Field <MoneyType>(nameof(CustomerOrder.PaymentTotal).ToCamelCase(), resolve: context => new Money(context.Source.Order.PaymentTotal, context.Source.Currency));
            Field <MoneyType>(nameof(CustomerOrder.PaymentTotalWithTax).ToCamelCase(), resolve: context => new Money(context.Source.Order.PaymentTotalWithTax, context.Source.Currency));
            Field <MoneyType>(nameof(CustomerOrder.PaymentSubTotal).ToCamelCase(), resolve: context => new Money(context.Source.Order.PaymentSubTotal, context.Source.Currency));
            Field <MoneyType>(nameof(CustomerOrder.PaymentSubTotalWithTax).ToCamelCase(), resolve: context => new Money(context.Source.Order.PaymentSubTotalWithTax, context.Source.Currency));
            Field <MoneyType>(nameof(CustomerOrder.PaymentDiscountTotal).ToCamelCase(), resolve: context => new Money(context.Source.Order.PaymentDiscountTotal, context.Source.Currency));
            Field <MoneyType>(nameof(CustomerOrder.PaymentDiscountTotalWithTax).ToCamelCase(), resolve: context => new Money(context.Source.Order.PaymentDiscountTotalWithTax, context.Source.Currency));
            Field <MoneyType>(nameof(CustomerOrder.PaymentTaxTotal).ToCamelCase(), resolve: context => new Money(context.Source.Order.PaymentTaxTotal, context.Source.Currency));
            Field <MoneyType>(nameof(CustomerOrder.DiscountTotal).ToCamelCase(), resolve: context => new Money(context.Source.Order.DiscountTotal, context.Source.Currency));
            Field <MoneyType>(nameof(CustomerOrder.DiscountTotalWithTax).ToCamelCase(), resolve: context => new Money(context.Source.Order.DiscountTotalWithTax, context.Source.Currency));

            Field <NonNullGraphType <ListGraphType <OrderAddressType> > >(nameof(CustomerOrder.Addresses), resolve: x => x.Source.Order.Addresses);
            Field <NonNullGraphType <ListGraphType <OrderLineItemType> > >(nameof(CustomerOrder.Items), resolve: x => x.Source.Order.Items);
            Field <NonNullGraphType <ListGraphType <PaymentInType> > >(nameof(CustomerOrder.InPayments), resolve: x => x.Source.Order.InPayments);
            //Field<NonNullGraphType<ListGraphType<OrderShipmentType>>>(nameof(CustomerOrder.Shipments), resolve: x => x.Source.Order.Shipments);
            //TODO: By this registration we support the schema types extensions. Need to move this code into extensions and replace everywhere to this version.
            var orderShipmentsField = new FieldType
            {
                Name     = "shipments",
                Type     = typeof(ListGraphType <>).MakeGenericType(GraphTypeExtenstionHelper.GetActualType <OrderShipmentType>()),
                Resolver = new FuncFieldResolver <CustomerOrderAggregate, object>(context => context.Source.Order.Shipments)
            };

            AddField(orderShipmentsField);

            Field <NonNullGraphType <ListGraphType <OrderTaxDetailType> > >(nameof(CustomerOrder.TaxDetails), resolve: x => x.Source.Order.TaxDetails);
            //TODO
            //public ICollection<DynamicObjectProperty> DynamicProperties);
        }
Пример #26
0
        public void Build(ISchema schema)
        {
            _ = schema.Query.AddField(new FieldType
            {
                Name      = "order",
                Arguments = new QueryArguments(
                    new QueryArgument <StringGraphType> {
                    Name = "id"
                },
                    new QueryArgument <StringGraphType> {
                    Name = "number"
                },
                    new QueryArgument <StringGraphType> {
                    Name = "cultureName", Description = "Culture name (\"en-US\")"
                }),
                Type     = GraphTypeExtenstionHelper.GetActualType <CustomerOrderType>(),
                Resolver = new AsyncFieldResolver <object>(async context =>
                {
                    var request = new GetOrderQuery
                    {
                        Number      = context.GetArgument <string>("number"),
                        OrderId     = context.GetArgument <string>("id"),
                        CultureName = context.GetArgument <string>(nameof(Currency.CultureName))
                    };

                    var orderAggregate = await _mediator.Send(request);

                    var authorizationResult = await _authorizationService.AuthorizeAsync(context.GetCurrentPrincipal(), orderAggregate.Order, new CanAccessOrderAuthorizationRequirement());

                    if (!authorizationResult.Succeeded)
                    {
                        throw new ExecutionError($"Access denied");
                    }

                    var allCurrencies = await _currencyService.GetAllCurrenciesAsync();
                    //Store all currencies in the user context for future resolve in the schema types
                    context.SetCurrencies(allCurrencies, request.CultureName);

                    //store order aggregate in the user context for future usage in the graph types resolvers
                    context.SetExpandedObjectGraph(orderAggregate);

                    return(orderAggregate);
                })
            });

            var orderConnectionBuilder = GraphTypeExtenstionHelper.CreateConnection <CustomerOrderType, object>()
                                         .Name("orders")
                                         .Argument <StringGraphType>("filter", "This parameter applies a filter to the query results")
                                         .Argument <StringGraphType>("sort", "The sort expression")
                                         .Argument <StringGraphType>("cultureName", "Culture name (\"en-US\")")
                                         .Argument <StringGraphType>("userId", "")
                                         .Unidirectional()
                                         .PageSize(20);

            orderConnectionBuilder.ResolveAsync(async context => await ResolveOrdersConnectionAsync(_mediator, context));

            schema.Query.AddField(orderConnectionBuilder.FieldType);


            var paymentsConnectionBuilder = GraphTypeExtenstionHelper.CreateConnection <PaymentInType, object>()
                                            .Name("payments")
                                            .Argument <StringGraphType>("filter", "This parameter applies a filter to the query results")
                                            .Argument <StringGraphType>("sort", "The sort expression")
                                            .Argument <StringGraphType>("cultureName", "Culture name (\"en-US\")")
                                            .Argument <NonNullGraphType <StringGraphType> >("userId", "")
                                            .Unidirectional()
                                            .PageSize(20);

            paymentsConnectionBuilder.ResolveAsync(async context => await ResolvePaymentsConnectionAsync(_mediator, context));
            schema.Query.AddField(paymentsConnectionBuilder.FieldType);


            _ = schema.Mutation.AddField(FieldBuilder.Create <object, CustomerOrderAggregate>(typeof(CustomerOrderType))
                                         .Name("createOrderFromCart")
                                         .Argument <NonNullGraphType <InputCreateOrderFromCartType> >(_commandName)
                                         .ResolveAsync(async context =>
            {
                var response = await _mediator.Send(context.GetArgument <CreateOrderFromCartCommand>(_commandName));
                context.SetExpandedObjectGraph(response);
                return(response);
            })
                                         .FieldType);

            _ = schema.Mutation.AddField(FieldBuilder.Create <object, bool>(typeof(BooleanGraphType))
                                         .Name("changeOrderStatus")
                                         .Argument <NonNullGraphType <InputChangeOrderStatusType> >(_commandName)
                                         .ResolveAsync(async context =>
            {
                var command = context.GetArgument <ChangeOrderStatusCommand>(_commandName);

                var order = await _customerOrderService.GetByIdAsync(command.OrderId);

                var authorizationResult = await _authorizationService.AuthorizeAsync(context.GetCurrentPrincipal(), order, new CanAccessOrderAuthorizationRequirement());

                if (!authorizationResult.Succeeded)
                {
                    throw new ExecutionError($"Access denied");
                }

                return(await _mediator.Send(command));
            })
                                         .FieldType);

            _ = schema.Mutation.AddField(FieldBuilder.Create <object, bool>(typeof(BooleanGraphType))
                                         .Name("confirmOrderPayment")
                                         .Argument <NonNullGraphType <InputConfirmOrderPaymentType> >(_commandName)
                                         .ResolveAsync(async context =>
            {
                var command = context.GetArgument <ConfirmOrderPaymentCommand>(_commandName);
                var order   = await _customerOrderService.GetByIdAsync(command.Payment.OrderId);

                var authorizationResult = await _authorizationService.AuthorizeAsync(context.GetCurrentPrincipal(), order, new CanAccessOrderAuthorizationRequirement());

                if (!authorizationResult.Succeeded)
                {
                    throw new ExecutionError($"Access denied");
                }

                return(await _mediator.Send(command));
            })
                                         .FieldType);

            _ = schema.Mutation.AddField(FieldBuilder.Create <object, bool>(typeof(BooleanGraphType))
                                         .Name("cancelOrderPayment")
                                         .Argument <NonNullGraphType <InputCancelOrderPaymentType> >(_commandName)
                                         .ResolveAsync(async context =>
            {
                var command = context.GetArgument <CancelOrderPaymentCommand>(_commandName);
                var order   = await _customerOrderService.GetByIdAsync(command.Payment.OrderId);

                var authorizationResult = await _authorizationService.AuthorizeAsync(context.GetCurrentPrincipal(), order, new CanAccessOrderAuthorizationRequirement());

                if (!authorizationResult.Succeeded)
                {
                    throw new ExecutionError($"Access denied");
                }

                return(await _mediator.Send(command));
            })
                                         .FieldType);
        }
        public void Build(ISchema schema)
        {
            //Queries
            //We can't use the fluent syntax for new types registration provided by dotnet graphql here, because we have the strict requirement for underlying types extensions
            //and must use GraphTypeExtenstionHelper to resolve the effective type on execution time
            var cartField = new FieldType
            {
                Name      = "cart",
                Arguments = new QueryArguments(
                    new QueryArgument <NonNullGraphType <StringGraphType> > {
                    Name = "storeId", Description = "Store Id"
                },
                    new QueryArgument <StringGraphType> {
                    Name = "userId", Description = "User Id"
                },
                    new QueryArgument <NonNullGraphType <StringGraphType> > {
                    Name = "currencyCode", Description = "Currency code (\"USD\")"
                },
                    new QueryArgument <StringGraphType> {
                    Name = "cultureName", Description = "Culture name (\"en-Us\")"
                },
                    new QueryArgument <StringGraphType> {
                    Name = "cartName", Description = "Cart name"
                },
                    new QueryArgument <StringGraphType> {
                    Name = "type", Description = "Cart type"
                }),
                Type     = GraphTypeExtenstionHelper.GetActualType <CartType>(),
                Resolver = new AsyncFieldResolver <object>(async context =>
                {
                    var getCartQuery           = context.GetCartQuery <GetCartQuery>();
                    getCartQuery.IncludeFields = context.SubFields.Values.GetAllNodesPaths().ToArray();
                    context.CopyArgumentsToUserContext();
                    var cartAggregate = await _mediator.Send(getCartQuery);
                    if (cartAggregate == null)
                    {
                        var createCartCommand = new CreateCartCommand(getCartQuery.StoreId, getCartQuery.CartType, getCartQuery.CartName, getCartQuery.UserId, getCartQuery.CurrencyCode, getCartQuery.CultureName);
                        cartAggregate         = await _mediator.Send(createCartCommand);
                    }

                    context.SetExpandedObjectGraph(cartAggregate);

                    return(cartAggregate);
                })
            };

            schema.Query.AddField(cartField);


            var orderConnectionBuilder = GraphTypeExtenstionHelper.CreateConnection <CartType, object>()
                                         .Name("carts")
                                         .Argument <StringGraphType>("storeId", "")
                                         .Argument <StringGraphType>("userId", "")
                                         .Argument <StringGraphType>("currencyCode", "")
                                         .Argument <StringGraphType>("cultureName", "")
                                         .Argument <StringGraphType>("cartType", "")
                                         .Argument <StringGraphType>("filter", "This parameter applies a filter to the query results")
                                         .Argument <StringGraphType>("sort", "The sort expression")
                                         .Unidirectional()
                                         .PageSize(20);

            orderConnectionBuilder.ResolveAsync(async context => await ResolveConnectionAsync(_mediator, context));

            schema.Query.AddField(orderConnectionBuilder.FieldType);

            //Mutations
            /// <example>
            /// This is an example JSON request for a mutation
            /// {
            ///   "query": "mutation ($command:InputAddItemType!){ addItem(command: $command) {  total { formatedAmount } } }",
            ///   "variables": {
            ///      "command": {
            ///          "storeId": "Electronics",
            ///          "cartName": "default",
            ///          "userId": "b57d06db-1638-4d37-9734-fd01a9bc59aa",
            ///          "language": "en-US",
            ///          "currency": "USD",
            ///          "cartType": "cart",
            ///          "productId": "9cbd8f316e254a679ba34a900fccb076",
            ///          "quantity": 1
            ///      }
            ///   }
            /// }
            /// </example>
            var addItemField = FieldBuilder.Create <CartAggregate, CartAggregate>(typeof(CartType))
                               .Name("addItem")
                               .Argument <NonNullGraphType <InputAddItemType> >(_commandName)
                               //TODO: Write the unit-tests for successfully mapping input variable to the command
                               .ResolveAsync(async context =>
            {
                //TODO: Need to refactor later to prevent ugly code duplication
                //We need to add cartAggregate to the context to be able use it on nested cart types resolvers (e.g for currency)
                var cartAggregate = await _mediator.Send(context.GetCartCommand <AddCartItemCommand>());
                //store cart aggregate in the user context for future usage in the graph types resolvers
                context.SetExpandedObjectGraph(cartAggregate);
                return(cartAggregate);
            })
                               .FieldType;

            schema.Mutation.AddField(addItemField);

            /// <example>
            /// This is an example JSON request for a mutation
            /// {
            ///   "query": "mutation ($command:InputClearCartType!){ clearCart(command: $command) {  total { formatedAmount } } }",
            ///   "variables": {
            ///      "command": {
            ///          "storeId": "Electronics",
            ///          "cartName": "default",
            ///          "userId": "b57d06db-1638-4d37-9734-fd01a9bc59aa",
            ///          "language": "en-US",
            ///          "currency": "USD",
            ///          "cartType": "cart"
            ///      }
            ///   }
            /// }
            /// </example>
            var clearCartField = FieldBuilder.Create <CartAggregate, CartAggregate>(typeof(CartType))
                                 .Name("clearCart")
                                 .Argument <NonNullGraphType <InputClearCartType> >(_commandName)
                                 .ResolveAsync(async context =>
            {
                //TODO: Need to refactor later to prevent ugly code duplication
                //We need to add cartAggregate to the context to be able use it on nested cart types resolvers (e.g for currency)
                var cartAggregate = await _mediator.Send(context.GetCartCommand <ClearCartCommand>());
                //store cart aggregate in the user context for future usage in the graph types resolvers
                context.SetExpandedObjectGraph(cartAggregate);
                return(cartAggregate);
            }).FieldType;

            schema.Mutation.AddField(clearCartField);

            /// <example>
            /// This is an example JSON request for a mutation
            /// {
            ///   "query": "mutation ($command:InputChangeCommentType!){ changeComment(command: $command) {  total { formatedAmount } } }",
            ///   "variables": {
            ///      "command": {
            ///          "storeId": "Electronics",
            ///          "cartName": "default",
            ///          "userId": "b57d06db-1638-4d37-9734-fd01a9bc59aa",
            ///          "language": "en-US",
            ///          "currency": "USD",
            ///          "cartType": "cart",
            ///          "comment": "Hi, Virto!"
            ///      }
            ///   }
            /// }
            /// </example>
            var changeCommentField = FieldBuilder.Create <CartAggregate, CartAggregate>(typeof(CartType))
                                     .Name("changeComment")
                                     .Argument <InputChangeCommentType>(_commandName)
                                     .ResolveAsync(async context =>
            {
                //TODO: Need to refactor later to prevent ugly code duplication
                //We need to add cartAggregate to the context to be able use it on nested cart types resolvers (e.g for currency)
                var cartAggregate = await _mediator.Send(context.GetCartCommand <ChangeCommentCommand>());
                //store cart aggregate in the user context for future usage in the graph types resolvers
                context.SetExpandedObjectGraph(cartAggregate);
                return(cartAggregate);
            })
                                     .FieldType;

            schema.Mutation.AddField(changeCommentField);

            /// <example>
            /// This is an example JSON request for a mutation
            /// {
            ///   "query": "mutation ($command:InputChangeCartItemPriceType!){ changeCartItemPrice(command: $command) {  total { formatedAmount } } }",
            ///   "variables": {
            ///      "command": {
            ///          "storeId": "Electronics",
            ///          "cartName": "default",
            ///          "userId": "b57d06db-1638-4d37-9734-fd01a9bc59aa",
            ///          "language": "en-US",
            ///          "currency": "USD",
            ///          "cartType": "cart",
            ///          "lineItemId": "9cbd8f316e254a679ba34a900fccb076",
            ///          "price": 777
            ///      }
            ///   }
            /// }
            /// </example>
            var changeCartItemPriceField = FieldBuilder.Create <CartAggregate, CartAggregate>(typeof(CartType))
                                           .Name("changeCartItemPrice")
                                           .Argument <NonNullGraphType <InputChangeCartItemPriceType> >(_commandName)
                                           .ResolveAsync(async context =>
            {
                //TODO: Need to refactor later to prevent ugly code duplication
                //We need to add cartAggregate to the context to be able use it on nested cart types resolvers (e.g for currency)
                var cartAggregate = await _mediator.Send(context.GetCartCommand <ChangeCartItemPriceCommand>());
                //store cart aggregate in the user context for future usage in the graph types resolvers
                context.SetExpandedObjectGraph(cartAggregate);
                return(cartAggregate);
            }).FieldType;

            schema.Mutation.AddField(changeCartItemPriceField);

            /// <example>
            /// This is an example JSON request for a mutation
            /// {
            ///   "query": "mutation ($command:InputChangeCartItemQuantityType!){ changeCartItemQuantity(command: $command) {  total { formatedAmount } } }",
            ///   "variables": {
            ///      "command": {
            ///          "storeId": "Electronics",
            ///          "cartName": "default",
            ///          "userId": "b57d06db-1638-4d37-9734-fd01a9bc59aa",
            ///          "language": "en-US",
            ///          "currency": "USD",
            ///          "cartType": "cart",
            ///          "lineItemId": "9cbd8f316e254a679ba34a900fccb076",
            ///          "quantity": 777
            ///      }
            ///   }
            /// }
            /// </example>
            var changeCartItemQuantityField = FieldBuilder.Create <CartAggregate, CartAggregate>(typeof(CartType))
                                              .Name("changeCartItemQuantity")
                                              .Argument <NonNullGraphType <InputChangeCartItemQuantityType> >(_commandName)
                                              .ResolveAsync(async context =>
            {
                //TODO: Need to refactor later to prevent ugly code duplication
                //We need to add cartAggregate to the context to be able use it on nested cart types resolvers (e.g for currency)
                var cartAggregate = await _mediator.Send(context.GetCartCommand <ChangeCartItemQuantityCommand>());
                //store cart aggregate in the user context for future usage in the graph types resolvers
                context.SetExpandedObjectGraph(cartAggregate);
                return(cartAggregate);
            }).FieldType;

            schema.Mutation.AddField(changeCartItemQuantityField);

            /// <example>
            /// This is an example JSON request for a mutation
            /// {
            ///   "query": "mutation ($command:InputChangeCartItemCommentType!){ changeCartItemComment(command: $command) {  total { formatedAmount } } }",
            ///   "variables": {
            ///      "command": {
            ///          "storeId": "Electronics",
            ///          "cartName": "default",
            ///          "userId": "b57d06db-1638-4d37-9734-fd01a9bc59aa",
            ///          "language": "en-US",
            ///          "currency": "USD",
            ///          "cartType": "cart",
            ///          "lineItemId": "9cbd8f316e254a679ba34a900fccb076",
            ///          "comment": "verynicecomment"
            ///      }
            ///   }
            /// }
            /// </example>
            var changeCartItemCommentField = FieldBuilder.Create <CartAggregate, CartAggregate>(typeof(CartType))
                                             .Name("changeCartItemComment")
                                             .Argument <InputChangeCartItemCommentType>(_commandName)
                                             .ResolveAsync(async context =>
            {
                //TODO: Need to refactor later to prevent ugly code duplication
                //We need to add cartAggregate to the context to be able use it on nested cart types resolvers (e.g for currency)
                var cartAggregate = await _mediator.Send(context.GetCartCommand <ChangeCartItemCommentCommand>());
                //store cart aggregate in the user context for future usage in the graph types resolvers
                context.SetExpandedObjectGraph(cartAggregate);
                return(cartAggregate);
            }).FieldType;

            schema.Mutation.AddField(changeCartItemCommentField);

            /// <example>
            /// This is an example JSON request for a mutation
            /// {
            ///   "query": "mutation ($command:InputRemoveItemType!){ removeCartItem(command: $command) {  total { formatedAmount } } }",
            ///   "variables": {
            ///      "command": {
            ///          "storeId": "Electronics",
            ///          "cartName": "default",
            ///          "userId": "b57d06db-1638-4d37-9734-fd01a9bc59aa",
            ///          "language": "en-US",
            ///          "currency": "USD",
            ///          "cartType": "cart",
            ///          "lineItemId": "9cbd8f316e254a679ba34a900fccb076"
            ///      }
            ///   }
            /// }
            /// </example>
            var removeCartItemField = FieldBuilder.Create <CartAggregate, CartAggregate>(typeof(CartType))
                                      .Name("removeCartItem")
                                      .Argument <NonNullGraphType <InputRemoveItemType> >(_commandName)
                                      .ResolveAsync(async context =>
            {
                //TODO: Need to refactor later to prevent ugly code duplication
                //We need to add cartAggregate to the context to be able use it on nested cart types resolvers (e.g for currency)
                var cartAggregate = await _mediator.Send(context.GetCartCommand <RemoveCartItemCommand>());
                //store cart aggregate in the user context for future usage in the graph types resolvers
                context.SetExpandedObjectGraph(cartAggregate);
                return(cartAggregate);
            }).FieldType;

            schema.Mutation.AddField(removeCartItemField);

            /// <example>
            /// This is an example JSON request for a mutation
            /// {
            ///   "query": "mutation ($command:InputAddCouponType!){ addCoupon(command: $command) {  total { formatedAmount } } }",
            ///   "variables": {
            ///      "command": {
            ///          "storeId": "Electronics",
            ///          "cartName": "default",
            ///          "userId": "b57d06db-1638-4d37-9734-fd01a9bc59aa",
            ///          "language": "en-US",
            ///          "currency": "USD",
            ///          "cartType": "cart",
            ///          "couponCode": "verynicecouponcode"
            ///      }
            ///   }
            /// }
            /// </example>
            var addCouponField = FieldBuilder.Create <CartAggregate, CartAggregate>(typeof(CartType))
                                 .Name("addCoupon")
                                 .Argument <NonNullGraphType <InputAddCouponType> >(_commandName)
                                 .ResolveAsync(async context =>
            {
                //TODO: Need to refactor later to prevent ugly code duplication
                //We need to add cartAggregate to the context to be able use it on nested cart types resolvers (e.g for currency)
                var cartAggregate = await _mediator.Send(context.GetCartCommand <AddCouponCommand>());
                //store cart aggregate in the user context for future usage in the graph types resolvers
                context.SetExpandedObjectGraph(cartAggregate);
                return(cartAggregate);
            }).FieldType;

            schema.Mutation.AddField(addCouponField);

            /// <example>
            /// This is an example JSON request for a mutation
            /// {
            ///   "query": "mutation ($command:InputRemoveCouponType!){ removeCoupon(command: $command) {  total { formatedAmount } } }",
            ///   "variables": {
            ///      "command": {
            ///          "storeId": "Electronics",
            ///          "cartName": "default",
            ///          "userId": "b57d06db-1638-4d37-9734-fd01a9bc59aa",
            ///          "language": "en-US",
            ///          "currency": "USD",
            ///          "cartType": "cart",
            ///          "couponCode": "verynicecouponcode"
            ///      }
            ///   }
            /// }
            /// </example>
            var removeCouponField = FieldBuilder.Create <CartAggregate, CartAggregate>(typeof(CartType))
                                    .Name("removeCoupon")
                                    .Argument <NonNullGraphType <InputRemoveCouponType> >(_commandName)
                                    .ResolveAsync(async context =>
            {
                //TODO: Need to refactor later to prevent ugly code duplication
                //We need to add cartAggregate to the context to be able use it on nested cart types resolvers (e.g for currency)
                var cartAggregate = await _mediator.Send(context.GetCartCommand <RemoveCouponCommand>());
                //store cart aggregate in the user context for future usage in the graph types resolvers
                context.SetExpandedObjectGraph(cartAggregate);
                return(cartAggregate);
            }).FieldType;

            schema.Mutation.AddField(removeCouponField);

            /// <example>
            /// This is an example JSON request for a mutation
            /// {
            ///   "query": "mutation ($command:InputRemoveShipmentType!){ removeShipment(command: $command) {  total { formatedAmount } } }",
            ///   "variables": {
            ///      "command": {
            ///          "storeId": "Electronics",
            ///          "cartName": "default",
            ///          "userId": "b57d06db-1638-4d37-9734-fd01a9bc59aa",
            ///          "language": "en-US",
            ///          "currency": "USD",
            ///          "cartType": "cart",
            ///          "shipmentId": "7777-7777-7777-7777"
            ///      }
            ///   }
            /// }
            /// </example>
            var removeShipmentField = FieldBuilder.Create <CartAggregate, CartAggregate>(typeof(CartType))
                                      .Name("removeShipment")
                                      .Argument <NonNullGraphType <InputRemoveShipmentType> >(_commandName)
                                      .ResolveAsync(async context =>
            {
                //TODO: Need to refactor later to prevent ugly code duplication
                //We need to add cartAggregate to the context to be able use it on nested cart types resolvers (e.g for currency)
                var cartAggregate = await _mediator.Send(context.GetCartCommand <RemoveShipmentCommand>());
                //store cart aggregate in the user context for future usage in the graph types resolvers
                context.SetExpandedObjectGraph(cartAggregate);
                return(cartAggregate);
            }).FieldType;

            schema.Mutation.AddField(removeShipmentField);

            //TODO: add shipment model to example
            /// <example>
            /// This is an example JSON request for a mutation
            /// {
            ///   "query": "mutation ($command:InputAddOrUpdateCartShipmentType!){ addOrUpdateCartShipment(command: $command) {  total { formatedAmount } } }",
            ///   "variables": {
            ///      "command": {
            ///          "storeId": "Electronics",
            ///          "cartName": "default",
            ///          "userId": "b57d06db-1638-4d37-9734-fd01a9bc59aa",
            ///          "language": "en-US",
            ///          "currency": "USD",
            ///          "cartType": "cart",
            ///          "shipment": { }
            ///      }
            ///   }
            /// }
            /// </example>
            var addOrUpdateCartShipmentField = FieldBuilder.Create <CartAggregate, CartAggregate>(typeof(CartType))
                                               .Name("addOrUpdateCartShipment")
                                               .Argument <NonNullGraphType <InputAddOrUpdateCartShipmentType> >(_commandName)
                                               .ResolveAsync(async context =>
            {
                //TODO: Need to refactor later to prevent ugly code duplication
                //We need to add cartAggregate to the context to be able use it on nested cart types resolvers (e.g for currency)
                var cartAggregate = await _mediator.Send(context.GetCartCommand <AddOrUpdateCartShipmentCommand>());
                //store cart aggregate in the user context for future usage in the graph types resolvers
                context.SetExpandedObjectGraph(cartAggregate);
                return(cartAggregate);
            }).FieldType;

            schema.Mutation.AddField(addOrUpdateCartShipmentField);

            //TODO: add payment model to example
            /// <example>
            /// This is an example JSON request for a mutation
            /// {
            ///   "query": "mutation ($command:InputAddOrUpdateCartPaymentType!){ addOrUpdateCartPayment(command: $command) {  total { formatedAmount } } }",
            ///   "variables": {
            ///      "command": {
            ///          "storeId": "Electronics",
            ///          "cartName": "default",
            ///          "userId": "b57d06db-1638-4d37-9734-fd01a9bc59aa",
            ///          "language": "en-US",
            ///          "currency": "USD",
            ///          "cartType": "cart",
            ///          "payment": { }
            ///      }
            ///   }
            /// }
            /// </example>
            var addOrUpdateCartPaymentField = FieldBuilder.Create <CartAggregate, CartAggregate>(typeof(CartType))
                                              .Name("addOrUpdateCartPayment")
                                              .Argument <NonNullGraphType <InputAddOrUpdateCartPaymentType> >(_commandName)
                                              .ResolveAsync(async context =>
            {
                //TODO: Need to refactor later to prevent ugly code duplication
                //We need to add cartAggregate to the context to be able use it on nested cart types resolvers (e.g for currency)
                var cartAggregate = await _mediator.Send(context.GetCartCommand <AddOrUpdateCartPaymentCommand>());
                //store cart aggregate in the user context for future usage in the graph types resolvers
                context.SetExpandedObjectGraph(cartAggregate);
                return(cartAggregate);
            }).FieldType;

            schema.Mutation.AddField(addOrUpdateCartPaymentField);

            /// <example>
            /// This is an example JSON request for a mutation
            /// {
            ///   "query": "mutation ($command:InputValidateCouponType!){ validateCoupon(command: $command) }",
            ///   "variables": {
            ///      "command": {
            ///          "storeId": "Electronics",
            ///          "cartName": "default",
            ///          "userId": "b57d06db-1638-4d37-9734-fd01a9bc59aa",
            ///          "language": "en-US",
            ///          "currency": "USD",
            ///          "cartType": "cart",
            ///          "coupon": {
            ///             "code":"verynicecodeforvalidation"
            ///         }
            ///      }
            ///   }
            /// }
            /// </example>
            var validateCouponField = FieldBuilder.Create <CartAggregate, bool>(typeof(BooleanGraphType))
                                      .Name("validateCoupon")
                                      .Argument <NonNullGraphType <InputValidateCouponType> >(_commandName)
                                      .ResolveAsync(async context => await _mediator.Send(context.GetArgument <ValidateCouponCommand>(_commandName)))
                                      .FieldType;

            schema.Mutation.AddField(validateCouponField);

            /// <example>
            /// This is an example JSON request for a mutation
            /// {
            ///   "query": "mutation ($command:MergeCartType!){ mergeCart(command: $command) {  total { formatedAmount } } }",
            ///   "variables": {
            ///      "command": {
            ///          "storeId": "Electronics",
            ///          "cartName": "default",
            ///          "userId": "b57d06db-1638-4d37-9734-fd01a9bc59aa",
            ///          "language": "en-US",
            ///          "currency": "USD",
            ///          "cartType": "cart",
            ///          "secondCartId": "7777-7777-7777-7777"
            ///      }
            ///   }
            /// }
            /// </example>
            var margeCartField = FieldBuilder.Create <CartAggregate, CartAggregate>(typeof(CartType))
                                 .Name("mergeCart")
                                 .Argument <NonNullGraphType <InputMergeCartType> >(_commandName)
                                 .ResolveAsync(async context =>
            {
                //TODO: Need to refactor later to prevent ugly code duplication
                //We need to add cartAggregate to the context to be able use it on nested cart types resolvers (e.g for currency)
                var cartAggregate = await _mediator.Send(context.GetCartCommand <MergeCartCommand>());
                //store cart aggregate in the user context for future usage in the graph types resolvers
                context.SetExpandedObjectGraph(cartAggregate);
                return(cartAggregate);
            }).FieldType;

            schema.Mutation.AddField(margeCartField);

            /// <example>
            /// This is an example JSON request for a mutation
            /// {
            ///   "query": "mutation ($command:InputRemoveCartType!){ removeCart(command: $command) {  total { formatedAmount } } }",
            ///   "variables": {
            ///      "command": {
            ///          "cartId": "7777-7777-7777-7777"
            ///      }
            ///   }
            /// }
            /// </example>
            var removeCartField = FieldBuilder.Create <CartAggregate, bool>(typeof(BooleanGraphType))
                                  .Name("removeCart")
                                  .Argument <NonNullGraphType <InputRemoveCartType> >(_commandName)
                                  .ResolveAsync(async context => await _mediator.Send(context.GetArgument <RemoveCartCommand>(_commandName)))
                                  .FieldType;

            schema.Mutation.AddField(removeCartField);

            /// <example>
            /// This is an example JSON request for a mutation
            /// {
            ///   "query": "mutation ($command:InputClearShipmentsType!){ clearShipments(command: $command) {  total { formatedAmount } } }",
            ///   "variables": {
            ///      "command": {
            ///          "cartId": "7777-7777-7777-7777"
            ///      }
            ///   }
            /// }
            /// </example>
            var clearShipmentsField = FieldBuilder.Create <CartAggregate, CartAggregate>(typeof(CartType))
                                      .Name("clearShipments")
                                      .Argument <NonNullGraphType <InputClearShipmentsType> >(_commandName)
                                      .ResolveAsync(async context =>
            {
                //TODO: Need to refactor later to prevent ugly code duplication
                //We need to add cartAggregate to the context to be able use it on nested cart types resolvers (e.g for currency)
                var cartAggregate = await _mediator.Send(context.GetArgument <ClearShipmentsCommand>(_commandName));
                //store cart aggregate in the user context for future usage in the graph types resolvers
                context.SetExpandedObjectGraph(cartAggregate);
                return(cartAggregate);
            })
                                      .FieldType;

            schema.Mutation.AddField(clearShipmentsField);

            /// <example>
            /// This is an example JSON request for a mutation
            /// {
            ///   "query": "mutation ($command:InputClearPaymentsType!){ clearPayments(command: $command) {  total { formatedAmount } } }",
            ///   "variables": {
            ///      "command": {
            ///          "cartId": "7777-7777-7777-7777"
            ///      }
            ///   }
            /// }
            /// </example>
            var clearPaymentsField = FieldBuilder.Create <CartAggregate, CartAggregate>(typeof(CartType))
                                     .Name("clearPayments")
                                     .Argument <NonNullGraphType <InputClearPaymentsType> >(_commandName)
                                     .ResolveAsync(async context =>
            {
                //TODO: Need to refactor later to prevent ugly code duplication
                //We need to add cartAggregate to the context to be able use it on nested cart types resolvers (e.g for currency)
                var cartAggregate = await _mediator.Send(context.GetArgument <ClearPaymentsCommand>(_commandName));
                //store cart aggregate in the user context for future usage in the graph types resolvers
                context.SetExpandedObjectGraph(cartAggregate);
                return(cartAggregate);
            })
                                     .FieldType;

            schema.Mutation.AddField(clearPaymentsField);


            /// <example>
            /// This is an example JSON request for a mutation
            /// {
            ///   "query": "mutation ($command:InputAddOrUpdateCartAddressType!){ addOrUpdateCartAddress(command: $command) {  total { formatedAmount } } }",
            ///   "variables": {
            ///      "command": {
            ///          "storeId": "Electronics",
            ///          "cartName": "default",
            ///          "userId": "b57d06db-1638-4d37-9734-fd01a9bc59aa",
            ///          "language": "en-US",
            ///          "currency": "USD",
            ///          "cartType": "cart",
            ///          "address": {
            ///             "line1":"st street 1"
            ///         }
            ///      }
            ///   }
            /// }
            /// </example>
            var addOrUpdateCartAddress = FieldBuilder.Create <CartAggregate, CartAggregate>(typeof(CartType))
                                         .Name("addOrUpdateCartAddress")
                                         .Argument <NonNullGraphType <InputAddOrUpdateCartAddressType> >(_commandName)
                                         .ResolveAsync(async context =>
            {
                //TODO: Need to refactor later to prevent ugly code duplication
                //We need to add cartAggregate to the context to be able use it on nested cart types resolvers (e.g for currency)
                var cartAggregate = await _mediator.Send(context.GetArgument <AddOrUpdateCartAddressCommand>(_commandName));
                //store cart aggregate in the user context for future usage in the graph types resolvers
                context.SetExpandedObjectGraph(cartAggregate);
                return(cartAggregate);
            })
                                         .FieldType;

            schema.Mutation.AddField(addOrUpdateCartAddress);

            /// <example>
            /// This is an example JSON request for a mutation
            /// {
            ///   "query": "mutation ($command:InputRemoveCartAddressType!){ removeCartAddress(command: $command) {  total { formatedAmount } } }",
            ///   "variables": {
            ///      "command": {
            ///          "cartId": "7777-7777-7777-7777",
            ///          "addressId": "111"
            ///      }
            ///   }
            /// }
            /// </example>
            var removeCartAddressField = FieldBuilder.Create <CartAggregate, CartAggregate>(typeof(CartType))
                                         .Name("removeCartAddress")
                                         .Argument <NonNullGraphType <InputRemoveCartAddressType> >(_commandName)
                                         .ResolveAsync(async context => await _mediator.Send(context.GetArgument <RemoveCartAddressCommand>(_commandName)))
                                         .FieldType;

            schema.Mutation.AddField(removeCartAddressField);
        }
        public LineItemType(IMediator mediator, IDataLoaderContextAccessor dataLoader)
        {
            var productField = new FieldType
            {
                Name     = "product",
                Type     = GraphTypeExtenstionHelper.GetActualType <ProductType>(),
                Resolver = new FuncFieldResolver <LineItem, IDataLoaderResult <ExpProduct> >(context =>
                {
                    var includeFields = context.SubFields.Values.GetAllNodesPaths();
                    var loader        = dataLoader.Context.GetOrAddBatchLoader <string, ExpProduct>("order_lineItems_products", async(ids) =>
                    {
                        //Get currencies and store only from one cart.
                        //We intentionally ignore the case when there are ma be the carts with the different currencies and stores in the resulting set
                        var cart    = context.GetValueForSource <CartAggregate>().Cart;
                        var request = new LoadProductsQuery
                        {
                            StoreId       = cart.StoreId,
                            CurrencyCode  = cart.Currency,
                            ObjectIds     = ids.ToArray(),
                            IncludeFields = includeFields.ToArray()
                        };

                        var response = await mediator.Send(request);

                        return(response.Products.ToDictionary(x => x.Id));
                    });
                    return(loader.LoadAsync(context.Source.ProductId));
                })
            };

            AddField(productField);

            //Field<MoneyType>("paymentPlan", resolve: context => context.Source.PaymentPlan);
            Field <IntGraphType>("inStockQuantity", resolve: context => context.GetCart().CartProducts[context.Source.ProductId]?.AvailableQuantity ?? 0);
            Field <StringGraphType>("warehouseLocation", resolve: context => context.GetCart().CartProducts[context.Source.ProductId]?.Inventory?.FulfillmentCenter?.Address);

            Field <BooleanGraphType>("IsValid", resolve: context => !context.GetCart().ValidationErrors.GetEntityCartErrors(context.Source).Any());
            Field <ListGraphType <ValidationErrorType> >("validationErrors", resolve: context => context.GetCart().ValidationErrors.GetEntityCartErrors(context.Source));

            Field(x => x.CatalogId, nullable: true).Description("Value of catalog id");
            Field(x => x.CategoryId, nullable: true).Description("Value of category id");
            Field(x => x.CreatedDate, nullable: true).Description("Line item created date");
            Field(x => x.Height, nullable: true).Description("Value of height");
            Field(x => x.Id, nullable: false).Description("Line item id");
            Field(x => x.ImageUrl, nullable: true).Description("Value of line item image absolute URL");
            Field(x => x.IsGift, nullable: true).Description("flag of line item is a gift");
            Field(x => x.IsReadOnly, nullable: true).Description("Is readOnly");
            Field(x => x.IsReccuring, nullable: true).Description("flag of line item is recurring");
            Field(x => x.LanguageCode, nullable: true).Description("Culture name in ISO 3166-1 alpha-3 format");
            Field(x => x.Length, nullable: true).Description("Value of length");
            Field(x => x.MeasureUnit, nullable: true).Description("Value of measurement unit");
            Field(x => x.Name, nullable: true).Description("Value of line item name");
            Field(x => x.Note, nullable: true).Description("Value of line item comment");
            Field(x => x.ObjectType, nullable: true).Description("Value of line item quantity");
            Field(x => x.ProductId, nullable: true).Description("Value of product id");
            Field(x => x.ProductType, nullable: true).Description("type of product (can be Physical, Digital or Subscription)");
            Field(x => x.Quantity, nullable: true).Description("Value of line item quantity");
            Field(x => x.RequiredShipping, nullable: true).Description("requirement for line item shipping");
            Field(x => x.ShipmentMethodCode, nullable: true).Description("Value of line item shipping method code");
            Field(x => x.Sku, nullable: true).Description("Value of product SKU");
            Field(x => x.TaxPercentRate, nullable: true).Description("Value of total shipping tax amount");
            Field(x => x.TaxType, nullable: true).Description("Value of shipping tax type");
            Field(x => x.ThumbnailImageUrl, nullable: true).Description("Value of line item thumbnail image absolute URL");
            Field(x => x.VolumetricWeight, nullable: true).Description("Value of volumetric weight");
            Field(x => x.Weight, nullable: true).Description("Value of shopping cart weight");
            Field(x => x.WeightUnit, nullable: true).Description("Value of weight unit");
            Field(x => x.Width, nullable: true).Description("Value of width");
            Field <ListGraphType <DiscountType> >("discounts", resolve: context => context.Source.Discounts);
            Field <ListGraphType <TaxDetailType> >("taxDetails", resolve: context => context.Source.TaxDetails);
            Field <MoneyType>("discountAmount", resolve: context => context.Source.DiscountAmount.ToMoney(context.GetCart().Currency));
            Field <MoneyType>("discountAmountWithTax", resolve: context => context.Source.DiscountAmountWithTax.ToMoney(context.GetCart().Currency));
            Field <MoneyType>("discountTotal", resolve: context => context.Source.DiscountTotal.ToMoney(context.GetCart().Currency));
            Field <MoneyType>("discountTotalWithTax", resolve: context => context.Source.DiscountTotalWithTax.ToMoney(context.GetCart().Currency));
            Field <MoneyType>("extendedPrice", resolve: context => context.Source.ExtendedPrice.ToMoney(context.GetCart().Currency));
            Field <MoneyType>("extendedPriceWithTax", resolve: context => context.Source.ExtendedPriceWithTax.ToMoney(context.GetCart().Currency));
            Field <MoneyType>("listPrice", resolve: context => context.Source.ListPrice.ToMoney(context.GetCart().Currency));
            Field <MoneyType>("listPriceWithTax", resolve: context => context.Source.ListPriceWithTax.ToMoney(context.GetCart().Currency));
            Field <MoneyType>("placedPrice", resolve: context => context.Source.PlacedPrice.ToMoney(context.GetCart().Currency));
            Field <MoneyType>("placedPriceWithTax", resolve: context => context.Source.PlacedPriceWithTax.ToMoney(context.GetCart().Currency));
            Field <MoneyType>("salePrice", resolve: context => context.Source.SalePrice.ToMoney(context.GetCart().Currency));
            Field <MoneyType>("salePriceWithTax", resolve: context => context.Source.SalePriceWithTax.ToMoney(context.GetCart().Currency));
            Field <MoneyType>("taxTotal", resolve: context => context.Source.TaxTotal.ToMoney(context.GetCart().Currency));
        }