feat(order): bundled actions (#7133)

This commit is contained in:
Carlos R. L. Rodrigues
2024-04-25 07:06:23 -03:00
committed by GitHub
parent e4898fb00d
commit d02905cefa
23 changed files with 1114 additions and 232 deletions
@@ -241,9 +241,9 @@ medusaIntegrationTestRunner({
draft_order: expect.objectContaining({ draft_order: expect.objectContaining({
status: "draft", status: "draft",
version: 1, version: 1,
summary: { summary: expect.objectContaining({
total: 8400, // TODO: add summary fields
}, }),
items: [ items: [
expect.objectContaining({ expect.objectContaining({
title: "Test variant", title: "Test variant",
@@ -153,9 +153,9 @@ medusaIntegrationTestRunner({
id: expect.any(String), id: expect.any(String),
status: "pending", status: "pending",
version: 1, version: 1,
summary: { summary: expect.objectContaining({
total: 50, // TODO: add all summary fields
}, }),
total: 59.8, total: 59.8,
subtotal: 50, subtotal: 50,
tax_total: 0.9, tax_total: 0.9,
@@ -226,7 +226,7 @@ medusaIntegrationTestRunner({
promotion_id: expect.any(String), promotion_id: expect.any(String),
code: "VIP_25 ETH", code: "VIP_25 ETH",
raw_amount: { raw_amount: {
value: "5.0000000000000000000e-18", value: "5e-18",
precision: 20, precision: 20,
}, },
provider_id: expect.any(String), provider_id: expect.any(String),
@@ -237,11 +237,11 @@ medusaIntegrationTestRunner({
subtotal: 5e-18, subtotal: 5e-18,
total: 5e-18, total: 5e-18,
raw_subtotal: { raw_subtotal: {
value: "5.0000000000000000000e-18", value: "5e-18",
precision: 20, precision: 20,
}, },
raw_total: { raw_total: {
value: "5.0000000000000000000e-18", value: "5e-18",
precision: 20, precision: 20,
}, },
}, },
@@ -289,6 +289,7 @@ medusaIntegrationTestRunner({
metadata: null, metadata: null,
created_at: expect.any(String), created_at: expect.any(String),
updated_at: expect.any(String), updated_at: expect.any(String),
deleted_at: null,
quantity: 1, quantity: 1,
fulfilled_quantity: 0, fulfilled_quantity: 0,
shipped_quantity: 0, shipped_quantity: 0,
@@ -317,7 +318,7 @@ medusaIntegrationTestRunner({
precision: 20, precision: 20,
}, },
raw_discount_total: { raw_discount_total: {
value: "5.0000000000000000000e-18", value: "5e-18",
precision: 20, precision: 20,
}, },
raw_discount_tax_total: { raw_discount_tax_total: {
@@ -369,10 +370,9 @@ medusaIntegrationTestRunner({
updated_at: expect.any(String), updated_at: expect.any(String),
}, },
shipping_methods: [ shipping_methods: [
{ expect.objectContaining({
id: expect.any(String), id: expect.any(String),
order_id: expect.any(String), order_id: expect.any(String),
version: 1,
name: "Test shipping method", name: "Test shipping method",
description: null, description: null,
raw_amount: { raw_amount: {
@@ -475,7 +475,7 @@ medusaIntegrationTestRunner({
value: "1", value: "1",
precision: 20, precision: 20,
}, },
}, }),
], ],
}) })
}) })
@@ -123,7 +123,7 @@ moduleIntegrationTestRunner({
id: expect.stringContaining("order_"), id: expect.stringContaining("order_"),
version: 1, version: 1,
summary: expect.objectContaining({ summary: expect.objectContaining({
total: expect.any(Number), // TODO: add all summary fields
}), }),
shipping_address: expect.objectContaining({ shipping_address: expect.objectContaining({
id: expect.stringContaining("ordaddr_"), id: expect.stringContaining("ordaddr_"),
@@ -326,6 +326,209 @@ moduleIntegrationTestRunner({
) )
expect(orders4.length).toEqual(0) expect(orders4.length).toEqual(0)
}) })
it("should create an order, fulfill, ship and return the items", async function () {
const createdOrder = await service.create(input)
// Fullfilment
await service.registerFulfillment({
order_id: createdOrder.id,
items: createdOrder.items!.map((item) => {
return {
id: item.id,
quantity: item.quantity,
}
}),
})
let getOrder = await service.retrieve(createdOrder.id, {
select: [
"id",
"version",
"items.id",
"items.quantity",
"items.detail.id",
"items.detail.version",
"items.detail.quantity",
"items.detail.shipped_quantity",
"items.detail.fulfilled_quantity",
],
relations: ["items", "items.detail"],
})
let serializedOrder = JSON.parse(JSON.stringify(getOrder))
expect(serializedOrder).toEqual(
expect.objectContaining({
version: 2,
items: [
expect.objectContaining({
quantity: 1,
detail: expect.objectContaining({
version: 2,
quantity: 1,
fulfilled_quantity: 1,
shipped_quantity: 0,
}),
}),
expect.objectContaining({
quantity: 2,
detail: expect.objectContaining({
version: 2,
quantity: 2,
fulfilled_quantity: 2,
shipped_quantity: 0,
}),
}),
expect.objectContaining({
quantity: 1,
detail: expect.objectContaining({
version: 2,
quantity: 1,
fulfilled_quantity: 1,
shipped_quantity: 0,
}),
}),
],
})
)
// Shipment
await service.registerShipment({
order_id: createdOrder.id,
reference: Modules.FULFILLMENT,
shipping_method: createdOrder.shipping_methods![0].id,
items: createdOrder.items!.map((item) => {
return {
id: item.id,
quantity: item.quantity,
}
}),
})
getOrder = await service.retrieve(createdOrder.id, {
select: [
"id",
"version",
"items.id",
"items.quantity",
"items.detail.id",
"items.detail.version",
"items.detail.quantity",
"items.detail.shipped_quantity",
"items.detail.fulfilled_quantity",
],
relations: ["items", "items.detail"],
})
serializedOrder = JSON.parse(JSON.stringify(getOrder))
expect(serializedOrder).toEqual(
expect.objectContaining({
version: 3,
items: [
expect.objectContaining({
quantity: 1,
detail: expect.objectContaining({
version: 3,
quantity: 1,
fulfilled_quantity: 1,
shipped_quantity: 1,
}),
}),
expect.objectContaining({
quantity: 2,
detail: expect.objectContaining({
version: 3,
quantity: 2,
fulfilled_quantity: 2,
shipped_quantity: 2,
}),
}),
expect.objectContaining({
quantity: 1,
detail: expect.objectContaining({
version: 3,
quantity: 1,
fulfilled_quantity: 1,
shipped_quantity: 1,
}),
}),
],
})
)
// Return
await service.createReturn({
order_id: createdOrder.id,
reference: Modules.FULFILLMENT,
description: "Return all the items",
internal_note: "user wants to return all items",
shipping_method: createdOrder.shipping_methods![0].id,
items: createdOrder.items!.map((item) => {
return {
id: item.id,
quantity: item.quantity,
}
}),
})
getOrder = await service.retrieve(createdOrder.id, {
select: [
"id",
"version",
"items.id",
"items.quantity",
"items.detail.id",
"items.detail.version",
"items.detail.quantity",
"items.detail.shipped_quantity",
"items.detail.fulfilled_quantity",
"items.detail.return_requested_quantity",
],
relations: ["items", "items.detail"],
})
serializedOrder = JSON.parse(JSON.stringify(getOrder))
expect(serializedOrder).toEqual(
expect.objectContaining({
version: 4,
items: [
expect.objectContaining({
quantity: 1,
detail: expect.objectContaining({
version: 4,
quantity: 1,
fulfilled_quantity: 1,
shipped_quantity: 1,
return_requested_quantity: 1,
}),
}),
expect.objectContaining({
quantity: 2,
detail: expect.objectContaining({
version: 4,
quantity: 2,
fulfilled_quantity: 2,
shipped_quantity: 2,
return_requested_quantity: 2,
}),
}),
expect.objectContaining({
quantity: 1,
detail: expect.objectContaining({
version: 4,
quantity: 1,
fulfilled_quantity: 1,
shipped_quantity: 1,
return_requested_quantity: 1,
}),
}),
],
})
)
})
}) })
}, },
}) })
@@ -1,5 +1,10 @@
import { Modules } from "@medusajs/modules-sdk" import { Modules } from "@medusajs/modules-sdk"
import { CreateOrderDTO, IOrderModuleService } from "@medusajs/types" import {
CreateOrderChangeActionDTO,
CreateOrderChangeDTO,
CreateOrderDTO,
IOrderModuleService,
} from "@medusajs/types"
import { BigNumber } from "@medusajs/utils" import { BigNumber } from "@medusajs/utils"
import { SuiteOptions, moduleIntegrationTestRunner } from "medusa-test-utils" import { SuiteOptions, moduleIntegrationTestRunner } from "medusa-test-utils"
import { ChangeActionType } from "../../src/utils" import { ChangeActionType } from "../../src/utils"
@@ -7,7 +12,7 @@ import { ChangeActionType } from "../../src/utils"
jest.setTimeout(100000) jest.setTimeout(100000)
moduleIntegrationTestRunner({ moduleIntegrationTestRunner({
debug: 0, debug: false,
moduleName: Modules.ORDER, moduleName: Modules.ORDER,
testSuite: ({ service }: SuiteOptions<IOrderModuleService>) => { testSuite: ({ service }: SuiteOptions<IOrderModuleService>) => {
describe("Order Module Service - Order Edits", () => { describe("Order Module Service - Order Edits", () => {
@@ -132,9 +137,10 @@ moduleIntegrationTestRunner({
version: createdOrder.version, version: createdOrder.version,
internal_note: "adding an item", internal_note: "adding an item",
reference: "order_line_item", reference: "order_line_item",
reference_id: createdOrder.items[0].id, reference_id: createdOrder.items![0].id,
amount: amount:
createdOrder.items[0].unit_price * createdOrder.items[0].quantity, createdOrder.items![0].unit_price *
createdOrder.items![0].quantity,
details: { details: {
quantity: 1, quantity: 1,
}, },
@@ -144,9 +150,10 @@ moduleIntegrationTestRunner({
order_id: createdOrder.id, order_id: createdOrder.id,
version: createdOrder.version, version: createdOrder.version,
reference: "order_line_item", reference: "order_line_item",
reference_id: createdOrder.items[1].id, reference_id: createdOrder.items![1].id,
amount: amount:
createdOrder.items[1].unit_price * createdOrder.items[1].quantity, createdOrder.items![1].unit_price *
createdOrder.items![1].quantity,
details: { details: {
quantity: 3, quantity: 3,
}, },
@@ -158,7 +165,7 @@ moduleIntegrationTestRunner({
reference: "fullfilment", reference: "fullfilment",
reference_id: "fulfill_123", reference_id: "fulfill_123",
details: { details: {
reference_id: createdOrder.items[2].id, reference_id: createdOrder.items![2].id,
quantity: 1, quantity: 1,
}, },
}, },
@@ -169,7 +176,7 @@ moduleIntegrationTestRunner({
reference: "fullfilment", reference: "fullfilment",
reference_id: "shipping_123", reference_id: "shipping_123",
details: { details: {
reference_id: createdOrder.items[2].id, reference_id: createdOrder.items![2].id,
quantity: 1, quantity: 1,
}, },
}, },
@@ -181,7 +188,7 @@ moduleIntegrationTestRunner({
reference: "return", reference: "return",
reference_id: "return_123", reference_id: "return_123",
details: { details: {
reference_id: createdOrder.items[2].id, reference_id: createdOrder.items![2].id,
quantity: 1, quantity: 1,
}, },
}, },
@@ -193,11 +200,11 @@ moduleIntegrationTestRunner({
reference: "return", reference: "return",
reference_id: "return_123", reference_id: "return_123",
details: { details: {
reference_id: createdOrder.items[2].id, reference_id: createdOrder.items![2].id,
quantity: 1, quantity: 1,
}, },
}, },
]) ] as CreateOrderChangeActionDTO[])
await service.applyPendingOrderActions(createdOrder.id) await service.applyPendingOrderActions(createdOrder.id)
@@ -327,7 +334,7 @@ moduleIntegrationTestRunner({
]) ])
}) })
it("should create an order change, add actions to it and confirm the changes.", async function () { it("should create an order change, add actions to it, confirm the changes, revert all the changes and restore the changes again.", async function () {
const createdOrder = await service.create(input) const createdOrder = await service.create(input)
const orderChange = await service.createOrderChange({ const orderChange = await service.createOrderChange({
@@ -339,10 +346,10 @@ moduleIntegrationTestRunner({
{ {
action: ChangeActionType.ITEM_ADD, action: ChangeActionType.ITEM_ADD,
reference: "order_line_item", reference: "order_line_item",
reference_id: createdOrder.items[0].id, reference_id: createdOrder.items![0].id,
amount: amount:
createdOrder.items[0].unit_price * createdOrder.items![0].unit_price *
createdOrder.items[0].quantity, createdOrder.items![0].quantity,
details: { details: {
quantity: 1, quantity: 1,
}, },
@@ -350,10 +357,10 @@ moduleIntegrationTestRunner({
{ {
action: ChangeActionType.ITEM_ADD, action: ChangeActionType.ITEM_ADD,
reference: "order_line_item", reference: "order_line_item",
reference_id: createdOrder.items[1].id, reference_id: createdOrder.items![1].id,
amount: amount:
createdOrder.items[1].unit_price * createdOrder.items![1].unit_price *
createdOrder.items[1].quantity, createdOrder.items![1].quantity,
details: { details: {
quantity: 3, quantity: 3,
}, },
@@ -363,7 +370,7 @@ moduleIntegrationTestRunner({
reference: "fullfilment", reference: "fullfilment",
reference_id: "fulfill_123", reference_id: "fulfill_123",
details: { details: {
reference_id: createdOrder.items[2].id, reference_id: createdOrder.items![2].id,
quantity: 1, quantity: 1,
}, },
}, },
@@ -372,7 +379,7 @@ moduleIntegrationTestRunner({
reference: "fullfilment", reference: "fullfilment",
reference_id: "shipping_123", reference_id: "shipping_123",
details: { details: {
reference_id: createdOrder.items[2].id, reference_id: createdOrder.items![2].id,
quantity: 1, quantity: 1,
}, },
}, },
@@ -381,7 +388,7 @@ moduleIntegrationTestRunner({
reference: "return", reference: "return",
reference_id: "return_123", reference_id: "return_123",
details: { details: {
reference_id: createdOrder.items[2].id, reference_id: createdOrder.items![2].id,
quantity: 1, quantity: 1,
}, },
}, },
@@ -391,7 +398,7 @@ moduleIntegrationTestRunner({
reference: "return", reference: "return",
reference_id: "return_123", reference_id: "return_123",
details: { details: {
reference_id: createdOrder.items[2].id, reference_id: createdOrder.items![2].id,
quantity: 1, quantity: 1,
}, },
}, },
@@ -427,6 +434,9 @@ moduleIntegrationTestRunner({
}) })
) )
expect(serializedModifiedOrder.shipping_methods).toHaveLength(1)
expect(serializedModifiedOrder.shipping_methods[0].amount).toEqual(10)
expect(serializedModifiedOrder.items).toEqual([ expect(serializedModifiedOrder.items).toEqual([
expect.objectContaining({ expect.objectContaining({
quantity: 2, quantity: 2,
@@ -466,6 +476,72 @@ moduleIntegrationTestRunner({
}), }),
}), }),
]) ])
// Revert Last Changes
await service.revertLastVersion(createdOrder.id)
const revertedOrder = await service.retrieve(createdOrder.id, {
select: [
"id",
"version",
"items.detail",
"summary",
"shipping_methods",
],
relations: ["items"],
})
const serializedRevertedOrder = JSON.parse(
JSON.stringify(revertedOrder)
)
expect(serializedRevertedOrder).toEqual(
expect.objectContaining({
version: 1,
})
)
expect(serializedRevertedOrder.shipping_methods).toHaveLength(1)
expect(serializedRevertedOrder.shipping_methods[0].amount).toEqual(10)
expect(serializedRevertedOrder.items).toEqual([
expect.objectContaining({
quantity: 1,
unit_price: 8,
detail: expect.objectContaining({
version: 1,
quantity: 1,
}),
}),
expect.objectContaining({
title: "Item 2",
unit_price: 5,
quantity: 2,
detail: expect.objectContaining({
version: 1,
quantity: 2,
fulfilled_quantity: 0,
shipped_quantity: 0,
return_requested_quantity: 0,
return_received_quantity: 0,
return_dismissed_quantity: 0,
written_off_quantity: 0,
}),
}),
expect.objectContaining({
title: "Item 3",
unit_price: 30,
quantity: 1,
detail: expect.objectContaining({
version: 1,
quantity: 1,
fulfilled_quantity: 0,
shipped_quantity: 0,
return_requested_quantity: 0,
return_received_quantity: 0,
return_dismissed_quantity: 0,
written_off_quantity: 0,
}),
}),
])
}) })
it("should create order changes, cancel and reject them.", async function () { it("should create order changes, cancel and reject them.", async function () {
@@ -487,16 +563,16 @@ moduleIntegrationTestRunner({
{ {
action: ChangeActionType.ITEM_ADD, action: ChangeActionType.ITEM_ADD,
reference: "order_line_item", reference: "order_line_item",
reference_id: createdOrder.items[0].id, reference_id: createdOrder.items![0].id,
amount: amount:
createdOrder.items[0].unit_price * createdOrder.items![0].unit_price *
createdOrder.items[0].quantity, createdOrder.items![0].quantity,
details: { details: {
quantity: 1, quantity: 1,
}, },
}, },
], ],
}) } as CreateOrderChangeDTO)
await service.cancelOrderChange({ await service.cancelOrderChange({
id: orderChange.id, id: orderChange.id,
@@ -790,7 +790,7 @@ moduleIntegrationTestRunner({
}, },
]) ])
const methods = await service.createShippingMethods([ const [eurMethod, usdMethod] = await service.createShippingMethods([
{ {
order_id: eurOrder.id, order_id: eurOrder.id,
amount: 100, amount: 100,
@@ -811,47 +811,14 @@ moduleIntegrationTestRunner({
eurOrder = orders.find((c) => c.currency_code === "eur")! eurOrder = orders.find((c) => c.currency_code === "eur")!
usdOrder = orders.find((c) => c.currency_code === "usd")! usdOrder = orders.find((c) => c.currency_code === "usd")!
const eurMethods = methods.filter((m) => m.order_id === eurOrder.id) expect(eurOrder.shipping_methods![0].id).toBe(eurMethod.id)
const usdMethods = methods.filter((m) => m.order_id === usdOrder.id) expect(usdOrder.shipping_methods![0].id).toBe(usdMethod.id)
expect(eurOrder.shipping_methods![0].id).toBe(eurMethods[0].id)
expect(usdOrder.shipping_methods![0].id).toBe(usdMethods[0].id)
expect(eurOrder.shipping_methods?.length).toBe(1) expect(eurOrder.shipping_methods?.length).toBe(1)
expect(usdOrder.shipping_methods?.length).toBe(1) expect(usdOrder.shipping_methods?.length).toBe(1)
}) })
}) })
describe("deleteShippingMethods", () => {
it("should delete a line item succesfully", async () => {
const [createdOrder] = await service.create([
{
currency_code: "eur",
},
])
const [method] = await service.createShippingMethods(
createdOrder.id,
[
{
amount: 100,
name: "test",
},
]
)
expect(method.id).not.toBe(null)
await service.deleteShippingMethods(method.id)
const order = await service.retrieve(createdOrder.id, {
relations: ["shipping_methods"],
})
expect(order.shipping_methods?.length).toBe(0)
})
})
describe("setLineItemAdjustments", () => { describe("setLineItemAdjustments", () => {
it("should set line item adjustments for an order", async () => { it("should set line item adjustments for an order", async () => {
const [createdOrder] = await service.create([ const [createdOrder] = await service.create([
@@ -1457,6 +1424,7 @@ moduleIntegrationTestRunner({
}) })
const serialized = JSON.parse(JSON.stringify(order)) const serialized = JSON.parse(JSON.stringify(order))
expect(serialized.shipping_methods).toEqual( expect(serialized.shipping_methods).toEqual(
expect.arrayContaining([ expect.arrayContaining([
expect.objectContaining({ expect.objectContaining({
@@ -1750,39 +1718,43 @@ moduleIntegrationTestRunner({
}, },
]) ])
const orderOneMethods = await service.listShippingMethods( const orderOneMethods = await service.listOrderShippingMethods(
{ order_id: orderOne.id }, { order_id: orderOne.id },
{ relations: ["adjustments", "order"] } { relations: ["shipping_method.adjustments"] }
) )
const orderTwoMethods = await service.listShippingMethods( const orderTwoMethods = await service.listOrderShippingMethods(
{ order_id: orderTwo.id }, { order_id: orderTwo.id },
{ relations: ["adjustments", "order"] } { relations: ["shipping_method.adjustments"] }
) )
expect(orderOneMethods).toEqual( expect(orderOneMethods).toEqual(
expect.arrayContaining([ expect.arrayContaining([
expect.objectContaining({ expect.objectContaining({
adjustments: expect.arrayContaining([ shipping_method: expect.objectContaining({
expect.objectContaining({ adjustments: expect.arrayContaining([
shipping_method_id: shippingMethodOne.id, expect.objectContaining({
amount: 100, shipping_method_id: shippingMethodOne.id,
code: "FREE", amount: 100,
}), code: "FREE",
]), }),
]),
}),
}), }),
]) ])
) )
expect(orderTwoMethods).toEqual( expect(orderTwoMethods).toEqual(
expect.arrayContaining([ expect.arrayContaining([
expect.objectContaining({ expect.objectContaining({
adjustments: expect.arrayContaining([ shipping_method: expect.objectContaining({
expect.objectContaining({ adjustments: expect.arrayContaining([
shipping_method_id: shippingMethodTwo.id, expect.objectContaining({
amount: 150, shipping_method_id: shippingMethodTwo.id,
code: "CODE-2", amount: 150,
}), code: "CODE-2",
]), }),
]),
}),
}), }),
]) ])
) )
@@ -1828,7 +1800,7 @@ moduleIntegrationTestRunner({
}) })
describe("deleteShippingMethodAdjustments", () => { describe("deleteShippingMethodAdjustments", () => {
it("should delete a shipping method succesfully", async () => { it("should delete a shipping method adjustment succesfully", async () => {
const [createdOrder] = await service.create([ const [createdOrder] = await service.create([
{ {
currency_code: "eur", currency_code: "eur",
@@ -158,13 +158,15 @@ export class Migration20240219102530 extends Migration {
"totals" JSONB NULL, "totals" JSONB NULL,
"created_at" TIMESTAMPTZ NOT NULL DEFAULT Now(), "created_at" TIMESTAMPTZ NOT NULL DEFAULT Now(),
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT Now(), "updated_at" TIMESTAMPTZ NOT NULL DEFAULT Now(),
"deleted_at" timestamptz NULL,
CONSTRAINT "order_summary_pkey" PRIMARY KEY ("id") CONSTRAINT "order_summary_pkey" PRIMARY KEY ("id")
); );
CREATE INDEX IF NOT EXISTS "IDX_order_summary_order_id_version" ON "order_summary" ( CREATE INDEX IF NOT EXISTS "IDX_order_summary_order_id_version" ON "order_summary" (
order_id, order_id,
version version
); )
WHERE deleted_at IS NOT NULL;
CREATE TABLE IF NOT EXISTS "order_change" ( CREATE TABLE IF NOT EXISTS "order_change" (
"id" TEXT NOT NULL, "id" TEXT NOT NULL,
@@ -181,7 +183,7 @@ export class Migration20240219102530 extends Migration {
) )
) NOT NULL DEFAULT 'pending', ) NOT NULL DEFAULT 'pending',
"internal_note" text NULL, "internal_note" text NULL,
"created_by" text NOT NULL, "created_by" text NULL,
"requested_by" text NULL, "requested_by" text NULL,
"requested_at" timestamptz NULL, "requested_at" timestamptz NULL,
"confirmed_by" text NULL, "confirmed_by" text NULL,
@@ -261,22 +263,53 @@ export class Migration20240219102530 extends Migration {
"metadata" JSONB NULL, "metadata" JSONB NULL,
"created_at" TIMESTAMPTZ NOT NULL DEFAULT Now(), "created_at" TIMESTAMPTZ NOT NULL DEFAULT Now(),
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT Now(), "updated_at" TIMESTAMPTZ NOT NULL DEFAULT Now(),
"deleted_at" timestamptz NULL,
CONSTRAINT "order_item_pkey" PRIMARY KEY ("id") CONSTRAINT "order_item_pkey" PRIMARY KEY ("id")
); );
CREATE INDEX IF NOT EXISTS "IDX_order_item_order_id" ON "order_item" ( CREATE INDEX IF NOT EXISTS "IDX_order_item_order_id" ON "order_item" (
order_id order_id
); )
WHERE deleted_at IS NOT NULL;
CREATE INDEX IF NOT EXISTS "IDX_order_item_order_id_version" ON "order_item" ( CREATE INDEX IF NOT EXISTS "IDX_order_item_order_id_version" ON "order_item" (
order_id, order_id,
version version
); )
WHERE deleted_at IS NOT NULL;
CREATE INDEX IF NOT EXISTS "IDX_order_item_item_id" ON "order_item" ( CREATE INDEX IF NOT EXISTS "IDX_order_item_item_id" ON "order_item" (
item_id item_id
)
WHERE deleted_at IS NOT NULL;
CREATE TABLE IF NOT EXISTS "order_shipping" (
"id" TEXT NOT NULL,
"order_id" TEXT NOT NULL,
"version" INTEGER NOT NULL,
"shipping_method_id" TEXT NOT NULL,
"created_at" TIMESTAMPTZ NOT NULL DEFAULT Now(),
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT Now(),
"deleted_at" timestamptz NULL,
CONSTRAINT "order_shipping_pkey" PRIMARY KEY ("id")
); );
CREATE INDEX IF NOT EXISTS "IDX_order_shipping_order_id" ON "order_shipping" (
order_id
)
WHERE deleted_at IS NOT NULL;
CREATE INDEX IF NOT EXISTS "IDX_order_shipping_order_id_version" ON "order_shipping" (
order_id,
version
)
WHERE deleted_at IS NOT NULL;
CREATE INDEX IF NOT EXISTS "IDX_order_shipping_item_id" ON "order_shipping" (
shipping_method_id
)
WHERE deleted_at IS NOT NULL;
CREATE TABLE IF NOT EXISTS "order_line_item" ( CREATE TABLE IF NOT EXISTS "order_line_item" (
"id" TEXT NOT NULL, "id" TEXT NOT NULL,
"totals_id" TEXT NULL, "totals_id" TEXT NULL,
@@ -350,8 +383,6 @@ export class Migration20240219102530 extends Migration {
CREATE TABLE IF NOT EXISTS "order_shipping_method" ( CREATE TABLE IF NOT EXISTS "order_shipping_method" (
"id" TEXT NOT NULL, "id" TEXT NOT NULL,
"order_id" TEXT NOT NULL,
"version" INTEGER NOT NULL DEFAULT 1,
"name" TEXT NOT NULL, "name" TEXT NOT NULL,
"description" JSONB NULL, "description" JSONB NULL,
"amount" NUMERIC NOT NULL, "amount" NUMERIC NOT NULL,
@@ -365,15 +396,6 @@ export class Migration20240219102530 extends Migration {
CONSTRAINT "order_shipping_method_pkey" PRIMARY KEY ("id") CONSTRAINT "order_shipping_method_pkey" PRIMARY KEY ("id")
); );
CREATE INDEX IF NOT EXISTS "IDX_order_shipping_method_order_id" ON "order_shipping_method" (
order_id
);
CREATE INDEX IF NOT EXISTS "IDX_order_shipping_method_order_id_version" ON "order_shipping_method" (
order_id,
version
);
CREATE INDEX IF NOT EXISTS "IDX_order_shipping_method_shipping_option_id" ON "order_shipping_method" ( CREATE INDEX IF NOT EXISTS "IDX_order_shipping_method_shipping_option_id" ON "order_shipping_method" (
shipping_option_id shipping_option_id
); );
@@ -484,8 +506,8 @@ export class Migration20240219102530 extends Migration {
UPDATE CASCADE ON UPDATE CASCADE ON
DELETE CASCADE; DELETE CASCADE;
ALTER TABLE if exists "order_shipping_method" ALTER TABLE if exists "order_shipping"
ADD CONSTRAINT "order_shipping_method_order_id_foreign" FOREIGN KEY ("order_id") REFERENCES "order" ("id") ON ADD CONSTRAINT "order_shipping_order_id_foreign" FOREIGN KEY ("order_id") REFERENCES "order" ("id") ON
UPDATE CASCADE ON UPDATE CASCADE ON
DELETE CASCADE; DELETE CASCADE;
+1
View File
@@ -6,6 +6,7 @@ export { default as Order } from "./order"
export { default as OrderChange } from "./order-change" export { default as OrderChange } from "./order-change"
export { default as OrderChangeAction } from "./order-change-action" export { default as OrderChangeAction } from "./order-change-action"
export { default as OrderItem } from "./order-item" export { default as OrderItem } from "./order-item"
export { default as OrderShippingMethod } from "./order-shipping-method"
export { default as OrderSummary } from "./order-summary" export { default as OrderSummary } from "./order-summary"
export { default as ShippingMethod } from "./shipping-method" export { default as ShippingMethod } from "./shipping-method"
export { default as ShippingMethodAdjustment } from "./shipping-method-adjustment" export { default as ShippingMethodAdjustment } from "./shipping-method-adjustment"
@@ -136,14 +136,16 @@ export default class OrderChangeAction {
@BeforeCreate() @BeforeCreate()
onCreate() { onCreate() {
this.id = generateEntityId(this.id, "ordchact") this.id = generateEntityId(this.id, "ordchact")
this.order_id ??= this.order?.id ?? null this.order_id ??= this.order?.id ?? this.order_change?.order_id ?? null
this.order_change_id ??= this.order_change?.id ?? null this.order_change_id ??= this.order_change?.id ?? null
this.version ??= this.order_change?.version ?? null
} }
@OnInit() @OnInit()
onInit() { onInit() {
this.id = generateEntityId(this.id, "ordchact") this.id = generateEntityId(this.id, "ordchact")
this.order_id ??= this.order?.id ?? null this.order_id ??= this.order?.id ?? this.order_change?.order_id ?? null
this.order_change_id ??= this.order_change?.id ?? null this.order_change_id ??= this.order_change?.id ?? null
this.version ??= this.order_change?.version ?? null
} }
} }
+1 -1
View File
@@ -82,7 +82,7 @@ export default class OrderChange {
@Property({ columnType: "text", nullable: true }) @Property({ columnType: "text", nullable: true })
internal_note: string | null = null internal_note: string | null = null
@Property({ columnType: "text" }) @Property({ columnType: "text", nullable: true })
created_by: string // customer, user, third party, etc. created_by: string // customer, user, third party, etc.
@Property({ columnType: "text", nullable: true }) @Property({ columnType: "text", nullable: true })
+15
View File
@@ -22,16 +22,25 @@ type OptionalLineItemProps = DAL.EntityDateColumns
const OrderIdIndex = createPsqlIndexStatementHelper({ const OrderIdIndex = createPsqlIndexStatementHelper({
tableName: "order_item", tableName: "order_item",
columns: ["order_id"], columns: ["order_id"],
where: "deleted_at IS NOT NULL",
}) })
const OrderVersionIndex = createPsqlIndexStatementHelper({ const OrderVersionIndex = createPsqlIndexStatementHelper({
tableName: "order_item", tableName: "order_item",
columns: ["version"], columns: ["version"],
where: "deleted_at IS NOT NULL",
}) })
const ItemIdIndex = createPsqlIndexStatementHelper({ const ItemIdIndex = createPsqlIndexStatementHelper({
tableName: "order_item", tableName: "order_item",
columns: ["item_id"], columns: ["item_id"],
where: "deleted_at IS NOT NULL",
})
const DeletedAtIndex = createPsqlIndexStatementHelper({
tableName: "order",
columns: "deleted_at",
where: "deleted_at IS NOT NULL",
}) })
@Entity({ tableName: "order_item" }) @Entity({ tableName: "order_item" })
@@ -133,11 +142,16 @@ export default class OrderItem {
}) })
updated_at: Date updated_at: Date
@Property({ columnType: "timestamptz", nullable: true })
@DeletedAtIndex.MikroORMIndex()
deleted_at: Date | null = null
@BeforeCreate() @BeforeCreate()
onCreate() { onCreate() {
this.id = generateEntityId(this.id, "orditem") this.id = generateEntityId(this.id, "orditem")
this.order_id ??= this.order?.id this.order_id ??= this.order?.id
this.item_id ??= this.item?.id this.item_id ??= this.item?.id
this.version ??= this.order?.version
} }
@OnInit() @OnInit()
@@ -145,5 +159,6 @@ export default class OrderItem {
this.id = generateEntityId(this.id, "orditem") this.id = generateEntityId(this.id, "orditem")
this.order_id ??= this.order?.id this.order_id ??= this.order?.id
this.item_id ??= this.item?.id this.item_id ??= this.item?.id
this.version ??= this.order?.version
} }
} }
@@ -0,0 +1,117 @@
import { DAL } from "@medusajs/types"
import {
createPsqlIndexStatementHelper,
generateEntityId,
} from "@medusajs/utils"
import {
BeforeCreate,
Entity,
ManyToOne,
OnInit,
OptionalProps,
PrimaryKey,
Property,
} from "@mikro-orm/core"
import Order from "./order"
import ShippingMethod from "./shipping-method"
type OptionalShippingMethodProps = DAL.EntityDateColumns
const OrderIdIndex = createPsqlIndexStatementHelper({
tableName: "order_shipping",
columns: ["order_id"],
where: "deleted_at IS NOT NULL",
})
const OrderVersionIndex = createPsqlIndexStatementHelper({
tableName: "order_shipping",
columns: ["version"],
where: "deleted_at IS NOT NULL",
})
const ItemIdIndex = createPsqlIndexStatementHelper({
tableName: "order_shipping",
columns: ["shipping_method_id"],
where: "deleted_at IS NOT NULL",
})
const DeletedAtIndex = createPsqlIndexStatementHelper({
tableName: "order",
columns: "deleted_at",
where: "deleted_at IS NOT NULL",
})
@Entity({ tableName: "order_shipping" })
export default class OrderShippingMethod {
[OptionalProps]?: OptionalShippingMethodProps
@PrimaryKey({ columnType: "text" })
id: string
@ManyToOne({
entity: () => Order,
mapToPk: true,
fieldName: "order_id",
columnType: "text",
})
@OrderIdIndex.MikroORMIndex()
order_id: string
@Property({ columnType: "integer" })
@OrderVersionIndex.MikroORMIndex()
version: number
@ManyToOne(() => Order, {
persist: false,
})
order: Order
@ManyToOne({
entity: () => ShippingMethod,
fieldName: "shipping_method_id",
mapToPk: true,
columnType: "text",
})
@ItemIdIndex.MikroORMIndex()
shipping_method_id: string
@ManyToOne(() => ShippingMethod, {
persist: false,
})
shipping_method: ShippingMethod
@Property({
onCreate: () => new Date(),
columnType: "timestamptz",
defaultRaw: "now()",
})
created_at: Date
@Property({
onCreate: () => new Date(),
onUpdate: () => new Date(),
columnType: "timestamptz",
defaultRaw: "now()",
})
updated_at: Date
@Property({ columnType: "timestamptz", nullable: true })
@DeletedAtIndex.MikroORMIndex()
deleted_at: Date | null = null
@BeforeCreate()
onCreate() {
this.id = generateEntityId(this.id, "ordspmv")
this.order_id ??= this.order?.id
this.shipping_method_id ??= this.shipping_method?.id
this.version ??= this.order?.version
}
@OnInit()
onInit() {
this.id = generateEntityId(this.id, "ordspmv")
this.order_id ??= this.order?.id
this.shipping_method_id ??= this.shipping_method?.id
this.version ??= this.order?.version
}
}
@@ -41,6 +41,13 @@ type OrderSummaryTotals = {
const OrderIdVersionIndex = createPsqlIndexStatementHelper({ const OrderIdVersionIndex = createPsqlIndexStatementHelper({
tableName: "order_summary", tableName: "order_summary",
columns: ["order_id", "version"], columns: ["order_id", "version"],
where: "deleted_at IS NOT NULL",
})
const DeletedAtIndex = createPsqlIndexStatementHelper({
tableName: "order",
columns: "deleted_at",
where: "deleted_at IS NOT NULL",
}) })
@Entity({ tableName: "order_summary" }) @Entity({ tableName: "order_summary" })
@@ -87,6 +94,10 @@ export default class OrderSummary {
}) })
updated_at: Date updated_at: Date
@Property({ columnType: "timestamptz", nullable: true })
@DeletedAtIndex.MikroORMIndex()
deleted_at: Date | null = null
@BeforeCreate() @BeforeCreate()
onCreate() { onCreate() {
this.id = generateEntityId(this.id, "ordsum") this.id = generateEntityId(this.id, "ordsum")
+9 -5
View File
@@ -19,8 +19,8 @@ import {
} from "@mikro-orm/core" } from "@mikro-orm/core"
import Address from "./address" import Address from "./address"
import OrderItem from "./order-item" import OrderItem from "./order-item"
import OrderShippingMethod from "./order-shipping-method"
import OrderSummary from "./order-summary" import OrderSummary from "./order-summary"
import ShippingMethod from "./shipping-method"
import Transaction from "./transaction" import Transaction from "./transaction"
type OptionalOrderProps = type OptionalOrderProps =
@@ -166,10 +166,14 @@ export default class Order {
}) })
items = new Collection<OrderItem>(this) items = new Collection<OrderItem>(this)
@OneToMany(() => ShippingMethod, (shippingMethod) => shippingMethod.order, { @OneToMany(
cascade: [Cascade.PERSIST], () => OrderShippingMethod,
}) (shippingMethod) => shippingMethod.order,
shipping_methods = new Collection<ShippingMethod>(this) {
cascade: [Cascade.PERSIST],
}
)
shipping_methods = new Collection<OrderShippingMethod>(this)
@OneToMany(() => Transaction, (transaction) => transaction.order, { @OneToMany(() => Transaction, (transaction) => transaction.order, {
cascade: [Cascade.PERSIST], cascade: [Cascade.PERSIST],
@@ -10,13 +10,11 @@ import {
Cascade, Cascade,
Collection, Collection,
Entity, Entity,
ManyToOne,
OneToMany, OneToMany,
OnInit, OnInit,
PrimaryKey, PrimaryKey,
Property, Property,
} from "@mikro-orm/core" } from "@mikro-orm/core"
import Order from "./order"
import ShippingMethodAdjustment from "./shipping-method-adjustment" import ShippingMethodAdjustment from "./shipping-method-adjustment"
import ShippingMethodTaxLine from "./shipping-method-tax-line" import ShippingMethodTaxLine from "./shipping-method-tax-line"
@@ -25,43 +23,11 @@ const ShippingOptionIdIndex = createPsqlIndexStatementHelper({
columns: "shipping_option_id", columns: "shipping_option_id",
}) })
const OrderIdIndex = createPsqlIndexStatementHelper({
tableName: "order_shipping_method",
columns: "order_id",
})
const OrderVersionIndex = createPsqlIndexStatementHelper({
tableName: "order_shipping_method",
columns: ["order_id", "version"],
})
@Entity({ tableName: "order_shipping_method" }) @Entity({ tableName: "order_shipping_method" })
@OrderVersionIndex.MikroORMIndex()
export default class ShippingMethod { export default class ShippingMethod {
@PrimaryKey({ columnType: "text" }) @PrimaryKey({ columnType: "text" })
id: string id: string
@ManyToOne({
entity: () => Order,
columnType: "text",
fieldName: "order_id",
mapToPk: true,
onDelete: "cascade",
})
@OrderIdIndex.MikroORMIndex()
order_id: string
@ManyToOne(() => Order, {
persist: false,
})
order: Order
@Property({
columnType: "integer",
defaultRaw: "1",
})
version: number = 1
@Property({ columnType: "text" }) @Property({ columnType: "text" })
name: string name: string
@@ -126,11 +92,9 @@ export default class ShippingMethod {
@BeforeCreate() @BeforeCreate()
onCreate() { onCreate() {
this.id = generateEntityId(this.id, "ordsm") this.id = generateEntityId(this.id, "ordsm")
this.order_id ??= this.order?.id
} }
@OnInit() @OnInit()
onInit() { onInit() {
this.id = generateEntityId(this.id, "ordsm") this.id = generateEntityId(this.id, "ordsm")
this.order_id ??= this.order?.id
} }
} }
@@ -56,9 +56,7 @@ describe("Order Exchange - Actions", function () {
price: 0, price: 0,
}, },
], ],
summary: { total: 270,
total: 270,
},
} }
it("should perform an item exchage", function () { it("should perform an item exchage", function () {
@@ -98,14 +96,14 @@ describe("Order Exchange - Actions", function () {
const sumToJSON = JSON.parse(JSON.stringify(changes.summary)) const sumToJSON = JSON.parse(JSON.stringify(changes.summary))
expect(sumToJSON).toEqual({ expect(sumToJSON).toEqual({
transactionTotal: "0", transactionTotal: 0,
originalOrderTotal: 270, originalOrderTotal: 270,
currentOrderTotal: "312.5", currentOrderTotal: 312.5,
temporaryDifference: "62.5", temporaryDifference: 62.5,
futureDifference: 0, futureDifference: 0,
futureTemporaryDifference: "0", futureTemporaryDifference: 0,
pendingDifference: "312.5", pendingDifference: 312.5,
differenceSum: "42.5", differenceSum: 42.5,
}) })
const toJson = JSON.parse(JSON.stringify(changes.order.items)) const toJson = JSON.parse(JSON.stringify(changes.order.items))
@@ -74,6 +74,10 @@ export default class OrderChangeService<
} }
} }
if (!orderChange) {
return []
}
const relations = deduplicate([...(config.relations ?? []), "actions"]) const relations = deduplicate([...(config.relations ?? []), "actions"])
config.relations = relations config.relations = relations
@@ -1,16 +1,21 @@
import { import {
Context, Context,
CreateOrderChangeActionDTO,
DAL, DAL,
FindConfig, FindConfig,
InternalModuleDeclaration, InternalModuleDeclaration,
IOrderModuleService, IOrderModuleService,
ModuleJoinerConfig, ModuleJoinerConfig,
ModulesSdkTypes, ModulesSdkTypes,
OrderDTO,
OrderTypes, OrderTypes,
UpdateOrderItemWithSelectorDTO, UpdateOrderItemWithSelectorDTO,
} from "@medusajs/types" } from "@medusajs/types"
import { import {
createRawPropertiesFromBigNumber,
decorateCartTotals,
deduplicate, deduplicate,
getShippingMethodsTotals,
InjectManager, InjectManager,
InjectTransactionManager, InjectTransactionManager,
isObject, isObject,
@@ -30,6 +35,7 @@ import {
OrderChange, OrderChange,
OrderChangeAction, OrderChangeAction,
OrderItem, OrderItem,
OrderShippingMethod,
OrderSummary, OrderSummary,
ShippingMethod, ShippingMethod,
ShippingMethodAdjustment, ShippingMethodAdjustment,
@@ -48,7 +54,7 @@ import {
UpdateOrderShippingMethodTaxLineDTO, UpdateOrderShippingMethodTaxLineDTO,
} from "@types" } from "@types"
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config" import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
import { calculateOrderChange } from "../utils" import { calculateOrderChange, ChangeActionType } from "../utils"
import { formatOrder } from "../utils/transform-order" import { formatOrder } from "../utils/transform-order"
import OrderChangeService from "./order-change-service" import OrderChangeService from "./order-change-service"
import OrderService from "./order-service" import OrderService from "./order-service"
@@ -68,6 +74,7 @@ type InjectedDependencies = {
orderChangeActionService: ModulesSdkTypes.InternalModuleService<any> orderChangeActionService: ModulesSdkTypes.InternalModuleService<any>
orderItemService: ModulesSdkTypes.InternalModuleService<any> orderItemService: ModulesSdkTypes.InternalModuleService<any>
orderSummaryService: ModulesSdkTypes.InternalModuleService<any> orderSummaryService: ModulesSdkTypes.InternalModuleService<any>
orderShippingMethodService: ModulesSdkTypes.InternalModuleService<any>
} }
const generateMethodForModels = [ const generateMethodForModels = [
@@ -83,6 +90,7 @@ const generateMethodForModels = [
OrderChangeAction, OrderChangeAction,
OrderItem, OrderItem,
OrderSummary, OrderSummary,
OrderShippingMethod,
] ]
export default class OrderModuleService< export default class OrderModuleService<
@@ -98,7 +106,8 @@ export default class OrderModuleService<
TOrderChange extends OrderChange = OrderChange, TOrderChange extends OrderChange = OrderChange,
TOrderChangeAction extends OrderChangeAction = OrderChangeAction, TOrderChangeAction extends OrderChangeAction = OrderChangeAction,
TOrderItem extends OrderItem = OrderItem, TOrderItem extends OrderItem = OrderItem,
TOrderSummary extends OrderSummary = OrderSummary TOrderSummary extends OrderSummary = OrderSummary,
TOrderShippingMethod extends OrderShippingMethod = OrderShippingMethod
> >
extends ModulesSdkUtils.abstractModuleServiceFactory< extends ModulesSdkUtils.abstractModuleServiceFactory<
InjectedDependencies, InjectedDependencies,
@@ -118,6 +127,7 @@ export default class OrderModuleService<
OrderChangeAction: { dto: OrderTypes.OrderChangeActionDTO } OrderChangeAction: { dto: OrderTypes.OrderChangeActionDTO }
OrderItem: { dto: OrderTypes.OrderItemDTO } OrderItem: { dto: OrderTypes.OrderItemDTO }
OrderSummary: { dto: OrderTypes.OrderSummaryDTO } OrderSummary: { dto: OrderTypes.OrderSummaryDTO }
OrderShippingMethod: { dto: OrderShippingMethod }
} }
>(Order, generateMethodForModels, entityNameToLinkableKeysMap) >(Order, generateMethodForModels, entityNameToLinkableKeysMap)
implements IOrderModuleService implements IOrderModuleService
@@ -136,6 +146,7 @@ export default class OrderModuleService<
protected orderChangeActionService_: ModulesSdkTypes.InternalModuleService<TOrderChangeAction> protected orderChangeActionService_: ModulesSdkTypes.InternalModuleService<TOrderChangeAction>
protected orderItemService_: ModulesSdkTypes.InternalModuleService<TOrderItem> protected orderItemService_: ModulesSdkTypes.InternalModuleService<TOrderItem>
protected orderSummaryService_: ModulesSdkTypes.InternalModuleService<TOrderSummary> protected orderSummaryService_: ModulesSdkTypes.InternalModuleService<TOrderSummary>
protected orderShippingMethodService_: ModulesSdkTypes.InternalModuleService<TOrderShippingMethod>
constructor( constructor(
{ {
@@ -153,6 +164,7 @@ export default class OrderModuleService<
orderChangeActionService, orderChangeActionService,
orderItemService, orderItemService,
orderSummaryService, orderSummaryService,
orderShippingMethodService,
}: InjectedDependencies, }: InjectedDependencies,
protected readonly moduleDeclaration: InternalModuleDeclaration protected readonly moduleDeclaration: InternalModuleDeclaration
) { ) {
@@ -173,6 +185,7 @@ export default class OrderModuleService<
this.orderChangeActionService_ = orderChangeActionService this.orderChangeActionService_ = orderChangeActionService
this.orderItemService_ = orderItemService this.orderItemService_ = orderItemService
this.orderSummaryService_ = orderSummaryService this.orderSummaryService_ = orderSummaryService
this.orderShippingMethodService_ = orderShippingMethodService
} }
__joinerConfig(): ModuleJoinerConfig { __joinerConfig(): ModuleJoinerConfig {
@@ -304,20 +317,6 @@ export default class OrderModuleService<
): Promise<OrderTypes.OrderDTO[] | OrderTypes.OrderDTO> { ): Promise<OrderTypes.OrderDTO[] | OrderTypes.OrderDTO> {
const input = Array.isArray(data) ? data : [data] const input = Array.isArray(data) ? data : [data]
// TODO: calculate order total
for (const inp of input) {
const ordTotals = inp as any
ordTotals.summary = {
totals: {
total:
inp.items?.reduce((acc, item) => {
const it = item as any
return acc + it.unit_price * it.quantity
}, 0) ?? 0,
},
}
}
const orders = await this.create_(input, sharedContext) const orders = await this.create_(input, sharedContext)
const result = await this.list( const result = await this.list(
@@ -354,8 +353,33 @@ export default class OrderModuleService<
const lineItemsToCreate: CreateOrderLineItemDTO[] = [] const lineItemsToCreate: CreateOrderLineItemDTO[] = []
const createdOrders: Order[] = [] const createdOrders: Order[] = []
for (const { items, ...order } of data) { for (const { items, shipping_methods, ...order } of data) {
const created = await this.orderService_.create(order, sharedContext) const ord = order as any
const shippingMethods = shipping_methods?.map((sm: any) => {
return {
shipping_method: { ...sm },
}
})
ord.shipping_methods = shippingMethods
const orderWithTotals = decorateCartTotals({
...ord,
items,
}) as any
const calculated = calculateOrderChange({
order: orderWithTotals,
actions: [],
transactions: order.transactions,
})
createRawPropertiesFromBigNumber(calculated)
ord.summary = {
totals: calculated.summary,
}
const created = await this.orderService_.create(ord, sharedContext)
createdOrders.push(created) createdOrders.push(created)
@@ -484,7 +508,26 @@ export default class OrderModuleService<
const data = Array.isArray(orderIdOrData) const data = Array.isArray(orderIdOrData)
? orderIdOrData ? orderIdOrData
: [orderIdOrData] : [orderIdOrData]
items = await this.createLineItemsBulk_(data, sharedContext)
const allOrderIds = data.map((dt) => dt.order_id)
const order = await this.list(
{ id: allOrderIds },
{ select: ["id", "version"] },
sharedContext
)
const mapOrderVersion = order.reduce((acc, curr) => {
acc[curr.id] = curr.version
return acc
}, {})
const lineItems = data.map((dt) => {
return {
...dt,
version: mapOrderVersion[dt.order_id],
}
})
items = await this.createLineItemsBulk_(lineItems, sharedContext)
} }
return await this.baseRepository_.serialize<OrderTypes.OrderLineItemDTO[]>( return await this.baseRepository_.serialize<OrderTypes.OrderLineItemDTO[]>(
@@ -867,8 +910,27 @@ export default class OrderModuleService<
const data = Array.isArray(orderIdOrData) const data = Array.isArray(orderIdOrData)
? orderIdOrData ? orderIdOrData
: [orderIdOrData] : [orderIdOrData]
const allOrderIds = data.map((dt) => dt.order_id)
const order = await this.list(
{ id: allOrderIds },
{ select: ["id", "version"] },
sharedContext
)
const mapOrderVersion = order.reduce((acc, curr) => {
acc[curr.id] = curr.version
return acc
}, {})
const orderShippingMethodData = data.map((dt) => {
return {
shipping_method: dt,
order_id: dt.order_id,
version: mapOrderVersion[dt.order_id],
}
})
methods = await this.createShippingMethodsBulk_( methods = await this.createShippingMethodsBulk_(
data as OrderTypes.CreateOrderShippingMethodDTO[], orderShippingMethodData as any,
sharedContext sharedContext
) )
} }
@@ -886,13 +948,13 @@ export default class OrderModuleService<
): Promise<ShippingMethod[]> { ): Promise<ShippingMethod[]> {
const order = await this.retrieve( const order = await this.retrieve(
orderId, orderId,
{ select: ["id"] }, { select: ["id", "version"] },
sharedContext sharedContext
) )
const methods = data.map((method) => { const methods = data.map((method) => {
return { return {
...method, shipping_method: method,
order_id: order.id, order_id: order.id,
version: method.version ?? order.version ?? 1, version: method.version ?? order.version ?? 1,
} }
@@ -903,13 +965,19 @@ export default class OrderModuleService<
@InjectTransactionManager("baseRepository_") @InjectTransactionManager("baseRepository_")
protected async createShippingMethodsBulk_( protected async createShippingMethodsBulk_(
data: OrderTypes.CreateOrderShippingMethodDTO[], data: {
shipping_method: OrderTypes.CreateOrderShippingMethodDTO
order_id: string
version: number
}[],
@MedusaContext() sharedContext: Context = {} @MedusaContext() sharedContext: Context = {}
): Promise<ShippingMethod[]> { ): Promise<ShippingMethod[]> {
return await this.shippingMethodService_.create( const sm = await this.orderShippingMethodService_.create(
data as unknown as CreateOrderShippingMethodDTO[], data as unknown as CreateOrderShippingMethodDTO[],
sharedContext sharedContext
) )
return sm.map((s) => s.shipping_method)
} }
async createLineItemAdjustments( async createLineItemAdjustments(
@@ -1494,12 +1562,12 @@ export default class OrderModuleService<
} }
async confirmOrderChange( async confirmOrderChange(
orderId: string, orderChangeId: string,
sharedContext?: Context sharedContext?: Context
): Promise<void> ): Promise<void>
async confirmOrderChange( async confirmOrderChange(
orderId: string[], orderChangeId: string[],
sharedContext?: Context sharedContext?: Context
): Promise<void> ): Promise<void>
@@ -1561,12 +1629,12 @@ export default class OrderModuleService<
} }
async declineOrderChange( async declineOrderChange(
orderId: string, orderChangeId: string,
sharedContext?: Context sharedContext?: Context
): Promise<void> ): Promise<void>
async declineOrderChange( async declineOrderChange(
orderId: string[], orderChangeId: string[],
sharedContext?: Context sharedContext?: Context
): Promise<void> ): Promise<void>
@@ -1656,6 +1724,120 @@ export default class OrderModuleService<
await this.applyOrderChanges_(changes, sharedContext) await this.applyOrderChanges_(changes, sharedContext)
} }
@InjectManager("baseRepository_")
async revertLastVersion(orderId: string, sharedContext?: Context) {
const order = await super.retrieve(
orderId,
{
select: ["id", "version"],
},
sharedContext
)
if (order.version < 2) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`Order with id ${orderId} has no previous versions`
)
}
return await this.revertLastChange_(order, sharedContext)
}
@InjectTransactionManager("baseRepository_")
protected async revertLastChange_(
order: OrderDTO,
sharedContext?: Context
): Promise<void> {
const currentVersion = order.version
// Order Changes
const orderChanges = await this.orderChangeService_.list(
{
order_id: order.id,
version: currentVersion,
},
{ select: ["id", "version"] },
sharedContext
)
const orderChangesIds = orderChanges.map((change) => change.id)
await this.orderChangeService_.softDelete(orderChangesIds, sharedContext)
// Order Changes Actions
const orderChangesActions = await this.orderChangeActionService_.list(
{
order_id: order.id,
version: currentVersion,
},
{ select: ["id", "version"] },
sharedContext
)
const orderChangeActionsIds = orderChangesActions.map((action) => action.id)
await this.orderChangeActionService_.softDelete(
orderChangeActionsIds,
sharedContext
)
// Order Summary
const orderSummary = await this.orderSummaryService_.list(
{
order_id: order.id,
version: currentVersion,
},
{ select: ["id", "version"] },
sharedContext
)
const orderSummaryIds = orderSummary.map((summary) => summary.id)
await this.orderSummaryService_.softDelete(orderSummaryIds, sharedContext)
// Order Items
const orderItems = await this.orderItemService_.list(
{
order_id: order.id,
version: currentVersion,
},
{ select: ["id", "version"] },
sharedContext
)
const orderItemIds = orderItems.map((summary) => summary.id)
await this.orderItemService_.softDelete(orderItemIds, sharedContext)
// Shipping Methods
const orderShippingMethods = await this.orderShippingMethodService_.list(
{
order_id: order.id,
version: currentVersion,
},
{ select: ["id", "version"] },
sharedContext
)
const orderShippingMethodIds = orderShippingMethods.map(
(summary) => summary.id
)
await this.orderShippingMethodService_.softDelete(
orderShippingMethodIds,
sharedContext
)
// Order
await this.orderService_.update(
{
selector: {
id: order.id,
},
data: {
version: order.version - 1,
},
},
sharedContext
)
}
private async getAndValidateOrderChange_( private async getAndValidateOrderChange_(
orderChangeIds: string[], orderChangeIds: string[],
includeActions: boolean, includeActions: boolean,
@@ -1812,14 +1994,22 @@ export default class OrderModuleService<
const orders = await this.list( const orders = await this.list(
{ id: deduplicate(ordersIds) }, { id: deduplicate(ordersIds) },
{ {
select: ["id", "version", "items.detail", "transactions", "summary"], select: [
"id",
"version",
"items.detail",
"transactions",
"summary",
"total",
],
relations: ["transactions", "items", "items.detail"], relations: ["transactions", "items", "items.detail"],
}, },
sharedContext sharedContext
) )
const itemsToUpsert: OrderItem[] = [] const itemsToUpsert: OrderItem[] = []
const summariesToUpdate: any[] = [] const shippingMethodsToInsert: OrderShippingMethod[] = []
const summariesToUpsert: any[] = []
const orderToUpdate: any[] = [] const orderToUpdate: any[] = []
for (const order of orders) { for (const order of orders) {
@@ -1829,11 +2019,14 @@ export default class OrderModuleService<
transactions: order.transactions, transactions: order.transactions,
}) })
createRawPropertiesFromBigNumber(calculated)
const version = actionsMap[order.id][0].version! const version = actionsMap[order.id][0].version!
for (const item of calculated.order.items) { for (const item of calculated.order.items) {
const orderItem = item.detail as any
itemsToUpsert.push({ itemsToUpsert.push({
id: item.detail.id, id: orderItem.version === version ? orderItem.id : undefined,
item_id: item.id, item_id: item.id,
order_id: order.id, order_id: order.id,
version, version,
@@ -1848,7 +2041,24 @@ export default class OrderModuleService<
} as any) } as any)
} }
const orderSummary = order.summary as any
summariesToUpsert.push({
id: orderSummary.version === version ? orderSummary.id : undefined,
order_id: order.id,
version,
totals: calculated.summary,
})
if (version > order.version) { if (version > order.version) {
for (const shippingMethod of order.shipping_methods ?? []) {
const sm = {
...(shippingMethod as any).detail,
version,
}
delete sm.id
shippingMethodsToInsert.push(sm)
}
orderToUpdate.push({ orderToUpdate.push({
selector: { selector: {
id: order.id, id: order.id,
@@ -1858,16 +2068,6 @@ export default class OrderModuleService<
}, },
}) })
} }
summariesToUpdate.push({
selector: {
order_id: order.id,
},
data: {
version,
totals: calculated.summary,
},
})
} }
await promiseAll([ await promiseAll([
@@ -1880,9 +2080,185 @@ export default class OrderModuleService<
itemsToUpsert.length itemsToUpsert.length
? this.orderItemService_.upsert(itemsToUpsert, sharedContext) ? this.orderItemService_.upsert(itemsToUpsert, sharedContext)
: null, : null,
summariesToUpdate.length summariesToUpsert.length
? this.orderSummaryService_.update(summariesToUpdate, sharedContext) ? this.orderSummaryService_.upsert(summariesToUpsert, sharedContext)
: null,
shippingMethodsToInsert.length
? this.orderShippingMethodService_.create(
shippingMethodsToInsert,
sharedContext
)
: null, : null,
]) ])
} }
@InjectTransactionManager("baseRepository_")
async registerFulfillment(
data: OrderTypes.RegisterOrderFulfillmentDTO,
sharedContext?: Context
): Promise<void> {
const items = data.items.map((item) => {
return {
action: ChangeActionType.FULFILL_ITEM,
internal_note: item.internal_note,
reference: data.reference,
reference_id: data.reference_id,
details: {
reference_id: item.id,
quantity: item.quantity,
metadata: item.metadata,
},
}
})
const change = await this.createOrderChange_(
{
order_id: data.order_id,
description: data.description,
internal_note: data.internal_note,
created_by: data.created_by,
metadata: data.metadata,
actions: items,
},
sharedContext
)
await this.confirmOrderChange(change[0].id, sharedContext)
}
@InjectTransactionManager("baseRepository_")
async registerShipment(
data: OrderTypes.RegisterOrderShipmentDTO,
sharedContext?: Context
): Promise<void> {
let shippingMethodId
if (!isString(data.shipping_method)) {
const methods = await this.createShippingMethods(
data.order_id,
data.shipping_method as any,
sharedContext
)
shippingMethodId = methods[0].id
} else {
shippingMethodId = data.shipping_method
}
const method = await this.shippingMethodService_.retrieve(
shippingMethodId,
{
relations: ["tax_lines", "adjustments"],
},
sharedContext
)
const calculatedAmount = getShippingMethodsTotals([method as any], {})[
method.id
]
const actions: CreateOrderChangeActionDTO[] = data.items.map((item) => {
return {
action: ChangeActionType.SHIP_ITEM,
internal_note: item.internal_note,
reference: data.reference,
reference_id: shippingMethodId,
details: {
reference_id: item.id,
quantity: item.quantity,
metadata: item.metadata,
},
}
})
if (shippingMethodId) {
actions.push({
action: ChangeActionType.SHIPPING_ADD,
reference: data.reference,
reference_id: shippingMethodId,
amount: calculatedAmount.total,
})
}
const change = await this.createOrderChange_(
{
order_id: data.order_id,
description: data.description,
internal_note: data.internal_note,
created_by: data.created_by,
metadata: data.metadata,
actions,
},
sharedContext
)
await this.confirmOrderChange(change[0].id, sharedContext)
}
@InjectTransactionManager("baseRepository_")
async createReturn(
data: OrderTypes.CreateOrderReturnDTO,
sharedContext?: Context
): Promise<void> {
let shippingMethodId
if (!isString(data.shipping_method)) {
const methods = await this.createShippingMethods(
data.order_id,
data.shipping_method as any,
sharedContext
)
shippingMethodId = methods[0].id
} else {
shippingMethodId = data.shipping_method
}
const method = await this.shippingMethodService_.retrieve(
shippingMethodId,
{
relations: ["tax_lines", "adjustments"],
},
sharedContext
)
const calculatedAmount = getShippingMethodsTotals([method as any], {})[
method.id
]
const actions: CreateOrderChangeActionDTO[] = data.items.map((item) => {
return {
action: ChangeActionType.RETURN_ITEM,
internal_note: item.internal_note,
reference: data.reference,
reference_id: shippingMethodId,
details: {
reference_id: item.id,
quantity: item.quantity,
metadata: item.metadata,
},
}
})
if (shippingMethodId) {
actions.push({
action: ChangeActionType.SHIPPING_ADD,
reference: data.reference,
reference_id: shippingMethodId,
amount: calculatedAmount.total,
})
}
const change = await this.createOrderChange_(
{
order_id: data.order_id,
description: data.description,
internal_note: data.internal_note,
created_by: data.created_by,
metadata: data.metadata,
actions,
},
sharedContext
)
await this.confirmOrderChange(change[0].id, sharedContext)
}
} }
+1 -3
View File
@@ -24,9 +24,7 @@ export type VirtualOrder = {
price: BigNumberInput price: BigNumberInput
}[] }[]
summary: { total: BigNumberInput
total: BigNumberInput
}
metadata?: Record<string, unknown> metadata?: Record<string, unknown>
} }
@@ -1,5 +1,6 @@
import { BigNumberInput, OrderSummaryDTO } from "@medusajs/types" import { BigNumberInput, OrderSummaryDTO } from "@medusajs/types"
import { import {
BigNumber,
MathBN, MathBN,
isDefined, isDefined,
transformPropertiesToBigNumber, transformPropertiesToBigNumber,
@@ -61,8 +62,8 @@ export class OrderChangeProcessing {
pendingDifference: 0, pendingDifference: 0,
futureTemporarySum: 0, futureTemporarySum: 0,
differenceSum: 0, differenceSum: 0,
currentOrderTotal: this.order.summary?.total ?? 0, currentOrderTotal: this.order.total ?? 0,
originalOrderTotal: this.order.summary?.total ?? 0, originalOrderTotal: this.order.total ?? 0,
transactionTotal, transactionTotal,
} }
} }
@@ -344,14 +345,16 @@ export class OrderChangeProcessing {
public getSummary(): OrderSummaryDTO { public getSummary(): OrderSummaryDTO {
const summary = this.summary const summary = this.summary
const orderSummary = { const orderSummary = {
transactionTotal: summary.transactionTotal, transactionTotal: new BigNumber(summary.transactionTotal),
originalOrderTotal: summary.originalOrderTotal, originalOrderTotal: new BigNumber(summary.originalOrderTotal),
currentOrderTotal: summary.currentOrderTotal, currentOrderTotal: new BigNumber(summary.currentOrderTotal),
temporaryDifference: summary.temporaryDifference, temporaryDifference: new BigNumber(summary.temporaryDifference),
futureDifference: summary.futureDifference, futureDifference: new BigNumber(summary.futureDifference),
futureTemporaryDifference: summary.futureTemporaryDifference, futureTemporaryDifference: new BigNumber(
pendingDifference: summary.pendingDifference, summary.futureTemporaryDifference
differenceSum: summary.differenceSum, ),
pendingDifference: new BigNumber(summary.pendingDifference),
differenceSum: new BigNumber(summary.differenceSum),
} as unknown as OrderSummaryDTO } as unknown as OrderSummaryDTO
/* /*
@@ -29,6 +29,19 @@ export function formatOrder(
} }
}) })
order.shipping_methods = order.shipping_methods?.map((shippingMethod) => {
const sm = { ...shippingMethod.shipping_method }
delete shippingMethod.shipping_method
return {
...sm,
order_id: shippingMethod.order_id,
detail: {
...shippingMethod,
},
}
})
order.summary = order.summary?.[0]?.totals order.summary = order.summary?.[0]?.totals
return options?.includeTotals return options?.includeTotals
@@ -58,6 +71,16 @@ export function mapRepositoryToOrderModel(config) {
if (rel == "summary" && type === "fields") { if (rel == "summary" && type === "fields") {
obj.populate.push("summary") obj.populate.push("summary")
return "summary.totals" return "summary.totals"
} else if (
rel.includes("shipping_methods") &&
!rel.includes("shipping_methods.shipping_method")
) {
obj.populate.push("shipping_methods.shipping_method")
return rel.replace(
"shipping_methods",
"shipping_methods.shipping_method"
)
} else if (rel.includes("items.detail")) { } else if (rel.includes("items.detail")) {
return rel.replace("items.detail", "items") return rel.replace("items.detail", "items")
} else if (rel == "items") { } else if (rel == "items") {
+58 -1
View File
@@ -52,7 +52,9 @@ export interface UpdateOrderDTO {
region_id?: string region_id?: string
customer_id?: string customer_id?: string
sales_channel_id?: string sales_channel_id?: string
status?: string items?: CreateOrderLineItemDTO[]
shipping_address?: CreateOrderAddressDTO | UpdateOrderAddressDTO
billing_address?: CreateOrderAddressDTO | UpdateOrderAddressDTO
email?: string email?: string
no_notification?: boolean no_notification?: boolean
metadata?: Record<string, unknown> metadata?: Record<string, unknown>
@@ -199,6 +201,7 @@ export interface UpdateOrderLineItemDTO
export interface CreateOrderShippingMethodDTO { export interface CreateOrderShippingMethodDTO {
name: string name: string
order_id: string order_id: string
version?: number
amount: BigNumberInput amount: BigNumberInput
shipping_option_id?: string shipping_option_id?: string
data?: Record<string, unknown> data?: Record<string, unknown>
@@ -289,10 +292,12 @@ export interface ConfirmOrderChangeDTO {
export interface CreateOrderChangeActionDTO { export interface CreateOrderChangeActionDTO {
order_change_id?: string order_change_id?: string
version?: number
reference?: string reference?: string
reference_id?: string reference_id?: string
action: string action: string
internal_note?: string internal_note?: string
amount?: BigNumberInput
details?: Record<string, unknown> details?: Record<string, unknown>
} }
@@ -344,3 +349,55 @@ export interface UpdateOrderItemWithSelectorDTO {
} }
/** ORDER DETAIL END */ /** ORDER DETAIL END */
/** ORDER bundled action flows */
export interface RegisterOrderFulfillmentDTO {
order_id: string
description?: string
internal_note?: string
reference?: string
reference_id?: string
created_by?: string
items: {
id: string
quantity: BigNumberInput
internal_note?: string
metadata?: Record<string, unknown>
}[]
metadata?: Record<string, unknown>
}
export interface RegisterOrderShipmentDTO {
order_id: string
description?: string
internal_note?: string
reference?: string
created_by?: string
shipping_method: Omit<CreateOrderShippingMethodDTO, "order_id"> | string
items: {
id: string
quantity: BigNumberInput
internal_note?: string
metadata?: Record<string, unknown>
}[]
metadata?: Record<string, unknown>
}
export interface CreateOrderReturnDTO {
order_id: string
description?: string
reference?: string
internal_note?: string
created_by?: string
shipping_method: Omit<CreateOrderShippingMethodDTO, "order_id"> | string
items: {
id: string
quantity: BigNumberInput
internal_note?: string
metadata?: Record<string, unknown>
}[]
metadata?: Record<string, unknown>
}
/** ORDER bundled action flows */
+40 -7
View File
@@ -34,10 +34,13 @@ import {
CreateOrderLineItemDTO, CreateOrderLineItemDTO,
CreateOrderLineItemForOrderDTO, CreateOrderLineItemForOrderDTO,
CreateOrderLineItemTaxLineDTO, CreateOrderLineItemTaxLineDTO,
CreateOrderReturnDTO,
CreateOrderShippingMethodAdjustmentDTO, CreateOrderShippingMethodAdjustmentDTO,
CreateOrderShippingMethodDTO, CreateOrderShippingMethodDTO,
CreateOrderShippingMethodTaxLineDTO, CreateOrderShippingMethodTaxLineDTO,
DeclineOrderChangeDTO, DeclineOrderChangeDTO,
RegisterOrderFulfillmentDTO,
RegisterOrderShipmentDTO,
UpdateOrderAddressDTO, UpdateOrderAddressDTO,
UpdateOrderDTO, UpdateOrderDTO,
UpdateOrderItemDTO, UpdateOrderItemDTO,
@@ -1130,12 +1133,15 @@ export interface IOrderModuleService extends IModuleService {
* ``` * ```
* *
*/ */
confirmOrderChange(orderId: string, sharedContext?: Context): Promise<void> confirmOrderChange(
orderChangeId: string,
sharedContext?: Context
): Promise<void>
/** /**
* This method Represents the completion of an asynchronous operation * This method Represents the completion of an asynchronous operation
* *
* @param {string[]} orderId - The order's ID. * @param {string[]} orderChangeId - The order change's ID.
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
* @returns {Promise<void>} Resolves when {summary} * @returns {Promise<void>} Resolves when {summary}
* *
@@ -1145,7 +1151,10 @@ export interface IOrderModuleService extends IModuleService {
* ``` * ```
* *
*/ */
confirmOrderChange(orderId: string[], sharedContext?: Context): Promise<void> confirmOrderChange(
orderChangeId: string[],
sharedContext?: Context
): Promise<void>
/** /**
* This method Represents the completion of an asynchronous operation * This method Represents the completion of an asynchronous operation
@@ -1192,7 +1201,7 @@ export interface IOrderModuleService extends IModuleService {
/** /**
* This method Represents the completion of an asynchronous operation * This method Represents the completion of an asynchronous operation
* *
* @param {string} orderId - The order's ID. * @param {string} orderChangeId - The order change's ID.
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
* @returns {Promise<void>} Resolves when {summary} * @returns {Promise<void>} Resolves when {summary}
* *
@@ -1202,12 +1211,15 @@ export interface IOrderModuleService extends IModuleService {
* ``` * ```
* *
*/ */
declineOrderChange(orderId: string, sharedContext?: Context): Promise<void> declineOrderChange(
orderChangeId: string,
sharedContext?: Context
): Promise<void>
/** /**
* This method Represents the completion of an asynchronous operation * This method Represents the completion of an asynchronous operation
* *
* @param {string[]} orderId - The order's ID. * @param {string[]} orderChangeId - The order change's ID.
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
* @returns {Promise<void>} Resolves when {summary} * @returns {Promise<void>} Resolves when {summary}
* *
@@ -1217,7 +1229,10 @@ export interface IOrderModuleService extends IModuleService {
* ``` * ```
* *
*/ */
declineOrderChange(orderId: string[], sharedContext?: Context): Promise<void> declineOrderChange(
orderChangeId: string[],
sharedContext?: Context
): Promise<void>
/** /**
* This method Represents the completion of an asynchronous operation * This method Represents the completion of an asynchronous operation
@@ -1371,4 +1386,22 @@ export interface IOrderModuleService extends IModuleService {
config?: RestoreReturn<TReturnableLinkableKeys>, config?: RestoreReturn<TReturnableLinkableKeys>,
sharedContext?: Context sharedContext?: Context
): Promise<Record<TReturnableLinkableKeys, string[]> | void> ): Promise<Record<TReturnableLinkableKeys, string[]> | void>
revertLastVersion(orderId: string, sharedContext?: Context): Promise<void>
// Bundled flows
registerFulfillment(
data: RegisterOrderFulfillmentDTO,
sharedContext?: Context
): Promise<void>
registerShipment(
data: RegisterOrderShipmentDTO,
sharedContext?: Context
): Promise<void>
createReturn(
returnData: CreateOrderReturnDTO,
sharedContext?: Context
): Promise<void>
} }
+6 -3
View File
@@ -2,13 +2,16 @@ export function trimZeros(value: string) {
const [whole, fraction] = value.split(".") const [whole, fraction] = value.split(".")
if (fraction) { if (fraction) {
const decimal = fraction.replace(/0+$/, "") const exp = fraction.split("e")
const decimal = exp[0].replace(/0+$/, "")
const expStr = exp.length > 1 ? `e${exp[1]}` : ""
if (!decimal) { if (!decimal) {
return whole return whole + expStr
} }
return `${whole}.${decimal}` return `${whole}.${decimal}` + expStr
} }
return whole return whole