type Query {
    "List Products"
    products(options: ProductListOptions): ProductList!
    "Get a Product either by id or slug. If neither id nor slug is specified, an error will result."
    product(id: ID, slug: String): Product
    "List ProductVariants either all or for the specific product."
    productVariants(options: ProductVariantListOptions, productId: ID): ProductVariantList!
    "Get a ProductVariant by id"
    productVariant(id: ID!): ProductVariant
}

type Mutation {
    "Create a new Product"
    createProduct(input: CreateProductInput!): Product!

    "Update an existing Product"
    updateProduct(input: UpdateProductInput!): Product!

    "Delete a Product"
    deleteProduct(id: ID!): DeletionResponse!

    "Add an OptionGroup to a Product"
    addOptionGroupToProduct(productId: ID!, optionGroupId: ID!): Product!

    "Remove an OptionGroup from a Product"
    removeOptionGroupFromProduct(productId: ID!, optionGroupId: ID!): RemoveOptionGroupFromProductResult!

    "Create a set of ProductVariants based on the OptionGroups assigned to the given Product"
    createProductVariants(input: [CreateProductVariantInput!]!): [ProductVariant]!

    "Update existing ProductVariants"
    updateProductVariants(input: [UpdateProductVariantInput!]!): [ProductVariant]!

    "Delete a ProductVariant"
    deleteProductVariant(id: ID!): DeletionResponse!

    "Assigns all ProductVariants of Product to the specified Channel"
    assignProductsToChannel(input: AssignProductsToChannelInput!): [Product!]!

    "Removes all ProductVariants of Product from the specified Channel"
    removeProductsFromChannel(input: RemoveProductsFromChannelInput!): [Product!]!

    "Assigns ProductVariants to the specified Channel"
    assignProductVariantsToChannel(input: AssignProductVariantsToChannelInput!): [ProductVariant!]!

    "Removes ProductVariants from the specified Channel"
    removeProductVariantsFromChannel(input: RemoveProductVariantsFromChannelInput!): [ProductVariant!]!
}

input StockMovementListOptions {
    type: StockMovementType
    skip: Int
    take: Int
}

# generated by generateListOptions function
input ProductListOptions

# generated by generateListOptions function
input ProductVariantListOptions

input ProductTranslationInput {
    id: ID
    languageCode: LanguageCode!
    name: String
    slug: String
    description: String
}

input CreateProductInput {
    featuredAssetId: ID
    enabled: Boolean
    assetIds: [ID!]
    facetValueIds: [ID!]
    translations: [ProductTranslationInput!]!
}

input UpdateProductInput {
    id: ID!
    enabled: Boolean
    featuredAssetId: ID
    assetIds: [ID!]
    facetValueIds: [ID!]
    translations: [ProductTranslationInput!]
}

input ProductVariantTranslationInput {
    id: ID
    languageCode: LanguageCode!
    name: String
}

input ProductOptionTranslationInput {
    id: ID
    languageCode: LanguageCode!
    name: String
}

input CreateProductVariantOptionInput {
    optionGroupId: ID!
    code: String!
    translations: [ProductOptionTranslationInput!]!
}

input CreateProductVariantInput {
    productId: ID!
    translations: [ProductVariantTranslationInput!]!
    facetValueIds: [ID!]
    sku: String!
    price: Int
    taxCategoryId: ID
    optionIds: [ID!]
    featuredAssetId: ID
    assetIds: [ID!]
    stockOnHand: Int
    outOfStockThreshold: Int
    useGlobalOutOfStockThreshold: Boolean
    trackInventory: GlobalFlag
}

input UpdateProductVariantInput {
    id: ID!
    enabled: Boolean
    translations: [ProductVariantTranslationInput!]
    facetValueIds: [ID!]
    sku: String
    taxCategoryId: ID
    price: Int
    featuredAssetId: ID
    assetIds: [ID!]
    stockOnHand: Int
    outOfStockThreshold: Int
    useGlobalOutOfStockThreshold: Boolean
    trackInventory: GlobalFlag
}

input AssignProductsToChannelInput {
    productIds: [ID!]!
    channelId: ID!
    priceFactor: Float
}

input RemoveProductsFromChannelInput {
    productIds: [ID!]!
    channelId: ID!
}

input AssignProductVariantsToChannelInput {
    productVariantIds: [ID!]!
    channelId: ID!
    priceFactor: Float
}

input RemoveProductVariantsFromChannelInput {
    productVariantIds: [ID!]!
    channelId: ID!
}

type ProductOptionInUseError implements ErrorResult {
    errorCode: ErrorCode!
    message: String!
    optionGroupCode: String!
    productVariantCount: Int!
}

union RemoveOptionGroupFromProductResult = Product | ProductOptionInUseError
