feat(medusa): Allow custom created_by on order edits (#3007)

This commit is contained in:
Oliver Windall Juhl authored and GitHub committed 2023-01-12 15:47:18 +01:00
1 parent d10ffa8118
commit b80124d32d
14 files changed
+80 -71

No files matched your search

+5
View File
@@ -0,0 +1,5 @@
---
"@medusajs/medusa": patch
---
feat(medusa): Allow custom created_by on order edits
@@ -30,7 +30,7 @@ describe("POST /admin/order-edits/:id/cancel", () => {
it("calls orderService cancel", () => { it("calls orderService cancel", () => {
expect(orderEditServiceMock.cancel).toHaveBeenCalledTimes(1) expect(orderEditServiceMock.cancel).toHaveBeenCalledTimes(1)
expect(orderEditServiceMock.cancel).toHaveBeenCalledWith(orderEditId, { expect(orderEditServiceMock.cancel).toHaveBeenCalledWith(orderEditId, {
loggedInUserId: IdMap.getId("admin_user"), canceledBy: IdMap.getId("admin_user"),
}) })
}) })
@@ -30,7 +30,7 @@ describe("POST /admin/order-edits/:id/confirm", () => {
it("calls orderService confirm", () => { it("calls orderService confirm", () => {
expect(orderEditServiceMock.confirm).toHaveBeenCalledTimes(1) expect(orderEditServiceMock.confirm).toHaveBeenCalledTimes(1)
expect(orderEditServiceMock.confirm).toHaveBeenCalledWith(orderEditId, { expect(orderEditServiceMock.confirm).toHaveBeenCalledWith(orderEditId, {
loggedInUserId: "admin_user", confirmedBy: "admin_user",
}) })
}) })
@@ -1,7 +1,7 @@
import { IdMap } from "medusa-test-utils" import { IdMap } from "medusa-test-utils"
import { request } from "../../../../../helpers/test-request" import { request } from "../../../../../helpers/test-request"
import { orderEditServiceMock } from "../../../../../services/__mocks__/order-edit"
import OrderEditingFeatureFlag from "../../../../../loaders/feature-flags/order-editing" import OrderEditingFeatureFlag from "../../../../../loaders/feature-flags/order-editing"
import { orderEditServiceMock } from "../../../../../services/__mocks__/order-edit"
describe("POST /admin/order-edits", () => { describe("POST /admin/order-edits", () => {
describe("successfully create an order edit", () => { describe("successfully create an order edit", () => {
@@ -41,7 +41,7 @@ describe("POST /admin/order-edits", () => {
internal_note: internalNote, internal_note: internalNote,
}, },
{ {
loggedInUserId: IdMap.getId("admin_user"), createdBy: IdMap.getId("admin_user"),
} }
) )
}) })
@@ -35,7 +35,7 @@ describe("GET /admin/order-edits/:id", () => {
expect(orderEditServiceMock.requestConfirmation).toHaveBeenCalledTimes(1) expect(orderEditServiceMock.requestConfirmation).toHaveBeenCalledTimes(1)
expect(orderEditServiceMock.requestConfirmation).toHaveBeenCalledWith( expect(orderEditServiceMock.requestConfirmation).toHaveBeenCalledWith(
orderEditId, orderEditId,
{ loggedInUserId: IdMap.getId("admin_user") } { requestedBy: IdMap.getId("admin_user") }
) )
expect(orderEditServiceMock.update).toHaveBeenCalledTimes(1) expect(orderEditServiceMock.update).toHaveBeenCalledTimes(1)
@@ -1,9 +1,9 @@
import { Request, Response } from "express" import { Request, Response } from "express"
import { OrderEditService } from "../../../../services"
import { EntityManager } from "typeorm" import { EntityManager } from "typeorm"
import { OrderEditService } from "../../../../services"
import { import {
defaultOrderEditFields, defaultOrderEditFields,
defaultOrderEditRelations, defaultOrderEditRelations
} from "../../../../types/order-edit" } from "../../../../types/order-edit"
/** /**
@@ -68,7 +68,7 @@ export default async (req: Request, res: Response) => {
await manager.transaction(async (transactionManager) => { await manager.transaction(async (transactionManager) => {
await orderEditService await orderEditService
.withTransaction(transactionManager) .withTransaction(transactionManager)
.cancel(id, { loggedInUserId: userId }) .cancel(id, { canceledBy: userId })
}) })
const orderEdit = await orderEditService.retrieve(id, { const orderEdit = await orderEditService.retrieve(id, {
@@ -1,9 +1,9 @@
import { Request, Response } from "express" import { Request, Response } from "express"
import { OrderEditService } from "../../../../services"
import { EntityManager } from "typeorm" import { EntityManager } from "typeorm"
import { OrderEditService } from "../../../../services"
import { import {
defaultOrderEditFields, defaultOrderEditFields,
defaultOrderEditRelations, defaultOrderEditRelations
} from "../../../../types/order-edit" } from "../../../../types/order-edit"
/** /**
@@ -68,7 +68,7 @@ export default async (req: Request, res: Response) => {
await manager.transaction(async (transactionManager) => { await manager.transaction(async (transactionManager) => {
await orderEditService await orderEditService
.withTransaction(transactionManager) .withTransaction(transactionManager)
.confirm(id, { loggedInUserId: userId }) .confirm(id, { confirmedBy: userId })
}) })
let orderEdit = await orderEditService.retrieve(id, { let orderEdit = await orderEditService.retrieve(id, {
@@ -1,10 +1,10 @@
import { Request, Response } from "express"
import { OrderEditService } from "../../../../services"
import { IsOptional, IsString } from "class-validator" import { IsOptional, IsString } from "class-validator"
import { Request, Response } from "express"
import { EntityManager } from "typeorm" import { EntityManager } from "typeorm"
import { OrderEditService } from "../../../../services"
import { import {
defaultOrderEditFields, defaultOrderEditFields,
defaultOrderEditRelations, defaultOrderEditRelations
} from "../../../../types/order-edit" } from "../../../../types/order-edit"
/** /**
@@ -71,13 +71,13 @@ export default async (req: Request, res: Response) => {
const manager = req.scope.resolve("manager") as EntityManager const manager = req.scope.resolve("manager") as EntityManager
const data = req.validatedBody as AdminPostOrderEditsReq const data = req.validatedBody as AdminPostOrderEditsReq
const loggedInUserId = (req.user?.id ?? req.user?.userId) as string const createdBy = (req.user?.id ?? req.user?.userId) as string
const createdOrderEdit = await manager.transaction( const createdOrderEdit = await manager.transaction(
async (transactionManager) => { async (transactionManager) => {
return await orderEditService return await orderEditService
.withTransaction(transactionManager) .withTransaction(transactionManager)
.create(data, { loggedInUserId }) .create(data, { createdBy })
} }
) )
@@ -110,4 +110,8 @@ export class AdminPostOrderEditsReq {
@IsOptional() @IsOptional()
@IsString() @IsString()
internal_note?: string internal_note?: string
@IsOptional()
@IsString()
created_by?: string
} }
@@ -1,15 +1,15 @@
import { EntityManager } from "typeorm"
import { IsOptional, IsString } from "class-validator" import { IsOptional, IsString } from "class-validator"
import { EntityManager } from "typeorm"
import { PaymentCollectionType } from "../../../../models"
import { import {
OrderEditService, OrderEditService,
OrderService, OrderService,
PaymentCollectionService, PaymentCollectionService
} from "../../../../services" } from "../../../../services"
import { import {
defaultOrderEditFields, defaultOrderEditFields,
defaultOrderEditRelations, defaultOrderEditRelations
} from "../../../../types/order-edit" } from "../../../../types/order-edit"
import { PaymentCollectionType } from "../../../../models"
/** /**
* @oas [post] /order-edits/{id}/request * @oas [post] /order-edits/{id}/request
@@ -82,7 +82,7 @@ export default async (req, res) => {
orderEditService.withTransaction(transactionManager) orderEditService.withTransaction(transactionManager)
const orderEdit = await orderEditServiceTx.requestConfirmation(id, { const orderEdit = await orderEditServiceTx.requestConfirmation(id, {
loggedInUserId: loggedInUser, requestedBy: loggedInUser,
}) })
const total = await orderEditServiceTx.getTotals(orderEdit.id) const total = await orderEditServiceTx.getTotals(orderEdit.id)
@@ -1,12 +1,12 @@
import { Request, Response } from "express" import { Request, Response } from "express"
import { MedusaError } from "medusa-core-utils"
import { EntityManager } from "typeorm" import { EntityManager } from "typeorm"
import { OrderEditStatus, PaymentCollectionStatus } from "../../../../models"
import { OrderEditService, PaymentProviderService } from "../../../../services" import { OrderEditService, PaymentProviderService } from "../../../../services"
import { import {
defaultStoreOrderEditFields, defaultStoreOrderEditFields,
defaultStoreOrderEditRelations, defaultStoreOrderEditRelations
} from "../../../../types/order-edit" } from "../../../../types/order-edit"
import { OrderEditStatus, PaymentCollectionStatus } from "../../../../models"
import { MedusaError } from "medusa-core-utils"
/** /**
* @oas [post] /order-edits/{id}/complete * @oas [post] /order-edits/{id}/complete
@@ -111,7 +111,7 @@ export default async (req: Request, res: Response) => {
} }
const returned = await orderEditServiceTx.confirm(id, { const returned = await orderEditServiceTx.confirm(id, {
loggedInUserId: userId, confirmedBy: userId,
}) })
return returned return returned
@@ -4,7 +4,7 @@ import { EntityManager } from "typeorm"
import { OrderEditService } from "../../../../services" import { OrderEditService } from "../../../../services"
import { import {
defaultStoreOrderEditFields, defaultStoreOrderEditFields,
defaultStoreOrderEditRelations, defaultStoreOrderEditRelations
} from "../../../../types/order-edit" } from "../../../../types/order-edit"
/** /**
@@ -70,7 +70,7 @@ export default async (req: Request, res: Response) => {
await manager.transaction(async (manager) => { await manager.transaction(async (manager) => {
await orderEditService.withTransaction(manager).decline(id, { await orderEditService.withTransaction(manager).decline(id, {
declinedReason: validatedBody.declined_reason, declinedReason: validatedBody.declined_reason,
loggedInUserId: userId, declinedBy: userId,
}) })
}) })
+5 -5
View File
@@ -6,14 +6,14 @@ import {
JoinColumn, JoinColumn,
ManyToOne, ManyToOne,
OneToMany, OneToMany,
OneToOne, OneToOne
} from "typeorm" } from "typeorm"
import OrderEditingFeatureFlag from "../loaders/feature-flags/order-editing"
import { FeatureFlagEntity } from "../utils/feature-flag-decorators"
import { resolveDbType } from "../utils/db-aware-column"
import { BaseEntity } from "../interfaces" import { BaseEntity } from "../interfaces"
import OrderEditingFeatureFlag from "../loaders/feature-flags/order-editing"
import { generateEntityId } from "../utils" import { generateEntityId } from "../utils"
import { resolveDbType } from "../utils/db-aware-column"
import { FeatureFlagEntity } from "../utils/feature-flag-decorators"
import { LineItem, Order, OrderItemChange, PaymentCollection } from "." import { LineItem, Order, OrderItemChange, PaymentCollection } from "."
@@ -44,7 +44,7 @@ export class OrderEdit extends BaseEntity {
internal_note?: string internal_note?: string
@Column() @Column()
created_by: string // customer or user ID created_by: string // customer, user, third party, etc.
@Column({ nullable: true }) @Column({ nullable: true })
requested_by?: string // customer or user ID requested_by?: string // customer or user ID
@@ -1,4 +1,5 @@
import { IdMap, MockManager, MockRepository } from "medusa-test-utils" import { IdMap, MockManager, MockRepository } from "medusa-test-utils"
import { OrderEditItemChangeType, OrderEditStatus } from "../../models"
import { import {
EventBusService, EventBusService,
LineItemService, LineItemService,
@@ -6,17 +7,16 @@ import {
OrderEditService, OrderEditService,
OrderService, OrderService,
TaxProviderService, TaxProviderService,
TotalsService, TotalsService
} from "../index" } from "../index"
import { OrderEditItemChangeType, OrderEditStatus } from "../../models" import LineItemAdjustmentService from "../line-item-adjustment"
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 { LineItemAdjustmentServiceMock } from "../__mocks__/line-item-adjustment"
import { OrderServiceMock } from "../__mocks__/order"
import { orderEditItemChangeServiceMock } from "../__mocks__/order-edit-item-change" import { orderEditItemChangeServiceMock } from "../__mocks__/order-edit-item-change"
import { taxProviderServiceMock } from "../__mocks__/tax-provider" import { taxProviderServiceMock } from "../__mocks__/tax-provider"
import { LineItemAdjustmentServiceMock } from "../__mocks__/line-item-adjustment" import { TotalsServiceMock } from "../__mocks__/totals"
import LineItemAdjustmentService from "../line-item-adjustment"
const orderEditToUpdate = { const orderEditToUpdate = {
id: IdMap.getId("order-edit-to-update"), id: IdMap.getId("order-edit-to-update"),
@@ -223,7 +223,7 @@ describe("OrderEditService", () => {
internal_note: "internal note", internal_note: "internal note",
} }
await orderEditService.create(data, { await orderEditService.create(data, {
loggedInUserId: IdMap.getId("admin_user"), createdBy: IdMap.getId("admin_user"),
}) })
expect(orderEditRepository.create).toHaveBeenCalledTimes(1) expect(orderEditRepository.create).toHaveBeenCalledTimes(1)
@@ -261,7 +261,7 @@ describe("OrderEditService", () => {
IdMap.getId("requested-order-edit"), IdMap.getId("requested-order-edit"),
{ {
declinedReason: "I requested a different color for the new product", declinedReason: "I requested a different color for the new product",
loggedInUserId: "admin_user", declinedBy: "admin_user",
} }
) )
@@ -279,7 +279,7 @@ describe("OrderEditService", () => {
await expect( await expect(
orderEditService.decline(IdMap.getId("confirmed-order-edit"), { orderEditService.decline(IdMap.getId("confirmed-order-edit"), {
declinedReason: "I requested a different color for the new product", declinedReason: "I requested a different color for the new product",
loggedInUserId: "admin_user", declinedBy: "admin_user",
}) })
).rejects.toThrowError( ).rejects.toThrowError(
"Cannot decline an order edit with status confirmed." "Cannot decline an order edit with status confirmed."
@@ -291,7 +291,7 @@ describe("OrderEditService", () => {
IdMap.getId("declined-order-edit"), IdMap.getId("declined-order-edit"),
{ {
declinedReason: "I requested a different color for the new product", declinedReason: "I requested a different color for the new product",
loggedInUserId: "admin_user", declinedBy: "admin_user",
} }
) )
@@ -335,7 +335,7 @@ describe("OrderEditService", () => {
} as any) } as any)
result = await orderEditService.requestConfirmation(orderEditId, { result = await orderEditService.requestConfirmation(orderEditId, {
loggedInUserId: userId, requestedBy: userId,
}) })
}) })
@@ -367,7 +367,7 @@ describe("OrderEditService", () => {
beforeEach(async () => { beforeEach(async () => {
result = await orderEditService.requestConfirmation(orderEditId, { result = await orderEditService.requestConfirmation(orderEditId, {
loggedInUserId: userId, requestedBy: userId,
}) })
}) })
@@ -381,7 +381,7 @@ describe("OrderEditService", () => {
const id = IdMap.getId("order-edit-with-changes") const id = IdMap.getId("order-edit-with-changes")
const userId = IdMap.getId("user-id") const userId = IdMap.getId("user-id")
await orderEditService.cancel(id, { loggedInUserId: userId }) await orderEditService.cancel(id, { canceledBy: userId })
expect(orderEditRepository.save).toHaveBeenCalledWith({ expect(orderEditRepository.save).toHaveBeenCalledWith({
...orderEditWithChanges, ...orderEditWithChanges,
@@ -401,7 +401,7 @@ describe("OrderEditService", () => {
const userId = IdMap.getId("user-id") const userId = IdMap.getId("user-id")
const result = await orderEditService.cancel(id, { const result = await orderEditService.cancel(id, {
loggedInUserId: userId, canceledBy: userId,
}) })
expect(result).toEqual(expect.objectContaining({ status: "canceled" })) expect(result).toEqual(expect.objectContaining({ status: "canceled" }))
@@ -418,7 +418,7 @@ describe("OrderEditService", () => {
const userId = IdMap.getId("user-id") const userId = IdMap.getId("user-id")
try { try {
await orderEditService.cancel(id, { loggedInUserId: userId }) await orderEditService.cancel(id, { canceledBy: userId })
} catch (err) { } catch (err) {
expect(err.message).toEqual( expect(err.message).toEqual(
`Cannot cancel order edit with status ${status}` `Cannot cancel order edit with status ${status}`
@@ -433,7 +433,7 @@ describe("OrderEditService", () => {
const id = IdMap.getId("order-edit-with-changes") const id = IdMap.getId("order-edit-with-changes")
const userId = IdMap.getId("user-id") const userId = IdMap.getId("user-id")
await orderEditService.confirm(id, { loggedInUserId: userId }) await orderEditService.confirm(id, { confirmedBy: userId })
expect(orderEditRepository.save).toHaveBeenCalledWith({ expect(orderEditRepository.save).toHaveBeenCalledWith({
...orderEditWithChanges, ...orderEditWithChanges,
@@ -453,7 +453,7 @@ describe("OrderEditService", () => {
const userId = IdMap.getId("user-id") const userId = IdMap.getId("user-id")
const result = await orderEditService.confirm(id, { const result = await orderEditService.confirm(id, {
loggedInUserId: userId, confirmedBy: userId,
}) })
expect(result).toEqual(expect.objectContaining({ status: "confirmed" })) expect(result).toEqual(expect.objectContaining({ status: "confirmed" }))
+22 -22
View File
@@ -1,17 +1,21 @@
import { DeepPartial, EntityManager, ILike, IsNull } from "typeorm"
import { isDefined, MedusaError } from "medusa-core-utils" import { isDefined, MedusaError } from "medusa-core-utils"
import { DeepPartial, EntityManager, ILike, IsNull } from "typeorm"
import { FindConfig, Selector } from "../types/common" import { TransactionBaseService } from "../interfaces"
import { buildQuery, isString } from "../utils"
import { OrderEditRepository } from "../repositories/order-edit"
import { import {
Cart, Cart,
Order, Order,
OrderEdit, OrderEdit,
OrderEditItemChangeType, OrderEditItemChangeType,
OrderEditStatus, OrderEditStatus
} from "../models" } from "../models"
import { TransactionBaseService } from "../interfaces" import { OrderEditRepository } from "../repositories/order-edit"
import { FindConfig, Selector } from "../types/common"
import {
AddOrderEditLineItemInput,
CreateOrderEditInput
} from "../types/order-edit"
import { buildQuery, isString } from "../utils"
import { import {
EventBusService, EventBusService,
LineItemAdjustmentService, LineItemAdjustmentService,
@@ -19,12 +23,8 @@ import {
OrderEditItemChangeService, OrderEditItemChangeService,
OrderService, OrderService,
TaxProviderService, TaxProviderService,
TotalsService, TotalsService
} from "./index" } from "./index"
import {
AddOrderEditLineItemInput,
CreateOrderEditInput,
} from "../types/order-edit"
type InjectedDependencies = { type InjectedDependencies = {
manager: EntityManager manager: EntityManager
@@ -213,7 +213,7 @@ export default class OrderEditService extends TransactionBaseService {
async create( async create(
data: CreateOrderEditInput, data: CreateOrderEditInput,
context: { loggedInUserId: string } context: { createdBy: string }
): Promise<OrderEdit> { ): Promise<OrderEdit> {
return await this.atomicPhase_(async (transactionManager) => { return await this.atomicPhase_(async (transactionManager) => {
const activeOrderEdit = await this.retrieveActive(data.order_id) const activeOrderEdit = await this.retrieveActive(data.order_id)
@@ -231,7 +231,7 @@ export default class OrderEditService extends TransactionBaseService {
const orderEditToCreate = orderEditRepository.create({ const orderEditToCreate = orderEditRepository.create({
order_id: data.order_id, order_id: data.order_id,
internal_note: data.internal_note, internal_note: data.internal_note,
created_by: context.loggedInUserId, created_by: context.createdBy,
}) })
const orderEdit = await orderEditRepository.save(orderEditToCreate) const orderEdit = await orderEditRepository.save(orderEditToCreate)
@@ -317,7 +317,7 @@ export default class OrderEditService extends TransactionBaseService {
orderEditId: string, orderEditId: string,
context: { context: {
declinedReason?: string declinedReason?: string
loggedInUserId?: string declinedBy?: string
} }
): Promise<OrderEdit> { ): Promise<OrderEdit> {
return await this.atomicPhase_(async (manager) => { return await this.atomicPhase_(async (manager) => {
@@ -325,7 +325,7 @@ export default class OrderEditService extends TransactionBaseService {
this.orderEditRepository_ this.orderEditRepository_
) )
const { loggedInUserId, declinedReason } = context const { declinedBy, declinedReason } = context
const orderEdit = await this.retrieve(orderEditId) const orderEdit = await this.retrieve(orderEditId)
@@ -341,7 +341,7 @@ export default class OrderEditService extends TransactionBaseService {
} }
orderEdit.declined_at = new Date() orderEdit.declined_at = new Date()
orderEdit.declined_by = loggedInUserId orderEdit.declined_by = declinedBy
orderEdit.declined_reason = declinedReason orderEdit.declined_reason = declinedReason
const result = await orderEditRepo.save(orderEdit) const result = await orderEditRepo.save(orderEdit)
@@ -658,7 +658,7 @@ export default class OrderEditService extends TransactionBaseService {
async requestConfirmation( async requestConfirmation(
orderEditId: string, orderEditId: string,
context: { context: {
loggedInUserId?: string requestedBy?: string
} = {} } = {}
): Promise<OrderEdit> { ): Promise<OrderEdit> {
return await this.atomicPhase_(async (manager) => { return await this.atomicPhase_(async (manager) => {
@@ -683,7 +683,7 @@ export default class OrderEditService extends TransactionBaseService {
} }
orderEdit.requested_at = new Date() orderEdit.requested_at = new Date()
orderEdit.requested_by = context.loggedInUserId orderEdit.requested_by = context.requestedBy
orderEdit = await orderEditRepo.save(orderEdit) orderEdit = await orderEditRepo.save(orderEdit)
@@ -697,7 +697,7 @@ export default class OrderEditService extends TransactionBaseService {
async cancel( async cancel(
orderEditId: string, orderEditId: string,
context: { loggedInUserId?: string } = {} context: { canceledBy?: string } = {}
): Promise<OrderEdit> { ): Promise<OrderEdit> {
return await this.atomicPhase_(async (manager) => { return await this.atomicPhase_(async (manager) => {
const orderEditRepository = manager.getCustomRepository( const orderEditRepository = manager.getCustomRepository(
@@ -722,7 +722,7 @@ export default class OrderEditService extends TransactionBaseService {
} }
orderEdit.canceled_at = new Date() orderEdit.canceled_at = new Date()
orderEdit.canceled_by = context.loggedInUserId orderEdit.canceled_by = context.canceledBy
const saved = await orderEditRepository.save(orderEdit) const saved = await orderEditRepository.save(orderEdit)
@@ -736,7 +736,7 @@ export default class OrderEditService extends TransactionBaseService {
async confirm( async confirm(
orderEditId: string, orderEditId: string,
context: { loggedInUserId?: string } = {} context: { confirmedBy?: string } = {}
): Promise<OrderEdit> { ): Promise<OrderEdit> {
return await this.atomicPhase_(async (manager) => { return await this.atomicPhase_(async (manager) => {
const orderEditRepository = manager.getCustomRepository( const orderEditRepository = manager.getCustomRepository(
@@ -774,7 +774,7 @@ export default class OrderEditService extends TransactionBaseService {
]) ])
orderEdit.confirmed_at = new Date() orderEdit.confirmed_at = new Date()
orderEdit.confirmed_by = context.loggedInUserId orderEdit.confirmed_by = context.confirmedBy
orderEdit = await orderEditRepository.save(orderEdit) orderEdit = await orderEditRepository.save(orderEdit)