From 87721f5438bc6ef5f2846fbf3fda173e32fb2cf8 Mon Sep 17 00:00:00 2001 From: Jamal Soueidan Date: Tue, 2 Jul 2024 00:17:00 +0200 Subject: [PATCH] add product-type to products --- openapi/paths/customer/product/add/body.yaml | 3 ++ .../paths/customer/product/update/body.yaml | 2 ++ .../paths/openai/product-title/response.yaml | 7 +++++ .../customer/controllers/product/add.spec.ts | 3 +- .../customer/controllers/product/add.ts | 1 + .../product/update/update-product.spec.ts | 5 +-- .../product/update/update-product.ts | 3 +- .../customer/services/product/add.spec.ts | 1 + .../customer/services/product/add.ts | 2 ++ .../openai/services/product-categorize.ts | 2 +- .../openai/services/product-title.ts | 31 ++++++++++++++++++- src/functions/schedule/schedule.types.ts | 1 + .../schedule/schemas/product.schema.ts | 1 + src/library/jest/helpers/product.ts | 1 + 14 files changed, 54 insertions(+), 9 deletions(-) diff --git a/openapi/paths/customer/product/add/body.yaml b/openapi/paths/customer/product/add/body.yaml index 3a105984..7335fc8b 100644 --- a/openapi/paths/customer/product/add/body.yaml +++ b/openapi/paths/customer/product/add/body.yaml @@ -2,6 +2,8 @@ type: object properties: title: type: string + productType: + type: string description: type: string descriptionHtml: @@ -31,6 +33,7 @@ properties: required: - title + - productType - description - descriptionHtml - scheduleId diff --git a/openapi/paths/customer/product/update/body.yaml b/openapi/paths/customer/product/update/body.yaml index 7ef9ac47..aaccd077 100644 --- a/openapi/paths/customer/product/update/body.yaml +++ b/openapi/paths/customer/product/update/body.yaml @@ -4,6 +4,8 @@ properties: type: string hideFromCombine: type: string + productType: + type: string price: type: object properties: diff --git a/openapi/paths/openai/product-title/response.yaml b/openapi/paths/openai/product-title/response.yaml index 9bc00e78..5b4521c9 100644 --- a/openapi/paths/openai/product-title/response.yaml +++ b/openapi/paths/openai/product-title/response.yaml @@ -6,6 +6,13 @@ properties: payload: type: object properties: + collection: + type: object + properties: + id: + type: string + title: + type: string title: type: string description: diff --git a/src/functions/customer/controllers/product/add.spec.ts b/src/functions/customer/controllers/product/add.spec.ts index 57167d57..d5fe3534 100644 --- a/src/functions/customer/controllers/product/add.spec.ts +++ b/src/functions/customer/controllers/product/add.spec.ts @@ -1,9 +1,9 @@ import { HttpRequest, InvocationContext } from "@azure/functions"; import { - HttpSuccessResponse, createContext, createHttpRequest, + HttpSuccessResponse, } from "~/library/jest/azure"; import { createUser } from "~/library/jest/helpers"; @@ -142,6 +142,7 @@ describe("CustomerProductControllerAdd", () => { hideFromProfile: true, title, description: "ok", + productType: "test", descriptionHtml: "test", scheduleId: newSchedule._id, locations, diff --git a/src/functions/customer/controllers/product/add.ts b/src/functions/customer/controllers/product/add.ts index 6ede6055..687e16ba 100644 --- a/src/functions/customer/controllers/product/add.ts +++ b/src/functions/customer/controllers/product/add.ts @@ -21,6 +21,7 @@ const CustomerProductControllerAddQuerySchema = z.object({ const CustomerProductControllerAddBodySchema = ScheduleProductZodSchema.pick({ locations: true, price: true, + productType: true, compareAtPrice: true, hideFromCombine: true, hideFromProfile: true, diff --git a/src/functions/customer/orchestrations/product/update/update-product.spec.ts b/src/functions/customer/orchestrations/product/update/update-product.spec.ts index bf710a6e..8bb33a08 100644 --- a/src/functions/customer/orchestrations/product/update/update-product.spec.ts +++ b/src/functions/customer/orchestrations/product/update/update-product.spec.ts @@ -244,10 +244,6 @@ describe("CustomerProductUpdateOrchestration", () => { `user-${user.username}`, `userid-${user.customerId}`, `treatments`, - `productid-${GidFormat.parse( - mockProductUpdate.productUpdate?.product?.id - )}`, - `product-${product.productHandle}`, `scheduleid-${newSchedule._id}`, `location_type-${location.locationType}`, "active", @@ -265,6 +261,7 @@ describe("CustomerProductUpdateOrchestration", () => { variables: { id: mockProductUpdate.productUpdate?.product?.id, title: product.title, + productType: product.productType, descriptionHtml: product.descriptionHtml, metafields: [ { diff --git a/src/functions/customer/orchestrations/product/update/update-product.ts b/src/functions/customer/orchestrations/product/update/update-product.ts index 1d4fb7ba..8ab0d2b3 100644 --- a/src/functions/customer/orchestrations/product/update/update-product.ts +++ b/src/functions/customer/orchestrations/product/update/update-product.ts @@ -124,6 +124,7 @@ export const updateProduct = async ({ const variables = { title: product.title, descriptionHtml: product.descriptionHtml || "", + productType: product.productType || "Andet", id: `gid://shopify/Product/${product.productId}`, metafields: [ { @@ -180,8 +181,6 @@ export const updateProduct = async ({ `user-${user.username}`, `userid-${user.customerId}`, "treatments", - `productid-${product.productId}`, - `product-${product.productHandle}`, `scheduleid-${schedule._id}`, ] .concat(tags) diff --git a/src/functions/customer/services/product/add.spec.ts b/src/functions/customer/services/product/add.spec.ts index e7fd16a6..47498020 100644 --- a/src/functions/customer/services/product/add.spec.ts +++ b/src/functions/customer/services/product/add.spec.ts @@ -156,6 +156,7 @@ describe("CustomerProductServiceAdd", () => { }, { ...productBody, + productType: "Andet", scheduleId: newSchedule._id, title, } diff --git a/src/functions/customer/services/product/add.ts b/src/functions/customer/services/product/add.ts index 4e2ba8bf..68317aae 100644 --- a/src/functions/customer/services/product/add.ts +++ b/src/functions/customer/services/product/add.ts @@ -15,6 +15,7 @@ export type CustomerProductServiceAdd = { export type CustomerProductServiceAddBody = Pick< ScheduleProduct, + | "productType" | "description" | "descriptionHtml" | "locations" @@ -62,6 +63,7 @@ export const CustomerProductServiceAdd = async ( productHandle: shopifyProduct.handle, productId: shopifyProductId, variantId: GidFormat.parse(variant.id), + productType: body.productType, price: { amount: body.price.amount, currencyCode: "DKK", diff --git a/src/functions/openai/services/product-categorize.ts b/src/functions/openai/services/product-categorize.ts index b17af97e..95060d8d 100644 --- a/src/functions/openai/services/product-categorize.ts +++ b/src/functions/openai/services/product-categorize.ts @@ -57,7 +57,7 @@ Respond with this JSON structure: content, }, ], - max_tokens: 300, + max_tokens: 20000, response_format: { type: "json_object", }, diff --git a/src/functions/openai/services/product-title.ts b/src/functions/openai/services/product-title.ts index a733f3e8..1043e21f 100644 --- a/src/functions/openai/services/product-title.ts +++ b/src/functions/openai/services/product-title.ts @@ -1,10 +1,16 @@ import OpenAI from "openai"; +import { shopifyAdmin } from "~/library/shopify"; +import { COLLECTIONS } from "./product-categorize"; const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY, }); type OpenAIServiceProductTitleReturn = { + collection: { + id: string; + title: string; + }; title: string; description: string; }; @@ -16,12 +22,35 @@ export const OpenAIServiceProductTitle = async ({ title: string; description?: string; }) => { + const { data } = await shopifyAdmin().request(COLLECTIONS); + + const onlyRootcollections = data?.collections.nodes.filter( + (col: any) => col.ruleSet.rules.length > 1 + ); + + const collectionsContext = JSON.stringify(onlyRootcollections, null, 2); + const response = await openai.chat.completions.create({ model: "gpt-4o-2024-05-13", messages: [ { role: "system", - content: `You are an expert in correcting treatment titles and descriptions. Please correct any grammatical errors in title and description. If the description is missing, add a short sentence that encourages customers to buy this treatment, the text should be from the indiviual beauty professional as seller of the treatment. Please responds with title, description json format and keep the language in danish.`, + content: ` +You are an expert in correcting treatment titles and descriptions. +Please correct any grammatical errors in title and description. If the description is missing, add a short sentence that encourages customers to buy this treatment, the text should be from the indiviual beauty professional as seller of the treatment. +Also figure out the collection the treatment belongs to. +### Collections +${collectionsContext} + +Respond with this JSON structure, and choose danish language for title and description. +{ + "collection": { + id: "gid://shopify/Collection/1111", + title: "example", + }, + title: "example", + description: "example", +}`, }, { role: "user", diff --git a/src/functions/schedule/schedule.types.ts b/src/functions/schedule/schedule.types.ts index bf476e70..d369e052 100644 --- a/src/functions/schedule/schedule.types.ts +++ b/src/functions/schedule/schedule.types.ts @@ -84,6 +84,7 @@ export const ScheduleProductZodSchema = z.object({ productHandle: z.string(), collectionIds: z.array(GidFormat), productId: GidFormat, + productType: z.string(), variantId: GidFormat, user: z .object({ diff --git a/src/functions/schedule/schemas/product.schema.ts b/src/functions/schedule/schemas/product.schema.ts index 9dd16ade..20b94939 100644 --- a/src/functions/schedule/schemas/product.schema.ts +++ b/src/functions/schedule/schemas/product.schema.ts @@ -59,6 +59,7 @@ export const ProductSchema = new mongoose.Schema( type: String, index: true, }, + productType: String, productId: { type: Number, index: true, diff --git a/src/library/jest/helpers/product.ts b/src/library/jest/helpers/product.ts index 273370da..df8827e4 100644 --- a/src/library/jest/helpers/product.ts +++ b/src/library/jest/helpers/product.ts @@ -9,6 +9,7 @@ export const getProductObject = ( ): ScheduleProduct => ({ title: "test", collectionIds: [], + productType: "test", productHandle: faker.internet.displayName(), productId: faker.number.int({ min: 1, max: 10000000 }), scheduleIdMetafieldId: String(faker.number.int({ min: 1, max: 10000000 })),