Skip to content

Commit

Permalink
feat(core-flows,types): cancel order changes workflow (#8035)
Browse files Browse the repository at this point in the history
what:

- adds cancel order changes workflow
  • Loading branch information
riqwan authored Jul 9, 2024
1 parent 101ebbe commit 566bbd5
Show file tree
Hide file tree
Showing 12 changed files with 608 additions and 9 deletions.
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 packages/core/core-flows/src/order/steps/cancel-order-change.ts
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)
}
)
Loading

0 comments on commit 566bbd5

Please sign in to comment.