16 February 2018
Composable Commerce
HTTP API
Enhancement
GraphQL
GraphQL API surface area was extended and now includes a lot of new query fields and types, as well as experimental mutation support.
  • [GraphQL API] Added support for DiscountCode, CartDiscount and ProductDiscount. Following changes were introduced in the GraphQL schema:
    extend type Query {
      discountCode(id: String!): DiscountCode
      discountCodes(where: String, sort: [String!], limit: Int, offset: Int): DiscountCodeQueryResult!
    
      cartDiscount(id: String!): CartDiscount
      cartDiscounts(where: String, sort: [String!], limit: Int, offset: Int): CartDiscountQueryResult!
    
      productDiscount(id: String!): ProductDiscount
      productDiscounts(where: String, sort: [String!], limit: Int, offset: Int): ProductDiscountQueryResult!
    }
    
    interface CartDiscountTarget {
      type: String!
    }
    
    interface CartDiscountValue {
      type: String!
    }
    
    interface ProductDiscountValue {
      type: String!
    }
    
    type AbsoluteDiscountValue implements CartDiscountValue, ProductDiscountValue {
      money: [Money!]!
      type: String!
    }
    
    type CartDiscount implements Versioned {
      id: String!
      version: Long!
      cartPredicate: String!
      validFrom: DateTime
      validUntil: DateTime
      stackingMode: StackingMode!
      isActive: Boolean!
      requiresDiscountCode: Boolean!
      sortOrder: String!
      createdAt: DateTime!
      lastModifiedAt: DateTime!
      name(
        "String is define for different locales. This argument specifies the desired locale."
        locale: Locale,
    
        "List of languages the client is able to understand, and which locale variant is preferred."
        acceptLanguage: [Locale!]): String
      description(
        "String is define for different locales. This argument specifies the desired locale."
        locale: Locale,
    
        "List of languages the client is able to understand, and which locale variant is preferred."
        acceptLanguage: [Locale!]): String
      nameAllLocales: [LocalizedString!]!
      descriptionAllLocales: [LocalizedString!]
      value: CartDiscountValue!
      target: CartDiscountTarget
    }
    
    type CartDiscountQueryResult {
      offset: Int!
      count: Int!
      total: Long!
      results: [CartDiscount!]!
    }
    
    type DiscountCode implements Versioned {
      id: String!
      version: Long!
      code: String!
      isActive: Boolean!
      maxApplications: Long
      maxApplicationsPerCustomer: Long
      cartPredicate: String
      applicationVersion: Long
      createdAt: DateTime!
      lastModifiedAt: DateTime!
      validFrom: DateTime
      validUntil: DateTime
      groups: [String!]!
      name(
        "String is define for different locales. This argument specifies the desired locale."
        locale: Locale,
    
        "List of languages the client is able to understand, and which locale variant is preferred."
        acceptLanguage: [Locale!]): String
      description(
        "String is define for different locales. This argument specifies the desired locale."
        locale: Locale,
    
        "List of languages the client is able to understand, and which locale variant is preferred."
        acceptLanguage: [Locale!]): String
      nameAllLocales: [LocalizedString!]
      descriptionAllLocales: [LocalizedString!]
      cartDiscounts: [CartDiscount!]!
    }
    
    type DiscountCodeQueryResult {
      offset: Int!
      count: Int!
      total: Long!
      results: [DiscountCode!]!
    }
    
    type ExternalDiscountValue implements ProductDiscountValue {
      type: String!
    }
    
    type LineItemsTarget implements CartDiscountTarget {
      predicate: String!
      type: String!
    }
    
    type MultiBuyCustomLineItemsTarget implements CartDiscountTarget {
      predicate: String!
      triggerQuantity: Int!
      discountedQuantity: Int!
      maxOccurrence: Int
      selectionMode: SelectionMode!
      type: String!
    }
    
    type MultiBuyLineItemsTarget implements CartDiscountTarget {
      predicate: String!
      triggerQuantity: Int!
      discountedQuantity: Int!
      maxOccurrence: Int
      selectionMode: SelectionMode!
      type: String!
    }
    
    type ProductDiscount implements Versioned {
      id: String!
      version: Long!
      predicate: String!
      validFrom: DateTime
      validUntil: DateTime
      isActive: Boolean!
      isValid: Boolean!
      sortOrder: String!
      createdAt: DateTime!
      lastModifiedAt: DateTime!
      name(
        "String is define for different locales. This argument specifies the desired locale."
        locale: Locale,
    
        "List of languages the client is able to understand, and which locale variant is preferred."
        acceptLanguage: [Locale!]): String
      description(
        "String is define for different locales. This argument specifies the desired locale."
        locale: Locale,
    
        "List of languages the client is able to understand, and which locale variant is preferred."
        acceptLanguage: [Locale!]): String
      nameAllLocales: [LocalizedString!]!
      descriptionAllLocales: [LocalizedString!]
      value: ProductDiscountValue!
    }
    
    type ProductDiscountQueryResult {
      offset: Int!
      count: Int!
      total: Long!
      results: [ProductDiscount!]!
    }
    
    type RelativeDiscountValue implements CartDiscountValue, ProductDiscountValue {
      permyriad: Int!
      type: String!
    }
    
  • [GraphQL API] Added support for Type and CustomFields. Custom fields support is very similar to product attributes where the type-safe GraphQL models are created for project-specific Type definitions. At the moment custom fields are available only on the DiscountCode and the CartDiscount. Following changes were introduced in the GraphQL schema:
    extend type Query {
      typeDefinition(id: String!): TypeDefinition
      typeDefinitions(where: String, sort: [String!], limit: Int, offset: Int): TypeDefinitionQueryResult!
    }
    
    interface CustomField {
      name: String!
    }
    
    interface FieldType {
      name: String!
    }
    
    type BooleanField implements CustomField {
      value: Boolean!
      name: String!
    }
    
    type BooleanType implements FieldType {
      name: String!
    }
    
    type DateField implements CustomField {
      value: Date!
      name: String!
    }
    
    type DateTimeField implements CustomField {
      value: DateTime!
      name: String!
    }
    
    type DateTimeType implements FieldType {
      name: String!
    }
    
    type DateType implements FieldType {
      name: String!
    }
    
    type EnumField implements CustomField {
      key: String!
      label: String!
      name: String!
    }
    
    type EnumType implements FieldType {
      values: [EnumValue!]!
      name: String!
    }
    
    type EnumValue {
      key: String!
      label: String!
    }
    
    "Field definitions describe custom fields and allow you to define some meta-information associated with the field."
    type FieldDefinition {
      name: String!
      required: Boolean!
      inputHint: TextInputHint!
      label(
        "String is define for different locales. This argument specifies the desired locale."
        locale: Locale,
    
        "List of languages the client is able to understand, and which locale variant is preferred."
        acceptLanguage: [Locale!]): String
      labelAllLocales: [LocalizedString!]!
      type: FieldType!
    }
    
    type LocalizedEnumField implements CustomField {
      key: String!
      label(
        "String is define for different locales. This argument specifies the desired locale."
        locale: Locale!): String
      name: String!
    }
    
    type LocalizedEnumType implements FieldType {
      values: [LocalizedEnumValue!]!
      name: String!
    }
    
    type LocalizedEnumValue {
      key: String!
      label(
        "String is define for different locales. This argument specifies the desired locale."
        locale: Locale,
    
        "List of languages the client is able to understand, and which locale variant is preferred."
        acceptLanguage: [Locale!]): String
      labelAllLocales: [LocalizedString!]!
    }
    
    type LocalizedString {
      locale: Locale!
      value: String!
    }
    
    type LocalizedStringField implements CustomField {
      value(
        "String is define for different locales. This argument specifies the desired locale."
        locale: Locale!): String
      name: String!
    }
    
    type LocalizedStringType implements FieldType {
      name: String!
    }
    
    type MoneyField implements CustomField {
      centAmount: Long!
      currencyCode: Currency!
      name: String!
    }
    
    type MoneyType implements FieldType {
      name: String!
    }
    
    type NumberField implements CustomField {
      value: BigDecimal!
      name: String!
    }
    
    type NumberType implements FieldType {
      name: String!
    }
    
    type ProductReferenceIdentifier {
      typeId: String!
      id: String
      key: String
    }
    
    type ReferenceField implements CustomField {
      typeId: String!
      id: String!
      name: String!
    }
    
    type ReferenceType implements FieldType {
      referenceTypeId: String!
      name: String!
    }
    
    type SetType implements FieldType {
      elementType: FieldType!
      name: String!
    }
    
    type ShippingTarget implements CartDiscountTarget {
      type: String!
    }
    
    type StringField implements CustomField {
      value: String!
      name: String!
    }
    
    type StringType implements FieldType {
      name: String!
    }
    
    type TimeField implements CustomField {
      value: Time!
      name: String!
    }
    
    type TimeType implements FieldType {
      name: String!
    }
    
    "Types define the structure of custom fields which can be attached to different entities that support them."
    type TypeDefinition implements Versioned {
      id: String!
      version: Long!
      key: String!
      fieldDefinitions: [FieldDefinition!]!
      createdAt: DateTime!
      lastModifiedAt: DateTime!
      name(
        "String is define for different locales. This argument specifies the desired locale."
        locale: Locale,
    
        "List of languages the client is able to understand, and which locale variant is preferred."
        acceptLanguage: [Locale!]): String
      description(
        "String is define for different locales. This argument specifies the desired locale."
        locale: Locale,
    
        "List of languages the client is able to understand, and which locale variant is preferred."
        acceptLanguage: [Locale!]): String
      nameAllLocales: [LocalizedString!]!
      descriptionAllLocales: [LocalizedString!]
      resourceTypeIds: [String!]!
    }
    
    type TypeDefinitionQueryResult {
      offset: Int!
      count: Int!
      total: Long!
      results: [TypeDefinition!]!
    }
    
  • [GraphQL API] Added support for DiscountCode mutation API. Please note that currently mutation API is experimental and subject to change. Following changes were introduced in the GraphQL schema:
    type Mutation {
      createDiscountCode(draft: DiscountCodeDraft!): DiscountCode
      updateDiscountCode(id: String!, version: Long!, actions: [DiscountCodeUpdateAction!]!): DiscountCode
      deleteDiscountCode(id: String!, version: Long!): DiscountCode
    }
    
    input ChangeDiscountCodeCartDiscounts {
      cartDiscounts: [ReferenceInput!]!
    }
    
    input ChangeDiscountCodeGroups {
      groups: [String!]!
    }
    
    input ChangeDiscountCodeIsActive {
      isActive: Boolean!
    }
    
    input CustomFieldInput {
      name: String!
      value: String!
    }
    
    input CustomFieldsDraft {
      typeId: String
      typeKey: String
      type: ResourceIdentifierInput
      fields: [CustomFieldInput!]
    }
    
    input DiscountCodeDraft {
      code: String!
      name: [LocalizedStringInput!]
      description: [LocalizedStringInput!]
      cartDiscounts: [ReferenceInput!]!
      isActive: Boolean = true
      maxApplications: Long
      maxApplicationsPerCustomer: Long
      cartPredicate: String
      custom: CustomFieldsDraft
      validFrom: DateTime
      validUntil: DateTime
      groups: [String!] = []
    }
    
    input DiscountCodeUpdateAction {
      setName: SetDiscountCodeName
      setDescription: SetDiscountCodeDescription
      setCartPredicate: SetDiscountCodeCartPredicate
      setMaxApplications: SetDiscountCodeMaxApplications
      setMaxApplicationsPerCustomer: SetDiscountCodeMaxApplicationsPerCustomer
      changeCartDiscounts: ChangeDiscountCodeCartDiscounts
      changeIsActive: ChangeDiscountCodeIsActive
      setCustomType: SetDiscountCodeCustomType
      setCustomField: SetDiscountCodeCustomField
      setValidFrom: SetDiscountCodeValidFrom
      setValidUntil: SetDiscountCodeValidUntil
      changeGroups: ChangeDiscountCodeGroups
    }
    
    input LocalizedStringInput {
      locale: Locale!
      value: String!
    }
    
    input LocalizedText {
      text: String!
      locale: Locale!
    }
    
    input ReferenceInput {
      typeId: String!
      id: String!
    }
    
    input ResourceIdentifierInput {
      id: String
      key: String
    }
    
    input SetDiscountCodeCartPredicate {
      cartPredicate: String
    }
    
    input SetDiscountCodeCustomField {
      name: String!
      value: String
    }
    
    input SetDiscountCodeCustomType {
      typeId: String
      typeKey: String
      type: ResourceIdentifierInput
      fields: [CustomFieldInput!]
    }
    
    input SetDiscountCodeDescription {
      description: [LocalizedStringInput!]
    }
    
    input SetDiscountCodeMaxApplications {
      maxApplications: Long
    }
    
    input SetDiscountCodeMaxApplicationsPerCustomer {
      maxApplicationsPerCustomer: Long
    }
    
    input SetDiscountCodeName {
      name: [LocalizedStringInput!]
    }
    
    input SetDiscountCodeValidFrom {
      validFrom: DateTime
    }
    
    input SetDiscountCodeValidUntil {
      validUntil: DateTime
    }