feat(medusa): Implement premises of order edit retrieval (#2183)

**What**
- Implements the admin/store retrieval end point 
- Service implementation of the retrieve method
- Service implementation of the computeLineItems method which aggregates the right line item based on the changes that are made
- client
  - medusa-js api
  - medusa-react queries hooks

**Tests**
- Unit tests of the retrieval end points
- Unit tests of the service retrieve method and computeLineItems
- Integration tests for admin/store
- client
  - medusa-js tests
  - medusa-react hooks tests

FIXES CORE-492
This commit is contained in:
Adrien de Peretti
2022-09-15 11:12:20 +02:00
committed by GitHub
parent 3efeb6b84f
commit f863d28b9a
36 changed files with 1317 additions and 2 deletions

View File

@@ -0,0 +1,182 @@
const path = require("path")
const startServerWithEnvironment =
require("../../../helpers/start-server-with-environment").default
const { useApi } = require("../../../helpers/use-api")
const { useDb } = require("../../../helpers/use-db")
const adminSeeder = require("../../helpers/admin-seeder")
const {
simpleOrderEditFactory,
} = require("../../factories/simple-order-edit-factory")
const { IdMap } = require("medusa-test-utils")
const {
simpleOrderItemChangeFactory,
} = require("../../factories/simple-order-item-change-factory")
const {
simpleLineItemFactory,
simpleProductFactory,
simpleOrderFactory,
} = require("../../factories")
const { OrderEditItemChangeType } = require("@medusajs/medusa")
jest.setTimeout(30000)
const adminHeaders = {
headers: {
Authorization: "Bearer test_token",
},
}
describe("[MEDUSA_FF_ORDER_EDITING] /admin/order-edits", () => {
let medusaProcess
let dbConnection
beforeAll(async () => {
const cwd = path.resolve(path.join(__dirname, "..", ".."))
const [process, connection] = await startServerWithEnvironment({
cwd,
env: { MEDUSA_FF_ORDER_EDITING: true },
verbose: false,
})
dbConnection = connection
medusaProcess = process
})
afterAll(async () => {
const db = useDb()
await db.shutdown()
medusaProcess.kill()
})
describe("GET /admin/order-edits/:id", () => {
const orderEditId = IdMap.getId("order-edit-1")
const prodId1 = IdMap.getId("prodId1")
const prodId2 = IdMap.getId("prodId2")
const prodId3 = IdMap.getId("prodId3")
const changeUpdateId = IdMap.getId("order-edit-1-change-update")
const changeCreateId = IdMap.getId("order-edit-1-change-create")
const changeRemoveId = IdMap.getId("order-edit-1-change-remove")
const lineItemId1 = IdMap.getId("line-item-1")
const lineItemId2 = IdMap.getId("line-item-2")
const lineItemCreateId = IdMap.getId("line-item-create")
const lineItemUpdateId = IdMap.getId("line-item-update")
beforeEach(async () => {
await adminSeeder(dbConnection)
const product1 = await simpleProductFactory(dbConnection, {
id: prodId1,
})
const product2 = await simpleProductFactory(dbConnection, {
id: prodId2,
})
const product3 = await simpleProductFactory(dbConnection, {
id: prodId3,
})
const order = await simpleOrderFactory(dbConnection, {
email: "test@testson.com",
tax_rate: null,
fulfillment_status: "fulfilled",
payment_status: "captured",
region: {
id: "test-region",
name: "Test region",
tax_rate: 12.5,
},
line_items: [
{
id: lineItemId1,
variant_id: product1.variants[0].id,
quantity: 1,
fulfilled_quantity: 1,
shipped_quantity: 1,
unit_price: 1000,
},
{
id: lineItemId2,
variant_id: product2.variants[0].id,
quantity: 1,
fulfilled_quantity: 1,
shipped_quantity: 1,
unit_price: 1000,
},
],
})
const orderEdit = await simpleOrderEditFactory(dbConnection, {
id: orderEditId,
order_id: order.id,
created_by: "admin_user",
internal_note: "test internal note",
})
await simpleLineItemFactory(dbConnection, {
id: lineItemUpdateId,
order_id: orderEdit.order_id,
variant_id: product1.variants[0].id,
quantity: 2,
})
await simpleLineItemFactory(dbConnection, {
id: lineItemCreateId,
order_id: orderEdit.order_id,
variant_id: product3.variants[0].id,
quantity: 2,
})
await simpleOrderItemChangeFactory(dbConnection, {
id: changeCreateId,
type: OrderEditItemChangeType.ITEM_ADD,
line_item_id: lineItemCreateId,
order_edit_id: orderEdit.id,
})
await simpleOrderItemChangeFactory(dbConnection, {
id: changeUpdateId,
type: OrderEditItemChangeType.ITEM_UPDATE,
line_item_id: lineItemUpdateId,
original_line_item_id: lineItemId1,
order_edit_id: orderEdit.id,
})
await simpleOrderItemChangeFactory(dbConnection, {
id: changeRemoveId,
type: OrderEditItemChangeType.ITEM_REMOVE,
original_line_item_id: lineItemId2,
order_edit_id: orderEdit.id,
})
})
afterEach(async () => {
const db = useDb()
return await db.teardown()
})
it("gets order edit", async () => {
const api = useApi()
const response = await api.get(
`/admin/order-edits/${orderEditId}`,
adminHeaders
)
expect(response.status).toEqual(200)
expect(response.data.order_edit).toEqual(
expect.objectContaining({
id: orderEditId,
created_by: "admin_user",
requested_by: null,
canceled_by: null,
confirmed_by: null,
internal_note: "test internal note",
items: expect.arrayContaining([
expect.objectContaining({ id: lineItemCreateId, quantity: 2 }),
expect.objectContaining({ id: lineItemId1, quantity: 2 }),
]),
removed_items: expect.arrayContaining([
expect.objectContaining({ id: lineItemId2, quantity: 1 }),
]),
})
)
})
})
})

View File

@@ -0,0 +1,180 @@
const path = require("path")
const startServerWithEnvironment =
require("../../../helpers/start-server-with-environment").default
const { useApi } = require("../../../helpers/use-api")
const { useDb } = require("../../../helpers/use-db")
const adminSeeder = require("../../helpers/admin-seeder")
const {
simpleOrderEditFactory,
} = require("../../factories/simple-order-edit-factory")
const { IdMap } = require("medusa-test-utils")
const {
simpleOrderItemChangeFactory,
} = require("../../factories/simple-order-item-change-factory")
const {
simpleLineItemFactory,
simpleProductFactory,
simpleOrderFactory,
} = require("../../factories")
const { OrderEditItemChangeType } = require("@medusajs/medusa")
jest.setTimeout(30000)
const adminHeaders = {
headers: {
Authorization: "Bearer test_token",
},
}
describe("[MEDUSA_FF_ORDER_EDITING] /store/order-edits", () => {
let medusaProcess
let dbConnection
beforeAll(async () => {
const cwd = path.resolve(path.join(__dirname, "..", ".."))
const [process, connection] = await startServerWithEnvironment({
cwd,
env: { MEDUSA_FF_ORDER_EDITING: true },
verbose: false,
})
dbConnection = connection
medusaProcess = process
})
afterAll(async () => {
const db = useDb()
await db.shutdown()
medusaProcess.kill()
})
describe("GET /store/order-edits/:id", () => {
const orderEditId = IdMap.getId("order-edit-1")
const prodId1 = IdMap.getId("prodId1")
const prodId2 = IdMap.getId("prodId2")
const prodId3 = IdMap.getId("prodId3")
const changeUpdateId = IdMap.getId("order-edit-1-change-update")
const changeCreateId = IdMap.getId("order-edit-1-change-create")
const changeRemoveId = IdMap.getId("order-edit-1-change-remove")
const lineItemId1 = IdMap.getId("line-item-1")
const lineItemId2 = IdMap.getId("line-item-2")
const lineItemCreateId = IdMap.getId("line-item-create")
const lineItemUpdateId = IdMap.getId("line-item-update")
beforeEach(async () => {
await adminSeeder(dbConnection)
const product1 = await simpleProductFactory(dbConnection, {
id: prodId1,
})
const product2 = await simpleProductFactory(dbConnection, {
id: prodId2,
})
const product3 = await simpleProductFactory(dbConnection, {
id: prodId3,
})
const order = await simpleOrderFactory(dbConnection, {
email: "test@testson.com",
tax_rate: null,
fulfillment_status: "fulfilled",
payment_status: "captured",
region: {
id: "test-region",
name: "Test region",
tax_rate: 12.5,
},
line_items: [
{
id: lineItemId1,
variant_id: product1.variants[0].id,
quantity: 1,
fulfilled_quantity: 1,
shipped_quantity: 1,
unit_price: 1000,
},
{
id: lineItemId2,
variant_id: product2.variants[0].id,
quantity: 1,
fulfilled_quantity: 1,
shipped_quantity: 1,
unit_price: 1000,
},
],
})
const orderEdit = await simpleOrderEditFactory(dbConnection, {
id: orderEditId,
order_id: order.id,
created_by: "admin_user",
internal_note: "test internal note",
})
await simpleLineItemFactory(dbConnection, {
id: lineItemUpdateId,
order_id: orderEdit.order_id,
variant_id: product1.variants[0].id,
quantity: 2,
})
await simpleLineItemFactory(dbConnection, {
id: lineItemCreateId,
order_id: orderEdit.order_id,
variant_id: product3.variants[0].id,
quantity: 2,
})
await simpleOrderItemChangeFactory(dbConnection, {
id: changeCreateId,
type: OrderEditItemChangeType.ITEM_ADD,
line_item_id: lineItemCreateId,
order_edit_id: orderEdit.id,
})
await simpleOrderItemChangeFactory(dbConnection, {
id: changeUpdateId,
type: OrderEditItemChangeType.ITEM_UPDATE,
line_item_id: lineItemUpdateId,
original_line_item_id: lineItemId1,
order_edit_id: orderEdit.id,
})
await simpleOrderItemChangeFactory(dbConnection, {
id: changeRemoveId,
type: OrderEditItemChangeType.ITEM_REMOVE,
original_line_item_id: lineItemId2,
order_edit_id: orderEdit.id,
})
})
afterEach(async () => {
const db = useDb()
return await db.teardown()
})
it("gets order edit", async () => {
const api = useApi()
const response = await api.get(`/store/order-edits/${orderEditId}`)
expect(response.status).toEqual(200)
expect(response.data.order_edit).toEqual(
expect.objectContaining({
id: orderEditId,
requested_by: null,
items: expect.arrayContaining([
expect.objectContaining({ id: lineItemCreateId, quantity: 2 }),
expect.objectContaining({ id: lineItemId1, quantity: 2 }),
]),
removed_items: expect.arrayContaining([
expect.objectContaining({ id: lineItemId2, quantity: 1 }),
]),
})
)
expect(response.data.order_edit.internal_note).not.toBeDefined()
expect(response.data.order_edit.created_by).not.toBeDefined()
expect(response.data.order_edit.canceled_by).not.toBeDefined()
expect(response.data.order_edit.confirmed_by).not.toBeDefined()
})
})
})

View File

@@ -0,0 +1,52 @@
import { Connection } from "typeorm"
import { OrderFactoryData, simpleOrderFactory } from "./simple-order-factory"
import { OrderEdit } from "@medusajs/medusa"
export type OrderEditFactoryData = {
id?: string
order?: OrderFactoryData
order_id?: string
internal_note?: string
declined_reason?: string
confirmed_at?: Date | string
confirmed_by?: string
created_at?: Date | string
created_by?: string
requested_at?: Date | string
requested_by?: string
canceled_at?: Date | string
canceled_by?: string
declined_at?: Date | string
declined_by?: string
}
export const simpleOrderEditFactory = async (
connection: Connection,
data: OrderEditFactoryData = {}
): Promise<OrderEdit> => {
const manager = connection.manager
if (!data.order_id) {
const order = await simpleOrderFactory(connection, data.order)
data.order_id = order.id
}
const orderEdit = manager.create<OrderEdit>(OrderEdit, {
id: data.id,
order_id: data.order_id,
internal_note: data.internal_note,
declined_reason: data.declined_reason,
declined_at: data.declined_at,
declined_by: data.declined_by,
canceled_at: data.canceled_at,
canceled_by: data.canceled_by,
requested_at: data.requested_at,
requested_by: data.requested_by,
created_at: data.created_at,
created_by: data.created_by,
confirmed_at: data.confirmed_at,
confirmed_by: data.confirmed_by,
})
return await manager.save<OrderEdit>(orderEdit)
}

View File

@@ -0,0 +1,30 @@
import {
OrderEdit,
OrderEditItemChangeType,
OrderItemChange,
} from "@medusajs/medusa"
import { Connection } from "typeorm"
type OrderItemChangeData = {
id: string
type: OrderEditItemChangeType
order_edit_id: string
original_line_item_id?: string
line_item_id?: string
}
export const simpleOrderItemChangeFactory = async (
connection: Connection,
data: OrderItemChangeData
) => {
const manager = connection.manager
const change = manager.create<OrderItemChange>(OrderItemChange, {
id: data.id,
type: data.type,
order_edit_id: data.order_edit_id,
line_item_id: data.line_item_id,
original_line_item_id: data.original_line_item_id,
})
return await manager.save<OrderItemChange>(change)
}