-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(core-flows,types): cancel order changes workflow (#8035)
what: - adds cancel order changes workflow
- Loading branch information
Showing
12 changed files
with
608 additions
and
9 deletions.
There are no files selected for viewing
319 changes: 319 additions & 0 deletions
319
integration-tests/modules/__tests__/order/workflows/order-change.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,319 @@ | ||
import { | ||
cancelOrderChangeWorkflow, | ||
cancelOrderChangeWorkflowId, | ||
createOrderChangeWorkflow, | ||
declineOrderChangeWorkflow, | ||
declineOrderChangeWorkflowId, | ||
deleteOrderChangeWorkflow, | ||
deleteOrderChangeWorkflowId, | ||
} from "@medusajs/core-flows" | ||
import { IOrderModuleService, OrderChangeDTO, OrderDTO } from "@medusajs/types" | ||
import { ModuleRegistrationName } from "@medusajs/utils" | ||
import { medusaIntegrationTestRunner } from "medusa-test-utils" | ||
import { createOrderFixture, prepareDataFixtures } from "./__fixtures__" | ||
|
||
jest.setTimeout(50000) | ||
|
||
medusaIntegrationTestRunner({ | ||
env: { MEDUSA_FF_MEDUSA_V2: true }, | ||
testSuite: ({ getContainer }) => { | ||
let container | ||
|
||
beforeAll(() => { | ||
container = getContainer() | ||
}) | ||
|
||
describe("Order change workflows", () => { | ||
let order: OrderDTO | ||
let service: IOrderModuleService | ||
|
||
describe("createOrderChangeWorkflow", () => { | ||
beforeEach(async () => { | ||
const fixtures = await prepareDataFixtures({ | ||
container, | ||
}) | ||
|
||
order = await createOrderFixture({ | ||
container, | ||
product: fixtures.product, | ||
location: fixtures.location, | ||
inventoryItem: fixtures.inventoryItem, | ||
}) | ||
}) | ||
|
||
it("should successfully create an order change", async () => { | ||
const { result } = await createOrderChangeWorkflow(container).run({ | ||
input: { | ||
order_id: order.id, | ||
}, | ||
}) | ||
|
||
expect(result).toEqual( | ||
expect.objectContaining({ | ||
id: expect.any(String), | ||
order_id: order.id, | ||
}) | ||
) | ||
}) | ||
|
||
it("should throw an error when creating an order change when an active one already exists", async () => { | ||
await createOrderChangeWorkflow(container).run({ | ||
input: { | ||
order_id: order.id, | ||
}, | ||
}) | ||
|
||
const { | ||
errors: [error], | ||
} = await createOrderChangeWorkflow(container).run({ | ||
input: { | ||
order_id: order.id, | ||
}, | ||
throwOnError: false, | ||
}) | ||
|
||
expect(error.error).toEqual( | ||
expect.objectContaining({ | ||
message: `Order (${order.id}) already has an existing active order change`, | ||
}) | ||
) | ||
}) | ||
}) | ||
|
||
describe("cancelOrderChangeWorkflow", () => { | ||
let orderChange: OrderChangeDTO | ||
|
||
beforeEach(async () => { | ||
const fixtures = await prepareDataFixtures({ | ||
container, | ||
}) | ||
|
||
order = await createOrderFixture({ | ||
container, | ||
product: fixtures.product, | ||
location: fixtures.location, | ||
inventoryItem: fixtures.inventoryItem, | ||
}) | ||
|
||
const { result } = await createOrderChangeWorkflow(container).run({ | ||
input: { order_id: order.id }, | ||
}) | ||
|
||
orderChange = result | ||
service = container.resolve(ModuleRegistrationName.ORDER) | ||
}) | ||
|
||
it("should successfully cancel an order change", async () => { | ||
await cancelOrderChangeWorkflow(container).run({ | ||
input: { | ||
id: orderChange.id, | ||
canceled_by: "test", | ||
}, | ||
}) | ||
|
||
const orderChange2 = await service.retrieveOrderChange(orderChange.id) | ||
|
||
expect(orderChange2).toEqual( | ||
expect.objectContaining({ | ||
id: expect.any(String), | ||
canceled_by: "test", | ||
canceled_at: expect.any(Date), | ||
}) | ||
) | ||
}) | ||
|
||
it("should rollback to its original state when step throws error", async () => { | ||
const workflow = cancelOrderChangeWorkflow(container) | ||
|
||
workflow.appendAction("throw", cancelOrderChangeWorkflowId, { | ||
invoke: async function failStep() { | ||
throw new Error(`Fail`) | ||
}, | ||
}) | ||
|
||
const { | ||
errors: [error], | ||
} = await workflow.run({ | ||
input: { | ||
id: orderChange.id, | ||
canceled_by: "test", | ||
}, | ||
throwOnError: false, | ||
}) | ||
|
||
expect(error.error).toEqual( | ||
expect.objectContaining({ | ||
message: `Fail`, | ||
}) | ||
) | ||
|
||
const orderChange2 = await service.retrieveOrderChange(orderChange.id) | ||
|
||
expect(orderChange2).toEqual( | ||
expect.objectContaining({ | ||
id: expect.any(String), | ||
canceled_by: null, | ||
canceled_at: null, | ||
}) | ||
) | ||
}) | ||
}) | ||
|
||
describe("deleteOrderChangeWorkflow", () => { | ||
let orderChange: OrderChangeDTO | ||
|
||
beforeEach(async () => { | ||
const fixtures = await prepareDataFixtures({ | ||
container, | ||
}) | ||
|
||
order = await createOrderFixture({ | ||
container, | ||
product: fixtures.product, | ||
location: fixtures.location, | ||
inventoryItem: fixtures.inventoryItem, | ||
}) | ||
|
||
const { result } = await createOrderChangeWorkflow(container).run({ | ||
input: { order_id: order.id }, | ||
}) | ||
|
||
orderChange = result | ||
service = container.resolve(ModuleRegistrationName.ORDER) | ||
}) | ||
|
||
it("should successfully delete an order change", async () => { | ||
await deleteOrderChangeWorkflow(container).run({ | ||
input: { id: orderChange.id }, | ||
}) | ||
|
||
const orderChange2 = await service.retrieveOrderChange( | ||
orderChange.id, | ||
{ withDeleted: true } | ||
) | ||
|
||
expect(orderChange2).toEqual( | ||
expect.objectContaining({ | ||
id: orderChange.id, | ||
deleted_at: expect.any(Date), | ||
}) | ||
) | ||
}) | ||
|
||
it("should rollback to its original state when step throws error", async () => { | ||
const workflow = deleteOrderChangeWorkflow(container) | ||
|
||
workflow.appendAction("throw", deleteOrderChangeWorkflowId, { | ||
invoke: async function failStep() { | ||
throw new Error(`Fail`) | ||
}, | ||
}) | ||
|
||
const { | ||
errors: [error], | ||
} = await workflow.run({ | ||
input: { id: orderChange.id }, | ||
throwOnError: false, | ||
}) | ||
|
||
expect(error.error).toEqual( | ||
expect.objectContaining({ | ||
message: `Fail`, | ||
}) | ||
) | ||
|
||
const orderChange2 = await service.retrieveOrderChange( | ||
orderChange.id, | ||
{ withDeleted: true } | ||
) | ||
|
||
expect(orderChange2).toEqual( | ||
expect.objectContaining({ | ||
id: orderChange.id, | ||
deleted_at: null, | ||
}) | ||
) | ||
}) | ||
}) | ||
|
||
describe("declineOrderChangeWorkflow", () => { | ||
let orderChange: OrderChangeDTO | ||
|
||
beforeEach(async () => { | ||
const fixtures = await prepareDataFixtures({ | ||
container, | ||
}) | ||
|
||
order = await createOrderFixture({ | ||
container, | ||
product: fixtures.product, | ||
location: fixtures.location, | ||
inventoryItem: fixtures.inventoryItem, | ||
}) | ||
|
||
const { result } = await createOrderChangeWorkflow(container).run({ | ||
input: { order_id: order.id }, | ||
}) | ||
|
||
orderChange = result | ||
service = container.resolve(ModuleRegistrationName.ORDER) | ||
}) | ||
|
||
it("should successfully decline an order change", async () => { | ||
await declineOrderChangeWorkflow(container).run({ | ||
input: { | ||
id: orderChange.id, | ||
declined_by: "test", | ||
}, | ||
}) | ||
|
||
const orderChange2 = await service.retrieveOrderChange(orderChange.id) | ||
|
||
expect(orderChange2).toEqual( | ||
expect.objectContaining({ | ||
id: expect.any(String), | ||
declined_by: "test", | ||
declined_at: expect.any(Date), | ||
}) | ||
) | ||
}) | ||
|
||
it("should rollback to its original state when step throws error", async () => { | ||
const workflow = declineOrderChangeWorkflow(container) | ||
|
||
workflow.appendAction("throw", declineOrderChangeWorkflowId, { | ||
invoke: async function failStep() { | ||
throw new Error(`Fail`) | ||
}, | ||
}) | ||
|
||
const { | ||
errors: [error], | ||
} = await workflow.run({ | ||
input: { | ||
id: orderChange.id, | ||
declined_by: "test", | ||
}, | ||
throwOnError: false, | ||
}) | ||
|
||
expect(error.error).toEqual( | ||
expect.objectContaining({ | ||
message: `Fail`, | ||
}) | ||
) | ||
|
||
const orderChange2 = await service.retrieveOrderChange(orderChange.id) | ||
|
||
expect(orderChange2).toEqual( | ||
expect.objectContaining({ | ||
id: expect.any(String), | ||
declined_by: null, | ||
declined_at: null, | ||
}) | ||
) | ||
}) | ||
}) | ||
}) | ||
}, | ||
}) |
45 changes: 45 additions & 0 deletions
45
packages/core/core-flows/src/order/steps/cancel-order-change.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { | ||
CancelOrderChangeDTO, | ||
IOrderModuleService, | ||
UpdateOrderChangeDTO, | ||
} from "@medusajs/types" | ||
import { | ||
getSelectsAndRelationsFromObjectArray, | ||
ModuleRegistrationName, | ||
} from "@medusajs/utils" | ||
import { createStep, StepResponse } from "@medusajs/workflows-sdk" | ||
|
||
export const cancelOrderChangeStepId = "cancel-order-change" | ||
export const cancelOrderChangeStep = createStep( | ||
cancelOrderChangeStepId, | ||
async (data: CancelOrderChangeDTO, { container }) => { | ||
const service = container.resolve<IOrderModuleService>( | ||
ModuleRegistrationName.ORDER | ||
) | ||
|
||
const { selects, relations } = getSelectsAndRelationsFromObjectArray( | ||
[data], | ||
{ objectFields: ["metadata"] } | ||
) | ||
|
||
const dataBeforeUpdate = await service.retrieveOrderChange(data.id, { | ||
select: [...selects, "canceled_at"], | ||
relations, | ||
}) | ||
|
||
await service.cancelOrderChange(data) | ||
|
||
return new StepResponse(void 0, dataBeforeUpdate) | ||
}, | ||
async (rollbackData, { container }) => { | ||
if (!rollbackData) { | ||
return | ||
} | ||
|
||
const service = container.resolve<IOrderModuleService>( | ||
ModuleRegistrationName.ORDER | ||
) | ||
|
||
await service.updateOrderChanges(rollbackData as UpdateOrderChangeDTO) | ||
} | ||
) |
Oops, something went wrong.