diff --git a/.changeset/modern-hands-ask.md b/.changeset/modern-hands-ask.md new file mode 100644 index 00000000..ffb74ff4 --- /dev/null +++ b/.changeset/modern-hands-ask.md @@ -0,0 +1,5 @@ +--- +"@labdigital/commercetools-mock": patch +--- + +Added support for addDelivery order update action diff --git a/src/repositories/order/actions.ts b/src/repositories/order/actions.ts index ddec02d2..b824777a 100644 --- a/src/repositories/order/actions.ts +++ b/src/repositories/order/actions.ts @@ -1,8 +1,10 @@ import type { CustomLineItemReturnItem, + Delivery, GeneralError, LineItemReturnItem, Order, + OrderAddDeliveryAction, OrderAddPaymentAction, OrderAddReturnInfoAction, OrderChangeOrderStateAction, @@ -25,6 +27,7 @@ import type { OrderTransitionStateAction, OrderUpdateAction, OrderUpdateSyncInfoAction, + Parcel, ReturnInfo, State, Store, @@ -35,7 +38,7 @@ import { getBaseResourceProperties } from "#src/helpers.ts"; import type { Writable } from "#src/types.ts"; import type { RepositoryContext, UpdateHandlerInterface } from "../abstract.ts"; import { AbstractUpdateHandler } from "../abstract.ts"; -import { createAddress } from "../helpers.ts"; +import { createAddress, createCustomFields } from "../helpers.ts"; export class OrderUpdateHandler extends AbstractUpdateHandler @@ -193,6 +196,50 @@ export class OrderUpdateHandler } } + addDelivery( + context: RepositoryContext, + resource: Writable, + { action, items, ...deliveryDraft }: OrderAddDeliveryAction, + ) { + if (!resource.shippingInfo) { + throw new Error("Resource has no shipping info"); + } + + if (!items) { + throw new Error("Delivery items are required"); + } + + if (!resource.shippingInfo.deliveries) { + resource.shippingInfo.deliveries = []; + } + + const parcels: Parcel[] = + deliveryDraft.parcels?.map((p) => ({ + ...getBaseResourceProperties(), + ...p, + custom: createCustomFields(p.custom, context.projectKey, this._storage), + })) ?? []; + + const delivery: Delivery = { + ...getBaseResourceProperties(), + ...deliveryDraft, + parcels, + items, + address: createAddress( + deliveryDraft.address, + context.projectKey, + this._storage, + ), + custom: createCustomFields( + deliveryDraft.custom, + context.projectKey, + this._storage, + ), + }; + + resource.shippingInfo.deliveries.push(delivery); + } + setDeliveryCustomField( context: RepositoryContext, resource: Writable, @@ -212,13 +259,7 @@ export class OrderUpdateHandler setLineItemCustomField( context: RepositoryContext, resource: Order, - { - lineItemId, - lineItemKey, - name, - value, - action, - }: OrderSetLineItemCustomFieldAction, + { lineItemId, lineItemKey, name, value }: OrderSetLineItemCustomFieldAction, ) { const lineItem = resource.lineItems.find( (x) => diff --git a/src/services/order.test.ts b/src/services/order.test.ts index 2e34e460..c88f5bec 100644 --- a/src/services/order.test.ts +++ b/src/services/order.test.ts @@ -1,7 +1,12 @@ import assert from "node:assert"; -import type { Order, Payment, State } from "@commercetools/platform-sdk"; +import type { + DeliveryDraft, + Order, + Payment, + State, +} from "@commercetools/platform-sdk"; import supertest from "supertest"; -import { afterEach, beforeEach, describe, expect, test } from "vitest"; +import { afterEach, beforeEach, describe, expect, it, test } from "vitest"; import { generateRandomString } from "#src/helpers.ts"; import { CommercetoolsMock, getBaseResourceProperties } from "../index.ts"; @@ -1024,6 +1029,224 @@ describe("Order Update Actions", () => { }, ]); }); + + describe("addDelivery", () => { + const order: Order = { + ...getBaseResourceProperties(), + customLineItems: [], + lineItems: [ + { + id: "d70b14c8-72cf-4cab-82ba-6339cebe1e79", + productId: "06028a97-d622-47ac-a194-a3d90baa2b3c", + productSlug: { "nl-NL": "test-product" }, + productType: { typeId: "product-type", id: "some-uuid" }, + name: { "nl-NL": "test product" }, + custom: { + type: { + typeId: "type", + id: "a493b7bb-d415-450c-b421-e128a8b26569", + }, + fields: {}, + }, + variant: { + id: 1, + sku: "1337", + attributes: [{ name: "test", value: "test" }], + prices: [], + assets: [], + images: [], + }, + price: { + id: "2f59a6c9-6a86-48d3-87f9-fabb3b12fd93", + value: { + type: "centPrecision", + centAmount: 14900, + currencyCode: "EUR", + fractionDigits: 2, + }, + }, + totalPrice: { + type: "centPrecision", + currencyCode: "EUR", + fractionDigits: 2, + centAmount: 14900, + }, + taxedPricePortions: [], + perMethodTaxRate: [], + quantity: 1, + discountedPricePerQuantity: [], + lineItemMode: "Standard", + priceMode: "Platform", + state: [], + }, + ], + orderNumber: "7777", + orderState: "Open", + origin: "Customer", + paymentInfo: { + payments: [ + { + typeId: "payment", + id: generateRandomString(10), + }, + ], + }, + refusedGifts: [], + shippingInfo: { + shippingMethodName: "Home delivery (package)", + price: { + type: "centPrecision", + currencyCode: "EUR", + centAmount: 999, + fractionDigits: 2, + }, + shippingRate: { + price: { + type: "centPrecision", + currencyCode: "EUR", + centAmount: 999, + fractionDigits: 2, + }, + tiers: [ + { + type: "CartScore", + score: 24, + price: { + type: "centPrecision", + currencyCode: "EUR", + centAmount: 1998, + fractionDigits: 2, + }, + }, + { + type: "CartScore", + score: 47, + price: { + type: "centPrecision", + currencyCode: "EUR", + centAmount: 2997, + fractionDigits: 2, + }, + }, + { + type: "CartScore", + score: 70, + price: { + type: "centPrecision", + currencyCode: "EUR", + centAmount: 3996, + fractionDigits: 2, + }, + }, + { + type: "CartScore", + score: 93, + price: { + type: "centPrecision", + currencyCode: "EUR", + centAmount: 4995, + fractionDigits: 2, + }, + }, + ], + }, + deliveries: [ + { + id: "6a458cad-dd46-4f5f-8b73-debOede6a17d", + key: "CT-Z243002", + createdAt: "2024-07-29T13:37:48.047Z", + items: [ + { + id: "d70b14c8-72cf-4cab-82ba-6339cebe1e79", + quantity: 1, + }, + ], + parcels: [ + { + id: "7a458cad-dd46-4f5f-8b73-debOede6a17d", + createdAt: "2024-07-29T13:37:48.047Z", + items: [ + { + id: "d70b14c8-72cf-4cab-82ba-6339cebe1e79", + quantity: 1, + }, + ], + custom: { + type: { + typeId: "type", + id: "c493b7bb-d415-450c-b421-e128a8b26569", + }, + fields: { + status: "created", + }, + }, + }, + ], + }, + ], + shippingMethodState: "MatchesCart", + }, + shipping: [], + shippingMode: "Single", + syncInfo: [], + totalPrice: { + type: "centPrecision", + fractionDigits: 2, + centAmount: 2000, + currencyCode: "EUR", + }, + }; + if (!order.shippingInfo) { + throw new Error("Order shippingInfo is required"); + } + const { deliveries: _, ...shippingInfoWithoutDeliveries } = + order.shippingInfo; + const orderWithoutDeliveries = { + ...order, + ...getBaseResourceProperties(), + orderNumber: "7778", + shippingInfo: shippingInfoWithoutDeliveries, + }; + + ctMock.project("dummy").add("order", order); + ctMock.project("dummy").add("order", orderWithoutDeliveries); + + const deliveryDraft: DeliveryDraft = { + key: `${order.orderNumber}-2`, + items: [ + { + id: order.lineItems[0].id, + quantity: order.lineItems[0].quantity, + }, + ], + }; + + it.each([ + [order, 1], + [orderWithoutDeliveries, 0], + ])("should add to deliveries", async (order, index) => { + const response = await supertest(ctMock.app).get( + `/dummy/orders/order-number=${order.orderNumber}`, + ); + const _updateResponse = await supertest(ctMock.app) + .post(`/dummy/orders/${response.body.id}`) + .send({ + version: 0, + actions: [ + { + action: "addDelivery", + ...deliveryDraft, + }, + ], + }); + + expect(_updateResponse.status).toBe(200); + expect(_updateResponse.body.version).toBe(1); + expect(_updateResponse.body.shippingInfo.deliveries[index].key).toBe( + deliveryDraft.key, + ); + }); + }); }); describe("Order Import", () => {