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

Saleor swatch #434

Merged
merged 3 commits into from
Nov 17, 2023
Merged
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
87 changes: 82 additions & 5 deletions pkg/integration-saleor-entities/src/products/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,65 @@ export class SaleorProductSyncService {
}
}

/**
* Unfortunately, we can't set swatch attribute values
* directly in the product create / update mutation. We need to
* first check, if the attribute value does already exist in saleor,
* create it if not and return the slug of the attribute value, so
* that it can be used as value in the product create / update mutation
*/
private async handleSwatchAttributeInSaleor(
saleorAttributeId: string,
attributeValueName: string,
attributeValueHex: string,
): Promise<string> {
const searchResult = await this.saleorClient.attributeValueSearch({
attributeId: saleorAttributeId,
searchvalue: attributeValueName,
});
if (!searchResult.attribute?.choices?.edges?.[0].node.id) {
this.logger.info(
`Creating swatch attribute value ${attributeValueName} for saleor attribute ${saleorAttributeId}`,
);
const resp = await this.saleorClient.attributeHexValueCreate({
attributeId: saleorAttributeId,
attributeValueHex,
attributeValueName,
});

if (
resp.attributeValueCreate?.errors &&
resp.attributeValueCreate?.errors.length > 0
) {
this.logger.error(
`Error creating swatch attribute value ${attributeValueName} for saleor attribute ${saleorAttributeId}: ${JSON.stringify(
resp.attributeValueCreate.errors,
)}`,
);
return "";
}
if (!resp.attributeValueCreate?.attributeValue?.slug) {
this.logger.error(
`Error creating swatch attribute value ${attributeValueName} for saleor attribute ${saleorAttributeId}: No slug returned`,
);
return "";
}

this.logger.info(
`Returning swatch slug ${resp.attributeValueCreate?.attributeValue?.slug} for swatch attribute value ${attributeValueName} for saleor attribute ${saleorAttributeId}`,
);
return resp.attributeValueCreate?.attributeValue?.slug;
}

if (!searchResult.attribute?.choices?.edges?.[0].node.slug) {
this.logger.error(
`Error getting swatch attribute value ${attributeValueName} for saleor attribute ${saleorAttributeId}: No slug returned`,
);
return "";
}
return searchResult.attribute?.choices?.edges?.[0].node.slug;
}

/**
* Find and create all products, that are not yet created in Saleor.
* Update products, that got changed since the last run
Expand Down Expand Up @@ -903,6 +962,8 @@ export class SaleorProductSyncService {
* Prepare the attributes to fit the saleor schema
*/
for (const attr of attributesWithSaleorAttributes) {
const saleorAttributeId =
attr.attribute.saleorAttributes[0].id;
if (attr.attribute.type === "BOOLEAN") {
const value = parseBoolean(attr.value);
if (value === undefined) {
Expand All @@ -912,12 +973,11 @@ export class SaleorProductSyncService {
continue;
} else {
attributes.push({
id: attr.attribute.saleorAttributes[0].id,
id: saleorAttributeId,
boolean: value,
});
}
}
// TODO: handle the case when we have a hexcode value
if (attr.attribute.type === "PRODUCT_REFERENCE") {
/// We store our internal product Id in value of product reference attributes.
/// We need to aks our DB for the saleor product id
Expand All @@ -942,7 +1002,7 @@ export class SaleorProductSyncService {
continue;
}
attributes.push({
id: attr.attribute.saleorAttributes[0].id,
id: saleorAttributeId,
references: [saleorProductId.saleorProducts[0].id],
});
} else if (attr.attribute.type === "VARIANT_REFERENCE") {
Expand All @@ -969,14 +1029,31 @@ export class SaleorProductSyncService {
continue;
}
attributes.push({
id: attr.attribute.saleorAttributes[0].id,
id: saleorAttributeId,
references: [
saleorVariantId.saleorProductVariant[0].id,
],
});
// Handle the special case SWATCH where the hex code and the name is given
} else if (
attr.attribute.type === "SWATCH" &&
attr.hexColor &&
attr.value
) {
const value = await this.handleSwatchAttributeInSaleor(
saleorAttributeId,
attr.value,
attr.hexColor,
);
attributes.push({
id: saleorAttributeId,
swatch: {
value,
},
});
} else {
attributes.push({
id: attr.attribute.saleorAttributes[0].id,
id: saleorAttributeId,
values: [attr.value],
});
}
Expand Down
122 changes: 121 additions & 1 deletion pkg/saleor/src/api/generated/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21460,6 +21460,7 @@ export enum ProductVariantBulkErrorCode {
NotProductsVariant = "NOT_PRODUCTS_VARIANT",
ProductNotAssignedToChannel = "PRODUCT_NOT_ASSIGNED_TO_CHANNEL",
Required = "REQUIRED",
StockAlreadyExists = "STOCK_ALREADY_EXISTS",
Unique = "UNIQUE",
}

Expand Down Expand Up @@ -32251,6 +32252,58 @@ export type AttributeSyncQuery = {
} | null;
};

export type AttributeValueSearchQueryVariables = Exact<{
attributeId: Scalars["ID"];
searchvalue?: InputMaybe<Scalars["String"]>;
}>;

export type AttributeValueSearchQuery = {
__typename?: "Query";
attribute?: {
__typename?: "Attribute";
id: string;
name?: string | null;
choices?: {
__typename?: "AttributeValueCountableConnection";
edges: Array<{
__typename?: "AttributeValueCountableEdge";
node: {
__typename?: "AttributeValue";
id: string;
name?: string | null;
slug?: string | null;
value?: string | null;
};
}>;
} | null;
} | null;
};

export type AttributeHexValueCreateMutationVariables = Exact<{
attributeId: Scalars["ID"];
attributeValueName: Scalars["String"];
attributeValueHex: Scalars["String"];
}>;

export type AttributeHexValueCreateMutation = {
__typename?: "Mutation";
attributeValueCreate?: {
__typename?: "AttributeValueCreate";
errors: Array<{
__typename?: "AttributeError";
field?: string | null;
code: AttributeErrorCode;
message?: string | null;
}>;
attributeValue?: {
__typename?: "AttributeValue";
id: string;
slug?: string | null;
value?: string | null;
} | null;
} | null;
};

export type CategoryValuesFragment = {
__typename?: "Category";
id: string;
Expand Down Expand Up @@ -33146,7 +33199,7 @@ export const AttributeCreateDocument = gql`
export const BulkOrderCreateDocument = gql`
mutation bulkOrderCreate($orders: [OrderBulkCreateInput!]!) {
orderBulkCreate(
errorPolicy: REJECT_FAILED_ROWS
errorPolicy: REJECT_EVERYTHING
orders: $orders
stockUpdatePolicy: SKIP
) {
Expand Down Expand Up @@ -33547,6 +33600,47 @@ export const AttributeSyncDocument = gql`
}
}
`;
export const AttributeValueSearchDocument = gql`
query attributeValueSearch($attributeId: ID!, $searchvalue: String) {
attribute(id: $attributeId) {
choices(first: 2, filter: { search: $searchvalue }) {
edges {
node {
id
name
slug
value
}
}
}
id
name
}
}
`;
export const AttributeHexValueCreateDocument = gql`
mutation attributeHexValueCreate(
$attributeId: ID!
$attributeValueName: String!
$attributeValueHex: String!
) {
attributeValueCreate(
attribute: $attributeId
input: { name: $attributeValueName, value: $attributeValueHex }
) {
errors {
field
code
message
}
attributeValue {
id
slug
value
}
}
}
`;
export const SaleorCronCategoriesDocument = gql`
query saleorCronCategories($first: Int, $last: Int, $after: String) {
categories(first: $first, last: $last, after: $after) {
Expand Down Expand Up @@ -34436,6 +34530,32 @@ export function getSdk<C, E>(requester: Requester<C, E>) {
options,
) as Promise<AttributeSyncQuery>;
},
attributeValueSearch(
variables: AttributeValueSearchQueryVariables,
options?: C,
): Promise<AttributeValueSearchQuery> {
return requester<
AttributeValueSearchQuery,
AttributeValueSearchQueryVariables
>(
AttributeValueSearchDocument,
variables,
options,
) as Promise<AttributeValueSearchQuery>;
},
attributeHexValueCreate(
variables: AttributeHexValueCreateMutationVariables,
options?: C,
): Promise<AttributeHexValueCreateMutation> {
return requester<
AttributeHexValueCreateMutation,
AttributeHexValueCreateMutationVariables
>(
AttributeHexValueCreateDocument,
variables,
options,
) as Promise<AttributeHexValueCreateMutation>;
},
saleorCronCategories(
variables?: SaleorCronCategoriesQueryVariables,
options?: C,
Expand Down
35 changes: 35 additions & 0 deletions pkg/saleor/src/api/queries/attributes.gql
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,38 @@ query attributeSync($first: Int!, $after: String) {
}
}
}

query attributeValueSearch($attributeId: ID!, $searchvalue: String) {
attribute(id: $attributeId) {
choices(first: 2, filter: {search: $searchvalue}) {
edges {
node {
id
name
slug
value
}
}
}
id
name
}
}

mutation attributeHexValueCreate($attributeId: ID!, $attributeValueName: String!, $attributeValueHex: String!) {
attributeValueCreate(
attribute: $attributeId
input: {name: $attributeValueName, value: $attributeValueHex}
) {
errors {
field
code
message
}
attributeValue {
id
slug
value
}
}
}
Loading