fix(medusa): Cancel order missing refunds relation (#2976)

**What**

The order cancelation does not include the refunds relation. It means that the check of the length of the refund is never true and therefore no errors are thrown if the order contains the refunds.

**How**

Add the refunds relation and tests

FIXES CORE-976

Co-authored-by: Oliver Windall Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
Adrien de PerettiandOliver Windall Juhl authored and GitHub committed 2023-01-10 09:38:59 +00:00
1 parent 47d075351f
commit 1817b810fc
5 files changed
+84 -40

No files matched your search

+5
View File
@@ -0,0 +1,5 @@
---
"@medusajs/medusa": patch
---
fix(medusa): Cancel order missing refunds relation
@@ -288,6 +288,48 @@ describe("/admin/orders", () => {
await db.teardown() await db.teardown()
}) })
it("cancels an order with refund should fail", async () => {
const api = useApi()
const refundOrder = await simpleOrderFactory(dbConnection, {
id: "refunded-order",
customer_id: "test-customer",
email: "test@email.com",
fulfillment_status: "not_fulfilled",
payment_status: "refunded",
billing_address: {
id: "test-billing-address",
first_name: "lebron",
},
shipping_address: {
id: "test-shipping-address",
first_name: "lebron",
country_code: "us",
},
region_id: "test-region",
currency_code: "usd",
tax_rate: 0,
discounts: [],
payments: [],
items: [],
refunds: [
{
amount: 1000,
reason: "return",
},
],
})
const err = await api
.post(`/admin/orders/${refundOrder.id}/cancel`, {}, adminReqConfig)
.catch((e) => e)
expect(err.response.status).toEqual(400)
expect(err.response.data.message).toEqual(
"Order with refund(s) cannot be canceled"
)
})
it("cancels an order and increments inventory_quantity", async () => { it("cancels an order and increments inventory_quantity", async () => {
const api = useApi() const api = useApi()
@@ -1,36 +1,13 @@
import { Connection } from "typeorm" import { Connection } from "typeorm"
import faker from "faker" import faker from "faker"
import { import { Discount, FulfillmentStatus, Order, PaymentStatus, Refund, } from "@medusajs/medusa"
Customer, import { DiscountFactoryData, simpleDiscountFactory, } from "./simple-discount-factory"
Order,
PaymentStatus,
FulfillmentStatus,
} from "@medusajs/medusa"
import {
DiscountFactoryData,
simpleDiscountFactory,
} from "./simple-discount-factory"
import { RegionFactoryData, simpleRegionFactory } from "./simple-region-factory" import { RegionFactoryData, simpleRegionFactory } from "./simple-region-factory"
import { import { LineItemFactoryData, simpleLineItemFactory, } from "./simple-line-item-factory"
LineItemFactoryData, import { AddressFactoryData, simpleAddressFactory, } from "./simple-address-factory"
simpleLineItemFactory, import { ShippingMethodFactoryData, simpleShippingMethodFactory, } from "./simple-shipping-method-factory"
} from "./simple-line-item-factory" import { SalesChannelFactoryData, simpleSalesChannelFactory, } from "./simple-sales-channel-factory"
import { import { CustomerFactoryData, simpleCustomerFactory, } from "./simple-customer-factory"
AddressFactoryData,
simpleAddressFactory,
} from "./simple-address-factory"
import {
ShippingMethodFactoryData,
simpleShippingMethodFactory,
} from "./simple-shipping-method-factory"
import {
SalesChannelFactoryData,
simpleSalesChannelFactory,
} from "./simple-sales-channel-factory"
import {
CustomerFactoryData,
simpleCustomerFactory,
} from "./simple-customer-factory"
export type OrderFactoryData = { export type OrderFactoryData = {
id?: string id?: string
@@ -46,11 +23,12 @@ export type OrderFactoryData = {
shipping_address?: AddressFactoryData shipping_address?: AddressFactoryData
shipping_methods?: ShippingMethodFactoryData[] shipping_methods?: ShippingMethodFactoryData[]
sales_channel?: SalesChannelFactoryData sales_channel?: SalesChannelFactoryData
refunds: Refund[]
} }
export const simpleOrderFactory = async ( export const simpleOrderFactory = async (
connection: Connection, connection: Connection,
data: OrderFactoryData = {}, data: OrderFactoryData = {} as OrderFactoryData,
seed?: number seed?: number
): Promise<Order> => { ): Promise<Order> => {
if (typeof seed !== "undefined") { if (typeof seed !== "undefined") {
@@ -63,13 +41,13 @@ export const simpleOrderFactory = async (
let regionId: string let regionId: string
let taxRate: number let taxRate: number
if (typeof data.region === "string") { if (typeof data.region === "string") {
currencyCode = data.currency_code currencyCode = data.currency_code as string
regionId = data.region regionId = data.region
taxRate = data.tax_rate taxRate = data.tax_rate as number
} else { } else {
const region = await simpleRegionFactory(connection, data.region) const region = await simpleRegionFactory(connection, data.region)
taxRate = taxRate =
typeof data.tax_rate !== "undefined" ? data.tax_rate : region.tax_rate (typeof data.tax_rate !== "undefined" ? data.tax_rate : region.tax_rate) as number
currencyCode = region.currency_code currencyCode = region.currency_code
regionId = region.id regionId = region.id
} }
@@ -80,7 +58,7 @@ export const simpleOrderFactory = async (
email: data.email ?? undefined, email: data.email ?? undefined,
}) })
let discounts = [] let discounts: Discount[] = []
if (typeof data.discounts !== "undefined") { if (typeof data.discounts !== "undefined") {
discounts = await Promise.all( discounts = await Promise.all(
data.discounts.map((d) => simpleDiscountFactory(connection, d, seed)) data.discounts.map((d) => simpleDiscountFactory(connection, d, seed))
@@ -109,6 +87,7 @@ export const simpleOrderFactory = async (
tax_rate: taxRate, tax_rate: taxRate,
shipping_address_id: address.id, shipping_address_id: address.id,
sales_channel_id: sales_channel?.id ?? null, sales_channel_id: sales_channel?.id ?? null,
refunds: data.refunds ?? []
}) })
const order = await manager.save(toSave) const order = await manager.save(toSave)
@@ -131,7 +110,7 @@ export const simpleOrderFactory = async (
}) || [] }) || []
for (const item of items) { for (const item of items) {
await simpleLineItemFactory(connection, { ...item, order_id: id }) await simpleLineItemFactory(connection, { ...item, order_id: id } as unknown as LineItemFactoryData)
} }
return order return order
@@ -647,6 +647,17 @@ describe("OrderService", () => {
payment_status: "paid", payment_status: "paid",
status: "pending", status: "pending",
}) })
case IdMap.getId("refunded-order"):
return Promise.resolve({
fulfillment_status: "fulfilled",
payment_status: "refunded",
refunds: [
{
order_id: IdMap.getId("refunded-order"),
},
],
status: "pending",
})
default: default:
return Promise.resolve({ return Promise.resolve({
fulfillment_status: "not_fulfilled", fulfillment_status: "not_fulfilled",
@@ -729,6 +740,12 @@ describe("OrderService", () => {
], ],
}) })
}) })
it("fails if order has refunds", async () => {
await expect(
orderService.cancel(IdMap.getId("refunded-order"))
).rejects.toThrow("Order with refund(s) cannot be canceled")
})
}) })
describe("capturePayment", () => { describe("capturePayment", () => {
+5 -4
View File
@@ -37,18 +37,18 @@ import {
DiscountService, DiscountService,
DraftOrderService, DraftOrderService,
EventBusService, EventBusService,
FulfillmentService,
FulfillmentProviderService, FulfillmentProviderService,
FulfillmentService,
GiftCardService, GiftCardService,
ProductVariantInventoryService,
LineItemService, LineItemService,
NewTotalsService,
PaymentProviderService, PaymentProviderService,
ProductVariantInventoryService,
RegionService, RegionService,
ShippingOptionService, ShippingOptionService,
ShippingProfileService, ShippingProfileService,
TotalsService,
NewTotalsService,
TaxProviderService, TaxProviderService,
TotalsService,
} from "." } from "."
export const ORDER_CART_ALREADY_EXISTS_ERROR = "Order from cart already exists" export const ORDER_CART_ALREADY_EXISTS_ERROR = "Order from cart already exists"
@@ -1102,6 +1102,7 @@ class OrderService extends TransactionBaseService {
return await this.atomicPhase_(async (manager) => { return await this.atomicPhase_(async (manager) => {
const order = await this.retrieve(orderId, { const order = await this.retrieve(orderId, {
relations: [ relations: [
"refunds",
"fulfillments", "fulfillments",
"payments", "payments",
"returns", "returns",