Feat/decline order edit (#2234)

**What**
- Decline an order edit from a store endpoint
- Refactor totals setting to a service method

Fixes CORE-502
This commit is contained in:
Philip Korsholm
2022-09-21 13:02:10 +02:00
committed by GitHub
parent de85a971c6
commit c661cc789b
17 changed files with 486 additions and 67 deletions
@@ -33,7 +33,7 @@ describe("GET /admin/order-edits/:id", () => {
select: defaultOrderEditFields,
relations: defaultOrderEditRelations,
})
expect(orderEditServiceMock.computeLineItems).toHaveBeenCalledTimes(1)
expect(orderEditServiceMock.decorateLineItemsAndTotals).toHaveBeenCalledTimes(1)
})
it("returns order", () => {
@@ -67,20 +67,7 @@ export default async (req: Request, res: Response) => {
orderEditService.withTransaction(transactionManager)
const orderEdit = await orderEditServiceTx.create(data, { loggedInUserId })
const { items } = await orderEditServiceTx.computeLineItems(orderEdit.id)
orderEdit.items = items
orderEdit.removed_items = []
const totals = await orderEditServiceTx.getTotals(orderEdit.id)
orderEdit.discount_total = totals.discount_total
orderEdit.gift_card_total = totals.gift_card_total
orderEdit.gift_card_tax_total = totals.gift_card_tax_total
orderEdit.shipping_total = totals.shipping_total
orderEdit.subtotal = totals.subtotal
orderEdit.tax_total = totals.tax_total
orderEdit.total = totals.total
return orderEdit
return await orderEditServiceTx.decorateLineItemsAndTotals(orderEdit)
})
return res.json({ order_edit: orderEdit })
@@ -59,20 +59,9 @@ export default async (req: Request, res: Response) => {
const { id } = req.params
const retrieveConfig = req.retrieveConfig
const orderEdit = await orderEditService.retrieve(id, retrieveConfig)
let orderEdit = await orderEditService.retrieve(id, retrieveConfig)
const { items, removedItems } = await orderEditService.computeLineItems(id)
orderEdit.items = items
orderEdit.removed_items = removedItems
const totals = await orderEditService.getTotals(orderEdit.id)
orderEdit.discount_total = totals.discount_total
orderEdit.gift_card_total = totals.gift_card_total
orderEdit.gift_card_tax_total = totals.gift_card_tax_total
orderEdit.shipping_total = totals.shipping_total
orderEdit.subtotal = totals.subtotal
orderEdit.tax_total = totals.tax_total
orderEdit.total = totals.total
orderEdit = await orderEditService.decorateLineItemsAndTotals(orderEdit)
return res.json({ order_edit: orderEdit })
}
@@ -0,0 +1,41 @@
import { IdMap } from "medusa-test-utils"
import { request } from "../../../../../helpers/test-request"
import { orderEditServiceMock } from "../../../../../services/__mocks__/order-edit"
import OrderEditingFeatureFlag from "../../../../../loaders/feature-flags/order-editing"
import {
defaultOrderEditFields,
defaultOrderEditRelations,
} from "../../../../../types/order-edit"
import { storeOrderEditNotAllowedFields } from "../index"
describe("GET /store/order-edits/:id", () => {
describe("successfully gets an order edit", () => {
const orderEditId = IdMap.getId("testDeclineOrderEdit")
let subject
const payload = {
declined_reason: "test",
}
beforeAll(async () => {
subject = await request("POST", `/store/order-edits/${orderEditId}/decline`, {
payload,
flags: [OrderEditingFeatureFlag],
})
})
afterAll(() => {
jest.clearAllMocks()
})
it("calls orderService decline", () => {
expect(orderEditServiceMock.decline).toHaveBeenCalledTimes(1)
expect(orderEditServiceMock.decline).toHaveBeenCalledWith(orderEditId, { declinedReason: "test", loggedInUser: undefined})
expect(orderEditServiceMock.decorateLineItemsAndTotals).toHaveBeenCalledTimes(1)
})
it("returns orderEdit", () => {
expect(subject.body.order_edit.id).toEqual(orderEditId)
})
})
})
@@ -33,7 +33,7 @@ describe("GET /store/order-edits/:id", () => {
(field) => !storeOrderEditNotAllowedFields.includes(field)
),
})
expect(orderEditServiceMock.computeLineItems).toHaveBeenCalledTimes(1)
expect(orderEditServiceMock.decorateLineItemsAndTotals).toHaveBeenCalledTimes(1)
})
it("returns order", () => {
@@ -0,0 +1,85 @@
import { IsOptional, IsString } from "class-validator"
import { Request, Response } from "express"
import { EntityManager } from "typeorm"
import { OrderEditService } from "../../../../services"
/**
* @oas [post] /order-edits/{id}/decline
* operationId: "PostOrderEditsOrderEditDecline"
* summary: "Decline an OrderEdit"
* description: "Declines an OrderEdit."
* parameters:
* - (path) id=* {string} The ID of the OrderEdit.
* requestBody:
* content:
* application/json:
* schema:
* properties:
* declined_reason:
* type: string
* description: The reason for declining the OrderEdit.
* x-codeSamples:
* - lang: JavaScript
* label: JS Client
* source: |
* import Medusa from "@medusajs/medusa-js"
* const medusa = new Medusa({ baseUrl: MEDUSA_BACKEND_URL, maxRetries: 3 })
* medusa.orderEdit.decline(orderEditId)
* .then(({ order_edit }) => {
* console.log(order_edit.id);
* })
* - lang: Shell
* label: cURL
* source: |
* curl --location --request POST 'https://medusa-url.com/store/order-edits/{id}/decline'
* tags:
* - OrderEdit
* responses:
* 200:
* description: OK
* content:
* application/json:
* schema:
* properties:
* order_edit:
* $ref: "#/components/schemas/order_edit"
* "400":
* $ref: "#/components/responses/400_error"
* "401":
* $ref: "#/components/responses/unauthorized"
* "404":
* $ref: "#/components/responses/not_found_error"
* "500":
* $ref: "#/components/responses/500_error"
*/
export default async (req: Request, res: Response) => {
const { id } = req.params
const { validatedBody } = req as {
validatedBody: StorePostOrderEditsOrderEditDecline
}
const orderEditService: OrderEditService =
req.scope.resolve("orderEditService")
const manager: EntityManager = req.scope.resolve("manager")
const userId = req.user?.customer_id ?? req.user?.id ?? req.user?.userId
await manager.transaction(async (manager) => {
await orderEditService.withTransaction(manager).decline(id, {
declinedReason: validatedBody.declined_reason,
loggedInUser: userId,
})
})
let orderEdit = await orderEditService.retrieve(id)
orderEdit = await orderEditService.decorateLineItemsAndTotals(orderEdit)
res.status(200).json({ order_edit: orderEdit })
}
export class StorePostOrderEditsOrderEditDecline {
@IsOptional()
@IsString()
declined_reason?: string
}
@@ -53,20 +53,9 @@ export default async (req: Request, res: Response) => {
const { id } = req.params
const retrieveConfig = req.retrieveConfig
const orderEdit = await orderEditService.retrieve(id, retrieveConfig)
let orderEdit = await orderEditService.retrieve(id, retrieveConfig)
const { items, removedItems } = await orderEditService.computeLineItems(id)
orderEdit.items = items
orderEdit.removed_items = removedItems
const totals = await orderEditService.getTotals(orderEdit.id)
orderEdit.discount_total = totals.discount_total
orderEdit.gift_card_total = totals.gift_card_total
orderEdit.gift_card_tax_total = totals.gift_card_tax_total
orderEdit.shipping_total = totals.shipping_total
orderEdit.subtotal = totals.subtotal
orderEdit.tax_total = totals.tax_total
orderEdit.total = totals.total
orderEdit = await orderEditService.decorateLineItemsAndTotals(orderEdit)
return res.json({ order_edit: orderEdit })
}
@@ -1,5 +1,8 @@
import { Router } from "express"
import middlewares, { transformQuery } from "../../../middlewares"
import middlewares, {
transformBody,
transformQuery,
} from "../../../middlewares"
import { EmptyQueryParams } from "../../../../types/common"
import { isFeatureFlagEnabled } from "../../../middlewares/feature-flag-enabled"
import OrderEditingFeatureFlag from "../../../../loaders/feature-flags/order-editing"
@@ -8,6 +11,7 @@ import {
defaultOrderEditRelations,
} from "../../../../types/order-edit"
import { OrderEdit } from "../../../../models"
import { StorePostOrderEditsOrderEditDecline } from "./decline-order-edit"
const route = Router()
@@ -33,6 +37,12 @@ export default (app) => {
middlewares.wrap(require("./get-order-edit").default)
)
route.post(
"/:id/decline",
transformBody(StorePostOrderEditsOrderEditDecline),
middlewares.wrap(require("./decline-order-edit").default)
)
return app
}
@@ -43,6 +53,8 @@ export type StoreOrderEditsRes = {
>
}
export * from "./decline-order-edit"
export const storeOrderEditNotAllowedFields = [
"internal_note",
"created_by",