From 4c7f43977f6807d93dbfeaa339a7911db5433c6a Mon Sep 17 00:00:00 2001 From: Bram Kaashoek Date: Wed, 3 Jun 2026 14:17:28 +0200 Subject: [PATCH 1/2] feat: as-associate business units --- .changeset/as-associate-business-units.md | 5 ++ src/repositories/as-associate.ts | 2 + src/repositories/index.ts | 2 + .../as-associate-business-unit.test.ts | 70 +++++++++++++++++++ src/services/as-associate-business-unit.ts | 19 +++++ src/services/as-associate.ts | 55 +++++++++++---- 6 files changed, 139 insertions(+), 14 deletions(-) create mode 100644 .changeset/as-associate-business-units.md create mode 100644 src/services/as-associate-business-unit.test.ts create mode 100644 src/services/as-associate-business-unit.ts diff --git a/.changeset/as-associate-business-units.md b/.changeset/as-associate-business-units.md new file mode 100644 index 00000000..b1839bec --- /dev/null +++ b/.changeset/as-associate-business-units.md @@ -0,0 +1,5 @@ +--- +"@labdigital/commercetools-mock": minor +--- + +Add support for the `asAssociate` business-units endpoint. diff --git a/src/repositories/as-associate.ts b/src/repositories/as-associate.ts index 484f4962..ea86ceba 100644 --- a/src/repositories/as-associate.ts +++ b/src/repositories/as-associate.ts @@ -1,3 +1,4 @@ +import { BusinessUnitRepository } from "./business-unit.ts"; import { CartRepository } from "./cart/index.ts"; import { OrderRepository } from "./order/index.ts"; import { QuoteRequestRepository } from "./quote-request/index.ts"; @@ -7,3 +8,4 @@ export class AsAssociateOrderRepository extends OrderRepository {} export class AsAssociateCartRepository extends CartRepository {} export class AsAssociateQuoteRequestRepository extends QuoteRequestRepository {} export class AsAssociateShoppingListRepository extends ShoppingListRepository {} +export class AsAssociateBusinessUnitRepository extends BusinessUnitRepository {} diff --git a/src/repositories/index.ts b/src/repositories/index.ts index b7a96da8..4bf9d3b9 100644 --- a/src/repositories/index.ts +++ b/src/repositories/index.ts @@ -1,6 +1,7 @@ import type { Config } from "#src/config.ts"; import { ProductTailoringRepository } from "#src/repositories/product-tailoring.ts"; import { + AsAssociateBusinessUnitRepository, AsAssociateCartRepository, AsAssociateOrderRepository, AsAssociateQuoteRequestRepository, @@ -51,6 +52,7 @@ export type RepositoryMap = ReturnType; export const createRepositories = (config: Config) => ({ "as-associate": { + "business-unit": new AsAssociateBusinessUnitRepository(config), cart: new AsAssociateCartRepository(config), order: new AsAssociateOrderRepository(config), "quote-request": new AsAssociateQuoteRequestRepository(config), diff --git a/src/services/as-associate-business-unit.test.ts b/src/services/as-associate-business-unit.test.ts new file mode 100644 index 00000000..8c167525 --- /dev/null +++ b/src/services/as-associate-business-unit.test.ts @@ -0,0 +1,70 @@ +import { afterEach, describe, expect, test } from "vitest"; +import { businessUnitDraftFactory } from "#src/testing/business-unit.ts"; +import { CommercetoolsMock } from "../index.ts"; + +const ctMock = new CommercetoolsMock(); +const projectKey = "dummy"; +const associateId = "5fac8fca-2484-4b14-a1d1-cfdce2f8d3c4"; + +describe("AsAssociateBusinessUnit", () => { + const businessUnitFactory = businessUnitDraftFactory(ctMock); + + afterEach(async () => { + await ctMock.clear(); + }); + + test("Get business units as associate", async () => { + await businessUnitFactory.create({ + key: "as-associate-bu", + unitType: "Company", + name: "As Associate BU", + contactEmail: "contact@example.com", + }); + + const response = await ctMock.app.inject({ + method: "GET", + url: `/${projectKey}/as-associate/${associateId}/business-units`, + }); + + expect(response.statusCode).toBe(200); + expect(response.json().results).toBeDefined(); + }); + + test("Get business unit by key as associate", async () => { + const businessUnit = await businessUnitFactory.create({ + key: "as-associate-bu", + unitType: "Company", + name: "As Associate BU", + contactEmail: "contact@example.com", + }); + + const response = await ctMock.app.inject({ + method: "GET", + url: `/${projectKey}/as-associate/${associateId}/business-units/key=${businessUnit.key}`, + }); + + expect(response.statusCode).toBe(200); + expect(response.json()).toEqual(businessUnit); + }); + + test("Update business unit by key as associate", async () => { + const businessUnit = await businessUnitFactory.create({ + key: "as-associate-bu", + unitType: "Company", + name: "As Associate BU", + contactEmail: "contact@example.com", + }); + + const response = await ctMock.app.inject({ + method: "POST", + url: `/${projectKey}/as-associate/${associateId}/business-units/key=${businessUnit.key}`, + payload: { + version: businessUnit.version, + actions: [{ action: "changeName", name: "Updated Name" }], + }, + }); + + expect(response.statusCode).toBe(200); + expect(response.json().name).toBe("Updated Name"); + }); +}); diff --git a/src/services/as-associate-business-unit.ts b/src/services/as-associate-business-unit.ts new file mode 100644 index 00000000..739e3a02 --- /dev/null +++ b/src/services/as-associate-business-unit.ts @@ -0,0 +1,19 @@ +import type { FastifyInstance } from "fastify"; +import type { AsAssociateBusinessUnitRepository } from "#src/repositories/as-associate.ts"; +import AbstractService from "./abstract.ts"; + +export class AsAssociateBusinessUnitService extends AbstractService { + public repository: AsAssociateBusinessUnitRepository; + + constructor( + parent: FastifyInstance, + repository: AsAssociateBusinessUnitRepository, + ) { + super(parent); + this.repository = repository; + } + + getBasePath() { + return "business-units"; + } +} diff --git a/src/services/as-associate.ts b/src/services/as-associate.ts index 06ec1b99..59dd11ae 100644 --- a/src/services/as-associate.ts +++ b/src/services/as-associate.ts @@ -1,16 +1,19 @@ import type { FastifyInstance } from "fastify"; import type { + AsAssociateBusinessUnitRepository, AsAssociateCartRepository, AsAssociateOrderRepository, AsAssociateQuoteRequestRepository, AsAssociateShoppingListRepository, } from "#src/repositories/as-associate.ts"; +import { AsAssociateBusinessUnitService } from "./as-associate-business-unit.ts"; import { AsAssociateCartService } from "./as-associate-cart.ts"; import { AsAssociateOrderService } from "./as-associate-order.ts"; import { AsAssociateQuoteRequestService } from "./as-associate-quote-request.ts"; import { AsAssociateShoppingListService } from "./as-associate-shopping-list.ts"; type Repositories = { + "business-unit": AsAssociateBusinessUnitRepository; cart: AsAssociateCartRepository; order: AsAssociateOrderRepository; "quote-request": AsAssociateQuoteRequestRepository; @@ -19,6 +22,7 @@ type Repositories = { export class AsAssociateService { subServices!: { + "business-unit": AsAssociateBusinessUnitService; cart: AsAssociateCartService; order: AsAssociateOrderService; "quote-request": AsAssociateQuoteRequestService; @@ -28,23 +32,46 @@ export class AsAssociateService { constructor(parent: FastifyInstance, repositories: Repositories) { parent.register( (instance, opts, done) => { - this.subServices = { - order: new AsAssociateOrderService(instance, repositories.order), - cart: new AsAssociateCartService(instance, repositories.cart), - "quote-request": new AsAssociateQuoteRequestService( - instance, - repositories["quote-request"], - ), - "shopping-list": new AsAssociateShoppingListService( - instance, - repositories["shopping-list"], - ), - }; + const businessUnitService = new AsAssociateBusinessUnitService( + instance, + repositories["business-unit"], + ); + + instance.register( + (scoped, _opts, scopedDone) => { + const order = new AsAssociateOrderService( + scoped, + repositories.order, + ); + const cart = new AsAssociateCartService( + scoped, + repositories.cart, + ); + const quoteRequest = new AsAssociateQuoteRequestService( + scoped, + repositories["quote-request"], + ); + const shoppingList = new AsAssociateShoppingListService( + scoped, + repositories["shopping-list"], + ); + + this.subServices = { + "business-unit": businessUnitService, + order, + cart, + "quote-request": quoteRequest, + "shopping-list": shoppingList, + }; + scopedDone(); + }, + { prefix: "/in-business-unit/key=:businessUnitId" }, + ); + done(); }, { - prefix: - "/as-associate/:associateId/in-business-unit/key=:businessUnitId", + prefix: "/as-associate/:associateId", }, ); } From 083d0f2c129a48c34611b0cca2620fe33da016c0 Mon Sep 17 00:00:00 2001 From: Bram Kaashoek Date: Wed, 3 Jun 2026 14:18:24 +0200 Subject: [PATCH 2/2] fix: format --- src/services/as-associate.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/services/as-associate.ts b/src/services/as-associate.ts index 59dd11ae..5394f0c0 100644 --- a/src/services/as-associate.ts +++ b/src/services/as-associate.ts @@ -43,10 +43,7 @@ export class AsAssociateService { scoped, repositories.order, ); - const cart = new AsAssociateCartService( - scoped, - repositories.cart, - ); + const cart = new AsAssociateCartService(scoped, repositories.cart); const quoteRequest = new AsAssociateQuoteRequestService( scoped, repositories["quote-request"],