feat(medusa): Migrate Return service to ts (#1926)
This commit is contained in:
1 parent
d617e21bf5
commit
844d7d1f5f
7 files changed
+283
-208
No files matched your search
@@ -1,8 +1,3 @@
|
|||||||
import {
|
|
||||||
EventBusService,
|
|
||||||
OrderService,
|
|
||||||
ReturnService,
|
|
||||||
} from "../../../../services"
|
|
||||||
import {
|
import {
|
||||||
IsArray,
|
IsArray,
|
||||||
IsBoolean,
|
IsBoolean,
|
||||||
@@ -12,13 +7,19 @@ import {
|
|||||||
ValidateNested,
|
ValidateNested,
|
||||||
} from "class-validator"
|
} from "class-validator"
|
||||||
import { defaultAdminOrdersFields, defaultAdminOrdersRelations } from "."
|
import { defaultAdminOrdersFields, defaultAdminOrdersRelations } from "."
|
||||||
|
import {
|
||||||
|
EventBusService,
|
||||||
|
OrderService,
|
||||||
|
ReturnService,
|
||||||
|
} from "../../../../services"
|
||||||
|
|
||||||
import { MedusaError } from "medusa-core-utils"
|
|
||||||
import { OrdersReturnItem } from "../../../../types/orders"
|
|
||||||
import { Type } from "class-transformer"
|
import { Type } from "class-transformer"
|
||||||
import { validator } from "../../../../utils/validator"
|
import { MedusaError } from "medusa-core-utils"
|
||||||
import { EntityManager } from "typeorm"
|
import { EntityManager } from "typeorm"
|
||||||
|
import { Order, Return } from "../../../../models"
|
||||||
|
import { OrdersReturnItem } from "../../../../types/orders"
|
||||||
import { isDefined } from "../../../../utils"
|
import { isDefined } from "../../../../utils"
|
||||||
|
import { validator } from "../../../../utils/validator"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @oas [post] /orders/{id}/return
|
* @oas [post] /orders/{id}/return
|
||||||
@@ -197,7 +198,7 @@ export default async (req, res) => {
|
|||||||
const { key, error } = await idempotencyKeyService
|
const { key, error } = await idempotencyKeyService
|
||||||
.withTransaction(transactionManager)
|
.withTransaction(transactionManager)
|
||||||
.workStage(idempotencyKey.idempotency_key, async (manager) => {
|
.workStage(idempotencyKey.idempotency_key, async (manager) => {
|
||||||
let order = await orderService
|
let order: Order | Return = await orderService
|
||||||
.withTransaction(manager)
|
.withTransaction(manager)
|
||||||
.retrieve(id, { relations: ["returns"] })
|
.retrieve(id, { relations: ["returns"] })
|
||||||
|
|
||||||
@@ -206,22 +207,24 @@ export default async (req, res) => {
|
|||||||
* and register it as received.
|
* and register it as received.
|
||||||
*/
|
*/
|
||||||
if (value.receive_now) {
|
if (value.receive_now) {
|
||||||
let ret = await returnService.withTransaction(manager).list({
|
const returns = await returnService
|
||||||
|
.withTransaction(manager)
|
||||||
|
.list({
|
||||||
idempotency_key: idempotencyKey.idempotency_key,
|
idempotency_key: idempotencyKey.idempotency_key,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!ret.length) {
|
if (!returns.length) {
|
||||||
throw new MedusaError(
|
throw new MedusaError(
|
||||||
MedusaError.Types.INVALID_DATA,
|
MedusaError.Types.INVALID_DATA,
|
||||||
`Return not found`
|
`Return not found`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ret[0]
|
const returnOrder = returns[0]
|
||||||
|
|
||||||
order = await returnService
|
order = await returnService
|
||||||
.withTransaction(manager)
|
.withTransaction(manager)
|
||||||
.receive(ret.id, value.items, value.refund)
|
.receive(returnOrder.id, value.items, value.refund)
|
||||||
}
|
}
|
||||||
|
|
||||||
order = await orderService
|
order = await orderService
|
||||||
@@ -278,7 +281,7 @@ export default async (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ReturnObj = {
|
type ReturnObj = {
|
||||||
order_id?: string
|
order_id: string
|
||||||
idempotency_key?: string
|
idempotency_key?: string
|
||||||
items?: OrdersReturnItem[]
|
items?: OrdersReturnItem[]
|
||||||
shipping_method?: ReturnShipping
|
shipping_method?: ReturnShipping
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import { IsNumber, IsOptional } from "class-validator"
|
|||||||
import { ReturnService } from "../../../../services"
|
import { ReturnService } from "../../../../services"
|
||||||
import { Type } from "class-transformer"
|
import { Type } from "class-transformer"
|
||||||
import { validator } from "../../../../utils/validator"
|
import { validator } from "../../../../utils/validator"
|
||||||
|
import { FindConfig } from "../../../../types/common"
|
||||||
|
import { Return } from "../../../../models"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @oas [get] /returns
|
* @oas [get] /returns
|
||||||
@@ -47,7 +49,7 @@ export default async (req, res) => {
|
|||||||
skip: validated.offset,
|
skip: validated.offset,
|
||||||
take: validated.limit,
|
take: validated.limit,
|
||||||
order: { created_at: "DESC" },
|
order: { created_at: "DESC" },
|
||||||
}
|
} as FindConfig<Return>
|
||||||
|
|
||||||
const returns = await returnService.list(selector, { ...listConfig })
|
const returns = await returnService.list(selector, { ...listConfig })
|
||||||
|
|
||||||
|
|||||||
@@ -8,14 +8,14 @@ import {
|
|||||||
ValidateNested,
|
ValidateNested,
|
||||||
} from "class-validator"
|
} from "class-validator"
|
||||||
|
|
||||||
|
import { Type } from "class-transformer"
|
||||||
|
import { MedusaError } from "medusa-core-utils"
|
||||||
|
import { EntityManager } from "typeorm"
|
||||||
import EventBusService from "../../../../services/event-bus"
|
import EventBusService from "../../../../services/event-bus"
|
||||||
import IdempotencyKeyService from "../../../../services/idempotency-key"
|
import IdempotencyKeyService from "../../../../services/idempotency-key"
|
||||||
import { MedusaError } from "medusa-core-utils"
|
|
||||||
import OrderService from "../../../../services/order"
|
import OrderService from "../../../../services/order"
|
||||||
import ReturnService from "../../../../services/return"
|
import ReturnService from "../../../../services/return"
|
||||||
import { Type } from "class-transformer"
|
|
||||||
import { validator } from "../../../../utils/validator"
|
import { validator } from "../../../../utils/validator"
|
||||||
import { EntityManager } from "typeorm";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @oas [post] /returns
|
* @oas [post] /returns
|
||||||
@@ -87,12 +87,9 @@ export default async (req, res) => {
|
|||||||
let idempotencyKey
|
let idempotencyKey
|
||||||
try {
|
try {
|
||||||
await manager.transaction(async (transactionManager) => {
|
await manager.transaction(async (transactionManager) => {
|
||||||
idempotencyKey = await idempotencyKeyService.withTransaction(transactionManager).initializeRequest(
|
idempotencyKey = await idempotencyKeyService
|
||||||
headerKey,
|
.withTransaction(transactionManager)
|
||||||
req.method,
|
.initializeRequest(headerKey, req.method, req.params, req.path)
|
||||||
req.params,
|
|
||||||
req.path
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(409).send("Failed to create idempotency key")
|
res.status(409).send("Failed to create idempotency key")
|
||||||
@@ -116,9 +113,7 @@ export default async (req, res) => {
|
|||||||
await manager.transaction(async (transactionManager) => {
|
await manager.transaction(async (transactionManager) => {
|
||||||
const { key, error } = await idempotencyKeyService
|
const { key, error } = await idempotencyKeyService
|
||||||
.withTransaction(transactionManager)
|
.withTransaction(transactionManager)
|
||||||
.workStage(
|
.workStage(idempotencyKey.idempotency_key, async (manager) => {
|
||||||
idempotencyKey.idempotency_key,
|
|
||||||
async (manager) => {
|
|
||||||
const order = await orderService
|
const order = await orderService
|
||||||
.withTransaction(manager)
|
.withTransaction(manager)
|
||||||
.retrieve(returnDto.order_id, {
|
.retrieve(returnDto.order_id, {
|
||||||
@@ -156,8 +151,7 @@ export default async (req, res) => {
|
|||||||
return {
|
return {
|
||||||
recovery_point: "return_requested",
|
recovery_point: "return_requested",
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
)
|
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
inProgress = false
|
inProgress = false
|
||||||
@@ -173,10 +167,10 @@ export default async (req, res) => {
|
|||||||
await manager.transaction(async (transactionManager) => {
|
await manager.transaction(async (transactionManager) => {
|
||||||
const { key, error } = await idempotencyKeyService
|
const { key, error } = await idempotencyKeyService
|
||||||
.withTransaction(transactionManager)
|
.withTransaction(transactionManager)
|
||||||
.workStage(
|
.workStage(idempotencyKey.idempotency_key, async (manager) => {
|
||||||
idempotencyKey.idempotency_key,
|
const returnOrders = await returnService
|
||||||
async (manager) => {
|
.withTransaction(manager)
|
||||||
let ret = await returnService.withTransaction(manager).list(
|
.list(
|
||||||
{
|
{
|
||||||
idempotency_key: idempotencyKey.idempotency_key,
|
idempotency_key: idempotencyKey.idempotency_key,
|
||||||
},
|
},
|
||||||
@@ -184,20 +178,19 @@ export default async (req, res) => {
|
|||||||
relations: ["items", "items.reason"],
|
relations: ["items", "items.reason"],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if (!ret.length) {
|
if (!returnOrders.length) {
|
||||||
throw new MedusaError(
|
throw new MedusaError(
|
||||||
MedusaError.Types.INVALID_DATA,
|
MedusaError.Types.INVALID_DATA,
|
||||||
`Return not found`
|
`Return not found`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ret = ret[0]
|
const returnOrder = returnOrders[0]
|
||||||
|
|
||||||
return {
|
return {
|
||||||
response_code: 200,
|
response_code: 200,
|
||||||
response_body: { return: ret },
|
response_body: { return: returnOrder },
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
)
|
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
inProgress = false
|
inProgress = false
|
||||||
@@ -218,14 +211,11 @@ export default async (req, res) => {
|
|||||||
await manager.transaction(async (transactionManager) => {
|
await manager.transaction(async (transactionManager) => {
|
||||||
idempotencyKey = await idempotencyKeyService
|
idempotencyKey = await idempotencyKeyService
|
||||||
.withTransaction(transactionManager)
|
.withTransaction(transactionManager)
|
||||||
.update(
|
.update(idempotencyKey.idempotency_key, {
|
||||||
idempotencyKey.idempotency_key,
|
|
||||||
{
|
|
||||||
recovery_point: "finished",
|
recovery_point: "finished",
|
||||||
response_code: 500,
|
response_code: 500,
|
||||||
response_body: { message: "Unknown recovery point" },
|
response_body: { message: "Unknown recovery point" },
|
||||||
}
|
})
|
||||||
)
|
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
ClaimType,
|
ClaimType,
|
||||||
FulfillmentItem,
|
FulfillmentItem,
|
||||||
LineItem,
|
LineItem,
|
||||||
|
ReturnItem,
|
||||||
} from "../models"
|
} from "../models"
|
||||||
import { ClaimRepository } from "../repositories/claim"
|
import { ClaimRepository } from "../repositories/claim"
|
||||||
import { DeepPartial, EntityManager } from "typeorm"
|
import { DeepPartial, EntityManager } from "typeorm"
|
||||||
@@ -425,11 +426,14 @@ export default class ClaimService extends TransactionBaseService {
|
|||||||
await this.returnService_.withTransaction(transactionManager).create({
|
await this.returnService_.withTransaction(transactionManager).create({
|
||||||
order_id: order.id,
|
order_id: order.id,
|
||||||
claim_order_id: result.id,
|
claim_order_id: result.id,
|
||||||
items: claim_items.map((ci) => ({
|
items: claim_items.map(
|
||||||
|
(ci) =>
|
||||||
|
({
|
||||||
item_id: ci.item_id,
|
item_id: ci.item_id,
|
||||||
quantity: ci.quantity,
|
quantity: ci.quantity,
|
||||||
metadata: (ci as any).metadata,
|
metadata: (ci as any).metadata,
|
||||||
})),
|
} as ReturnItem)
|
||||||
|
),
|
||||||
shipping_method: return_shipping,
|
shipping_method: return_shipping,
|
||||||
no_notification: evaluatedNoNotification,
|
no_notification: evaluatedNoNotification,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import { LineItem } from "../models/line-item"
|
|||||||
import LineItemAdjustmentService from "./line-item-adjustment"
|
import LineItemAdjustmentService from "./line-item-adjustment"
|
||||||
import { Cart } from "../models/cart"
|
import { Cart } from "../models/cart"
|
||||||
import { LineItemAdjustment } from "../models/line-item-adjustment"
|
import { LineItemAdjustment } from "../models/line-item-adjustment"
|
||||||
|
import { FindConfig } from "../types/common"
|
||||||
|
|
||||||
type InjectedDependencies = {
|
type InjectedDependencies = {
|
||||||
manager: EntityManager
|
manager: EntityManager
|
||||||
@@ -89,7 +90,11 @@ class LineItemService extends BaseService {
|
|||||||
|
|
||||||
async list(
|
async list(
|
||||||
selector,
|
selector,
|
||||||
config = { skip: 0, take: 50, order: { created_at: "DESC" } }
|
config: FindConfig<LineItem> = {
|
||||||
|
skip: 0,
|
||||||
|
take: 50,
|
||||||
|
order: { created_at: "DESC" },
|
||||||
|
}
|
||||||
): Promise<LineItem[]> {
|
): Promise<LineItem[]> {
|
||||||
const manager = this.manager_
|
const manager = this.manager_
|
||||||
const lineItemRepo = manager.getCustomRepository(this.lineItemRepository_)
|
const lineItemRepo = manager.getCustomRepository(this.lineItemRepository_)
|
||||||
|
|||||||
@@ -1,12 +1,66 @@
|
|||||||
|
import { isDefined } from "class-validator"
|
||||||
import { MedusaError } from "medusa-core-utils"
|
import { MedusaError } from "medusa-core-utils"
|
||||||
import { BaseService } from "medusa-interfaces"
|
import { DeepPartial, EntityManager } from "typeorm"
|
||||||
import { isDefined } from "../utils"
|
import { TransactionBaseService } from "../interfaces"
|
||||||
|
import {
|
||||||
|
FulfillmentStatus,
|
||||||
|
LineItem,
|
||||||
|
Order,
|
||||||
|
PaymentStatus,
|
||||||
|
Return,
|
||||||
|
ReturnItem,
|
||||||
|
ReturnStatus,
|
||||||
|
} from "../models"
|
||||||
|
import { ReturnRepository } from "../repositories/return"
|
||||||
|
import { ReturnItemRepository } from "../repositories/return-item"
|
||||||
|
import { FindConfig, Selector } from "../types/common"
|
||||||
|
import { OrdersReturnItem } from "../types/orders"
|
||||||
|
import { CreateReturnInput, UpdateReturnInput } from "../types/return"
|
||||||
|
import { buildQuery, setMetadata } from "../utils"
|
||||||
|
import FulfillmentProviderService from "./fulfillment-provider"
|
||||||
|
import InventoryService from "./inventory"
|
||||||
|
import LineItemService from "./line-item"
|
||||||
|
import OrderService from "./order"
|
||||||
|
import ReturnReasonService from "./return-reason"
|
||||||
|
import ShippingOptionService from "./shipping-option"
|
||||||
|
import TaxProviderService from "./tax-provider"
|
||||||
|
import TotalsService from "./totals"
|
||||||
|
|
||||||
|
type InjectedDependencies = {
|
||||||
|
manager: EntityManager
|
||||||
|
totalsService: TotalsService
|
||||||
|
lineItemService: LineItemService
|
||||||
|
returnRepository: typeof ReturnRepository
|
||||||
|
returnItemRepository: typeof ReturnItemRepository
|
||||||
|
shippingOptionService: ShippingOptionService
|
||||||
|
returnReasonService: ReturnReasonService
|
||||||
|
taxProviderService: TaxProviderService
|
||||||
|
fulfillmentProviderService: FulfillmentProviderService
|
||||||
|
inventoryService: InventoryService
|
||||||
|
orderService: OrderService
|
||||||
|
}
|
||||||
|
|
||||||
|
type Transformer = (
|
||||||
|
item?: LineItem,
|
||||||
|
quantity?: number,
|
||||||
|
additional?: OrdersReturnItem
|
||||||
|
) => Promise<DeepPartial<LineItem>> | DeepPartial<LineItem>
|
||||||
|
|
||||||
|
class ReturnService extends TransactionBaseService {
|
||||||
|
protected manager_: EntityManager
|
||||||
|
protected transactionManager_: EntityManager | undefined
|
||||||
|
|
||||||
|
protected readonly totalsService_: TotalsService
|
||||||
|
protected readonly returnRepository_: typeof ReturnRepository
|
||||||
|
protected readonly returnItemRepository_: typeof ReturnItemRepository
|
||||||
|
protected readonly lineItemService_: LineItemService
|
||||||
|
protected readonly taxProviderService_: TaxProviderService
|
||||||
|
protected readonly shippingOptionService_: ShippingOptionService
|
||||||
|
protected readonly fulfillmentProviderService_: FulfillmentProviderService
|
||||||
|
protected readonly returnReasonService_: ReturnReasonService
|
||||||
|
protected readonly inventoryService_: InventoryService
|
||||||
|
protected readonly orderService_: OrderService
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles Returns
|
|
||||||
* @extends BaseService
|
|
||||||
*/
|
|
||||||
class ReturnService extends BaseService {
|
|
||||||
constructor({
|
constructor({
|
||||||
manager,
|
manager,
|
||||||
totalsService,
|
totalsService,
|
||||||
@@ -19,75 +73,54 @@ class ReturnService extends BaseService {
|
|||||||
fulfillmentProviderService,
|
fulfillmentProviderService,
|
||||||
inventoryService,
|
inventoryService,
|
||||||
orderService,
|
orderService,
|
||||||
}) {
|
}: InjectedDependencies) {
|
||||||
super()
|
super({
|
||||||
|
manager,
|
||||||
/** @private @const {EntityManager} */
|
totalsService,
|
||||||
this.manager_ = manager
|
lineItemService,
|
||||||
|
returnRepository,
|
||||||
/** @private @const {TotalsService} */
|
returnItemRepository,
|
||||||
this.totalsService_ = totalsService
|
shippingOptionService,
|
||||||
|
returnReasonService,
|
||||||
/** @private @const {ReturnRepository} */
|
taxProviderService,
|
||||||
this.returnRepository_ = returnRepository
|
fulfillmentProviderService,
|
||||||
|
inventoryService,
|
||||||
/** @private @const {ReturnItemRepository} */
|
orderService,
|
||||||
this.returnItemRepository_ = returnItemRepository
|
|
||||||
|
|
||||||
/** @private @const {ReturnItemRepository} */
|
|
||||||
this.lineItemService_ = lineItemService
|
|
||||||
|
|
||||||
this.taxProviderService_ = taxProviderService
|
|
||||||
|
|
||||||
/** @private @const {ShippingOptionService} */
|
|
||||||
this.shippingOptionService_ = shippingOptionService
|
|
||||||
|
|
||||||
/** @private @const {FulfillmentProviderService} */
|
|
||||||
this.fulfillmentProviderService_ = fulfillmentProviderService
|
|
||||||
|
|
||||||
this.returnReasonService_ = returnReasonService
|
|
||||||
|
|
||||||
this.inventoryService_ = inventoryService
|
|
||||||
|
|
||||||
/** @private @const {OrderService} */
|
|
||||||
this.orderService_ = orderService
|
|
||||||
}
|
|
||||||
|
|
||||||
withTransaction(transactionManager) {
|
|
||||||
if (!transactionManager) {
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
const cloned = new ReturnService({
|
|
||||||
manager: transactionManager,
|
|
||||||
totalsService: this.totalsService_,
|
|
||||||
lineItemService: this.lineItemService_,
|
|
||||||
returnRepository: this.returnRepository_,
|
|
||||||
taxProviderService: this.taxProviderService_,
|
|
||||||
returnItemRepository: this.returnItemRepository_,
|
|
||||||
shippingOptionService: this.shippingOptionService_,
|
|
||||||
fulfillmentProviderService: this.fulfillmentProviderService_,
|
|
||||||
returnReasonService: this.returnReasonService_,
|
|
||||||
inventoryService: this.inventoryService_,
|
|
||||||
orderService: this.orderService_,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
cloned.transactionManager_ = transactionManager
|
this.manager_ = manager
|
||||||
|
this.totalsService_ = totalsService
|
||||||
return cloned
|
this.returnRepository_ = returnRepository
|
||||||
|
this.returnItemRepository_ = returnItemRepository
|
||||||
|
this.lineItemService_ = lineItemService
|
||||||
|
this.taxProviderService_ = taxProviderService
|
||||||
|
this.shippingOptionService_ = shippingOptionService
|
||||||
|
this.fulfillmentProviderService_ = fulfillmentProviderService
|
||||||
|
this.returnReasonService_ = returnReasonService
|
||||||
|
this.inventoryService_ = inventoryService
|
||||||
|
this.orderService_ = orderService
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the order line items, given an array of items
|
* Retrieves the order line items, given an array of items
|
||||||
* @param {Order} order - the order to get line items from
|
* @param order - the order to get line items from
|
||||||
* @param {{ item_id: string, quantity: number }} items - the items to get
|
* @param items - the items to get
|
||||||
* @param {function} transformer - a function to apply to each of the items
|
* @param transformer - a function to apply to each of the items
|
||||||
* retrieved from the order, should return a line item. If the transformer
|
* retrieved from the order, should return a line item. If the transformer
|
||||||
* returns an undefined value the line item will be filtered from the
|
* returns an undefined value the line item will be filtered from the
|
||||||
* returned array.
|
* returned array.
|
||||||
* @return {Promise<Array<LineItem>>} the line items generated by the transformer.
|
* @return the line items generated by the transformer.
|
||||||
*/
|
*/
|
||||||
async getFulfillmentItems_(order, items, transformer) {
|
protected async getFulfillmentItems(
|
||||||
|
order: Order,
|
||||||
|
items: OrdersReturnItem[],
|
||||||
|
transformer: Transformer
|
||||||
|
): Promise<
|
||||||
|
(LineItem & {
|
||||||
|
reason_id?: string
|
||||||
|
note?: string
|
||||||
|
})[]
|
||||||
|
> {
|
||||||
let merged = [...order.items]
|
let merged = [...order.items]
|
||||||
|
|
||||||
// merge items from order with items from order swaps
|
// merge items from order with items from order swaps
|
||||||
@@ -110,33 +143,37 @@ class ReturnService extends BaseService {
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
return toReturn.filter((i) => !!i)
|
return toReturn.filter((i) => !!i) as (LineItem & OrdersReturnItem)[]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Object} selector - the query object for find
|
* @param selector - the query object for find
|
||||||
* @param {object} config - the config object for find
|
* @param config - the config object for find
|
||||||
* @return {Promise} the result of the find operation
|
* @return the result of the find operation
|
||||||
*/
|
*/
|
||||||
list(
|
list(
|
||||||
selector,
|
selector: Selector<Return>,
|
||||||
config = { skip: 0, take: 50, order: { created_at: "DESC" } }
|
config: FindConfig<Return> = {
|
||||||
) {
|
skip: 0,
|
||||||
|
take: 50,
|
||||||
|
order: { created_at: "DESC" },
|
||||||
|
}
|
||||||
|
): Promise<Return[]> {
|
||||||
const returnRepo = this.manager_.getCustomRepository(this.returnRepository_)
|
const returnRepo = this.manager_.getCustomRepository(this.returnRepository_)
|
||||||
const query = this.buildQuery_(selector, config)
|
const query = buildQuery(selector, config)
|
||||||
return returnRepo.find(query)
|
return returnRepo.find(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cancels a return if possible. Returns can be canceled if it has not been received.
|
* Cancels a return if possible. Returns can be canceled if it has not been received.
|
||||||
* @param {string} returnId - the id of the return to cancel.
|
* @param returnId - the id of the return to cancel.
|
||||||
* @return {Promise<Return>} the updated Return
|
* @return the updated Return
|
||||||
*/
|
*/
|
||||||
async cancel(returnId) {
|
async cancel(returnId: string): Promise<Return | never> {
|
||||||
return this.atomicPhase_(async (manager) => {
|
return await this.atomicPhase_(async (manager) => {
|
||||||
const ret = await this.retrieve(returnId)
|
const ret = await this.retrieve(returnId)
|
||||||
|
|
||||||
if (ret.status === "received") {
|
if (ret.status === ReturnStatus.RECEIVED) {
|
||||||
throw new MedusaError(
|
throw new MedusaError(
|
||||||
MedusaError.Types.NOT_ALLOWED,
|
MedusaError.Types.NOT_ALLOWED,
|
||||||
"Can't cancel a return which has been returned"
|
"Can't cancel a return which has been returned"
|
||||||
@@ -145,10 +182,9 @@ class ReturnService extends BaseService {
|
|||||||
|
|
||||||
const retRepo = manager.getCustomRepository(this.returnRepository_)
|
const retRepo = manager.getCustomRepository(this.returnRepository_)
|
||||||
|
|
||||||
ret.status = "canceled"
|
ret.status = ReturnStatus.CANCELED
|
||||||
|
|
||||||
const result = retRepo.save(ret)
|
return await retRepo.save(ret)
|
||||||
return result
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,13 +192,13 @@ class ReturnService extends BaseService {
|
|||||||
* Checks that an order has the statuses necessary to complete a return.
|
* Checks that an order has the statuses necessary to complete a return.
|
||||||
* fulfillment_status cannot be not_fulfilled or returned.
|
* fulfillment_status cannot be not_fulfilled or returned.
|
||||||
* payment_status must be captured.
|
* payment_status must be captured.
|
||||||
* @param {Order} order - the order to check statuses on
|
* @param order - the order to check statuses on
|
||||||
* @throws when statuses are not sufficient for returns.
|
* @throws when statuses are not sufficient for returns.
|
||||||
*/
|
*/
|
||||||
validateReturnStatuses_(order) {
|
protected validateReturnStatuses(order: Order): void | never {
|
||||||
if (
|
if (
|
||||||
order.fulfillment_status === "not_fulfilled" ||
|
order.fulfillment_status === FulfillmentStatus.NOT_FULFILLED ||
|
||||||
order.fulfillment_status === "returned"
|
order.fulfillment_status === FulfillmentStatus.RETURNED
|
||||||
) {
|
) {
|
||||||
throw new MedusaError(
|
throw new MedusaError(
|
||||||
MedusaError.Types.NOT_ALLOWED,
|
MedusaError.Types.NOT_ALLOWED,
|
||||||
@@ -170,7 +206,7 @@ class ReturnService extends BaseService {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (order.payment_status !== "captured") {
|
if (order.payment_status !== PaymentStatus.CAPTURED) {
|
||||||
throw new MedusaError(
|
throw new MedusaError(
|
||||||
MedusaError.Types.NOT_ALLOWED,
|
MedusaError.Types.NOT_ALLOWED,
|
||||||
"Can't return an order with payment unprocessed"
|
"Can't return an order with payment unprocessed"
|
||||||
@@ -182,14 +218,18 @@ class ReturnService extends BaseService {
|
|||||||
* Checks that a given quantity of a line item can be returned. Fails if the
|
* Checks that a given quantity of a line item can be returned. Fails if the
|
||||||
* item is undefined or if the returnable quantity of the item is lower, than
|
* item is undefined or if the returnable quantity of the item is lower, than
|
||||||
* the quantity that is requested to be returned.
|
* the quantity that is requested to be returned.
|
||||||
* @param {LineItem?} item - the line item to check has sufficient returnable
|
* @param item - the line item to check has sufficient returnable
|
||||||
* quantity.
|
* quantity.
|
||||||
* @param {number} quantity - the quantity that is requested to be returned.
|
* @param quantity - the quantity that is requested to be returned.
|
||||||
* @param {object} additional - the quantity that is requested to be returned.
|
* @param additional - the quantity that is requested to be returned.
|
||||||
* @return {LineItem} a line item where the quantity is set to the requested
|
* @return a line item where the quantity is set to the requested
|
||||||
* return quantity.
|
* return quantity.
|
||||||
*/
|
*/
|
||||||
validateReturnLineItem_(item, quantity, additional) {
|
protected validateReturnLineItem(
|
||||||
|
item?: LineItem,
|
||||||
|
quantity = 0,
|
||||||
|
additional: { reason_id?: string; note?: string } = {}
|
||||||
|
): DeepPartial<LineItem> {
|
||||||
if (!item) {
|
if (!item) {
|
||||||
throw new MedusaError(
|
throw new MedusaError(
|
||||||
MedusaError.Types.INVALID_DATA,
|
MedusaError.Types.INVALID_DATA,
|
||||||
@@ -205,13 +245,13 @@ class ReturnService extends BaseService {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const toReturn = {
|
const toReturn: DeepPartial<ReturnItem> = {
|
||||||
...item,
|
...item,
|
||||||
quantity,
|
quantity,
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("reason_id" in additional) {
|
if ("reason_id" in additional) {
|
||||||
toReturn.reason_id = additional.reason_id
|
toReturn.reason_id = additional.reason_id as string
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("note" in additional) {
|
if ("note" in additional) {
|
||||||
@@ -223,17 +263,19 @@ class ReturnService extends BaseService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves a return by its id.
|
* Retrieves a return by its id.
|
||||||
* @param {string} id - the id of the return to retrieve
|
* @param id - the id of the return to retrieve
|
||||||
* @param {object} config - the config object
|
* @param config - the config object
|
||||||
* @return {Return} the return
|
* @return the return
|
||||||
*/
|
*/
|
||||||
async retrieve(id, config = {}) {
|
async retrieve(
|
||||||
|
id: string,
|
||||||
|
config: FindConfig<Return> = {}
|
||||||
|
): Promise<Return | never> {
|
||||||
const returnRepository = this.manager_.getCustomRepository(
|
const returnRepository = this.manager_.getCustomRepository(
|
||||||
this.returnRepository_
|
this.returnRepository_
|
||||||
)
|
)
|
||||||
|
|
||||||
const validatedId = this.validateId_(id)
|
const query = buildQuery({ id }, config)
|
||||||
const query = this.buildQuery_({ id: validatedId }, config)
|
|
||||||
|
|
||||||
const returnObj = await returnRepository.findOne(query)
|
const returnObj = await returnRepository.findOne(query)
|
||||||
|
|
||||||
@@ -246,16 +288,17 @@ class ReturnService extends BaseService {
|
|||||||
return returnObj
|
return returnObj
|
||||||
}
|
}
|
||||||
|
|
||||||
async retrieveBySwap(swapId, relations = []) {
|
async retrieveBySwap(
|
||||||
|
swapId: string,
|
||||||
|
relations: string[] = []
|
||||||
|
): Promise<Return | never> {
|
||||||
const returnRepository = this.manager_.getCustomRepository(
|
const returnRepository = this.manager_.getCustomRepository(
|
||||||
this.returnRepository_
|
this.returnRepository_
|
||||||
)
|
)
|
||||||
|
|
||||||
const validatedId = this.validateId_(swapId)
|
|
||||||
|
|
||||||
const returnObj = await returnRepository.findOne({
|
const returnObj = await returnRepository.findOne({
|
||||||
where: {
|
where: {
|
||||||
swap_id: validatedId,
|
swap_id: swapId,
|
||||||
},
|
},
|
||||||
relations,
|
relations,
|
||||||
})
|
})
|
||||||
@@ -266,11 +309,12 @@ class ReturnService extends BaseService {
|
|||||||
`Return with swa_id: ${swapId} was not found`
|
`Return with swa_id: ${swapId} was not found`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnObj
|
return returnObj
|
||||||
}
|
}
|
||||||
|
|
||||||
async update(returnId, update) {
|
async update(returnId: string, update: UpdateReturnInput): Promise<Return> {
|
||||||
return this.atomicPhase_(async (manager) => {
|
return await this.atomicPhase_(async (manager) => {
|
||||||
const ret = await this.retrieve(returnId)
|
const ret = await this.retrieve(returnId)
|
||||||
|
|
||||||
if (ret.status === "canceled") {
|
if (ret.status === "canceled") {
|
||||||
@@ -283,7 +327,7 @@ class ReturnService extends BaseService {
|
|||||||
const { metadata, ...rest } = update
|
const { metadata, ...rest } = update
|
||||||
|
|
||||||
if (metadata) {
|
if (metadata) {
|
||||||
ret.metadata = this.setMetadata_(ret, metadata)
|
ret.metadata = setMetadata(ret, metadata)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(rest)) {
|
for (const [key, value] of Object.entries(rest)) {
|
||||||
@@ -291,8 +335,7 @@ class ReturnService extends BaseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const retRepo = manager.getCustomRepository(this.returnRepository_)
|
const retRepo = manager.getCustomRepository(this.returnRepository_)
|
||||||
const result = await retRepo.save(ret)
|
return await retRepo.save(ret)
|
||||||
return result
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,24 +343,25 @@ class ReturnService extends BaseService {
|
|||||||
* Creates a return request for an order, with given items, and a shipping
|
* Creates a return request for an order, with given items, and a shipping
|
||||||
* method. If no refund amount is provided the refund amount is calculated from
|
* method. If no refund amount is provided the refund amount is calculated from
|
||||||
* the return lines and the shipping cost.
|
* the return lines and the shipping cost.
|
||||||
* @param {object} data - data to use for the return e.g. shipping_method,
|
* @param data - data to use for the return e.g. shipping_method,
|
||||||
* items or refund_amount
|
* items or refund_amount
|
||||||
* @param {object} orderLike - order object
|
* @return the created return
|
||||||
* @return {Promise<Return>} the created return
|
|
||||||
*/
|
*/
|
||||||
async create(data) {
|
async create(data: CreateReturnInput): Promise<Return | never> {
|
||||||
return this.atomicPhase_(async (manager) => {
|
return await this.atomicPhase_(async (manager) => {
|
||||||
const returnRepository = manager.getCustomRepository(
|
const returnRepository = manager.getCustomRepository(
|
||||||
this.returnRepository_
|
this.returnRepository_
|
||||||
)
|
)
|
||||||
|
|
||||||
const orderId = data.order_id
|
const orderId = data.order_id
|
||||||
if (data.swap_id) {
|
if (data.swap_id) {
|
||||||
delete data.order_id
|
delete (data as Partial<CreateReturnInput>).order_id
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const item of data.items) {
|
for (const item of data.items ?? []) {
|
||||||
const line = await this.lineItemService_.retrieve(item.item_id, {
|
const line = await this.lineItemService_
|
||||||
|
.withTransaction(manager)
|
||||||
|
.retrieve(item.item_id, {
|
||||||
relations: ["order", "swap", "claim_order"],
|
relations: ["order", "swap", "claim_order"],
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -351,10 +395,10 @@ class ReturnService extends BaseService {
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
const returnLines = await this.getFulfillmentItems_(
|
const returnLines = await this.getFulfillmentItems(
|
||||||
order,
|
order,
|
||||||
data.items,
|
data.items ?? [],
|
||||||
this.validateReturnLineItem_
|
this.validateReturnLineItem
|
||||||
)
|
)
|
||||||
|
|
||||||
let toRefund = data.refund_amount
|
let toRefund = data.refund_amount
|
||||||
@@ -363,7 +407,7 @@ class ReturnService extends BaseService {
|
|||||||
// refundable
|
// refundable
|
||||||
const refundable = order.refundable_amount
|
const refundable = order.refundable_amount
|
||||||
|
|
||||||
if (toRefund > refundable) {
|
if (toRefund! > refundable) {
|
||||||
throw new MedusaError(
|
throw new MedusaError(
|
||||||
MedusaError.Types.INVALID_DATA,
|
MedusaError.Types.INVALID_DATA,
|
||||||
"Cannot refund more than the original payment"
|
"Cannot refund more than the original payment"
|
||||||
@@ -371,7 +415,7 @@ class ReturnService extends BaseService {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Merchant hasn't specified refund amount so we calculate it
|
// Merchant hasn't specified refund amount so we calculate it
|
||||||
toRefund = await this.totalsService_.getRefundTotal(order, returnLines)
|
toRefund = this.totalsService_.getRefundTotal(order, returnLines)
|
||||||
}
|
}
|
||||||
|
|
||||||
const method = data.shipping_method
|
const method = data.shipping_method
|
||||||
@@ -379,12 +423,14 @@ class ReturnService extends BaseService {
|
|||||||
|
|
||||||
const returnObject = {
|
const returnObject = {
|
||||||
...data,
|
...data,
|
||||||
status: "requested",
|
status: ReturnStatus.REQUESTED,
|
||||||
refund_amount: Math.floor(toRefund),
|
refund_amount: Math.floor(toRefund!),
|
||||||
}
|
}
|
||||||
|
|
||||||
const returnReasons = await this.returnReasonService_.list(
|
const returnReasons = await this.returnReasonService_
|
||||||
{ id: [...returnLines.map((rl) => rl.reason_id)] },
|
.withTransaction(manager)
|
||||||
|
.list(
|
||||||
|
{ id: [...returnLines.map((rl) => rl.reason_id as string)] },
|
||||||
{ relations: ["return_reason_children"] }
|
{ relations: ["return_reason_children"] }
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -404,14 +450,13 @@ class ReturnService extends BaseService {
|
|||||||
reason_id: i.reason_id,
|
reason_id: i.reason_id,
|
||||||
note: i.note,
|
note: i.note,
|
||||||
metadata: i.metadata,
|
metadata: i.metadata,
|
||||||
no_notification: data.no_notification,
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
const created = await returnRepository.create(returnObject)
|
const created = (await returnRepository.create(returnObject)) as Return
|
||||||
const result = await returnRepository.save(created)
|
const result = await returnRepository.save(created)
|
||||||
|
|
||||||
if (method) {
|
if (method && method.option_id) {
|
||||||
const shippingMethod = await this.shippingOptionService_
|
const shippingMethod = await this.shippingOptionService_
|
||||||
.withTransaction(manager)
|
.withTransaction(manager)
|
||||||
.createShippingMethod(
|
.createShippingMethod(
|
||||||
@@ -439,7 +484,7 @@ class ReturnService extends BaseService {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (typeof data.refund_amount === "undefined") {
|
if (typeof data.refund_amount === "undefined") {
|
||||||
result.refund_amount = toRefund - shippingTotal
|
result.refund_amount = toRefund! - shippingTotal
|
||||||
return await returnRepository.save(result)
|
return await returnRepository.save(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -448,8 +493,8 @@ class ReturnService extends BaseService {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fulfill(returnId) {
|
async fulfill(returnId: string): Promise<Return | never> {
|
||||||
return this.atomicPhase_(async (manager) => {
|
return await this.atomicPhase_(async (manager) => {
|
||||||
const returnOrder = await this.retrieve(returnId, {
|
const returnOrder = await this.retrieve(returnId, {
|
||||||
relations: [
|
relations: [
|
||||||
"items",
|
"items",
|
||||||
@@ -470,7 +515,7 @@ class ReturnService extends BaseService {
|
|||||||
|
|
||||||
const returnData = { ...returnOrder }
|
const returnData = { ...returnOrder }
|
||||||
|
|
||||||
const items = await this.lineItemService_.list(
|
const items = await this.lineItemService_.withTransaction(manager).list(
|
||||||
{
|
{
|
||||||
id: returnOrder.items.map(({ item_id }) => item_id),
|
id: returnOrder.items.map(({ item_id }) => item_id),
|
||||||
},
|
},
|
||||||
@@ -482,7 +527,7 @@ class ReturnService extends BaseService {
|
|||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
item: found,
|
item: found,
|
||||||
}
|
} as ReturnItem
|
||||||
})
|
})
|
||||||
|
|
||||||
if (returnOrder.shipping_data) {
|
if (returnOrder.shipping_data) {
|
||||||
@@ -496,14 +541,11 @@ class ReturnService extends BaseService {
|
|||||||
return returnOrder
|
return returnOrder
|
||||||
}
|
}
|
||||||
|
|
||||||
const fulfillmentData =
|
returnOrder.shipping_data =
|
||||||
await this.fulfillmentProviderService_.createReturn(returnData)
|
await this.fulfillmentProviderService_.createReturn(returnData)
|
||||||
|
|
||||||
returnOrder.shipping_data = fulfillmentData
|
|
||||||
|
|
||||||
const returnRepo = manager.getCustomRepository(this.returnRepository_)
|
const returnRepo = manager.getCustomRepository(this.returnRepository_)
|
||||||
const result = await returnRepo.save(returnOrder)
|
return await returnRepo.save(returnOrder)
|
||||||
return result
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -515,29 +557,29 @@ class ReturnService extends BaseService {
|
|||||||
* retuned items are not matching the requested items. Setting the
|
* retuned items are not matching the requested items. Setting the
|
||||||
* allowMismatch argument to true, will process the return, ignoring any
|
* allowMismatch argument to true, will process the return, ignoring any
|
||||||
* mismatches.
|
* mismatches.
|
||||||
* @param {string} return_id - the orderId to return to
|
* @param returnId - the orderId to return to
|
||||||
* @param {Item[]} received_items - the items received after return.
|
* @param receivedItems - the items received after return.
|
||||||
* @param {number | undefined} refund_amount - the amount to return
|
* @param refundAmount - the amount to return
|
||||||
* @param {bool} allow_mismatch - whether to ignore return/received
|
* @param allowMismatch - whether to ignore return/received
|
||||||
* product mismatch
|
* product mismatch
|
||||||
* @return {Promise} the result of the update operation
|
* @return the result of the update operation
|
||||||
*/
|
*/
|
||||||
async receive(
|
async receive(
|
||||||
return_id,
|
returnId: string,
|
||||||
received_items,
|
receivedItems: OrdersReturnItem[],
|
||||||
refund_amount,
|
refundAmount?: number,
|
||||||
allow_mismatch = false
|
allowMismatch = false
|
||||||
) {
|
): Promise<Return | never> {
|
||||||
return this.atomicPhase_(async (manager) => {
|
return await this.atomicPhase_(async (manager) => {
|
||||||
const returnRepository = manager.getCustomRepository(
|
const returnRepository = manager.getCustomRepository(
|
||||||
this.returnRepository_
|
this.returnRepository_
|
||||||
)
|
)
|
||||||
|
|
||||||
const returnObj = await this.retrieve(return_id, {
|
const returnObj = await this.retrieve(returnId, {
|
||||||
relations: ["items", "swap", "swap.additional_items"],
|
relations: ["items", "swap", "swap.additional_items"],
|
||||||
})
|
})
|
||||||
|
|
||||||
if (returnObj.status === "canceled") {
|
if (returnObj.status === ReturnStatus.CANCELED) {
|
||||||
throw new MedusaError(
|
throw new MedusaError(
|
||||||
MedusaError.Types.NOT_ALLOWED,
|
MedusaError.Types.NOT_ALLOWED,
|
||||||
"Cannot receive a canceled return"
|
"Cannot receive a canceled return"
|
||||||
@@ -569,17 +611,17 @@ class ReturnService extends BaseService {
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
if (returnObj.status === "received") {
|
if (returnObj.status === ReturnStatus.RECEIVED) {
|
||||||
throw new MedusaError(
|
throw new MedusaError(
|
||||||
MedusaError.Types.NOT_ALLOWED,
|
MedusaError.Types.NOT_ALLOWED,
|
||||||
`Return with id ${return_id} has already been received`
|
`Return with id ${returnId} has already been received`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const returnLines = await this.getFulfillmentItems_(
|
const returnLines = await this.getFulfillmentItems(
|
||||||
order,
|
order,
|
||||||
received_items,
|
receivedItems,
|
||||||
this.validateReturnLineItem_
|
this.validateReturnLineItem
|
||||||
)
|
)
|
||||||
|
|
||||||
const newLines = returnLines.map((l) => {
|
const newLines = returnLines.map((l) => {
|
||||||
@@ -604,15 +646,14 @@ class ReturnService extends BaseService {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
let returnStatus = "received"
|
let returnStatus = ReturnStatus.RECEIVED
|
||||||
|
|
||||||
const isMatching = newLines.every((l) => l.is_requested)
|
const isMatching = newLines.every((l) => l.is_requested)
|
||||||
if (!isMatching && !allow_mismatch) {
|
if (!isMatching && !allowMismatch) {
|
||||||
// Should update status
|
returnStatus = ReturnStatus.REQUIRES_ACTION
|
||||||
returnStatus = "requires_action"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const totalRefundableAmount = refund_amount || returnObj.refund_amount
|
const totalRefundableAmount = refundAmount || returnObj.refund_amount
|
||||||
|
|
||||||
const now = new Date()
|
const now = new Date()
|
||||||
const updateObj = {
|
const updateObj = {
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
type OrdersReturnItem = {
|
||||||
|
item_id: string
|
||||||
|
quantity: number
|
||||||
|
reason_id?: string
|
||||||
|
note?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CreateReturnInput = {
|
||||||
|
order_id: string
|
||||||
|
swap_id?: string
|
||||||
|
claim_order_id?: string
|
||||||
|
items?: OrdersReturnItem[]
|
||||||
|
shipping_method?: {
|
||||||
|
option_id?: string
|
||||||
|
price?: number
|
||||||
|
}
|
||||||
|
no_notification?: boolean
|
||||||
|
metadata?: Record<string, unknown>
|
||||||
|
refund_amount?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UpdateReturnInput = {
|
||||||
|
items?: OrdersReturnItem[]
|
||||||
|
shipping_method?: {
|
||||||
|
option_id: string
|
||||||
|
price?: number
|
||||||
|
}
|
||||||
|
no_notification?: boolean
|
||||||
|
metadata?: Record<string, unknown>
|
||||||
|
}
|
||||||
Reference in new issue
Block a user