feat(medusa, medusa-js, medusa-react): Implement item change deletion from an order edit (#2241)

This commit is contained in:
Adrien de Peretti
2022-09-22 11:02:58 +02:00
committed by GitHub
parent eb8034502b
commit 14e808c724
18 changed files with 700 additions and 17 deletions
@@ -520,4 +520,230 @@ describe("[MEDUSA_FF_ORDER_EDITING] /admin/order-edits", () => {
) )
}) })
}) })
describe("DELETE /admin/order-edits/:id/changes/:change_id", () => {
let product
const orderId1 = IdMap.getId("order-id-1")
const orderEditId = IdMap.getId("order-edit-1")
const orderEditId2 = IdMap.getId("order-edit-2")
const prodId1 = IdMap.getId("prodId1")
const lineItemId1 = IdMap.getId("line-item-1")
const changeUpdateId = IdMap.getId("order-id-1-change-1")
const changeUpdateId2 = IdMap.getId("order-id-1-change-2")
const lineItemUpdateId = IdMap.getId("line-item-1-update")
const lineItemUpdateId2 = IdMap.getId("line-item-1-update-2")
beforeEach(async () => {
await adminSeeder(dbConnection)
product = await simpleProductFactory(dbConnection, {
id: prodId1,
})
await simpleOrderFactory(dbConnection, {
id: orderId1,
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: product.variants[0].id,
quantity: 1,
fulfilled_quantity: 1,
shipped_quantity: 1,
unit_price: 1000,
},
],
})
await simpleLineItemFactory(dbConnection, {
id: lineItemUpdateId,
order_id: null,
variant_id: product.variants[0].id,
unit_price: 100,
quantity: 2,
})
await simpleLineItemFactory(dbConnection, {
id: lineItemUpdateId2,
order_id: null,
variant_id: product.variants[0].id,
unit_price: 100,
quantity: 2,
})
})
afterEach(async () => {
const db = useDb()
return await db.teardown()
})
it("deletes an item change from an order edit", async () => {
await simpleLineItemFactory(dbConnection, {
id: lineItemUpdateId,
order_id: null,
variant_id: product.variants[0].id,
unit_price: 100,
quantity: 2,
})
await simpleOrderEditFactory(dbConnection, {
id: orderEditId,
order_id: orderId1,
created_by: "admin_user",
internal_note: "test internal note",
})
await simpleOrderItemChangeFactory(dbConnection, {
id: changeUpdateId,
type: OrderEditItemChangeType.ITEM_UPDATE,
line_item_id: lineItemUpdateId,
original_line_item_id: lineItemId1,
order_edit_id: orderEditId,
})
const api = useApi()
let res = await api.get(`/admin/order-edits/${orderEditId}`, adminHeaders)
expect(res.status).toEqual(200)
expect(res.data.order_edit.changes.length).toBe(1)
res = await api.delete(
`/admin/order-edits/${orderEditId}/changes/${changeUpdateId}`,
adminHeaders
)
expect(res.status).toEqual(200)
expect(res.data).toEqual(
expect.objectContaining({
id: changeUpdateId,
object: "item_change",
deleted: true,
})
)
res = await api.get(`/admin/order-edits/${orderEditId}`, adminHeaders)
expect(res.status).toEqual(200)
expect(res.data.order_edit.changes.length).toBe(0)
})
it("return invalid error if the item change does not belong to the order edit", async () => {
await simpleOrderEditFactory(dbConnection, {
id: orderEditId,
order_id: orderId1,
created_by: "admin_user",
internal_note: "test internal note 2",
})
await simpleOrderItemChangeFactory(dbConnection, {
id: changeUpdateId,
type: OrderEditItemChangeType.ITEM_UPDATE,
line_item_id: lineItemUpdateId,
original_line_item_id: lineItemId1,
order_edit_id: orderEditId,
})
await simpleOrderEditFactory(dbConnection, {
id: orderEditId2,
order_id: orderId1,
created_by: "admin_user",
internal_note: "test internal note 2",
})
await simpleOrderItemChangeFactory(dbConnection, {
id: changeUpdateId2,
type: OrderEditItemChangeType.ITEM_UPDATE,
line_item_id: lineItemUpdateId2,
original_line_item_id: lineItemId1,
order_edit_id: orderEditId2,
})
const api = useApi()
const response = await api
.delete(
`/admin/order-edits/${orderEditId}/changes/${changeUpdateId2}`,
adminHeaders
)
.catch((e) => e)
expect(response.response.status).toEqual(400)
expect(response.response.data.message).toEqual(
`The item change you are trying to delete doesn't belong to the OrderEdit with id: ${orderEditId}.`
)
})
it("return an error if the order edit is confirmed", async () => {
await simpleOrderEditFactory(dbConnection, {
id: orderEditId,
order_id: orderId1,
created_by: "admin_user",
internal_note: "test internal note 3",
confirmed_at: new Date(),
})
await simpleOrderItemChangeFactory(dbConnection, {
id: changeUpdateId,
type: OrderEditItemChangeType.ITEM_UPDATE,
line_item_id: lineItemUpdateId,
original_line_item_id: lineItemId1,
order_edit_id: orderEditId,
})
const api = useApi()
const response = await api
.delete(
`/admin/order-edits/${orderEditId}/changes/${changeUpdateId}`,
adminHeaders
)
.catch((e) => e)
expect(response.response.status).toEqual(400)
expect(response.response.data.message).toEqual(
"Cannot delete and item change from a confirmed order edit"
)
})
it("return an error if the order edit is canceled", async () => {
await simpleOrderEditFactory(dbConnection, {
id: orderEditId,
order_id: orderId1,
created_by: "admin_user",
internal_note: "test internal note 4",
canceled_at: new Date(),
})
await simpleOrderItemChangeFactory(dbConnection, {
id: changeUpdateId,
type: OrderEditItemChangeType.ITEM_UPDATE,
line_item_id: lineItemUpdateId,
original_line_item_id: lineItemId1,
order_edit_id: orderEditId,
})
const api = useApi()
const response = await api
.delete(
`/admin/order-edits/${orderEditId}/changes/${changeUpdateId}`,
adminHeaders
)
.catch((e) => e)
expect(response.response.status).toEqual(400)
expect(response.response.data.message).toEqual(
"Cannot delete and item change from a canceled order edit"
)
})
})
}) })
@@ -1,8 +1,9 @@
import { import {
AdminOrderEditsRes,
AdminPostOrderEditsReq,
AdminOrderEditDeleteRes, AdminOrderEditDeleteRes,
AdminOrderEditItemChangeDeleteRes,
AdminOrderEditsRes,
AdminPostOrderEditsOrderEditReq, AdminPostOrderEditsOrderEditReq,
AdminPostOrderEditsReq,
} from "@medusajs/medusa" } from "@medusajs/medusa"
import { ResponsePromise } from "../../typings" import { ResponsePromise } from "../../typings"
import BaseResource from "../base" import BaseResource from "../base"
@@ -40,6 +41,15 @@ class AdminOrderEditsResource extends BaseResource {
const path = `/admin/order-edits/${id}` const path = `/admin/order-edits/${id}`
return this.client.request("DELETE", path, undefined, {}, customHeaders) return this.client.request("DELETE", path, undefined, {}, customHeaders)
} }
deleteItemChange(
orderEditId: string,
itemChangeId: string,
customHeaders: Record<string, any> = {}
): ResponsePromise<AdminOrderEditItemChangeDeleteRes> {
const path = `/admin/order-edits/${orderEditId}/changes/${itemChangeId}`
return this.client.request("DELETE", path, undefined, {}, customHeaders)
}
} }
export default AdminOrderEditsResource export default AdminOrderEditsResource
+13 -1
View File
@@ -1703,7 +1703,19 @@ export const adminHandlers = [
ctx.json({ ctx.json({
id, id,
object: "order_edit", object: "order_edit",
deleted: true deleted: true,
})
)
}),
rest.delete("/admin/order-edits/:id/changes/:change_id", (req, res, ctx) => {
const { change_id } = req.params
return res(
ctx.status(200),
ctx.json({
id: change_id,
object: "item_change",
deleted: true,
}) })
) )
}), }),
@@ -3,8 +3,9 @@ import { Response } from "@medusajs/medusa-js"
import { import {
AdminOrderEditDeleteRes, AdminOrderEditDeleteRes,
AdminPostOrderEditsOrderEditReq, AdminOrderEditItemChangeDeleteRes,
AdminOrderEditsRes, AdminOrderEditsRes,
AdminPostOrderEditsOrderEditReq,
AdminPostOrderEditsReq, AdminPostOrderEditsReq,
} from "@medusajs/medusa" } from "@medusajs/medusa"
@@ -45,6 +46,28 @@ export const useAdminDeleteOrderEdit = (
) )
} }
export const useAdminDeleteOrderEditItemChange = (
orderEditId: string,
itemChangeId: string,
options?: UseMutationOptions<
Response<AdminOrderEditItemChangeDeleteRes>,
Error,
void
>
) => {
const { client } = useMedusa()
const queryClient = useQueryClient()
return useMutation(
() => client.admin.orderEdits.deleteItemChange(orderEditId, itemChangeId),
buildOptions(
queryClient,
[adminOrderEditsKeys.detail(orderEditId), adminOrderEditsKeys.lists()],
options
)
)
}
export const useAdminUpdateOrderEdit = ( export const useAdminUpdateOrderEdit = (
id: string, id: string,
options?: UseMutationOptions< options?: UseMutationOptions<
@@ -2,13 +2,38 @@ import { renderHook } from "@testing-library/react-hooks"
import { import {
useAdminCreateOrderEdit, useAdminCreateOrderEdit,
useAdminUpdateOrderEdit,
useAdminDeleteOrderEdit, useAdminDeleteOrderEdit,
useAdminDeleteOrderEditItemChange,
useAdminUpdateOrderEdit,
} from "../../../../src/" } from "../../../../src/"
import { fixtures } from "../../../../mocks/data" import { fixtures } from "../../../../mocks/data"
import { fixtures } from "../../../../mocks/data"
import { createWrapper } from "../../../utils" import { createWrapper } from "../../../utils"
describe("useAdminDeleteOrderEditItemChange hook", () => {
test("Deletes an order edit item change", async () => {
const id = "oe_1"
const itemChangeId = "oeic_1"
const { result, waitFor } = renderHook(
() => useAdminDeleteOrderEditItemChange(id, itemChangeId),
{
wrapper: createWrapper(),
}
)
result.current.mutate()
await waitFor(() => result.current.isSuccess)
expect(result.current.data.response.status).toEqual(200)
expect(result.current.data).toEqual(
expect.objectContaining({
id: itemChangeId,
object: "item_change",
deleted: true,
})
)
})
})
describe("useAdminDelete hook", () => { describe("useAdminDelete hook", () => {
test("Deletes an order edit", async () => { test("Deletes an order edit", async () => {
const id = "oe_1" const id = "oe_1"
@@ -0,0 +1,51 @@
import { IdMap } from "medusa-test-utils"
import { request } from "../../../../../helpers/test-request"
import OrderEditingFeatureFlag from "../../../../../loaders/feature-flags/order-editing"
import { orderEditServiceMock } from "../../../../../services/__mocks__/order-edit"
describe("DELETE /admin/order-edits/:id/changes/:change_id", () => {
describe("deletes an order edit item change", () => {
const orderEditId = IdMap.getId("test-order-edit")
const orderEditItemChangeId = IdMap.getId("test-order-edit-item-change")
let subject
beforeAll(async () => {
subject = await request(
"DELETE",
`/admin/order-edits/${orderEditId}/changes/${orderEditItemChangeId}`,
{
adminSession: {
jwt: {
userId: IdMap.getId("admin_user"),
},
},
flags: [OrderEditingFeatureFlag],
}
)
})
afterAll(() => {
jest.clearAllMocks()
})
it("calls orderEditService delete", () => {
expect(orderEditServiceMock.deleteItemChange).toHaveBeenCalledTimes(1)
expect(orderEditServiceMock.deleteItemChange).toHaveBeenCalledWith(
orderEditId,
orderEditItemChangeId
)
})
it("returns 200", () => {
expect(subject.status).toEqual(200)
})
it("returns delete result", () => {
expect(subject.body).toEqual({
id: orderEditItemChangeId,
object: "item_change",
deleted: true,
})
})
})
})
@@ -23,7 +23,7 @@ describe("DELETE /admin/order-edits/:id", () => {
jest.clearAllMocks() jest.clearAllMocks()
}) })
it("calls orderService retrieve", () => { it("calls orderEditService delete", () => {
expect(orderEditServiceMock.delete).toHaveBeenCalledTimes(1) expect(orderEditServiceMock.delete).toHaveBeenCalledTimes(1)
expect(orderEditServiceMock.delete).toHaveBeenCalledWith(orderEditId) expect(orderEditServiceMock.delete).toHaveBeenCalledWith(orderEditId)
}) })
@@ -0,0 +1,74 @@
import { EntityManager } from "typeorm"
import { OrderEditService } from "../../../../services"
/**
* @oas [delete] /order-edits/{id}/changes/{change_id}
* operationId: "DeleteOrderEditsOrderEditItemChange"
* summary: "Delete an Order Edit Item Change"
* description: "Deletes an Order Edit Item Change"
* x-authenticated: true
* parameters:
* - (path) id=* {string} The ID of the Order Edit to delete.
* - (path) change_id=* {string} The ID of the Order Edit Item Change to delete.
* x-codeSamples:
* - lang: JavaScript
* label: JS Client
* source: |
* import Medusa from "@medusajs/medusa-js"
* const medusa = new Medusa({ baseUrl: MEDUSA_BACKEND_URL, maxRetries: 3 })
* // must be previously logged in or use api token
* medusa.admin.orderEdits.deleteItemChange(item_change_id, order_edit_id)
* .then(({ id, object, deleted }) => {
* console.log(id);
* });
* - lang: Shell
* label: cURL
* source: |
* curl --location --request DELETE 'https://medusa-url.com/admin/order-edits/{id}/changes/{change_id}' \
* --header 'Authorization: Bearer {api_token}'
* security:
* - api_token: []
* - cookie_auth: []
* tags:
* - OrderEdit
* responses:
* 200:
* description: OK
* content:
* application/json:
* schema:
* properties:
* id:
* type: string
* description: The ID of the deleted Order Edit Item Change.
* object:
* type: string
* description: The type of the object that was deleted.
* format: item_change
* deleted:
* type: boolean
* description: Whether or not the Order Edit Item Change was deleted.
* default: true
* "400":
* $ref: "#/components/responses/400_error"
*/
export default async (req, res) => {
const { id, change_id } = req.params
const orderEditService: OrderEditService =
req.scope.resolve("orderEditService")
const manager: EntityManager = req.scope.resolve("manager")
await manager.transaction(async (transactionManager) => {
await orderEditService
.withTransaction(transactionManager)
.deleteItemChange(id, change_id)
})
res.status(200).send({
id: change_id,
object: "item_change",
deleted: true,
})
}
@@ -48,6 +48,11 @@ export default (app) => {
route.delete("/:id", middlewares.wrap(require("./delete-order-edit").default)) route.delete("/:id", middlewares.wrap(require("./delete-order-edit").default))
route.delete(
"/:id/changes/:change_id",
middlewares.wrap(require("./delete-order-edit-item-change").default)
)
return app return app
} }
@@ -55,7 +60,11 @@ export type AdminOrderEditsRes = {
order_edit: OrderEdit order_edit: OrderEdit
} }
export type AdminOrderEditDeleteRes = DeleteResponse export type AdminOrderEditDeleteRes = DeleteResponse
export type AdminOrderEditItemChangeDeleteRes = {
id: string
object: "item_change"
deleted: boolean
}
export * from "./update-order-edit" export * from "./update-order-edit"
export * from "./create-order-edit" export * from "./create-order-edit"
@@ -61,6 +61,7 @@ export const LineItemServiceMock = {
metadata, metadata,
}) })
}), }),
delete: jest.fn().mockImplementation(() => Promise.resolve()),
} }
const mock = jest.fn().mockImplementation(() => { const mock = jest.fn().mockImplementation(() => {
@@ -0,0 +1,22 @@
export const orderEditItemChangeServiceMock = {
withTransaction: function () {
return this
},
retrieveItemChangeByOrderEdit: jest
.fn()
.mockImplementation((itemChangeId, orderEditId) => {
return Promise.resolve({
id: itemChangeId,
order_edit_id: orderEditId,
})
}),
delete: jest.fn().mockImplementation(() => {
return Promise.resolve()
}),
}
const mock = jest.fn().mockImplementation(() => {
return orderEditItemChangeServiceMock
})
export default mock
@@ -90,6 +90,9 @@ export const orderEditServiceMock = {
...withLineItems, ...withLineItems,
}) })
}), }),
deleteItemChange: jest.fn().mockImplementation((_) => {
return Promise.resolve()
}),
} }
const mock = jest.fn().mockImplementation(() => { const mock = jest.fn().mockImplementation(() => {
@@ -0,0 +1,68 @@
import { IdMap, MockManager, MockRepository } from "medusa-test-utils"
import {
EventBusService,
LineItemService,
OrderEditItemChangeService,
TaxProviderService,
} from "../index"
import { EventBusServiceMock } from "../__mocks__/event-bus"
import { FindManyOptions, In } from "typeorm"
import { LineItemServiceMock } from "../__mocks__/line-item"
const taxProviderServiceMock = {
withTransaction: function () {
return this
},
clearLineItemsTaxLines: jest.fn().mockImplementation(() => Promise.resolve()),
}
describe("OrderEditItemChangeService", () => {
afterEach(() => {
jest.clearAllMocks()
})
const orderItemChangeRepository = MockRepository({
delete: jest.fn().mockImplementation(() => {
return Promise.resolve()
}),
find: jest.fn().mockImplementation((conditions: FindManyOptions) => {
return Promise.resolve(
conditions.where?.id?.value?.map((id) => ({
id,
line_item_id: "li_" + id,
}))
)
}),
})
const orderEditItemChangeService = new OrderEditItemChangeService({
manager: MockManager,
orderItemChangeRepository,
eventBusService: EventBusServiceMock as unknown as EventBusService,
lineItemService: LineItemServiceMock as unknown as LineItemService,
taxProviderService: taxProviderServiceMock as unknown as TaxProviderService,
})
it("should remove a item change", async () => {
const itemChangeId = IdMap.getId("order-edit-item-change-1")
await orderEditItemChangeService.delete(itemChangeId)
expect(orderItemChangeRepository.delete).toHaveBeenCalledTimes(1)
expect(orderItemChangeRepository.delete).toHaveBeenCalledWith({
id: In([itemChangeId]),
})
expect(taxProviderServiceMock.clearLineItemsTaxLines).toHaveBeenCalledTimes(
1
)
expect(taxProviderServiceMock.clearLineItemsTaxLines).toHaveBeenCalledWith([
"li_" + itemChangeId,
])
expect(EventBusServiceMock.emit).toHaveBeenCalledTimes(1)
expect(EventBusServiceMock.emit).toHaveBeenCalledWith(
OrderEditItemChangeService.Events.DELETED,
{ ids: [itemChangeId] }
)
})
})
@@ -2,6 +2,7 @@ import { IdMap, MockManager, MockRepository } from "medusa-test-utils"
import { import {
EventBusService, EventBusService,
LineItemService, LineItemService,
OrderEditItemChangeService,
OrderEditService, OrderEditService,
OrderService, OrderService,
TotalsService, TotalsService,
@@ -11,6 +12,7 @@ import { OrderServiceMock } from "../__mocks__/order"
import { EventBusServiceMock } from "../__mocks__/event-bus" import { EventBusServiceMock } from "../__mocks__/event-bus"
import { LineItemServiceMock } from "../__mocks__/line-item" import { LineItemServiceMock } from "../__mocks__/line-item"
import { TotalsServiceMock } from "../__mocks__/totals" import { TotalsServiceMock } from "../__mocks__/totals"
import { orderEditItemChangeServiceMock } from "../__mocks__/order-edit-item-change"
const orderEditToUpdate = { const orderEditToUpdate = {
id: IdMap.getId("order-edit-to-update"), id: IdMap.getId("order-edit-to-update"),
@@ -115,6 +117,8 @@ describe("OrderEditService", () => {
eventBusService: EventBusServiceMock as unknown as EventBusService, eventBusService: EventBusServiceMock as unknown as EventBusService,
totalsService: TotalsServiceMock as unknown as TotalsService, totalsService: TotalsServiceMock as unknown as TotalsService,
lineItemService: lineItemServiceMock as unknown as LineItemService, lineItemService: lineItemServiceMock as unknown as LineItemService,
orderEditItemChangeService:
orderEditItemChangeServiceMock as unknown as OrderEditItemChangeService,
}) })
it("should retrieve an order edit and call the repository with the right arguments", async () => { it("should retrieve an order edit and call the repository with the right arguments", async () => {
+1
View File
@@ -22,6 +22,7 @@ export { default as NotificationService } from "./notification"
export { default as OauthService } from "./oauth" export { default as OauthService } from "./oauth"
export { default as OrderService } from "./order" export { default as OrderService } from "./order"
export { default as OrderEditService } from "./order-edit" export { default as OrderEditService } from "./order-edit"
export { default as OrderEditItemChangeService } from "./order-edit-item-change"
export { default as PaymentProviderService } from "./payment-provider" export { default as PaymentProviderService } from "./payment-provider"
export { default as PricingService } from "./pricing" export { default as PricingService } from "./pricing"
export { default as ProductCollectionService } from "./product-collection" export { default as ProductCollectionService } from "./product-collection"
@@ -0,0 +1,108 @@
import { TransactionBaseService } from "../interfaces"
import { OrderItemChangeRepository } from "../repositories/order-item-change"
import { EntityManager, In } from "typeorm"
import { EventBusService, LineItemService } from "./index"
import { FindConfig } from "../types/common"
import { OrderItemChange } from "../models"
import { buildQuery } from "../utils"
import { MedusaError } from "medusa-core-utils"
import TaxProviderService from "./tax-provider"
type InjectedDependencies = {
manager: EntityManager
orderItemChangeRepository: typeof OrderItemChangeRepository
eventBusService: EventBusService
lineItemService: LineItemService
taxProviderService: TaxProviderService
}
export default class OrderEditItemChangeService extends TransactionBaseService {
static readonly Events = {
DELETED: "order-edit-item-change.DELETED",
}
protected manager_: EntityManager
protected transactionManager_: EntityManager | undefined
protected readonly orderItemChangeRepository_: typeof OrderItemChangeRepository
protected readonly eventBus_: EventBusService
protected readonly lineItemService_: LineItemService
protected readonly taxProviderService_: TaxProviderService
constructor({
manager,
orderItemChangeRepository,
eventBusService,
lineItemService,
taxProviderService,
}: InjectedDependencies) {
// @ts-ignore
super(arguments[0])
this.manager_ = manager
this.orderItemChangeRepository_ = orderItemChangeRepository
this.eventBus_ = eventBusService
this.lineItemService_ = lineItemService
this.taxProviderService_ = taxProviderService
}
async retrieve(
id: string,
config: FindConfig<OrderItemChange> = {}
): Promise<OrderItemChange> {
const manager = this.transactionManager_ ?? this.manager_
const orderItemChangeRepo = manager.getCustomRepository(
this.orderItemChangeRepository_
)
const query = buildQuery({ id }, config)
const itemChange = await orderItemChangeRepo.findOne(query)
if (!itemChange) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Order edit item change ${id} was not found`
)
}
return itemChange
}
async delete(itemChangeIds: string | string[]): Promise<void> {
itemChangeIds = Array.isArray(itemChangeIds)
? itemChangeIds
: [itemChangeIds]
return await this.atomicPhase_(async (manager) => {
const orderItemChangeRepo = manager.getCustomRepository(
this.orderItemChangeRepository_
)
const changes = await orderItemChangeRepo.find({
where: {
id: In(itemChangeIds as string[]),
},
})
const lineItemIdsToRemove = changes
.map((change) => {
return change.line_item_id
})
.filter(Boolean) as string[]
await orderItemChangeRepo.delete({ id: In(itemChangeIds as string[]) })
const lineItemServiceTx = this.lineItemService_.withTransaction(manager)
await Promise.all([
...lineItemIdsToRemove.map((id) => lineItemServiceTx.delete(id)),
this.taxProviderService_
.withTransaction(manager)
.clearLineItemsTaxLines(lineItemIdsToRemove),
])
await this.eventBus_
.withTransaction(manager)
.emit(OrderEditItemChangeService.Events.DELETED, { ids: itemChangeIds })
})
}
}
+38 -2
View File
@@ -14,11 +14,11 @@ import { TransactionBaseService } from "../interfaces"
import { import {
EventBusService, EventBusService,
LineItemService, LineItemService,
OrderEditItemChangeService,
OrderService, OrderService,
TotalsService, TotalsService,
} from "./index" } from "./index"
import { CreateOrderEditInput } from "../types/order-edit" import { CreateOrderEditInput, UpdateOrderEditInput } from "../types/order-edit"
import { UpdateOrderEditInput } from "../types/order-edit"
type InjectedDependencies = { type InjectedDependencies = {
manager: EntityManager manager: EntityManager
@@ -27,6 +27,7 @@ type InjectedDependencies = {
eventBusService: EventBusService eventBusService: EventBusService
totalsService: TotalsService totalsService: TotalsService
lineItemService: LineItemService lineItemService: LineItemService
orderEditItemChangeService: OrderEditItemChangeService
} }
export default class OrderEditService extends TransactionBaseService { export default class OrderEditService extends TransactionBaseService {
@@ -43,6 +44,7 @@ export default class OrderEditService extends TransactionBaseService {
protected readonly lineItemService_: LineItemService protected readonly lineItemService_: LineItemService
protected readonly eventBusService_: EventBusService protected readonly eventBusService_: EventBusService
protected readonly totalsService_: TotalsService protected readonly totalsService_: TotalsService
protected readonly orderEditItemChangeService_: OrderEditItemChangeService
constructor({ constructor({
manager, manager,
@@ -51,6 +53,7 @@ export default class OrderEditService extends TransactionBaseService {
lineItemService, lineItemService,
eventBusService, eventBusService,
totalsService, totalsService,
orderEditItemChangeService,
}: InjectedDependencies) { }: InjectedDependencies) {
// eslint-disable-next-line prefer-rest-params // eslint-disable-next-line prefer-rest-params
super(arguments[0]) super(arguments[0])
@@ -61,6 +64,7 @@ export default class OrderEditService extends TransactionBaseService {
this.lineItemService_ = lineItemService this.lineItemService_ = lineItemService
this.eventBusService_ = eventBusService this.eventBusService_ = eventBusService
this.totalsService_ = totalsService this.totalsService_ = totalsService
this.orderEditItemChangeService_ = orderEditItemChangeService
} }
async retrieve( async retrieve(
@@ -382,4 +386,36 @@ export default class OrderEditService extends TransactionBaseService {
return orderEdit return orderEdit
} }
async deleteItemChange(
orderEditId: string,
itemChangeId: string
): Promise<void> {
return await this.atomicPhase_(async (manager) => {
const itemChange = await this.orderEditItemChangeService_.retrieve(
itemChangeId,
{ select: ["id", "order_edit_id"] }
)
const orderEdit = await this.retrieve(orderEditId, {
select: ["id", "confirmed_at", "canceled_at"],
})
if (orderEdit.id !== itemChange.order_edit_id) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`The item change you are trying to delete doesn't belong to the OrderEdit with id: ${orderEditId}.`
)
}
if (orderEdit.confirmed_at !== null || orderEdit.canceled_at !== null) {
throw new MedusaError(
MedusaError.Types.NOT_ALLOWED,
`Cannot delete and item change from a ${orderEdit.status} order edit`
)
}
return await this.orderEditItemChangeService_.delete(itemChangeId)
})
}
} }
+17 -7
View File
@@ -1,19 +1,19 @@
import { MedusaError } from "medusa-core-utils" import { MedusaError } from "medusa-core-utils"
import { AwilixContainer } from "awilix" import { AwilixContainer } from "awilix"
import { EntityManager } from "typeorm" import { EntityManager, In } from "typeorm"
import Redis from "ioredis" import Redis from "ioredis"
import { LineItemTaxLineRepository } from "../repositories/line-item-tax-line" import { LineItemTaxLineRepository } from "../repositories/line-item-tax-line"
import { ShippingMethodTaxLineRepository } from "../repositories/shipping-method-tax-line" import { ShippingMethodTaxLineRepository } from "../repositories/shipping-method-tax-line"
import { TaxProviderRepository } from "../repositories/tax-provider" import { TaxProviderRepository } from "../repositories/tax-provider"
import { import {
LineItemTaxLine,
TaxProvider,
LineItem,
ShippingMethodTaxLine,
ShippingMethod,
Region,
Cart, Cart,
LineItem,
LineItemTaxLine,
Region,
ShippingMethod,
ShippingMethodTaxLine,
TaxProvider,
} from "../models" } from "../models"
import { isCart } from "../types/cart" import { isCart } from "../types/cart"
import { import {
@@ -91,6 +91,16 @@ class TaxProviderService extends TransactionBaseService {
return provider return provider
} }
async clearLineItemsTaxLines(itemIds: string[]): Promise<void> {
return await this.atomicPhase_(async (transactionManager) => {
const taxLineRepo = transactionManager.getCustomRepository(
this.taxLineRepo_
)
await taxLineRepo.delete({ item_id: In(itemIds) })
})
}
async clearTaxLines(cartId: string): Promise<void> { async clearTaxLines(cartId: string): Promise<void> {
return await this.atomicPhase_(async (transactionManager) => { return await this.atomicPhase_(async (transactionManager) => {
const taxLineRepo = transactionManager.getCustomRepository( const taxLineRepo = transactionManager.getCustomRepository(