Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support of custom attributes values for entities like customer/product/address #458

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,19 @@ type CustomAttributeMetadata {
}

type Attribute {
uid: ID!
attribute_code: String
attribute_options: [AttributeOption]
attribute_type: String
entity_type: String
input_type: String
is_required: Bolean!
}

type AttributeOption {
uid: ID!
value: String @deprecated(reason: "use `uid` instead")
label: String
value: String
}
```

Expand Down
96 changes: 80 additions & 16 deletions design-documents/graph-ql/coverage/customer/customer.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,25 @@ type StoreConfig {
}

type Query {
customer: Customer @resolver(class: "Magento\\CustomerGraphQl\\Model\\Resolver\\Customer") @doc(description: "The customer query returns information about a customer account") @cache(cacheable: false)
customer: Customer @doc(description: "The customer query returns information about a customer account") @cache(cacheable: false)
isEmailAvailable (
email: String! @doc(description: "The new customer email")
): IsEmailAvailableOutput @resolver(class: "Magento\\CustomerGraphQl\\Model\\Resolver\\IsEmailAvailable")
): IsEmailAvailableOutput
}

type Mutation {
generateCustomerToken(email: String!, password: String!): CustomerToken @resolver(class: "\\Magento\\CustomerGraphQl\\Model\\Resolver\\GenerateCustomerToken") @doc(description:"Retrieve the customer token")
changeCustomerPassword(currentPassword: String!, newPassword: String!): Customer @resolver(class: "\\Magento\\CustomerGraphQl\\Model\\Resolver\\ChangePassword") @doc(description:"Changes the password for the logged-in customer")
createCustomer (input: CustomerInput!): CustomerOutput @resolver(class: "\\Magento\\CustomerGraphQl\\Model\\Resolver\\CreateCustomer") @doc(description:"Create customer account")
updateCustomer (input: CustomerInput!): CustomerOutput @resolver(class: "\\Magento\\CustomerGraphQl\\Model\\Resolver\\UpdateCustomer") @doc(description:"Update the customer's personal information")
revokeCustomerToken: RevokeCustomerTokenOutput @resolver(class: "\\Magento\\CustomerGraphQl\\Model\\Resolver\\RevokeCustomerToken") @doc(description:"Revoke the customer token")
createCustomerAddress(input: CustomerAddressInput!): CustomerAddress @resolver(class: "Magento\\CustomerGraphQl\\Model\\Resolver\\CreateCustomerAddress") @doc(description: "Create customer address")
updateCustomerAddress(id: Int!, input: CustomerAddressInput): CustomerAddress @resolver(class: "Magento\\CustomerGraphQl\\Model\\Resolver\\UpdateCustomerAddress") @doc(description: "Update customer address")
deleteCustomerAddress(id: Int!): Boolean @resolver(class: "Magento\\CustomerGraphQl\\Model\\Resolver\\DeleteCustomerAddress") @doc(description: "Delete customer address")
requestPasswordResetEmail(email: String!): Boolean @resolver(class: "\\Magento\\CustomerGraphQl\\Model\\Resolver\\RequestPasswordResetEmail") @doc(description: "Request an email with a reset password token for the registered customer identified by the specified email.")
resetPassword(email: String!, resetPasswordToken: String!, newPassword: String!): Boolean @resolver(class: "\\Magento\\CustomerGraphQl\\Model\\Resolver\\ResetPassword") @doc(description: "Reset a customer's password using the reset password token that the customer received in an email after requesting it using requestPasswordResetEmail.")
generateCustomerToken(email: String!, password: String!): CustomerToken @doc(description:"Retrieve the customer token")
changeCustomerPassword(currentPassword: String!, newPassword: String!): Customer @doc(description:"Changes the password for the logged-in customer")
createCustomer (input: CustomerInput!): CustomerOutput @deprecated(reason: "createCustomerV2") @doc(description:"Create customer account")
createCustomerV2 (input: CustomerCreateInput!): CustomerOutput @doc(description:"Create customer account")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updateCustomer (input: CustomerInput!): CustomerOutput @deprecated(reason: "createCustomerV2") @doc(description:"Update the customer's personal information")
updateCustomerV2 (input: CustomerUpdateInput!): CustomerOutput @doc(description:"Update the customer's personal information")
revokeCustomerToken: RevokeCustomerTokenOutput @doc(description:"Revoke the customer token")
createCustomerAddress(input: CustomerAddressInput!): CustomerAddress @doc(description: "Create customer address")
updateCustomerAddress(id: Int!, input: CustomerAddressInput): CustomerAddress @doc(description: "Update customer address")
deleteCustomerAddress(id: Int!): Boolean @doc(description: "Delete customer address")
requestPasswordResetEmail(email: String!): Boolean @doc(description: "Request an email with a reset password token for the registered customer identified by the specified email.")
resetPassword(email: String!, resetPasswordToken: String!, newPassword: String!): Boolean @doc(description: "Reset a customer's password using the reset password token that the customer received in an email after requesting it using requestPasswordResetEmail.")
}

input CustomerAddressInput {
Expand All @@ -45,7 +47,8 @@ input CustomerAddressInput {
prefix: String @doc(description: "An honorific, such as Dr., Mr., or Mrs.")
suffix: String @doc(description: "A value such as Sr., Jr., or III")
vat_id: String @doc(description: "The customer's Tax/VAT number (for corporate customers)")
custom_attributes: [CustomerAddressAttributeInput] @doc(description: "Deprecated: Custom attributes should not be put into container.")
custom_attributes: [CustomerAddressAttributeInput] @deprecated(reason: "Use `custom_attributes`instead.")
custom_attributes_v2: [CustomAttributeInput] @doc(description: "Stored custom attributes input.")
}

input CustomerAddressRegionInput @doc(description: "CustomerAddressRegionInput defines the customer's state or province") {
Expand All @@ -59,6 +62,16 @@ input CustomerAddressAttributeInput {
value: String! @doc(description: "Attribute value")
}

input CustomAttributeInput {
selected_attribute_options: [ID!] # this is a unique id that identifies a unique attribute option(value). It doesn't need an additional attribute uid.
entered_attributes: [EnteredAttributeInput]
}

input EnteredAttributeInput {
attribute_uid: ID! # since the value is string we need the attribute uid here.
value: String!
}

type CustomerToken {
token: String @doc(description: "The customer token")
}
Expand All @@ -76,6 +89,37 @@ input CustomerInput {
gender: Int @doc(description: "The customer's gender (Male - 1, Female - 2)")
password: String @doc(description: "The customer's password")
is_subscribed: Boolean @doc(description: "Indicates whether the customer is subscribed to the company's newsletter")
custom_attributes: [CustomAttributeInput] @doc(description: "Stored custom attributes input.")
}

input CustomerCreateInput {
prefix: String @doc(description: "An honorific, such as Dr., Mr., or Mrs.")
firstname: String! @doc(description: "The customer's first name")
middlename: String @doc(description: "The customer's middle name")
lastname: String! @doc(description: "The customer's family name")
suffix: String @doc(description: "A value such as Sr., Jr., or III")
email: String! @doc(description: "The customer's email address. Required for customer creation")
dob: String @doc(description: "Deprecated: Use `date_of_birth` instead")
date_of_birth: String @doc(description: "The customer's date of birth")
taxvat: String @doc(description: "The customer's Tax/VAT number (for corporate customers)")
gender: Int @doc(description: "The customer's gender (Male - 1, Female - 2)")
password: String @doc(description: "The customer's password")
is_subscribed: Boolean @doc(description: "Indicates whether the customer is subscribed to the company's newsletter")
custom_attributes: [CustomAttributeInput] @doc(description: "Stored custom attributes input.")
}

input CustomerUpdateInput {
date_of_birth: String @doc(description: "The customer's date of birth")
dob: String @doc(description: "Deprecated: Use `date_of_birth` instead")
firstname: String @doc(description: "The customer's first name")
gender: Int @doc(description: "The customer's gender (Male - 1, Female - 2)")
is_subscribed: Boolean @doc(description: "Indicates whether the customer is subscribed to the company's newsletter")
lastname: String @doc(description: "The customer's family name")
middlename: String @doc(description: "The customer's middle name")
prefix: String @doc(description: "An honorific, such as Dr., Mr., or Mrs.")
suffix: String @doc(description: "A value such as Sr., Jr., or III")
taxvat: String @doc(description: "The customer's Tax/VAT number (for corporate customers)")
custom_attributes: [CustomAttributeInput] @doc(description: "Stored custom attributes input.")
}

type CustomerOutput {
Expand All @@ -101,9 +145,10 @@ type Customer @doc(description: "Customer defines the customer name and address
date_of_birth: String @doc(description: "The customer's date of birth")
taxvat: String @doc(description: "The customer's Value-added tax (VAT) number (for corporate customers)")
id: Int @doc(description: "The ID assigned to the customer") @deprecated(reason: "id is not needed as part of Customer because on server side it can be identified based on customer token used for authentication. There is no need to know customer ID on the client side.")
is_subscribed: Boolean @doc(description: "Indicates whether the customer is subscribed to the company's newsletter") @resolver(class: "\\Magento\\CustomerGraphQl\\Model\\Resolver\\IsSubscribed")
addresses: [CustomerAddress] @doc(description: "An array containing the customer's shipping and billing addresses") @resolver(class: "\\Magento\\CustomerGraphQl\\Model\\Resolver\\CustomerAddresses")
is_subscribed: Boolean @doc(description: "Indicates whether the customer is subscribed to the company's newsletter")
addresses: [CustomerAddress] @doc(description: "An array containing the customer's shipping and billing addresses")
gender: Int @doc(description: "The customer's gender (Male - 1, Female - 2)")
custom_attributes: [CustomAttribute]! @doc(description: "Stored custom attributes")
}

type CustomerAddress @doc(description: "CustomerAddress contains detailed information about a customer's billing and shipping addresses"){
Expand All @@ -128,10 +173,29 @@ type CustomerAddress @doc(description: "CustomerAddress contains detailed inform
vat_id: String @doc(description: "The customer's Value-added tax (VAT) number (for corporate customers)")
default_shipping: Boolean @doc(description: "Indicates whether the address is the default shipping address")
default_billing: Boolean @doc(description: "Indicates whether the address is the default billing address")
custom_attributes: [CustomerAddressAttribute] @deprecated(reason: "Custom attributes should not be put into container")
custom_attributes: [CustomerAddressAttribute] @deprecated(reason: "Use `custom_attributesV2` instead.")
custom_attributes_v2: [CustomAttribute]! @doc(description: "Stored custom attributes")
extension_attributes: [CustomerAddressAttribute] @doc(description: "Address extension attributes")
}

# See https://github.com/magento/architecture/blob/master/design-documents/graph-ql/custom-attributes-container.md
# See https://github.com/magento/architecture/blob/master/design-documents/graph-ql/attributes-metadata.md
type CustomAttribute {
selected_attribute_options: [SelectedAttributeOption] # unique value for attribute option
entered_attribute_value: EnteredAttributeValue
attribute_metadata: AttributeMetadataInterface # used to get full metadata info and avoid another query to customAttributeMetadata
}

type SelectedAttributeOption {
attribute_option: AttributeOptionInterface
attribute_metadata: AttributeMetadataInterface
}

type EnteredAttributeValue {
attribute_metadata: AttributeMetadataInterface
value: String
}

type CustomerAddressRegion @doc(description: "CustomerAddressRegion defines the customer's state or province") {
region_code: String @doc(description: "The address region code")
region: String @doc(description: "The state or province name")
Expand Down
25 changes: 5 additions & 20 deletions design-documents/graph-ql/coverage/returns.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ input RequestReturnInput {
input RequestReturnItemInput {
order_item_id: ID! @doc(description: "ID of the order item associated with the return.")
quantity_to_return: Float! @doc(description: "The quantity of the item requested to be returned.")
selected_custom_attributes: [ID!] @doc(description: "Values of return item attributes defined by the merchant, e.g. select attributes.")
entered_custom_attributes: [EnteredCustomAttributeInput!] @doc(description: "Values of return item attributes defined by the merchant, e.g. file or text attributes.")
selected_attributes: [ID!] @doc(description: "Values of return item attributes defined by the merchant, e.g. select attributes.")
entered_attributes: [EnteredAttributeInput!] @doc(description: "Values of return item attributes defined by the merchant, e.g. file or text attributes.")
}

input EnteredCustomAttributeInput {
uid: ID!
input EnteredAttributeInput {
attribute_uid: ID!
value: String!
}

Expand Down Expand Up @@ -119,19 +119,12 @@ type Return @doc(description: "Customer return") {
type ReturnItem {
uid: ID!
order_item: OrderItemInterface! @doc(description: "Order item provides access to the product being returned, including selected/entered options information.")
custom_attributes: [CustomAttribute] @doc(description: "Return item custom attributes, which are marked by the admin to be visible on the storefront.")
custom_attributes: [CustomAttribute]! @doc(description: "Return item custom attributes, which are marked by the admin to be visible on the storefront.")
request_quantity: Float! @doc(description: "The quantity of the item requested to be returned.")
quantity: Float! @doc(description: "The quantity of the items authorized by the merchant to be returned .")
status: ReturnItemStatus! @doc(description: "The return status of the item being returned.")
}

# See https://github.com/magento/architecture/blob/master/design-documents/graph-ql/custom-attributes-container.md
type CustomAttribute {
uid: ID!
label: String!
value: String! @doc(description: "JSON encoded value of the attribute.")
}

type ReturnComment {
uid: ID! @doc(description: "Comment ID.")
author_firstname: String! @doc(description: "First name of the user who posted the comment.")
Expand Down Expand Up @@ -205,11 +198,3 @@ type StoreConfig {
# sales_magento/rma/enabled
returns_enabled: String! @doc(description: "Returns functionality status on the storefront: enabled/disabled.")
}

type Attribute {
uid: ID!
}

type AttributeOption {
uid: ID!
}