Browse Source

feat(core): Allow custom fields to be set on OrderLine

BREAKING CHANGE: This change allows custom fields to be defined on the OrderLine entity. When they are, then the "addItemToOrder" mutation will accept a third argument - "customFields", which matches the fields specified in the config. Additionally, a couple of mutations have been renamed: "removeItemFromOrder" -> "removeOrderLine", "adjustItemQuantity" -> "adjustOrderLine" and their "orderItemId" argument has been renamed to "orderLineId".

Closes #109
Michael Bromley 6 years ago
parent
commit
a4b7e07438

+ 130 - 124
admin-ui/src/app/common/generated-types.ts

@@ -1414,6 +1414,10 @@ export type Mutation = {
   assignRoleToAdministrator: Administrator,
   /** Create a new Asset */
   createAssets: Array<Asset>,
+  /** Create a new Channel */
+  createChannel: Channel,
+  /** Update an existing Channel */
+  updateChannel: Channel,
   login: LoginResult,
   logout: Scalars['Boolean'],
   /** Create a new Collection */
@@ -1422,16 +1426,24 @@ export type Mutation = {
   updateCollection: Collection,
   /** Move a Collection to a different parent or index */
   moveCollection: Collection,
-  /** Create a new Channel */
-  createChannel: Channel,
-  /** Update an existing Channel */
-  updateChannel: Channel,
   /** Create a new Country */
   createCountry: Country,
   /** Update an existing Country */
   updateCountry: Country,
   /** Delete a Country */
   deleteCountry: DeletionResponse,
+  /** Create a new Facet */
+  createFacet: Facet,
+  /** Update an existing Facet */
+  updateFacet: Facet,
+  /** Delete an existing Facet */
+  deleteFacet: DeletionResponse,
+  /** Create one or more FacetValues */
+  createFacetValues: Array<FacetValue>,
+  /** Update one or more FacetValues */
+  updateFacetValues: Array<FacetValue>,
+  /** Delete one or more FacetValues */
+  deleteFacetValues: Array<DeletionResponse>,
   /** Create a new CustomerGroup */
   createCustomerGroup: CustomerGroup,
   /** Update an existing CustomerGroup */
@@ -1452,27 +1464,14 @@ export type Mutation = {
   updateCustomerAddress: Address,
   /** Update an existing Address */
   deleteCustomerAddress: Scalars['Boolean'],
-  /** Create a new Facet */
-  createFacet: Facet,
-  /** Update an existing Facet */
-  updateFacet: Facet,
-  /** Delete an existing Facet */
-  deleteFacet: DeletionResponse,
-  /** Create one or more FacetValues */
-  createFacetValues: Array<FacetValue>,
-  /** Update one or more FacetValues */
-  updateFacetValues: Array<FacetValue>,
-  /** Delete one or more FacetValues */
-  deleteFacetValues: Array<DeletionResponse>,
-  updateGlobalSettings: GlobalSettings,
   importProducts?: Maybe<ImportInfo>,
+  updateGlobalSettings: GlobalSettings,
   /** Update an existing PaymentMethod */
   updatePaymentMethod: PaymentMethod,
   /** Create a new ProductOptionGroup */
   createProductOptionGroup: ProductOptionGroup,
   /** Update an existing ProductOptionGroup */
   updateProductOptionGroup: ProductOptionGroup,
-  reindex: SearchReindexResponse,
   /** Create a new Product */
   createProduct: Product,
   /** Update an existing Product */
@@ -1487,6 +1486,7 @@ export type Mutation = {
   generateVariantsForProduct: Product,
   /** Update existing ProductVariants */
   updateProductVariants: Array<Maybe<ProductVariant>>,
+  reindex: SearchReindexResponse,
   createPromotion: Promotion,
   updatePromotion: Promotion,
   deletePromotion: DeletionResponse,
@@ -1498,14 +1498,6 @@ export type Mutation = {
   createShippingMethod: ShippingMethod,
   /** Update an existing ShippingMethod */
   updateShippingMethod: ShippingMethod,
-  /** Create a new TaxCategory */
-  createTaxCategory: TaxCategory,
-  /** Update an existing TaxCategory */
-  updateTaxCategory: TaxCategory,
-  /** Create a new TaxRate */
-  createTaxRate: TaxRate,
-  /** Update an existing TaxRate */
-  updateTaxRate: TaxRate,
   /** Create a new Zone */
   createZone: Zone,
   /** Update an existing Zone */
@@ -1516,6 +1508,14 @@ export type Mutation = {
   addMembersToZone: Zone,
   /** Remove members from a Zone */
   removeMembersFromZone: Zone,
+  /** Create a new TaxCategory */
+  createTaxCategory: TaxCategory,
+  /** Update an existing TaxCategory */
+  updateTaxCategory: TaxCategory,
+  /** Create a new TaxRate */
+  createTaxRate: TaxRate,
+  /** Update an existing TaxRate */
+  updateTaxRate: TaxRate,
   requestStarted: Scalars['Int'],
   requestCompleted: Scalars['Int'],
   setAsLoggedIn: UserStatus,
@@ -1545,6 +1545,16 @@ export type MutationCreateAssetsArgs = {
 };
 
 
+export type MutationCreateChannelArgs = {
+  input: CreateChannelInput
+};
+
+
+export type MutationUpdateChannelArgs = {
+  input: UpdateChannelInput
+};
+
+
 export type MutationLoginArgs = {
   username: Scalars['String'],
   password: Scalars['String'],
@@ -1567,16 +1577,6 @@ export type MutationMoveCollectionArgs = {
 };
 
 
-export type MutationCreateChannelArgs = {
-  input: CreateChannelInput
-};
-
-
-export type MutationUpdateChannelArgs = {
-  input: UpdateChannelInput
-};
-
-
 export type MutationCreateCountryArgs = {
   input: CreateCountryInput
 };
@@ -1592,6 +1592,38 @@ export type MutationDeleteCountryArgs = {
 };
 
 
+export type MutationCreateFacetArgs = {
+  input: CreateFacetInput
+};
+
+
+export type MutationUpdateFacetArgs = {
+  input: UpdateFacetInput
+};
+
+
+export type MutationDeleteFacetArgs = {
+  id: Scalars['ID'],
+  force?: Maybe<Scalars['Boolean']>
+};
+
+
+export type MutationCreateFacetValuesArgs = {
+  input: Array<CreateFacetValueInput>
+};
+
+
+export type MutationUpdateFacetValuesArgs = {
+  input: Array<UpdateFacetValueInput>
+};
+
+
+export type MutationDeleteFacetValuesArgs = {
+  ids: Array<Scalars['ID']>,
+  force?: Maybe<Scalars['Boolean']>
+};
+
+
 export type MutationCreateCustomerGroupArgs = {
   input: CreateCustomerGroupInput
 };
@@ -1646,35 +1678,8 @@ export type MutationDeleteCustomerAddressArgs = {
 };
 
 
-export type MutationCreateFacetArgs = {
-  input: CreateFacetInput
-};
-
-
-export type MutationUpdateFacetArgs = {
-  input: UpdateFacetInput
-};
-
-
-export type MutationDeleteFacetArgs = {
-  id: Scalars['ID'],
-  force?: Maybe<Scalars['Boolean']>
-};
-
-
-export type MutationCreateFacetValuesArgs = {
-  input: Array<CreateFacetValueInput>
-};
-
-
-export type MutationUpdateFacetValuesArgs = {
-  input: Array<UpdateFacetValueInput>
-};
-
-
-export type MutationDeleteFacetValuesArgs = {
-  ids: Array<Scalars['ID']>,
-  force?: Maybe<Scalars['Boolean']>
+export type MutationImportProductsArgs = {
+  csvFile: Scalars['Upload']
 };
 
 
@@ -1683,11 +1688,6 @@ export type MutationUpdateGlobalSettingsArgs = {
 };
 
 
-export type MutationImportProductsArgs = {
-  csvFile: Scalars['Upload']
-};
-
-
 export type MutationUpdatePaymentMethodArgs = {
   input: UpdatePaymentMethodInput
 };
@@ -1778,26 +1778,6 @@ export type MutationUpdateShippingMethodArgs = {
 };
 
 
-export type MutationCreateTaxCategoryArgs = {
-  input: CreateTaxCategoryInput
-};
-
-
-export type MutationUpdateTaxCategoryArgs = {
-  input: UpdateTaxCategoryInput
-};
-
-
-export type MutationCreateTaxRateArgs = {
-  input: CreateTaxRateInput
-};
-
-
-export type MutationUpdateTaxRateArgs = {
-  input: UpdateTaxRateInput
-};
-
-
 export type MutationCreateZoneArgs = {
   input: CreateZoneInput
 };
@@ -1825,6 +1805,26 @@ export type MutationRemoveMembersFromZoneArgs = {
 };
 
 
+export type MutationCreateTaxCategoryArgs = {
+  input: CreateTaxCategoryInput
+};
+
+
+export type MutationUpdateTaxCategoryArgs = {
+  input: UpdateTaxCategoryInput
+};
+
+
+export type MutationCreateTaxRateArgs = {
+  input: CreateTaxRateInput
+};
+
+
+export type MutationUpdateTaxRateArgs = {
+  input: UpdateTaxRateInput
+};
+
+
 export type MutationSetAsLoggedInArgs = {
   username: Scalars['String'],
   loginTime: Scalars['String']
@@ -1932,6 +1932,11 @@ export type OrderLine = Node & {
   totalPrice: Scalars['Int'],
   adjustments: Array<Adjustment>,
   order: Order,
+  customFields?: Maybe<OrderLineCustomFields>,
+};
+
+export type OrderLineCustomFields = {
+  message?: Maybe<Scalars['String']>,
 };
 
 export type OrderList = PaginatedList & {
@@ -2297,21 +2302,21 @@ export type Query = {
   administrator?: Maybe<Administrator>,
   assets: AssetList,
   asset?: Maybe<Asset>,
+  channels: Array<Channel>,
+  channel?: Maybe<Channel>,
+  activeChannel: Channel,
   me?: Maybe<CurrentUser>,
   collections: CollectionList,
   collection?: Maybe<Collection>,
   collectionFilters: Array<ConfigurableOperation>,
-  channels: Array<Channel>,
-  channel?: Maybe<Channel>,
-  activeChannel: Channel,
   countries: CountryList,
   country?: Maybe<Country>,
+  facets: FacetList,
+  facet?: Maybe<Facet>,
   customerGroups: Array<CustomerGroup>,
   customerGroup?: Maybe<CustomerGroup>,
   customers: CustomerList,
   customer?: Maybe<Customer>,
-  facets: FacetList,
-  facet?: Maybe<Facet>,
   globalSettings: GlobalSettings,
   order?: Maybe<Order>,
   orders: OrderList,
@@ -2319,9 +2324,10 @@ export type Query = {
   paymentMethod?: Maybe<PaymentMethod>,
   productOptionGroups: Array<ProductOptionGroup>,
   productOptionGroup?: Maybe<ProductOptionGroup>,
-  search: SearchResponse,
   products: ProductList,
+  /** Get a Product either by id or slug. If neither id nor slug is speicified, an error will result. */
   product?: Maybe<Product>,
+  search: SearchResponse,
   promotion?: Maybe<Promotion>,
   promotions: PromotionList,
   adjustmentOperations: AdjustmentOperations,
@@ -2331,12 +2337,12 @@ export type Query = {
   shippingMethod?: Maybe<ShippingMethod>,
   shippingEligibilityCheckers: Array<ConfigurableOperation>,
   shippingCalculators: Array<ConfigurableOperation>,
+  zones: Array<Zone>,
+  zone?: Maybe<Zone>,
   taxCategories: Array<TaxCategory>,
   taxCategory?: Maybe<TaxCategory>,
   taxRates: TaxRateList,
   taxRate?: Maybe<TaxRate>,
-  zones: Array<Zone>,
-  zone?: Maybe<Zone>,
   temp__?: Maybe<Scalars['Boolean']>,
   networkStatus: NetworkStatus,
   userStatus: UserStatus,
@@ -2364,6 +2370,11 @@ export type QueryAssetArgs = {
 };
 
 
+export type QueryChannelArgs = {
+  id: Scalars['ID']
+};
+
+
 export type QueryCollectionsArgs = {
   languageCode?: Maybe<LanguageCode>,
   options?: Maybe<CollectionListOptions>
@@ -2376,11 +2387,6 @@ export type QueryCollectionArgs = {
 };
 
 
-export type QueryChannelArgs = {
-  id: Scalars['ID']
-};
-
-
 export type QueryCountriesArgs = {
   options?: Maybe<CountryListOptions>
 };
@@ -2391,30 +2397,30 @@ export type QueryCountryArgs = {
 };
 
 
-export type QueryCustomerGroupArgs = {
-  id: Scalars['ID']
+export type QueryFacetsArgs = {
+  languageCode?: Maybe<LanguageCode>,
+  options?: Maybe<FacetListOptions>
 };
 
 
-export type QueryCustomersArgs = {
-  options?: Maybe<CustomerListOptions>
+export type QueryFacetArgs = {
+  id: Scalars['ID'],
+  languageCode?: Maybe<LanguageCode>
 };
 
 
-export type QueryCustomerArgs = {
+export type QueryCustomerGroupArgs = {
   id: Scalars['ID']
 };
 
 
-export type QueryFacetsArgs = {
-  languageCode?: Maybe<LanguageCode>,
-  options?: Maybe<FacetListOptions>
+export type QueryCustomersArgs = {
+  options?: Maybe<CustomerListOptions>
 };
 
 
-export type QueryFacetArgs = {
-  id: Scalars['ID'],
-  languageCode?: Maybe<LanguageCode>
+export type QueryCustomerArgs = {
+  id: Scalars['ID']
 };
 
 
@@ -2450,11 +2456,6 @@ export type QueryProductOptionGroupArgs = {
 };
 
 
-export type QuerySearchArgs = {
-  input: SearchInput
-};
-
-
 export type QueryProductsArgs = {
   languageCode?: Maybe<LanguageCode>,
   options?: Maybe<ProductListOptions>
@@ -2468,6 +2469,11 @@ export type QueryProductArgs = {
 };
 
 
+export type QuerySearchArgs = {
+  input: SearchInput
+};
+
+
 export type QueryPromotionArgs = {
   id: Scalars['ID']
 };
@@ -2498,6 +2504,11 @@ export type QueryShippingMethodArgs = {
 };
 
 
+export type QueryZoneArgs = {
+  id: Scalars['ID']
+};
+
+
 export type QueryTaxCategoryArgs = {
   id: Scalars['ID']
 };
@@ -2512,11 +2523,6 @@ export type QueryTaxRateArgs = {
   id: Scalars['ID']
 };
 
-
-export type QueryZoneArgs = {
-  id: Scalars['ID']
-};
-
 export type Return = Node & StockMovement & {
   id: Scalars['ID'],
   createdAt: Scalars['DateTime'],

+ 19 - 7
packages/common/src/generated-shop-types.ts

@@ -1105,8 +1105,8 @@ export type LoginResult = {
 
 export type Mutation = {
     addItemToOrder?: Maybe<Order>;
-    removeItemFromOrder?: Maybe<Order>;
-    adjustItemQuantity?: Maybe<Order>;
+    removeOrderLine?: Maybe<Order>;
+    adjustOrderLine?: Maybe<Order>;
     transitionOrderToState?: Maybe<Order>;
     setOrderShippingAddress?: Maybe<Order>;
     setOrderShippingMethod?: Maybe<Order>;
@@ -1153,15 +1153,17 @@ export type Mutation = {
 export type MutationAddItemToOrderArgs = {
     productVariantId: Scalars['ID'];
     quantity: Scalars['Int'];
+    customFields?: Maybe<OrderLineCustomFieldsInput>;
 };
 
-export type MutationRemoveItemFromOrderArgs = {
-    orderItemId: Scalars['ID'];
+export type MutationRemoveOrderLineArgs = {
+    orderLineId: Scalars['ID'];
 };
 
-export type MutationAdjustItemQuantityArgs = {
-    orderItemId: Scalars['ID'];
-    quantity: Scalars['Int'];
+export type MutationAdjustOrderLineArgs = {
+    orderLineId: Scalars['ID'];
+    quantity?: Maybe<Scalars['Int']>;
+    customFields?: Maybe<OrderLineCustomFieldsInput>;
 };
 
 export type MutationTransitionOrderToStateArgs = {
@@ -1335,6 +1337,15 @@ export type OrderLine = Node & {
     totalPrice: Scalars['Int'];
     adjustments: Array<Adjustment>;
     order: Order;
+    customFields?: Maybe<OrderLineCustomFields>;
+};
+
+export type OrderLineCustomFields = {
+    message?: Maybe<Scalars['String']>;
+};
+
+export type OrderLineCustomFieldsInput = {
+    message?: Maybe<Scalars['String']>;
 };
 
 export type OrderList = PaginatedList & {
@@ -1620,6 +1631,7 @@ export type Query = {
     nextOrderStates: Array<Scalars['String']>;
     order?: Maybe<Order>;
     orderByCode?: Maybe<Order>;
+    /** Get a Product either by id or slug. If neither id nor slug is speicified, an error will result. */
     product?: Maybe<Product>;
     products: ProductList;
     search: SearchResponse;

+ 130 - 124
packages/common/src/generated-types.ts

@@ -1413,6 +1413,10 @@ export type Mutation = {
   assignRoleToAdministrator: Administrator,
   /** Create a new Asset */
   createAssets: Array<Asset>,
+  /** Create a new Channel */
+  createChannel: Channel,
+  /** Update an existing Channel */
+  updateChannel: Channel,
   login: LoginResult,
   logout: Scalars['Boolean'],
   /** Create a new Collection */
@@ -1421,16 +1425,24 @@ export type Mutation = {
   updateCollection: Collection,
   /** Move a Collection to a different parent or index */
   moveCollection: Collection,
-  /** Create a new Channel */
-  createChannel: Channel,
-  /** Update an existing Channel */
-  updateChannel: Channel,
   /** Create a new Country */
   createCountry: Country,
   /** Update an existing Country */
   updateCountry: Country,
   /** Delete a Country */
   deleteCountry: DeletionResponse,
+  /** Create a new Facet */
+  createFacet: Facet,
+  /** Update an existing Facet */
+  updateFacet: Facet,
+  /** Delete an existing Facet */
+  deleteFacet: DeletionResponse,
+  /** Create one or more FacetValues */
+  createFacetValues: Array<FacetValue>,
+  /** Update one or more FacetValues */
+  updateFacetValues: Array<FacetValue>,
+  /** Delete one or more FacetValues */
+  deleteFacetValues: Array<DeletionResponse>,
   /** Create a new CustomerGroup */
   createCustomerGroup: CustomerGroup,
   /** Update an existing CustomerGroup */
@@ -1451,27 +1463,14 @@ export type Mutation = {
   updateCustomerAddress: Address,
   /** Update an existing Address */
   deleteCustomerAddress: Scalars['Boolean'],
-  /** Create a new Facet */
-  createFacet: Facet,
-  /** Update an existing Facet */
-  updateFacet: Facet,
-  /** Delete an existing Facet */
-  deleteFacet: DeletionResponse,
-  /** Create one or more FacetValues */
-  createFacetValues: Array<FacetValue>,
-  /** Update one or more FacetValues */
-  updateFacetValues: Array<FacetValue>,
-  /** Delete one or more FacetValues */
-  deleteFacetValues: Array<DeletionResponse>,
-  updateGlobalSettings: GlobalSettings,
   importProducts?: Maybe<ImportInfo>,
+  updateGlobalSettings: GlobalSettings,
   /** Update an existing PaymentMethod */
   updatePaymentMethod: PaymentMethod,
   /** Create a new ProductOptionGroup */
   createProductOptionGroup: ProductOptionGroup,
   /** Update an existing ProductOptionGroup */
   updateProductOptionGroup: ProductOptionGroup,
-  reindex: SearchReindexResponse,
   /** Create a new Product */
   createProduct: Product,
   /** Update an existing Product */
@@ -1486,6 +1485,7 @@ export type Mutation = {
   generateVariantsForProduct: Product,
   /** Update existing ProductVariants */
   updateProductVariants: Array<Maybe<ProductVariant>>,
+  reindex: SearchReindexResponse,
   createPromotion: Promotion,
   updatePromotion: Promotion,
   deletePromotion: DeletionResponse,
@@ -1497,14 +1497,6 @@ export type Mutation = {
   createShippingMethod: ShippingMethod,
   /** Update an existing ShippingMethod */
   updateShippingMethod: ShippingMethod,
-  /** Create a new TaxCategory */
-  createTaxCategory: TaxCategory,
-  /** Update an existing TaxCategory */
-  updateTaxCategory: TaxCategory,
-  /** Create a new TaxRate */
-  createTaxRate: TaxRate,
-  /** Update an existing TaxRate */
-  updateTaxRate: TaxRate,
   /** Create a new Zone */
   createZone: Zone,
   /** Update an existing Zone */
@@ -1515,6 +1507,14 @@ export type Mutation = {
   addMembersToZone: Zone,
   /** Remove members from a Zone */
   removeMembersFromZone: Zone,
+  /** Create a new TaxCategory */
+  createTaxCategory: TaxCategory,
+  /** Update an existing TaxCategory */
+  updateTaxCategory: TaxCategory,
+  /** Create a new TaxRate */
+  createTaxRate: TaxRate,
+  /** Update an existing TaxRate */
+  updateTaxRate: TaxRate,
 };
 
 
@@ -1539,6 +1539,16 @@ export type MutationCreateAssetsArgs = {
 };
 
 
+export type MutationCreateChannelArgs = {
+  input: CreateChannelInput
+};
+
+
+export type MutationUpdateChannelArgs = {
+  input: UpdateChannelInput
+};
+
+
 export type MutationLoginArgs = {
   username: Scalars['String'],
   password: Scalars['String'],
@@ -1561,16 +1571,6 @@ export type MutationMoveCollectionArgs = {
 };
 
 
-export type MutationCreateChannelArgs = {
-  input: CreateChannelInput
-};
-
-
-export type MutationUpdateChannelArgs = {
-  input: UpdateChannelInput
-};
-
-
 export type MutationCreateCountryArgs = {
   input: CreateCountryInput
 };
@@ -1586,6 +1586,38 @@ export type MutationDeleteCountryArgs = {
 };
 
 
+export type MutationCreateFacetArgs = {
+  input: CreateFacetInput
+};
+
+
+export type MutationUpdateFacetArgs = {
+  input: UpdateFacetInput
+};
+
+
+export type MutationDeleteFacetArgs = {
+  id: Scalars['ID'],
+  force?: Maybe<Scalars['Boolean']>
+};
+
+
+export type MutationCreateFacetValuesArgs = {
+  input: Array<CreateFacetValueInput>
+};
+
+
+export type MutationUpdateFacetValuesArgs = {
+  input: Array<UpdateFacetValueInput>
+};
+
+
+export type MutationDeleteFacetValuesArgs = {
+  ids: Array<Scalars['ID']>,
+  force?: Maybe<Scalars['Boolean']>
+};
+
+
 export type MutationCreateCustomerGroupArgs = {
   input: CreateCustomerGroupInput
 };
@@ -1640,35 +1672,8 @@ export type MutationDeleteCustomerAddressArgs = {
 };
 
 
-export type MutationCreateFacetArgs = {
-  input: CreateFacetInput
-};
-
-
-export type MutationUpdateFacetArgs = {
-  input: UpdateFacetInput
-};
-
-
-export type MutationDeleteFacetArgs = {
-  id: Scalars['ID'],
-  force?: Maybe<Scalars['Boolean']>
-};
-
-
-export type MutationCreateFacetValuesArgs = {
-  input: Array<CreateFacetValueInput>
-};
-
-
-export type MutationUpdateFacetValuesArgs = {
-  input: Array<UpdateFacetValueInput>
-};
-
-
-export type MutationDeleteFacetValuesArgs = {
-  ids: Array<Scalars['ID']>,
-  force?: Maybe<Scalars['Boolean']>
+export type MutationImportProductsArgs = {
+  csvFile: Scalars['Upload']
 };
 
 
@@ -1677,11 +1682,6 @@ export type MutationUpdateGlobalSettingsArgs = {
 };
 
 
-export type MutationImportProductsArgs = {
-  csvFile: Scalars['Upload']
-};
-
-
 export type MutationUpdatePaymentMethodArgs = {
   input: UpdatePaymentMethodInput
 };
@@ -1772,26 +1772,6 @@ export type MutationUpdateShippingMethodArgs = {
 };
 
 
-export type MutationCreateTaxCategoryArgs = {
-  input: CreateTaxCategoryInput
-};
-
-
-export type MutationUpdateTaxCategoryArgs = {
-  input: UpdateTaxCategoryInput
-};
-
-
-export type MutationCreateTaxRateArgs = {
-  input: CreateTaxRateInput
-};
-
-
-export type MutationUpdateTaxRateArgs = {
-  input: UpdateTaxRateInput
-};
-
-
 export type MutationCreateZoneArgs = {
   input: CreateZoneInput
 };
@@ -1818,6 +1798,26 @@ export type MutationRemoveMembersFromZoneArgs = {
   memberIds: Array<Scalars['ID']>
 };
 
+
+export type MutationCreateTaxCategoryArgs = {
+  input: CreateTaxCategoryInput
+};
+
+
+export type MutationUpdateTaxCategoryArgs = {
+  input: UpdateTaxCategoryInput
+};
+
+
+export type MutationCreateTaxRateArgs = {
+  input: CreateTaxRateInput
+};
+
+
+export type MutationUpdateTaxRateArgs = {
+  input: UpdateTaxRateInput
+};
+
 export type Node = {
   id: Scalars['ID'],
 };
@@ -1911,6 +1911,11 @@ export type OrderLine = Node & {
   totalPrice: Scalars['Int'],
   adjustments: Array<Adjustment>,
   order: Order,
+  customFields?: Maybe<OrderLineCustomFields>,
+};
+
+export type OrderLineCustomFields = {
+  message?: Maybe<Scalars['String']>,
 };
 
 export type OrderList = PaginatedList & {
@@ -2276,21 +2281,21 @@ export type Query = {
   administrator?: Maybe<Administrator>,
   assets: AssetList,
   asset?: Maybe<Asset>,
+  channels: Array<Channel>,
+  channel?: Maybe<Channel>,
+  activeChannel: Channel,
   me?: Maybe<CurrentUser>,
   collections: CollectionList,
   collection?: Maybe<Collection>,
   collectionFilters: Array<ConfigurableOperation>,
-  channels: Array<Channel>,
-  channel?: Maybe<Channel>,
-  activeChannel: Channel,
   countries: CountryList,
   country?: Maybe<Country>,
+  facets: FacetList,
+  facet?: Maybe<Facet>,
   customerGroups: Array<CustomerGroup>,
   customerGroup?: Maybe<CustomerGroup>,
   customers: CustomerList,
   customer?: Maybe<Customer>,
-  facets: FacetList,
-  facet?: Maybe<Facet>,
   globalSettings: GlobalSettings,
   order?: Maybe<Order>,
   orders: OrderList,
@@ -2298,9 +2303,10 @@ export type Query = {
   paymentMethod?: Maybe<PaymentMethod>,
   productOptionGroups: Array<ProductOptionGroup>,
   productOptionGroup?: Maybe<ProductOptionGroup>,
-  search: SearchResponse,
   products: ProductList,
+  /** Get a Product either by id or slug. If neither id nor slug is speicified, an error will result. */
   product?: Maybe<Product>,
+  search: SearchResponse,
   promotion?: Maybe<Promotion>,
   promotions: PromotionList,
   adjustmentOperations: AdjustmentOperations,
@@ -2310,12 +2316,12 @@ export type Query = {
   shippingMethod?: Maybe<ShippingMethod>,
   shippingEligibilityCheckers: Array<ConfigurableOperation>,
   shippingCalculators: Array<ConfigurableOperation>,
+  zones: Array<Zone>,
+  zone?: Maybe<Zone>,
   taxCategories: Array<TaxCategory>,
   taxCategory?: Maybe<TaxCategory>,
   taxRates: TaxRateList,
   taxRate?: Maybe<TaxRate>,
-  zones: Array<Zone>,
-  zone?: Maybe<Zone>,
   temp__?: Maybe<Scalars['Boolean']>,
 };
 
@@ -2340,6 +2346,11 @@ export type QueryAssetArgs = {
 };
 
 
+export type QueryChannelArgs = {
+  id: Scalars['ID']
+};
+
+
 export type QueryCollectionsArgs = {
   languageCode?: Maybe<LanguageCode>,
   options?: Maybe<CollectionListOptions>
@@ -2352,11 +2363,6 @@ export type QueryCollectionArgs = {
 };
 
 
-export type QueryChannelArgs = {
-  id: Scalars['ID']
-};
-
-
 export type QueryCountriesArgs = {
   options?: Maybe<CountryListOptions>
 };
@@ -2367,30 +2373,30 @@ export type QueryCountryArgs = {
 };
 
 
-export type QueryCustomerGroupArgs = {
-  id: Scalars['ID']
+export type QueryFacetsArgs = {
+  languageCode?: Maybe<LanguageCode>,
+  options?: Maybe<FacetListOptions>
 };
 
 
-export type QueryCustomersArgs = {
-  options?: Maybe<CustomerListOptions>
+export type QueryFacetArgs = {
+  id: Scalars['ID'],
+  languageCode?: Maybe<LanguageCode>
 };
 
 
-export type QueryCustomerArgs = {
+export type QueryCustomerGroupArgs = {
   id: Scalars['ID']
 };
 
 
-export type QueryFacetsArgs = {
-  languageCode?: Maybe<LanguageCode>,
-  options?: Maybe<FacetListOptions>
+export type QueryCustomersArgs = {
+  options?: Maybe<CustomerListOptions>
 };
 
 
-export type QueryFacetArgs = {
-  id: Scalars['ID'],
-  languageCode?: Maybe<LanguageCode>
+export type QueryCustomerArgs = {
+  id: Scalars['ID']
 };
 
 
@@ -2426,11 +2432,6 @@ export type QueryProductOptionGroupArgs = {
 };
 
 
-export type QuerySearchArgs = {
-  input: SearchInput
-};
-
-
 export type QueryProductsArgs = {
   languageCode?: Maybe<LanguageCode>,
   options?: Maybe<ProductListOptions>
@@ -2444,6 +2445,11 @@ export type QueryProductArgs = {
 };
 
 
+export type QuerySearchArgs = {
+  input: SearchInput
+};
+
+
 export type QueryPromotionArgs = {
   id: Scalars['ID']
 };
@@ -2474,6 +2480,11 @@ export type QueryShippingMethodArgs = {
 };
 
 
+export type QueryZoneArgs = {
+  id: Scalars['ID']
+};
+
+
 export type QueryTaxCategoryArgs = {
   id: Scalars['ID']
 };
@@ -2488,11 +2499,6 @@ export type QueryTaxRateArgs = {
   id: Scalars['ID']
 };
 
-
-export type QueryZoneArgs = {
-  id: Scalars['ID']
-};
-
 export type Return = Node & StockMovement & {
   id: Scalars['ID'],
   createdAt: Scalars['DateTime'],

+ 1 - 0
packages/common/src/shared-types.ts

@@ -88,6 +88,7 @@ export interface CustomFields {
     Facet?: CustomFieldConfig[];
     FacetValue?: CustomFieldConfig[];
     GlobalSettings?: CustomFieldConfig[];
+    OrderLine?: CustomFieldConfig[];
     Product?: CustomFieldConfig[];
     ProductOption?: CustomFieldConfig[];
     ProductOptionGroup?: CustomFieldConfig[];

+ 130 - 124
packages/core/e2e/graphql/generated-e2e-admin-types.ts

@@ -1410,6 +1410,10 @@ export type Mutation = {
     assignRoleToAdministrator: Administrator;
     /** Create a new Asset */
     createAssets: Array<Asset>;
+    /** Create a new Channel */
+    createChannel: Channel;
+    /** Update an existing Channel */
+    updateChannel: Channel;
     login: LoginResult;
     logout: Scalars['Boolean'];
     /** Create a new Collection */
@@ -1418,16 +1422,24 @@ export type Mutation = {
     updateCollection: Collection;
     /** Move a Collection to a different parent or index */
     moveCollection: Collection;
-    /** Create a new Channel */
-    createChannel: Channel;
-    /** Update an existing Channel */
-    updateChannel: Channel;
     /** Create a new Country */
     createCountry: Country;
     /** Update an existing Country */
     updateCountry: Country;
     /** Delete a Country */
     deleteCountry: DeletionResponse;
+    /** Create a new Facet */
+    createFacet: Facet;
+    /** Update an existing Facet */
+    updateFacet: Facet;
+    /** Delete an existing Facet */
+    deleteFacet: DeletionResponse;
+    /** Create one or more FacetValues */
+    createFacetValues: Array<FacetValue>;
+    /** Update one or more FacetValues */
+    updateFacetValues: Array<FacetValue>;
+    /** Delete one or more FacetValues */
+    deleteFacetValues: Array<DeletionResponse>;
     /** Create a new CustomerGroup */
     createCustomerGroup: CustomerGroup;
     /** Update an existing CustomerGroup */
@@ -1448,27 +1460,14 @@ export type Mutation = {
     updateCustomerAddress: Address;
     /** Update an existing Address */
     deleteCustomerAddress: Scalars['Boolean'];
-    /** Create a new Facet */
-    createFacet: Facet;
-    /** Update an existing Facet */
-    updateFacet: Facet;
-    /** Delete an existing Facet */
-    deleteFacet: DeletionResponse;
-    /** Create one or more FacetValues */
-    createFacetValues: Array<FacetValue>;
-    /** Update one or more FacetValues */
-    updateFacetValues: Array<FacetValue>;
-    /** Delete one or more FacetValues */
-    deleteFacetValues: Array<DeletionResponse>;
-    updateGlobalSettings: GlobalSettings;
     importProducts?: Maybe<ImportInfo>;
+    updateGlobalSettings: GlobalSettings;
     /** Update an existing PaymentMethod */
     updatePaymentMethod: PaymentMethod;
     /** Create a new ProductOptionGroup */
     createProductOptionGroup: ProductOptionGroup;
     /** Update an existing ProductOptionGroup */
     updateProductOptionGroup: ProductOptionGroup;
-    reindex: SearchReindexResponse;
     /** Create a new Product */
     createProduct: Product;
     /** Update an existing Product */
@@ -1483,6 +1482,7 @@ export type Mutation = {
     generateVariantsForProduct: Product;
     /** Update existing ProductVariants */
     updateProductVariants: Array<Maybe<ProductVariant>>;
+    reindex: SearchReindexResponse;
     createPromotion: Promotion;
     updatePromotion: Promotion;
     deletePromotion: DeletionResponse;
@@ -1494,14 +1494,6 @@ export type Mutation = {
     createShippingMethod: ShippingMethod;
     /** Update an existing ShippingMethod */
     updateShippingMethod: ShippingMethod;
-    /** Create a new TaxCategory */
-    createTaxCategory: TaxCategory;
-    /** Update an existing TaxCategory */
-    updateTaxCategory: TaxCategory;
-    /** Create a new TaxRate */
-    createTaxRate: TaxRate;
-    /** Update an existing TaxRate */
-    updateTaxRate: TaxRate;
     /** Create a new Zone */
     createZone: Zone;
     /** Update an existing Zone */
@@ -1512,6 +1504,14 @@ export type Mutation = {
     addMembersToZone: Zone;
     /** Remove members from a Zone */
     removeMembersFromZone: Zone;
+    /** Create a new TaxCategory */
+    createTaxCategory: TaxCategory;
+    /** Update an existing TaxCategory */
+    updateTaxCategory: TaxCategory;
+    /** Create a new TaxRate */
+    createTaxRate: TaxRate;
+    /** Update an existing TaxRate */
+    updateTaxRate: TaxRate;
 };
 
 export type MutationCreateAdministratorArgs = {
@@ -1531,6 +1531,14 @@ export type MutationCreateAssetsArgs = {
     input: Array<CreateAssetInput>;
 };
 
+export type MutationCreateChannelArgs = {
+    input: CreateChannelInput;
+};
+
+export type MutationUpdateChannelArgs = {
+    input: UpdateChannelInput;
+};
+
 export type MutationLoginArgs = {
     username: Scalars['String'];
     password: Scalars['String'];
@@ -1549,14 +1557,6 @@ export type MutationMoveCollectionArgs = {
     input: MoveCollectionInput;
 };
 
-export type MutationCreateChannelArgs = {
-    input: CreateChannelInput;
-};
-
-export type MutationUpdateChannelArgs = {
-    input: UpdateChannelInput;
-};
-
 export type MutationCreateCountryArgs = {
     input: CreateCountryInput;
 };
@@ -1569,6 +1569,32 @@ export type MutationDeleteCountryArgs = {
     id: Scalars['ID'];
 };
 
+export type MutationCreateFacetArgs = {
+    input: CreateFacetInput;
+};
+
+export type MutationUpdateFacetArgs = {
+    input: UpdateFacetInput;
+};
+
+export type MutationDeleteFacetArgs = {
+    id: Scalars['ID'];
+    force?: Maybe<Scalars['Boolean']>;
+};
+
+export type MutationCreateFacetValuesArgs = {
+    input: Array<CreateFacetValueInput>;
+};
+
+export type MutationUpdateFacetValuesArgs = {
+    input: Array<UpdateFacetValueInput>;
+};
+
+export type MutationDeleteFacetValuesArgs = {
+    ids: Array<Scalars['ID']>;
+    force?: Maybe<Scalars['Boolean']>;
+};
+
 export type MutationCreateCustomerGroupArgs = {
     input: CreateCustomerGroupInput;
 };
@@ -1613,40 +1639,14 @@ export type MutationDeleteCustomerAddressArgs = {
     id: Scalars['ID'];
 };
 
-export type MutationCreateFacetArgs = {
-    input: CreateFacetInput;
-};
-
-export type MutationUpdateFacetArgs = {
-    input: UpdateFacetInput;
-};
-
-export type MutationDeleteFacetArgs = {
-    id: Scalars['ID'];
-    force?: Maybe<Scalars['Boolean']>;
-};
-
-export type MutationCreateFacetValuesArgs = {
-    input: Array<CreateFacetValueInput>;
-};
-
-export type MutationUpdateFacetValuesArgs = {
-    input: Array<UpdateFacetValueInput>;
-};
-
-export type MutationDeleteFacetValuesArgs = {
-    ids: Array<Scalars['ID']>;
-    force?: Maybe<Scalars['Boolean']>;
+export type MutationImportProductsArgs = {
+    csvFile: Scalars['Upload'];
 };
 
 export type MutationUpdateGlobalSettingsArgs = {
     input: UpdateGlobalSettingsInput;
 };
 
-export type MutationImportProductsArgs = {
-    csvFile: Scalars['Upload'];
-};
-
 export type MutationUpdatePaymentMethodArgs = {
     input: UpdatePaymentMethodInput;
 };
@@ -1720,22 +1720,6 @@ export type MutationUpdateShippingMethodArgs = {
     input: UpdateShippingMethodInput;
 };
 
-export type MutationCreateTaxCategoryArgs = {
-    input: CreateTaxCategoryInput;
-};
-
-export type MutationUpdateTaxCategoryArgs = {
-    input: UpdateTaxCategoryInput;
-};
-
-export type MutationCreateTaxRateArgs = {
-    input: CreateTaxRateInput;
-};
-
-export type MutationUpdateTaxRateArgs = {
-    input: UpdateTaxRateInput;
-};
-
 export type MutationCreateZoneArgs = {
     input: CreateZoneInput;
 };
@@ -1758,6 +1742,22 @@ export type MutationRemoveMembersFromZoneArgs = {
     memberIds: Array<Scalars['ID']>;
 };
 
+export type MutationCreateTaxCategoryArgs = {
+    input: CreateTaxCategoryInput;
+};
+
+export type MutationUpdateTaxCategoryArgs = {
+    input: UpdateTaxCategoryInput;
+};
+
+export type MutationCreateTaxRateArgs = {
+    input: CreateTaxRateInput;
+};
+
+export type MutationUpdateTaxRateArgs = {
+    input: UpdateTaxRateInput;
+};
+
 export type Node = {
     id: Scalars['ID'];
 };
@@ -1851,6 +1851,11 @@ export type OrderLine = Node & {
     totalPrice: Scalars['Int'];
     adjustments: Array<Adjustment>;
     order: Order;
+    customFields?: Maybe<OrderLineCustomFields>;
+};
+
+export type OrderLineCustomFields = {
+    message?: Maybe<Scalars['String']>;
 };
 
 export type OrderList = PaginatedList & {
@@ -2215,21 +2220,21 @@ export type Query = {
     administrator?: Maybe<Administrator>;
     assets: AssetList;
     asset?: Maybe<Asset>;
+    channels: Array<Channel>;
+    channel?: Maybe<Channel>;
+    activeChannel: Channel;
     me?: Maybe<CurrentUser>;
     collections: CollectionList;
     collection?: Maybe<Collection>;
     collectionFilters: Array<ConfigurableOperation>;
-    channels: Array<Channel>;
-    channel?: Maybe<Channel>;
-    activeChannel: Channel;
     countries: CountryList;
     country?: Maybe<Country>;
+    facets: FacetList;
+    facet?: Maybe<Facet>;
     customerGroups: Array<CustomerGroup>;
     customerGroup?: Maybe<CustomerGroup>;
     customers: CustomerList;
     customer?: Maybe<Customer>;
-    facets: FacetList;
-    facet?: Maybe<Facet>;
     globalSettings: GlobalSettings;
     order?: Maybe<Order>;
     orders: OrderList;
@@ -2237,9 +2242,10 @@ export type Query = {
     paymentMethod?: Maybe<PaymentMethod>;
     productOptionGroups: Array<ProductOptionGroup>;
     productOptionGroup?: Maybe<ProductOptionGroup>;
-    search: SearchResponse;
     products: ProductList;
+    /** Get a Product either by id or slug. If neither id nor slug is speicified, an error will result. */
     product?: Maybe<Product>;
+    search: SearchResponse;
     promotion?: Maybe<Promotion>;
     promotions: PromotionList;
     adjustmentOperations: AdjustmentOperations;
@@ -2249,12 +2255,12 @@ export type Query = {
     shippingMethod?: Maybe<ShippingMethod>;
     shippingEligibilityCheckers: Array<ConfigurableOperation>;
     shippingCalculators: Array<ConfigurableOperation>;
+    zones: Array<Zone>;
+    zone?: Maybe<Zone>;
     taxCategories: Array<TaxCategory>;
     taxCategory?: Maybe<TaxCategory>;
     taxRates: TaxRateList;
     taxRate?: Maybe<TaxRate>;
-    zones: Array<Zone>;
-    zone?: Maybe<Zone>;
     temp__?: Maybe<Scalars['Boolean']>;
 };
 
@@ -2274,6 +2280,10 @@ export type QueryAssetArgs = {
     id: Scalars['ID'];
 };
 
+export type QueryChannelArgs = {
+    id: Scalars['ID'];
+};
+
 export type QueryCollectionsArgs = {
     languageCode?: Maybe<LanguageCode>;
     options?: Maybe<CollectionListOptions>;
@@ -2284,10 +2294,6 @@ export type QueryCollectionArgs = {
     languageCode?: Maybe<LanguageCode>;
 };
 
-export type QueryChannelArgs = {
-    id: Scalars['ID'];
-};
-
 export type QueryCountriesArgs = {
     options?: Maybe<CountryListOptions>;
 };
@@ -2296,26 +2302,26 @@ export type QueryCountryArgs = {
     id: Scalars['ID'];
 };
 
-export type QueryCustomerGroupArgs = {
-    id: Scalars['ID'];
+export type QueryFacetsArgs = {
+    languageCode?: Maybe<LanguageCode>;
+    options?: Maybe<FacetListOptions>;
 };
 
-export type QueryCustomersArgs = {
-    options?: Maybe<CustomerListOptions>;
+export type QueryFacetArgs = {
+    id: Scalars['ID'];
+    languageCode?: Maybe<LanguageCode>;
 };
 
-export type QueryCustomerArgs = {
+export type QueryCustomerGroupArgs = {
     id: Scalars['ID'];
 };
 
-export type QueryFacetsArgs = {
-    languageCode?: Maybe<LanguageCode>;
-    options?: Maybe<FacetListOptions>;
+export type QueryCustomersArgs = {
+    options?: Maybe<CustomerListOptions>;
 };
 
-export type QueryFacetArgs = {
+export type QueryCustomerArgs = {
     id: Scalars['ID'];
-    languageCode?: Maybe<LanguageCode>;
 };
 
 export type QueryOrderArgs = {
@@ -2344,10 +2350,6 @@ export type QueryProductOptionGroupArgs = {
     languageCode?: Maybe<LanguageCode>;
 };
 
-export type QuerySearchArgs = {
-    input: SearchInput;
-};
-
 export type QueryProductsArgs = {
     languageCode?: Maybe<LanguageCode>;
     options?: Maybe<ProductListOptions>;
@@ -2359,6 +2361,10 @@ export type QueryProductArgs = {
     languageCode?: Maybe<LanguageCode>;
 };
 
+export type QuerySearchArgs = {
+    input: SearchInput;
+};
+
 export type QueryPromotionArgs = {
     id: Scalars['ID'];
 };
@@ -2383,6 +2389,10 @@ export type QueryShippingMethodArgs = {
     id: Scalars['ID'];
 };
 
+export type QueryZoneArgs = {
+    id: Scalars['ID'];
+};
+
 export type QueryTaxCategoryArgs = {
     id: Scalars['ID'];
 };
@@ -2395,10 +2405,6 @@ export type QueryTaxRateArgs = {
     id: Scalars['ID'];
 };
 
-export type QueryZoneArgs = {
-    id: Scalars['ID'];
-};
-
 export type Return = Node &
     StockMovement & {
         id: Scalars['ID'];
@@ -3504,16 +3510,6 @@ export type CreateProductMutation = { __typename?: 'Mutation' } & {
     createProduct: { __typename?: 'Product' } & ProductWithVariantsFragment;
 };
 
-export type GetProductSimpleQueryVariables = {
-    id?: Maybe<Scalars['ID']>;
-    slug?: Maybe<Scalars['String']>;
-    languageCode?: Maybe<LanguageCode>;
-};
-
-export type GetProductSimpleQuery = { __typename?: 'Query' } & {
-    product: Maybe<{ __typename?: 'Product' } & Pick<Product, 'id' | 'slug'>>;
-};
-
 export type GetProductWithVariantsQueryVariables = {
     id?: Maybe<Scalars['ID']>;
     slug?: Maybe<Scalars['String']>;
@@ -3688,6 +3684,16 @@ export type DeleteProductMutation = { __typename?: 'Mutation' } & {
     deleteProduct: { __typename?: 'DeletionResponse' } & Pick<DeletionResponse, 'result'>;
 };
 
+export type GetProductSimpleQueryVariables = {
+    id?: Maybe<Scalars['ID']>;
+    slug?: Maybe<Scalars['String']>;
+    languageCode?: Maybe<LanguageCode>;
+};
+
+export type GetProductSimpleQuery = { __typename?: 'Query' } & {
+    product: Maybe<{ __typename?: 'Product' } & Pick<Product, 'id' | 'slug'>>;
+};
+
 export type GetProductsQueryVariables = {
     options?: Maybe<ProductListOptions>;
 };
@@ -4489,12 +4495,6 @@ export namespace CreateProduct {
     export type CreateProduct = ProductWithVariantsFragment;
 }
 
-export namespace GetProductSimple {
-    export type Variables = GetProductSimpleQueryVariables;
-    export type Query = GetProductSimpleQuery;
-    export type Product = NonNullable<GetProductSimpleQuery['product']>;
-}
-
 export namespace GetProductWithVariants {
     export type Variables = GetProductWithVariantsQueryVariables;
     export type Query = GetProductWithVariantsQuery;
@@ -4609,6 +4609,12 @@ export namespace DeleteProduct {
     export type DeleteProduct = DeleteProductMutation['deleteProduct'];
 }
 
+export namespace GetProductSimple {
+    export type Variables = GetProductSimpleQueryVariables;
+    export type Query = GetProductSimpleQuery;
+    export type Product = NonNullable<GetProductSimpleQuery['product']>;
+}
+
 export namespace GetProducts {
     export type Variables = GetProductsQueryVariables;
     export type Query = GetProductsQuery;

+ 25 - 13
packages/core/e2e/graphql/generated-e2e-shop-types.ts

@@ -1105,8 +1105,8 @@ export type LoginResult = {
 
 export type Mutation = {
     addItemToOrder?: Maybe<Order>;
-    removeItemFromOrder?: Maybe<Order>;
-    adjustItemQuantity?: Maybe<Order>;
+    removeOrderLine?: Maybe<Order>;
+    adjustOrderLine?: Maybe<Order>;
     transitionOrderToState?: Maybe<Order>;
     setOrderShippingAddress?: Maybe<Order>;
     setOrderShippingMethod?: Maybe<Order>;
@@ -1153,15 +1153,17 @@ export type Mutation = {
 export type MutationAddItemToOrderArgs = {
     productVariantId: Scalars['ID'];
     quantity: Scalars['Int'];
+    customFields?: Maybe<OrderLineCustomFieldsInput>;
 };
 
-export type MutationRemoveItemFromOrderArgs = {
-    orderItemId: Scalars['ID'];
+export type MutationRemoveOrderLineArgs = {
+    orderLineId: Scalars['ID'];
 };
 
-export type MutationAdjustItemQuantityArgs = {
-    orderItemId: Scalars['ID'];
-    quantity: Scalars['Int'];
+export type MutationAdjustOrderLineArgs = {
+    orderLineId: Scalars['ID'];
+    quantity?: Maybe<Scalars['Int']>;
+    customFields?: Maybe<OrderLineCustomFieldsInput>;
 };
 
 export type MutationTransitionOrderToStateArgs = {
@@ -1335,6 +1337,15 @@ export type OrderLine = Node & {
     totalPrice: Scalars['Int'];
     adjustments: Array<Adjustment>;
     order: Order;
+    customFields?: Maybe<OrderLineCustomFields>;
+};
+
+export type OrderLineCustomFields = {
+    message?: Maybe<Scalars['String']>;
+};
+
+export type OrderLineCustomFieldsInput = {
+    message?: Maybe<Scalars['String']>;
 };
 
 export type OrderList = PaginatedList & {
@@ -1620,6 +1631,7 @@ export type Query = {
     nextOrderStates: Array<Scalars['String']>;
     order?: Maybe<Order>;
     orderByCode?: Maybe<Order>;
+    /** Get a Product either by id or slug. If neither id nor slug is speicified, an error will result. */
     product?: Maybe<Product>;
     products: ProductList;
     search: SearchResponse;
@@ -2068,20 +2080,20 @@ export type GetActiveOrderQuery = { __typename?: 'Query' } & {
 };
 
 export type AdjustItemQuantityMutationVariables = {
-    orderItemId: Scalars['ID'];
+    orderLineId: Scalars['ID'];
     quantity: Scalars['Int'];
 };
 
 export type AdjustItemQuantityMutation = { __typename?: 'Mutation' } & {
-    adjustItemQuantity: Maybe<{ __typename?: 'Order' } & TestOrderFragmentFragment>;
+    adjustOrderLine: Maybe<{ __typename?: 'Order' } & TestOrderFragmentFragment>;
 };
 
 export type RemoveItemFromOrderMutationVariables = {
-    orderItemId: Scalars['ID'];
+    orderLineId: Scalars['ID'];
 };
 
 export type RemoveItemFromOrderMutation = { __typename?: 'Mutation' } & {
-    removeItemFromOrder: Maybe<{ __typename?: 'Order' } & TestOrderFragmentFragment>;
+    removeOrderLine: Maybe<{ __typename?: 'Order' } & TestOrderFragmentFragment>;
 };
 
 export type GetShippingMethodsQueryVariables = {};
@@ -2315,13 +2327,13 @@ export namespace GetActiveOrder {
 export namespace AdjustItemQuantity {
     export type Variables = AdjustItemQuantityMutationVariables;
     export type Mutation = AdjustItemQuantityMutation;
-    export type AdjustItemQuantity = TestOrderFragmentFragment;
+    export type AdjustOrderLine = TestOrderFragmentFragment;
 }
 
 export namespace RemoveItemFromOrder {
     export type Variables = RemoveItemFromOrderMutationVariables;
     export type Mutation = RemoveItemFromOrderMutation;
-    export type RemoveItemFromOrder = TestOrderFragmentFragment;
+    export type RemoveOrderLine = TestOrderFragmentFragment;
 }
 
 export namespace GetShippingMethods {

+ 5 - 5
packages/core/e2e/graphql/shop-definitions.ts

@@ -164,9 +164,9 @@ export const GET_ACTIVE_ORDER = gql`
     ${TEST_ORDER_FRAGMENT}
 `;
 
-export const ADJUST_ITEM_QUENTITY = gql`
-    mutation AdjustItemQuantity($orderItemId: ID!, $quantity: Int!) {
-        adjustItemQuantity(orderItemId: $orderItemId, quantity: $quantity) {
+export const ADJUST_ITEM_QUANTITY = gql`
+    mutation AdjustItemQuantity($orderLineId: ID!, $quantity: Int!) {
+        adjustOrderLine(orderLineId: $orderLineId, quantity: $quantity) {
             ...TestOrderFragment
         }
     }
@@ -174,8 +174,8 @@ export const ADJUST_ITEM_QUENTITY = gql`
 `;
 
 export const REMOVE_ITEM_FROM_ORDER = gql`
-    mutation RemoveItemFromOrder($orderItemId: ID!) {
-        removeItemFromOrder(orderItemId: $orderItemId) {
+    mutation RemoveItemFromOrder($orderLineId: ID!) {
+        removeOrderLine(orderLineId: $orderLineId) {
             ...TestOrderFragment
         }
     }

+ 45 - 45
packages/core/e2e/shop-order.e2e-spec.ts

@@ -25,7 +25,7 @@ import { GET_COUNTRY_LIST, GET_CUSTOMER, GET_CUSTOMER_LIST, UPDATE_COUNTRY } fro
 import {
     ADD_ITEM_TO_ORDER,
     ADD_PAYMENT,
-    ADJUST_ITEM_QUENTITY,
+    ADJUST_ITEM_QUANTITY,
     GET_ACTIVE_ORDER,
     GET_ACTIVE_ORDER_ADDRESSES,
     GET_AVAILABLE_COUNTRIES,
@@ -87,7 +87,7 @@ describe('Shop orders', () => {
     });
 
     describe('ordering as anonymous user', () => {
-        let firstOrderItemId: string;
+        let firstOrderLineId: string;
         let createdCustomerId: string;
         let orderCode: string;
 
@@ -117,7 +117,7 @@ describe('Shop orders', () => {
             expect(addItemToOrder!.lines[0].quantity).toBe(1);
             expect(addItemToOrder!.lines[0].productVariant.id).toBe('T_1');
             expect(addItemToOrder!.lines[0].id).toBe('T_1');
-            firstOrderItemId = addItemToOrder!.lines[0].id;
+            firstOrderLineId = addItemToOrder!.lines[0].id;
             orderCode = addItemToOrder!.code;
         });
 
@@ -168,26 +168,26 @@ describe('Shop orders', () => {
             }, 'Cannot add items. An order may consist of a maximum of 99 items'),
         );
 
-        it('adjustItemQuantity adjusts the quantity', async () => {
-            const { adjustItemQuantity } = await shopClient.query<
+        it('adjustOrderLine adjusts the quantity', async () => {
+            const { adjustOrderLine } = await shopClient.query<
                 AdjustItemQuantity.Mutation,
                 AdjustItemQuantity.Variables
-            >(ADJUST_ITEM_QUENTITY, {
-                orderItemId: firstOrderItemId,
+            >(ADJUST_ITEM_QUANTITY, {
+                orderLineId: firstOrderLineId,
                 quantity: 50,
             });
 
-            expect(adjustItemQuantity!.lines.length).toBe(1);
-            expect(adjustItemQuantity!.lines[0].quantity).toBe(50);
+            expect(adjustOrderLine!.lines.length).toBe(1);
+            expect(adjustOrderLine!.lines[0].quantity).toBe(50);
         });
 
         it(
-            'adjustItemQuantity errors when going beyond orderItemsLimit',
+            'adjustOrderLine errors when going beyond orderItemsLimit',
             assertThrowsWithMessage(async () => {
                 await shopClient.query<AdjustItemQuantity.Mutation, AdjustItemQuantity.Variables>(
-                    ADJUST_ITEM_QUENTITY,
+                    ADJUST_ITEM_QUANTITY,
                     {
-                        orderItemId: firstOrderItemId,
+                        orderLineId: firstOrderLineId,
                         quantity: 100,
                     },
                 );
@@ -195,13 +195,13 @@ describe('Shop orders', () => {
         );
 
         it(
-            'adjustItemQuantity errors with a negative quantity',
+            'adjustOrderLine errors with a negative quantity',
             assertThrowsWithMessage(
                 () =>
                     shopClient.query<AdjustItemQuantity.Mutation, AdjustItemQuantity.Variables>(
-                        ADJUST_ITEM_QUENTITY,
+                        ADJUST_ITEM_QUANTITY,
                         {
-                            orderItemId: firstOrderItemId,
+                            orderLineId: firstOrderLineId,
                             quantity: -3,
                         },
                     ),
@@ -210,13 +210,13 @@ describe('Shop orders', () => {
         );
 
         it(
-            'adjustItemQuantity errors with an invalid orderItemId',
+            'adjustOrderLine errors with an invalid orderLineId',
             assertThrowsWithMessage(
                 () =>
                     shopClient.query<AdjustItemQuantity.Mutation, AdjustItemQuantity.Variables>(
-                        ADJUST_ITEM_QUENTITY,
+                        ADJUST_ITEM_QUANTITY,
                         {
-                            orderItemId: 'T_999',
+                            orderLineId: 'T_999',
                             quantity: 5,
                         },
                     ),
@@ -235,14 +235,14 @@ describe('Shop orders', () => {
             expect(addItemToOrder!.lines.length).toBe(2);
             expect(addItemToOrder!.lines.map(i => i.productVariant.id)).toEqual(['T_1', 'T_3']);
 
-            const { removeItemFromOrder } = await shopClient.query<
+            const { removeOrderLine } = await shopClient.query<
                 RemoveItemFromOrder.Mutation,
                 RemoveItemFromOrder.Variables
             >(REMOVE_ITEM_FROM_ORDER, {
-                orderItemId: firstOrderItemId,
+                orderLineId: firstOrderLineId,
             });
-            expect(removeItemFromOrder!.lines.length).toBe(1);
-            expect(removeItemFromOrder!.lines.map(i => i.productVariant.id)).toEqual(['T_3']);
+            expect(removeOrderLine!.lines.length).toBe(1);
+            expect(removeOrderLine!.lines.map(i => i.productVariant.id)).toEqual(['T_3']);
         });
 
         it(
@@ -252,7 +252,7 @@ describe('Shop orders', () => {
                     shopClient.query<RemoveItemFromOrder.Mutation, RemoveItemFromOrder.Variables>(
                         REMOVE_ITEM_FROM_ORDER,
                         {
-                            orderItemId: 'T_999',
+                            orderLineId: 'T_999',
                         },
                     ),
                 `This order does not contain an OrderLine with the id 999`,
@@ -416,7 +416,7 @@ describe('Shop orders', () => {
     });
 
     describe('ordering as authenticated user', () => {
-        let firstOrderItemId: string;
+        let firstOrderLineId: string;
         let activeOrder: AddItemToOrder.AddItemToOrder;
         let authenticatedUserEmailAddress: string;
         let customers: GetCustomerList.Items[];
@@ -455,7 +455,7 @@ describe('Shop orders', () => {
             expect(addItemToOrder!.lines[0].quantity).toBe(1);
             expect(addItemToOrder!.lines[0].productVariant.id).toBe('T_1');
             activeOrder = addItemToOrder!;
-            firstOrderItemId = addItemToOrder!.lines[0].id;
+            firstOrderLineId = addItemToOrder!.lines[0].id;
         });
 
         it('activeOrder returns order after item has been added', async () => {
@@ -477,17 +477,17 @@ describe('Shop orders', () => {
             expect(addItemToOrder!.lines[0].quantity).toBe(3);
         });
 
-        it('adjustItemQuantity adjusts the quantity', async () => {
-            const { adjustItemQuantity } = await shopClient.query<
+        it('adjustOrderLine adjusts the quantity', async () => {
+            const { adjustOrderLine } = await shopClient.query<
                 AdjustItemQuantity.Mutation,
                 AdjustItemQuantity.Variables
-            >(ADJUST_ITEM_QUENTITY, {
-                orderItemId: firstOrderItemId,
+            >(ADJUST_ITEM_QUANTITY, {
+                orderLineId: firstOrderLineId,
                 quantity: 50,
             });
 
-            expect(adjustItemQuantity!.lines.length).toBe(1);
-            expect(adjustItemQuantity!.lines[0].quantity).toBe(50);
+            expect(adjustOrderLine!.lines.length).toBe(1);
+            expect(adjustOrderLine!.lines[0].quantity).toBe(50);
         });
 
         it('removeItemFromOrder removes the correct item', async () => {
@@ -501,14 +501,14 @@ describe('Shop orders', () => {
             expect(addItemToOrder!.lines.length).toBe(2);
             expect(addItemToOrder!.lines.map(i => i.productVariant.id)).toEqual(['T_1', 'T_3']);
 
-            const { removeItemFromOrder } = await shopClient.query<
+            const { removeOrderLine } = await shopClient.query<
                 RemoveItemFromOrder.Mutation,
                 RemoveItemFromOrder.Variables
             >(REMOVE_ITEM_FROM_ORDER, {
-                orderItemId: firstOrderItemId,
+                orderLineId: firstOrderLineId,
             });
-            expect(removeItemFromOrder!.lines.length).toBe(1);
-            expect(removeItemFromOrder!.lines.map(i => i.productVariant.id)).toEqual(['T_3']);
+            expect(removeOrderLine!.lines.length).toBe(1);
+            expect(removeOrderLine!.lines.map(i => i.productVariant.id)).toEqual(['T_3']);
         });
 
         it('nextOrderStates returns next valid states', async () => {
@@ -616,20 +616,20 @@ describe('Shop orders', () => {
                 expect(order.shippingMethod!.description).toBe(shippingMethods[1].description);
             });
 
-            it('shipping method is preserved after adjustItemQuantity', async () => {
+            it('shipping method is preserved after adjustOrderLine', async () => {
                 const activeOrderResult = await shopClient.query<GetActiveOrder.Query>(GET_ACTIVE_ORDER);
                 activeOrder = activeOrderResult.activeOrder!;
-                const { adjustItemQuantity } = await shopClient.query<
+                const { adjustOrderLine } = await shopClient.query<
                     AdjustItemQuantity.Mutation,
                     AdjustItemQuantity.Variables
-                >(ADJUST_ITEM_QUENTITY, {
-                    orderItemId: activeOrder.lines[0].id,
+                >(ADJUST_ITEM_QUANTITY, {
+                    orderLineId: activeOrder.lines[0].id,
                     quantity: 10,
                 });
 
-                expect(adjustItemQuantity!.shipping).toBe(shippingMethods[1].price);
-                expect(adjustItemQuantity!.shippingMethod!.id).toBe(shippingMethods[1].id);
-                expect(adjustItemQuantity!.shippingMethod!.description).toBe(
+                expect(adjustOrderLine!.shipping).toBe(shippingMethods[1].price);
+                expect(adjustOrderLine!.shippingMethod!.id).toBe(shippingMethods[1].id);
+                expect(adjustOrderLine!.shippingMethod!.description).toBe(
                     shippingMethods[1].description,
                 );
             });
@@ -684,9 +684,9 @@ describe('Shop orders', () => {
                 assertThrowsWithMessage(
                     () =>
                         shopClient.query<AdjustItemQuantity.Mutation, AdjustItemQuantity.Variables>(
-                            ADJUST_ITEM_QUENTITY,
+                            ADJUST_ITEM_QUANTITY,
                             {
-                                orderItemId: activeOrder.lines[0].id,
+                                orderLineId: activeOrder.lines[0].id,
                                 quantity: 12,
                             },
                         ),
@@ -701,7 +701,7 @@ describe('Shop orders', () => {
                         shopClient.query<RemoveItemFromOrder.Mutation, RemoveItemFromOrder.Variables>(
                             REMOVE_ITEM_FROM_ORDER,
                             {
-                                orderItemId: activeOrder.lines[0].id,
+                                orderLineId: activeOrder.lines[0].id,
                             },
                         ),
                     `Order contents may only be modified when in the "AddingItems" state`,

+ 20 - 0
packages/core/src/api/config/__snapshots__/graphql-custom-fields.spec.ts.snap

@@ -205,3 +205,23 @@ type Product {
 }
 "
 `;
+
+exports[`addOrderLineCustomFieldsInput() Does not modify schema when the addItemToOrder mutation not present 1`] = `
+"type Mutation {
+  createCustomer(id: ID!): Boolean
+}
+"
+`;
+
+exports[`addOrderLineCustomFieldsInput() Modifies the schema when the addItemToOrder & adjustOrderLine mutation is present 1`] = `
+"type Mutation {
+  addItemToOrder(id: ID!, quantity: Int!, customFields: OrderLineCustomFieldsInput): Boolean
+  adjustOrderLine(id: ID!, quantity: Int, customFields: OrderLineCustomFieldsInput): Boolean
+}
+
+input OrderLineCustomFieldsInput {
+  giftWrap: Boolean
+  message: String
+}
+"
+`;

+ 2 - 1
packages/core/src/api/config/configure-graphql-module.ts

@@ -17,7 +17,7 @@ import { IdEncoderExtension } from '../middleware/id-encoder-extension';
 import { TranslateErrorExtension } from '../middleware/translate-errors-extension';
 
 import { generateListOptions } from './generate-list-options';
-import { addGraphQLCustomFields } from './graphql-custom-fields';
+import { addGraphQLCustomFields, addOrderLineCustomFieldsInput } from './graphql-custom-fields';
 
 export interface GraphQLApiOptions {
     apiType: 'shop' | 'admin';
@@ -126,6 +126,7 @@ async function createGraphQLOptions(
         const typeDefs = await typesLoader.mergeTypesByPaths(options.typePaths);
         let schema = generateListOptions(typeDefs);
         schema = addGraphQLCustomFields(schema, customFields);
+        schema = addOrderLineCustomFieldsInput(schema, customFields.OrderLine || []);
         const pluginSchemaExtensions = getPluginAPIExtensions(configService.plugins, apiType).map(
             e => e.schema,
         );

+ 34 - 3
packages/core/src/api/config/graphql-custom-fields.spec.ts

@@ -1,8 +1,7 @@
+import { CustomFieldConfig, CustomFields } from '@vendure/common/lib/shared-types';
 import { printSchema } from 'graphql';
 
-import { CustomFields } from '@vendure/common/lib/shared-types';
-
-import { addGraphQLCustomFields } from './graphql-custom-fields';
+import { addGraphQLCustomFields, addOrderLineCustomFieldsInput } from './graphql-custom-fields';
 
 describe('addGraphQLCustomFields()', () => {
     it('uses JSON scalar if no custom fields defined', () => {
@@ -169,3 +168,35 @@ describe('addGraphQLCustomFields()', () => {
         expect(printSchema(result)).toMatchSnapshot();
     });
 });
+
+describe('addOrderLineCustomFieldsInput()', () => {
+
+    it('Modifies the schema when the addItemToOrder & adjustOrderLine mutation is present', () => {
+        const input = `
+            type Mutation {
+                addItemToOrder(id: ID!, quantity: Int!): Boolean
+                adjustOrderLine(id: ID!, quantity: Int): Boolean
+            }
+        `;
+        const customFieldConfig: CustomFieldConfig[] = [
+            { name: 'giftWrap', type: 'boolean' },
+            { name: 'message', type: 'string' },
+        ];
+        const result = addOrderLineCustomFieldsInput(input, customFieldConfig);
+        expect(printSchema(result)).toMatchSnapshot();
+    });
+
+    it('Does not modify schema when the addItemToOrder mutation not present', () => {
+        const input = `
+            type Mutation {
+                createCustomer(id: ID!): Boolean
+            }
+        `;
+        const customFieldConfig: CustomFieldConfig[] = [
+            { name: 'giftWrap', type: 'boolean' },
+            { name: 'message', type: 'string' },
+        ];
+        const result = addOrderLineCustomFieldsInput(input, customFieldConfig);
+        expect(printSchema(result)).toMatchSnapshot();
+    });
+});

+ 40 - 2
packages/core/src/api/config/graphql-custom-fields.ts

@@ -1,7 +1,6 @@
-import { buildSchema, extendSchema, GraphQLSchema, parse } from 'graphql';
-
 import { CustomFieldConfig, CustomFields, CustomFieldType } from '@vendure/common/lib/shared-types';
 import { assertNever } from '@vendure/common/lib/shared-utils';
+import { buildSchema, extendSchema, GraphQLArgument, GraphQLInputObjectType, GraphQLSchema, parse } from 'graphql';
 
 /**
  * Given a CustomFields config object, generates an SDL string extending the built-in
@@ -140,6 +139,45 @@ export function addGraphQLCustomFields(
     return extendSchema(schema, parse(customFieldTypeDefs));
 }
 
+/**
+ * If CustomFields are defined on the OrderLine entity, then an extra `customFields` argument
+ * must be added to the `addItemToOrder` and `adjustOrderLine` mutations.
+ */
+export function addOrderLineCustomFieldsInput(typeDefsOrSchema: string | GraphQLSchema, orderLineCustomFields: CustomFieldConfig[]): GraphQLSchema {
+    const schema = typeof typeDefsOrSchema === 'string' ? buildSchema(typeDefsOrSchema) : typeDefsOrSchema;
+    if (!orderLineCustomFields || orderLineCustomFields.length === 0) {
+        return schema;
+    }
+    const schemaConfig = schema.toConfig();
+    const mutationType = schemaConfig.mutation;
+    if (!mutationType) {
+        return schema;
+    }
+    const addItemToOrderMutation = mutationType.getFields().addItemToOrder;
+    const adjustOrderLineMutation = mutationType.getFields().adjustOrderLine;
+    if (!addItemToOrderMutation || !adjustOrderLineMutation) {
+        return schema;
+    }
+    const input = new GraphQLInputObjectType({
+        name: 'OrderLineCustomFieldsInput',
+        fields: orderLineCustomFields.reduce((fields, field) => {
+            return { ...fields, [field.name]: { type: schema.getType(getGraphQlType(field.type)) } };
+        }, {}),
+    });
+
+    schemaConfig.types.push(input);
+    addItemToOrderMutation.args.push({
+        name: 'customFields',
+        type: input,
+    });
+    adjustOrderLineMutation.args.push({
+        name: 'customFields',
+        type: input,
+    });
+
+    return new GraphQLSchema(schemaConfig);
+}
+
 type GraphQLFieldType = 'String' | 'Int' | 'Float' | 'Boolean' | 'ID';
 
 /**

+ 11 - 11
packages/core/src/api/resolvers/shop/shop-order.resolver.ts

@@ -2,8 +2,8 @@ import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
 import {
     MutationAddItemToOrderArgs,
     MutationAddPaymentToOrderArgs,
-    MutationAdjustItemQuantityArgs,
-    MutationRemoveItemFromOrderArgs,
+    MutationAdjustOrderLineArgs,
+    MutationRemoveOrderLineArgs,
     MutationSetCustomerForOrderArgs,
     MutationSetOrderShippingAddressArgs,
     MutationSetOrderShippingMethodArgs,
@@ -193,29 +193,29 @@ export class ShopOrderResolver {
         @Args() args: MutationAddItemToOrderArgs,
     ): Promise<Order> {
         const order = await this.getOrderFromContext(ctx, true);
-        return this.orderService.addItemToOrder(ctx, order.id, args.productVariantId, args.quantity);
+        return this.orderService.addItemToOrder(ctx, order.id, args.productVariantId, args.quantity, (args as any).customFields);
     }
 
     @Mutation()
     @Allow(Permission.UpdateOrder, Permission.Owner)
-    @Decode('orderItemId')
-    async adjustItemQuantity(
+    @Decode('orderLineId')
+    async adjustOrderLine(
         @Ctx() ctx: RequestContext,
-        @Args() args: MutationAdjustItemQuantityArgs,
+        @Args() args: MutationAdjustOrderLineArgs,
     ): Promise<Order> {
         const order = await this.getOrderFromContext(ctx, true);
-        return this.orderService.adjustItemQuantity(ctx, order.id, args.orderItemId, args.quantity);
+        return this.orderService.adjustOrderLine(ctx, order.id, args.orderLineId, args.quantity, (args as any).customFields);
     }
 
     @Mutation()
     @Allow(Permission.UpdateOrder, Permission.Owner)
-    @Decode('orderItemId')
-    async removeItemFromOrder(
+    @Decode('orderLineId')
+    async removeOrderLine(
         @Ctx() ctx: RequestContext,
-        @Args() args: MutationRemoveItemFromOrderArgs,
+        @Args() args: MutationRemoveOrderLineArgs,
     ): Promise<Order> {
         const order = await this.getOrderFromContext(ctx, true);
-        return this.orderService.removeItemFromOrder(ctx, order.id, args.orderItemId);
+        return this.orderService.removeItemFromOrder(ctx, order.id, args.orderLineId);
     }
 
     @Mutation()

+ 5 - 3
packages/core/src/api/schema/shop-api/shop.api.graphql

@@ -10,16 +10,18 @@ type Query {
     nextOrderStates: [String!]!
     order(id: ID!): Order
     orderByCode(code: String!): Order
-    "Get a Product either by id or slug. If neither id nor slug is speicified, an error will result."
+    "Get a Product either by id or slug. If neither 'id' nor 'slug' is speicified, an error will result."
     product(id: ID, slug: String, languageCode: LanguageCode): Product
     products(languageCode: LanguageCode, options: ProductListOptions): ProductList!
     search(input: SearchInput!): SearchResponse!
 }
 
 type Mutation {
+    "Adds an item to the order. If custom fields are defined on the OrderLine entity, a third argument 'customFields' will be available."
     addItemToOrder(productVariantId: ID!, quantity: Int!): Order
-    removeItemFromOrder(orderItemId: ID!): Order
-    adjustItemQuantity(orderItemId: ID!, quantity: Int!): Order
+    removeOrderLine(orderLineId: ID!): Order
+    "Adjusts an OrderLine. If custom fields are defined on the OrderLine entity, a third argument 'customFields' will be available."
+    adjustOrderLine(orderLineId: ID!, quantity: Int): Order
     transitionOrderToState(state: String!): Order
     setOrderShippingAddress(input: CreateAddressInput!): Order
     setOrderShippingMethod(shippingMethodId: ID!): Order

+ 1 - 0
packages/core/src/config/default-config.ts

@@ -87,6 +87,7 @@ export const defaultConfig: ReadOnlyRequired<VendureConfig> = {
         Facet: [],
         FacetValue: [],
         GlobalSettings: [],
+        OrderLine: [],
         Product: [],
         ProductOption: [],
         ProductOptionGroup: [],

+ 4 - 19
packages/core/src/entity/custom-entity-fields.ts

@@ -1,46 +1,29 @@
 import { CustomFieldConfig, CustomFields, CustomFieldType, Type } from '@vendure/common/lib/shared-types';
 import { assertNever } from '@vendure/common/lib/shared-utils';
-import { Column, ColumnType, Connection, ConnectionOptions, Entity, getConnection } from 'typeorm';
+import { Column, ColumnType, Connection, ConnectionOptions, getConnection } from 'typeorm';
 
 import { VendureConfig } from '../config/vendure-config';
 
 import { VendureEntity } from './base/base.entity';
 
-@Entity()
 export class CustomAddressFields {}
-@Entity()
 export class CustomFacetFields {}
-@Entity()
 export class CustomFacetFieldsTranslation {}
-@Entity()
 export class CustomFacetValueFields {}
-@Entity()
 export class CustomFacetValueFieldsTranslation {}
-@Entity()
 export class CustomCustomerFields {}
-@Entity()
+export class CustomOrderLineFields {}
 export class CustomProductFields {}
-@Entity()
 export class CustomProductFieldsTranslation {}
-@Entity()
 export class CustomCollectionFields {}
-@Entity()
 export class CustomCollectionFieldsTranslation {}
-@Entity()
 export class CustomProductOptionFields {}
-@Entity()
 export class CustomProductOptionFieldsTranslation {}
-@Entity()
 export class CustomProductOptionGroupFields {}
-@Entity()
 export class CustomProductOptionGroupFieldsTranslation {}
-@Entity()
 export class CustomProductVariantFields {}
-@Entity()
 export class CustomProductVariantFieldsTranslation {}
-@Entity()
 export class CustomUserFields {}
-@Entity()
 export class CustomGlobalSettingsFields {}
 
 /**
@@ -49,6 +32,7 @@ export class CustomGlobalSettingsFields {}
 function registerCustomFieldsForEntity(
     config: VendureConfig,
     entityName: keyof CustomFields,
+    // tslint:disable-next-line:callable-types
     ctor: { new (): any },
     translation = false,
 ) {
@@ -156,6 +140,7 @@ export function registerCustomEntityFields(config: VendureConfig) {
     registerCustomFieldsForEntity(config, 'Facet', CustomFacetFieldsTranslation, true);
     registerCustomFieldsForEntity(config, 'FacetValue', CustomFacetValueFields);
     registerCustomFieldsForEntity(config, 'FacetValue', CustomFacetValueFieldsTranslation, true);
+    registerCustomFieldsForEntity(config, 'OrderLine', CustomOrderLineFields);
     registerCustomFieldsForEntity(config, 'Product', CustomProductFields);
     registerCustomFieldsForEntity(config, 'Product', CustomProductFieldsTranslation, true);
     registerCustomFieldsForEntity(config, 'ProductOption', CustomProductOptionFields);

+ 6 - 2
packages/core/src/entity/order-line/order-line.entity.ts

@@ -1,10 +1,11 @@
 import { Adjustment, AdjustmentType } from '@vendure/common/lib/generated-types';
-import { DeepPartial } from '@vendure/common/lib/shared-types';
+import { DeepPartial, HasCustomFields } from '@vendure/common/lib/shared-types';
 import { Column, Entity, ManyToOne, OneToMany } from 'typeorm';
 
 import { Calculated } from '../../common/calculated-decorator';
 import { Asset } from '../asset/asset.entity';
 import { VendureEntity } from '../base/base.entity';
+import { CustomOrderLineFields, CustomProductFields } from '../custom-entity-fields';
 import { OrderItem } from '../order-item/order-item.entity';
 import { Order } from '../order/order.entity';
 import { ProductVariant } from '../product-variant/product-variant.entity';
@@ -17,7 +18,7 @@ import { TaxCategory } from '../tax-category/tax-category.entity';
  * @docsCategory entities
  */
 @Entity()
-export class OrderLine extends VendureEntity {
+export class OrderLine extends VendureEntity implements HasCustomFields {
     constructor(input?: DeepPartial<OrderLine>) {
         super(input);
     }
@@ -37,6 +38,9 @@ export class OrderLine extends VendureEntity {
     @ManyToOne(type => Order, order => order.lines, { onDelete: 'CASCADE' })
     order: Order;
 
+    @Column(type => CustomOrderLineFields)
+    customFields: CustomOrderLineFields;
+
     @Calculated()
     get unitPrice(): number {
         return this.items ? this.items[0].unitPrice : 0;

+ 37 - 27
packages/core/src/service/services/order.service.ts

@@ -171,53 +171,62 @@ export class OrderService {
         orderId: ID,
         productVariantId: ID,
         quantity: number,
+        customFields?: { [key: string]: any; },
     ): Promise<Order> {
         this.assertQuantityIsPositive(quantity);
         const order = await this.getOrderOrThrow(ctx, orderId);
         this.assertAddingItemsState(order);
         this.assertNotOverOrderItemsLimit(order, quantity);
         const productVariant = await this.getProductVariantOrThrow(ctx, productVariantId);
-        let orderLine = order.lines.find(line => idsAreEqual(line.productVariant.id, productVariantId));
+        let orderLine = order.lines.find(line => {
+            return idsAreEqual(line.productVariant.id, productVariantId) && JSON.stringify(line.customFields) === JSON.stringify(customFields);
+        });
 
         if (!orderLine) {
-            const newLine = this.createOrderLineFromVariant(productVariant);
+            const newLine = this.createOrderLineFromVariant(productVariant, customFields);
             orderLine = await this.connection.getRepository(OrderLine).save(newLine);
             order.lines.push(orderLine);
             await this.connection.getRepository(Order).save(order);
         }
-        return this.adjustItemQuantity(ctx, orderId, orderLine.id, orderLine.quantity + quantity);
+        return this.adjustOrderLine(ctx, orderId, orderLine.id, orderLine.quantity + quantity);
     }
 
-    async adjustItemQuantity(
+    async adjustOrderLine(
         ctx: RequestContext,
         orderId: ID,
         orderLineId: ID,
-        quantity: number,
+        quantity?: number | null,
+        customFields?: { [key: string]: any; },
     ): Promise<Order> {
-        this.assertQuantityIsPositive(quantity);
         const order = await this.getOrderOrThrow(ctx, orderId);
-        this.assertAddingItemsState(order);
         const orderLine = this.getOrderLineOrThrow(order, orderLineId);
-        const currentQuantity = orderLine.quantity;
-        this.assertNotOverOrderItemsLimit(order, quantity - currentQuantity);
-        if (currentQuantity < quantity) {
-            if (!orderLine.items) {
-                orderLine.items = [];
-            }
-            const productVariant = orderLine.productVariant;
-            for (let i = currentQuantity; i < quantity; i++) {
-                const orderItem = await this.connection.getRepository(OrderItem).save(
-                    new OrderItem({
-                        unitPrice: productVariant.price,
-                        pendingAdjustments: [],
-                        unitPriceIncludesTax: productVariant.priceIncludesTax,
-                        taxRate: productVariant.priceIncludesTax ? productVariant.taxRateApplied.value : 0,
-                    }),
-                );
-                orderLine.items.push(orderItem);
+        this.assertAddingItemsState(order);
+        if (quantity != null) {
+            this.assertQuantityIsPositive(quantity);
+            const currentQuantity = orderLine.quantity;
+            this.assertNotOverOrderItemsLimit(order, quantity - currentQuantity);
+            if (currentQuantity < quantity) {
+                if (!orderLine.items) {
+                    orderLine.items = [];
+                }
+                const productVariant = orderLine.productVariant;
+                for (let i = currentQuantity; i < quantity; i++) {
+                    const orderItem = await this.connection.getRepository(OrderItem).save(
+                        new OrderItem({
+                            unitPrice: productVariant.price,
+                            pendingAdjustments: [],
+                            unitPriceIncludesTax: productVariant.priceIncludesTax,
+                            taxRate: productVariant.priceIncludesTax ? productVariant.taxRateApplied.value : 0,
+                        }),
+                    );
+                    orderLine.items.push(orderItem);
+                }
+            } else if (quantity < currentQuantity) {
+                orderLine.items = orderLine.items.slice(0, quantity);
             }
-        } else if (quantity < currentQuantity) {
-            orderLine.items = orderLine.items.slice(0, quantity);
+        }
+        if (customFields != null) {
+            orderLine.customFields = customFields;
         }
         await this.connection.getRepository(OrderLine).save(orderLine);
         return this.applyPriceAdjustments(ctx, order);
@@ -363,11 +372,12 @@ export class OrderService {
         return orderItem;
     }
 
-    private createOrderLineFromVariant(productVariant: ProductVariant): OrderLine {
+    private createOrderLineFromVariant(productVariant: ProductVariant, customFields?: { [key: string]: any; }): OrderLine {
         return new OrderLine({
             productVariant,
             taxCategory: productVariant.taxCategory,
             featuredAsset: productVariant.product.featuredAsset,
+            customFields,
         });
     }
 

File diff suppressed because it is too large
+ 0 - 0
schema-admin.json


File diff suppressed because it is too large
+ 0 - 0
schema-shop.json


Some files were not shown because too many files changed in this diff