30 June 2022
Composable Commerce
HTTP API
New feature
CartsOrdersPricing and DiscountsExtensibilityGraphQL

We have released Quotes in public beta. This new feature allows you to negotiate quote requests for your products with your customers. The negotiation process involves utilizing several APIs that we introduced with this feature, allowing you to control each step of the intended workflow of the negotiation. All the introduced resources, such as Quote Request, Staged Quote, and Quote can be extended with Custom Fields. The discounts applied on a specific Quote, can be utilized by the newly added DirectDiscount. After successful negotiation, the Order can be created right from the Quote.

Changes:

  • [GraphQL API] Changed the Query type:
    • Added the quoteRequest field to the Query type.
    • Added the quotes field to the Query type.
    • Added the stagedQuotes field to the Query type.
    • Added the quote field to the Query type.
    • Added the quoteRequests field to the Query type.
    • Added the stagedQuote field to the Query type.
  • [GraphQL API] Changed the Me type:
    • Added the quoteRequests field to the Me type.
    • Added the quoteRequest field to the Me type.
    • Added the quote field to the Me type.
    • Added the quotes field to the Me type.
  • [GraphQL API] Changed the Mutation type:
    • Added the createQuoteRequest field to the Mutation type.
    • Added the updateQuoteRequest field to the Mutation type.
    • Added the updateMyQuoteRequest field to the Mutation type.
    • Added the createOrderFromQuote field to the Mutation type.
    • Added the updateQuote field to the Mutation type.
    • Added the deleteQuoteRequest field to the Mutation type.
    • Added the createStagedQuote field to the Mutation type.
    • Added the updateMyQuote field to the Mutation type.
    • Added the deleteStagedQuote field to the Mutation type.
    • Added the createQuote field to the Mutation type.
    • Added the updateStagedQuote field to the Mutation type.
    • Added the createMyQuoteRequest field to the Mutation type.
    • Added the createMyOrderFromQuote field to the Mutation type.
    • Added the deleteQuote field to the Mutation type.

The following changes were introduced in terms of GraphQL SDL:

extend type Query {
  quote(
    "Queries with specified ID"
    id: String,

    "Queries with specified key"
    key: String): Quote
  quoteRequest(
    "Queries with specified ID"
    id: String,

    "Queries with specified key"
    key: String): QuoteRequest
  quoteRequests(where: String, sort: [String!], limit: Int, offset: Int): QuoteRequestQueryResult!
  quotes(where: String, sort: [String!], limit: Int, offset: Int): QuoteQueryResult!
  stagedQuote(
    "Queries with specified ID"
    id: String,

    "Queries with specified key"
    key: String): StagedQuote
  stagedQuotes(where: String, sort: [String!], limit: Int, offset: Int): StagedQuoteQueryResult!
}

extend type Me {
  "BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
  quote(
    "Queries with specified ID"
    id: String,

    "Queries with specified key"
    key: String): Quote

  "BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
  quoteRequest(
    "Queries with specified ID"
    id: String,

    "Queries with specified key"
    key: String): QuoteRequest

  "BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
  quoteRequests(where: String, sort: [String!], limit: Int, offset: Int): QuoteRequestQueryResult!

  "BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
  quotes(where: String, sort: [String!], limit: Int, offset: Int): QuoteQueryResult!
}

extend type Mutation {
  "BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
  createMyOrderFromQuote(draft: OrderMyQuoteCommand!): Order
  createMyQuoteRequest(draft: MyQuoteRequestDraft!): QuoteRequest
  createOrderFromQuote(draft: OrderQuoteCommand!): Order
  createQuote(draft: QuoteDraft!): Quote
  createQuoteRequest(draft: QuoteRequestDraft!): QuoteRequest
  createStagedQuote(draft: StagedQuoteDraft!): StagedQuote
  deleteQuote(version: Long!, personalDataErasure: Boolean = false,

    "Queries with specified ID"
    id: String,

    "Queries with specified key"
    key: String): Quote
  deleteQuoteRequest(version: Long!, personalDataErasure: Boolean = false,

    "Queries with specified ID"
    id: String,

    "Queries with specified key"
    key: String): QuoteRequest
  deleteStagedQuote(version: Long!, personalDataErasure: Boolean = false,

    "Queries with specified ID"
    id: String,

    "Queries with specified key"
    key: String): StagedQuote
  updateMyQuote(version: Long!, actions: [MyQuoteUpdateAction!]!,

    "Queries with specified ID"
    id: String,

    "Queries with specified key"
    key: String): Quote
  updateMyQuoteRequest(version: Long!, actions: [MyQuoteRequestUpdateAction!]!,

    "Queries with specified ID"
    id: String,

    "Queries with specified key"
    key: String): QuoteRequest
  updateQuote(version: Long!, actions: [QuoteUpdateAction!]!,

    "Queries with specified ID"
    id: String,

    "Queries with specified key"
    key: String): Quote
  updateQuoteRequest(version: Long!, actions: [QuoteRequestUpdateAction!]!,

    "Queries with specified ID"
    id: String,

    "Queries with specified key"
    key: String): QuoteRequest
  updateStagedQuote(version: Long!, actions: [StagedQuoteUpdateAction!]!,

    "Queries with specified ID"
    id: String,

    "Queries with specified key"
    key: String): StagedQuote
}

input CancelQuoteRequest {
  dummy: String
}

input ChangeMyQuoteMyQuoteState {
  quoteState: MyQuoteState!
}

input ChangeQuoteRequestState {
  quoteRequestState: QuoteRequestState!
}

input ChangeQuoteState {
  quoteState: MyQuoteState!
}

input ChangeStagedQuoteState {
  stagedQuoteState: StagedQuoteState!
}

input MyQuoteRequestDraft {
  cartId: String!
  comment: String
  cartVersion: Long!
}

input MyQuoteRequestUpdateAction {
  cancelQuoteRequest: CancelQuoteRequest
  setCustomField: SetMyQuoteRequestCustomField
  setCustomType: SetMyQuoteRequestCustomType
}

enum MyQuoteState {
  Accepted
  Declined
  Failed
}

input MyQuoteUpdateAction {
  changeMyQuoteState: ChangeMyQuoteMyQuoteState
  setCustomField: SetQuoteCustomField
  setCustomType: SetQuoteCustomType
}

input OrderMyQuoteCommand {
  id: String!
  version: Long!
}

input OrderQuoteCommand {
  quote: ResourceIdentifierInput
  version: Long!
  paymentState: PaymentState
  orderState: OrderState
  state: ReferenceInput
  shipmentState: ShipmentState
  orderNumber: String
  custom: CustomFieldsDraft
}

type Quote implements Versioned {
  customerRef: Reference
  customer: Customer
  lineItems(
    "Queries with specified ID"
    id: String): [LineItem!]!
  customLineItems: [CustomLineItem!]!
  totalPrice: Money!
  taxedPrice: TaxedPrice
  shippingAddress: Address
  billingAddress: Address
  itemShippingAddresses: [Address!]!
  inventoryMode: InventoryMode!
  taxMode: TaxMode!
  taxRoundingMode: RoundingMode!
  taxCalculationMode: TaxCalculationMode!
  country: Country
  shippingInfo: ShippingInfo
  paymentInfo: PaymentInfo
  shippingRateInput: ShippingRateInput
  storeRef: KeyReference
  store: Store
  key: String
  quoteState: QuoteState!
  stagedQuoteRef: Reference!
  stagedQuote: StagedQuote
  quoteRequestRef: Reference!
  quoteRequest: QuoteRequest
  validTo: DateTime
  custom: CustomFieldsType
  id: String!
  version: Long!
  createdAt: DateTime!
  lastModifiedAt: DateTime!
  createdBy: Initiator
  lastModifiedBy: Initiator
}

input QuoteDraft {
  key: String
  stagedQuote: ResourceIdentifierInput
  stagedQuoteVersion: Long
  custom: CustomFieldsDraft
}

type QuoteQueryResult {
  offset: Int!
  count: Int!
  total: Long!

  "BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
  exists: Boolean!
  results: [Quote!]!
}

type QuoteRequest implements Versioned {
  customerRef: Reference
  customer: Customer
  lineItems(
    "Queries with specified ID"
    id: String): [LineItem!]!
  customLineItems: [CustomLineItem!]!
  totalPrice: Money!
  taxedPrice: TaxedPrice
  shippingAddress: Address
  billingAddress: Address
  itemShippingAddresses: [Address!]!
  inventoryMode: InventoryMode!
  taxMode: TaxMode!
  taxRoundingMode: RoundingMode!
  taxCalculationMode: TaxCalculationMode!
  country: Country
  shippingInfo: ShippingInfo
  paymentInfo: PaymentInfo
  shippingRateInput: ShippingRateInput
  storeRef: KeyReference
  store: Store
  key: String
  quoteRequestState: QuoteRequestState!
  comment: String
  custom: CustomFieldsType
  id: String!
  version: Long!
  createdAt: DateTime!
  lastModifiedAt: DateTime!
  createdBy: Initiator
  lastModifiedBy: Initiator
}

input QuoteRequestDraft {
  key: String
  cart: ResourceIdentifierInput
  comment: String
  cartVersion: Long
  custom: CustomFieldsDraft
}

type QuoteRequestQueryResult {
  offset: Int!
  count: Int!
  total: Long!

  "BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
  exists: Boolean!
  results: [QuoteRequest!]!
}

enum QuoteRequestState {
  Closed
  UnderReview
  Submitted
  Cancelled
  Accepted
  Rejected
}

input QuoteRequestUpdateAction {
  changeQuoteRequestState: ChangeQuoteRequestState
  setCustomField: SetQuoteRequestCustomField
  setCustomType: SetQuoteRequestCustomType
}

enum QuoteState {
  Accepted
  Declined
  Failed
  Pending
  Withdrawn
}

input QuoteUpdateAction {
  changeQuoteState: ChangeQuoteState
  setCustomField: SetQuoteCustomField
  setCustomType: SetQuoteCustomType
}

input SetMyQuoteRequestCustomField {
  name: String!
  value: String
}

input SetMyQuoteRequestCustomType {
  fields: [CustomFieldInput!]
  type: ResourceIdentifierInput
  typeKey: String
  typeId: String
}

input SetQuoteCustomField {
  name: String!
  value: String
}

input SetQuoteCustomType {
  fields: [CustomFieldInput!]
  type: ResourceIdentifierInput
  typeKey: String
  typeId: String
}

input SetQuoteRequestCustomField {
  name: String!
  value: String
}

input SetQuoteRequestCustomType {
  fields: [CustomFieldInput!]
  type: ResourceIdentifierInput
  typeKey: String
  typeId: String
}

input SetStagedQuoteCustomField {
  name: String!
  value: String
}

input SetStagedQuoteCustomType {
  fields: [CustomFieldInput!]
  type: ResourceIdentifierInput
  typeKey: String
  typeId: String
}

input SetStagedQuoteSellerComment {
  sellerComment: String
}

input SetStagedQuoteValidTo {
  validTo: DateTime
}

type StagedQuote implements Versioned {
  key: String
  stagedQuoteState: StagedQuoteState!
  quoteRequestRef: Reference!
  quoteRequest: QuoteRequest
  quotationCartRef: Reference!
  quotationCart: Cart
  customerRef: Reference
  customer: Customer
  validTo: DateTime
  custom: CustomFieldsType
  id: String!
  version: Long!
  createdAt: DateTime!
  lastModifiedAt: DateTime!
  createdBy: Initiator
  lastModifiedBy: Initiator
}

input StagedQuoteDraft {
  key: String
  quoteRequest: ResourceIdentifierInput
  quoteRequestVersion: Long
  custom: CustomFieldsDraft
}

type StagedQuoteQueryResult {
  offset: Int!
  count: Int!
  total: Long!

  "BETA: This feature can be subject to change and should be used carefully in production. https://docs.commercetools.com/api/contract#public-beta"
  exists: Boolean!
  results: [StagedQuote!]!
}

enum StagedQuoteState {
  Closed
  InProgress
  Sent
}

input StagedQuoteUpdateAction {
  changeStagedQuoteState: ChangeStagedQuoteState
  setSellerComment: SetStagedQuoteSellerComment
  setCustomField: SetStagedQuoteCustomField
  setCustomType: SetStagedQuoteCustomType
  setValidTo: SetStagedQuoteValidTo
}