diff --git a/src/functions/customer/orchestrations/customer/update.ts b/src/functions/customer/orchestrations/customer/update.ts index 6122cf8b..3e08b026 100644 --- a/src/functions/customer/orchestrations/customer/update.ts +++ b/src/functions/customer/orchestrations/customer/update.ts @@ -3,6 +3,7 @@ import * as df from "durable-functions"; import { OrchestrationContext } from "durable-functions"; import { User } from "~/functions/user"; import { activityType } from "~/library/orchestration"; +import { updateArticle } from "./update/update-article"; import { updateUserMetaobject } from "./update/update-user-metaobject"; const updateUserMetaobjectName = "updateUserMetaobject"; @@ -10,6 +11,11 @@ df.app.activity(updateUserMetaobjectName, { handler: updateUserMetaobject, }); +const updateArticleName = "updateArticle"; +df.app.activity(updateArticleName, { + handler: updateArticle, +}); + const orchestrator: df.OrchestrationHandler = function* ( context: OrchestrationContext ) { @@ -23,8 +29,17 @@ const orchestrator: df.OrchestrationHandler = function* ( }) ); + const article: Awaited> = + yield context.df.callActivity( + updateArticleName, + activityType({ + user, + }) + ); + return { userField, + article, }; }; diff --git a/src/functions/customer/orchestrations/customer/update/update-article.ts b/src/functions/customer/orchestrations/customer/update/update-article.ts new file mode 100644 index 00000000..72c907e0 --- /dev/null +++ b/src/functions/customer/orchestrations/customer/update/update-article.ts @@ -0,0 +1,103 @@ +import { CustomerLocationServiceList } from "~/functions/customer/services/location/list"; +import { ScheduleModel } from "~/functions/schedule"; +import { User } from "~/functions/user"; +import { shopifyRest } from "~/library/shopify/rest"; + +interface RootObject { + article: Article; +} +interface Article { + id: number; + title: string; + created_at: string; + body_html: string; + blog_id: number; + author: string; + user_id?: any; + published_at: string; + updated_at: string; + summary_html: string; + template_suffix?: any; + handle: string; + tags: string; + admin_graphql_api_id: string; + image: Image; +} +interface Image { + created_at: string; + alt: string; + width: number; + height: number; + src: string; +} + +export const updateArticle = async ({ + user, +}: { + user: User; +}): Promise => { + const schedules = await ScheduleModel.find({ + customerId: user.customerId, + }); + + const parentIds = schedules.flatMap((schedule) => + schedule.products.map((product) => product.parentId) + ); + + const days = schedules.flatMap((schedule) => + schedule.slots.map((slot) => slot.day.toLowerCase()) + ); + + const tags = [user.username]; + + if (user.professions) { + tags.push(user.professions?.join(",")); + } + + if (parentIds.length > 0) { + tags.push(`parentid-${parentIds.join(", parentid-")}`); + } + + if (days.length > 0) { + tags.push(`day-${days.join(", day-")}`); + } + + const locations = await CustomerLocationServiceList({ + customerId: user.customerId, + }); + + if (locations.length > 0) { + tags.push( + `city-${locations.map((l) => l.city.toLowerCase()).join(", city-")}` + ); + } + + const response = await shopifyRest.put( + `blogs/105364226375/articles/${user.articleId}`, + { + data: { + article: { + id: user.articleId, + body_html: user.aboutMeHtml, + tags: tags.join(", "), + summary_html: user.shortDescription, + ...(user.images?.profile + ? { + image: { + src: user.images?.profile.url, + alt: user.username, + }, + } + : {}), + published_at: user.active ? user.createdAt : null, + }, + }, + } + ); + + if (!response.ok) { + throw new Error(`Failed to create article for user ${user.username}`); + } + + return await response.json(); +}; diff --git a/src/functions/customer/services/location/list.ts b/src/functions/customer/services/location/list.ts index 610c4a99..c6b63d86 100644 --- a/src/functions/customer/services/location/list.ts +++ b/src/functions/customer/services/location/list.ts @@ -1,4 +1,5 @@ import { LocationModel } from "~/functions/location"; +import { NotFoundError } from "~/library/handler"; export type CustomerLocationServiceListProps = { customerId: number; @@ -7,5 +8,16 @@ export type CustomerLocationServiceListProps = { export const CustomerLocationServiceList = ( props: CustomerLocationServiceListProps ) => { - return LocationModel.find({ customerId: props.customerId, deletedAt: null }); + return LocationModel.find({ + customerId: props.customerId, + deletedAt: null, + }).orFail( + new NotFoundError([ + { + path: ["locationId", "customerId"], + message: "LOCATION_NOT_FOUND_IN_USER", + code: "custom", + }, + ]) + ); }; diff --git a/src/functions/customer/services/product/list-ids.ts b/src/functions/customer/services/product/list-ids.ts index 92f12c51..293d3068 100644 --- a/src/functions/customer/services/product/list-ids.ts +++ b/src/functions/customer/services/product/list-ids.ts @@ -15,8 +15,3 @@ export const CustomerProductsServiceListIds = async ( schedule.products.map((product) => product.productId) ); }; - -type CustomerProductsServiceListProps = { - customerId: Schedule["customerId"]; - scheduleId?: Schedule["_id"]; -};