feat(core-flows, fulfillment): Add create return specific method and add more tests (#7357)
* feat(core-flows, fulfillment): Add create return specific method and add more tests * fix defautl providers in tests fixtures * more tests * wip fixes * fix flow and tests * cleanup
This commit is contained in:
@@ -1,5 +1,10 @@
|
|||||||
import { ModuleRegistrationName, Modules } from "@medusajs/modules-sdk"
|
|
||||||
import {
|
import {
|
||||||
|
ModuleRegistrationName,
|
||||||
|
Modules,
|
||||||
|
RemoteLink,
|
||||||
|
} from "@medusajs/modules-sdk"
|
||||||
|
import {
|
||||||
|
FulfillmentSetDTO,
|
||||||
FulfillmentWorkflow,
|
FulfillmentWorkflow,
|
||||||
IOrderModuleService,
|
IOrderModuleService,
|
||||||
IRegionModuleService,
|
IRegionModuleService,
|
||||||
@@ -208,6 +213,7 @@ async function prepareDataFixtures({ container }) {
|
|||||||
salesChannel,
|
salesChannel,
|
||||||
location,
|
location,
|
||||||
product,
|
product,
|
||||||
|
fulfillmentSet,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,6 +318,17 @@ async function createOrderFixture({ container, product }) {
|
|||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
|
const returnReason = await orderService.createReturnReasons({
|
||||||
|
value: "Test reason",
|
||||||
|
label: "Test reason",
|
||||||
|
})
|
||||||
|
|
||||||
|
await orderService.createReturnReasons({
|
||||||
|
value: "Test child reason",
|
||||||
|
label: "Test child reason",
|
||||||
|
parent_return_reason_id: returnReason.id,
|
||||||
|
})
|
||||||
|
|
||||||
await orderService.applyPendingOrderActions(order.id)
|
await orderService.applyPendingOrderActions(order.id)
|
||||||
|
|
||||||
order = await orderService.retrieve(order.id, {
|
order = await orderService.retrieve(order.id, {
|
||||||
@@ -335,6 +352,7 @@ medusaIntegrationTestRunner({
|
|||||||
let region: RegionDTO
|
let region: RegionDTO
|
||||||
let location: StockLocationDTO
|
let location: StockLocationDTO
|
||||||
let product: ProductDTO
|
let product: ProductDTO
|
||||||
|
let fulfillmentSet: FulfillmentSetDTO
|
||||||
|
|
||||||
let orderService: IOrderModuleService
|
let orderService: IOrderModuleService
|
||||||
|
|
||||||
@@ -347,12 +365,18 @@ medusaIntegrationTestRunner({
|
|||||||
region = fixtures.region
|
region = fixtures.region
|
||||||
location = fixtures.location
|
location = fixtures.location
|
||||||
product = fixtures.product
|
product = fixtures.product
|
||||||
|
fulfillmentSet = fixtures.fulfillmentSet
|
||||||
|
|
||||||
orderService = container.resolve(ModuleRegistrationName.ORDER)
|
orderService = container.resolve(ModuleRegistrationName.ORDER)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should create a return order", async () => {
|
it("should create a return order", async () => {
|
||||||
const order = await createOrderFixture({ container, product })
|
const order = await createOrderFixture({ container, product })
|
||||||
|
const reasons = await orderService.listReturnReasons({})
|
||||||
|
const testReason = reasons.find(
|
||||||
|
(r) => r.value.toLowerCase() === "test child reason"
|
||||||
|
)!
|
||||||
|
|
||||||
const createReturnOrderData: OrderWorkflow.CreateOrderReturnWorkflowInput =
|
const createReturnOrderData: OrderWorkflow.CreateOrderReturnWorkflowInput =
|
||||||
{
|
{
|
||||||
order_id: order.id,
|
order_id: order.id,
|
||||||
@@ -363,6 +387,7 @@ medusaIntegrationTestRunner({
|
|||||||
{
|
{
|
||||||
id: order.items![0].id,
|
id: order.items![0].id,
|
||||||
quantity: 1,
|
quantity: 1,
|
||||||
|
reason_id: testReason.id,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
@@ -468,6 +493,80 @@ medusaIntegrationTestRunner({
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should fail when location is not linked", async () => {
|
||||||
|
const order = await createOrderFixture({ container, product })
|
||||||
|
const createReturnOrderData: OrderWorkflow.CreateOrderReturnWorkflowInput =
|
||||||
|
{
|
||||||
|
order_id: order.id,
|
||||||
|
return_shipping: {
|
||||||
|
option_id: shippingOption.id,
|
||||||
|
},
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: order.items![0].id,
|
||||||
|
quantity: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the location link
|
||||||
|
const remoteLink = container.resolve(
|
||||||
|
ContainerRegistrationKeys.REMOTE_LINK
|
||||||
|
) as RemoteLink
|
||||||
|
|
||||||
|
await remoteLink.dismiss([
|
||||||
|
{
|
||||||
|
[Modules.STOCK_LOCATION]: {
|
||||||
|
stock_location_id: location.id,
|
||||||
|
},
|
||||||
|
[Modules.FULFILLMENT]: {
|
||||||
|
fulfillment_set_id: fulfillmentSet.id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const { errors } = await createReturnOrderWorkflow(container).run({
|
||||||
|
input: createReturnOrderData,
|
||||||
|
throwOnError: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
await expect(errors[0].error.message).toBe(
|
||||||
|
`Cannot create return without stock location, either provide a location or you should link the shipping option ${shippingOption.id} to a stock location.`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should fail when a reason with children is provided", async () => {
|
||||||
|
const order = await createOrderFixture({ container, product })
|
||||||
|
const reasons = await orderService.listReturnReasons({})
|
||||||
|
const testReason = reasons.find(
|
||||||
|
(r) => r.value.toLowerCase() === "test reason"
|
||||||
|
)!
|
||||||
|
|
||||||
|
const createReturnOrderData: OrderWorkflow.CreateOrderReturnWorkflowInput =
|
||||||
|
{
|
||||||
|
order_id: order.id,
|
||||||
|
return_shipping: {
|
||||||
|
option_id: shippingOption.id,
|
||||||
|
},
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: order.items![0].id,
|
||||||
|
quantity: 1,
|
||||||
|
reason_id: testReason.id,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
const { errors } = await createReturnOrderWorkflow(container).run({
|
||||||
|
input: createReturnOrderData,
|
||||||
|
throwOnError: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(errors[0].error.message).toBe(
|
||||||
|
`Cannot apply return reason with id ${testReason.id} to order with id ${order.id}. Return reason has nested reasons.`
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
WithCalculatedPrice,
|
WithCalculatedPrice,
|
||||||
} from "@medusajs/types"
|
} from "@medusajs/types"
|
||||||
import {
|
import {
|
||||||
|
createStep,
|
||||||
createWorkflow,
|
createWorkflow,
|
||||||
transform,
|
transform,
|
||||||
WorkflowData,
|
WorkflowData,
|
||||||
@@ -19,6 +20,7 @@ import {
|
|||||||
MathBN,
|
MathBN,
|
||||||
MedusaError,
|
MedusaError,
|
||||||
Modules,
|
Modules,
|
||||||
|
remoteQueryObjectFromString,
|
||||||
} from "@medusajs/utils"
|
} from "@medusajs/utils"
|
||||||
import { updateOrderTaxLinesStep } from "../steps"
|
import { updateOrderTaxLinesStep } from "../steps"
|
||||||
import { createReturnStep } from "../steps/create-return"
|
import { createReturnStep } from "../steps/create-return"
|
||||||
@@ -55,7 +57,7 @@ function throwIfItemsDoesNotExistsInOrder({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateReturnReasons(
|
async function validateReturnReasons(
|
||||||
{
|
{
|
||||||
orderId,
|
orderId,
|
||||||
inputItems,
|
inputItems,
|
||||||
@@ -66,24 +68,32 @@ function validateReturnReasons(
|
|||||||
{ container }
|
{ container }
|
||||||
) {
|
) {
|
||||||
const reasonIds = inputItems.map((i) => i.reason_id).filter(Boolean)
|
const reasonIds = inputItems.map((i) => i.reason_id).filter(Boolean)
|
||||||
|
|
||||||
if (!reasonIds.length) {
|
if (!reasonIds.length) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const remoteQuery = container.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
|
const remoteQuery = container.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
|
||||||
|
|
||||||
const returnReasons = remoteQuery({
|
const remoteQueryObject = remoteQueryObjectFromString({
|
||||||
entry_point: "return_reasons",
|
entryPoint: "return_reasons",
|
||||||
fields: ["return_reason_children.*"],
|
fields: [
|
||||||
variables: { id: [inputItems.map((item) => item.reason_id)] },
|
"id",
|
||||||
|
"parent_return_reason_id",
|
||||||
|
"parent_return_reason",
|
||||||
|
"return_reason_children.id",
|
||||||
|
],
|
||||||
|
variables: { id: [inputItems.map((item) => item.reason_id)], limit: null },
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const returnReasons = await remoteQuery(remoteQueryObject)
|
||||||
|
|
||||||
const reasons = returnReasons.map((r) => r.id)
|
const reasons = returnReasons.map((r) => r.id)
|
||||||
const hasInvalidReasons = reasons.filter(
|
const hasInvalidReasons = returnReasons
|
||||||
|
.filter(
|
||||||
// We do not allow for root reason to be applied
|
// We do not allow for root reason to be applied
|
||||||
(reason) => reason.return_reason_children.length > 0
|
(reason) => reason.return_reason_children.length > 0
|
||||||
)
|
)
|
||||||
|
.map((r) => r.id)
|
||||||
const hasNonExistingReasons = arrayDifference(reasonIds, reasons)
|
const hasNonExistingReasons = arrayDifference(reasonIds, reasons)
|
||||||
|
|
||||||
if (hasNonExistingReasons.length) {
|
if (hasNonExistingReasons.length) {
|
||||||
@@ -95,7 +105,7 @@ function validateReturnReasons(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasInvalidReasons.length()) {
|
if (hasInvalidReasons.length) {
|
||||||
throw new MedusaError(
|
throw new MedusaError(
|
||||||
MedusaError.Types.INVALID_DATA,
|
MedusaError.Types.INVALID_DATA,
|
||||||
`Cannot apply return reason with id ${hasInvalidReasons.join(
|
`Cannot apply return reason with id ${hasInvalidReasons.join(
|
||||||
@@ -238,12 +248,34 @@ function prepareReturnShippingOptionQueryVariables({
|
|||||||
return variables
|
return variables
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const validationStep = createStep(
|
||||||
|
"create-return-order-validation",
|
||||||
|
async function (
|
||||||
|
{
|
||||||
|
order,
|
||||||
|
input,
|
||||||
|
}: {
|
||||||
|
order
|
||||||
|
input: OrderWorkflow.CreateOrderReturnWorkflowInput
|
||||||
|
},
|
||||||
|
context
|
||||||
|
) {
|
||||||
|
throwIfOrderIsCancelled({ order })
|
||||||
|
throwIfItemsDoesNotExistsInOrder({ order, inputItems: input.items })
|
||||||
|
await validateReturnReasons(
|
||||||
|
{ orderId: input.order_id, inputItems: input.items },
|
||||||
|
context
|
||||||
|
)
|
||||||
|
validateCustomRefundAmount({ order, refundAmount: input.refund_amount })
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
export const createReturnOrderWorkflowId = "create-return-order"
|
export const createReturnOrderWorkflowId = "create-return-order"
|
||||||
export const createReturnOrderWorkflow = createWorkflow(
|
export const createReturnOrderWorkflow = createWorkflow(
|
||||||
createReturnOrderWorkflowId,
|
createReturnOrderWorkflowId,
|
||||||
(
|
function (
|
||||||
input: WorkflowData<OrderWorkflow.CreateOrderReturnWorkflowInput>
|
input: WorkflowData<OrderWorkflow.CreateOrderReturnWorkflowInput>
|
||||||
): WorkflowData<void> => {
|
): WorkflowData<void> {
|
||||||
const order: OrderDTO = useRemoteQueryStep({
|
const order: OrderDTO = useRemoteQueryStep({
|
||||||
entry_point: "orders",
|
entry_point: "orders",
|
||||||
fields: [
|
fields: [
|
||||||
@@ -259,19 +291,7 @@ export const createReturnOrderWorkflow = createWorkflow(
|
|||||||
throw_if_key_not_found: true,
|
throw_if_key_not_found: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
transform({ order }, throwIfOrderIsCancelled)
|
validationStep({ order, input })
|
||||||
transform(
|
|
||||||
{ order, inputItems: input.items },
|
|
||||||
throwIfItemsDoesNotExistsInOrder
|
|
||||||
)
|
|
||||||
transform(
|
|
||||||
{ orderId: input.order_id, inputItems: input.items },
|
|
||||||
validateReturnReasons
|
|
||||||
)
|
|
||||||
transform(
|
|
||||||
{ order, refundAmount: input.refund_amount },
|
|
||||||
validateCustomRefundAmount
|
|
||||||
)
|
|
||||||
|
|
||||||
const returnShippingOptionsVariables = transform(
|
const returnShippingOptionsVariables = transform(
|
||||||
{ input, order },
|
{ input, order },
|
||||||
|
|||||||
@@ -2367,7 +2367,7 @@ export interface IFulfillmentModuleService extends IModuleService {
|
|||||||
): Promise<[FulfillmentDTO[], number]>
|
): Promise<[FulfillmentDTO[], number]>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method creates a fulfillment.
|
* This method creates a fulfillment and call the provider to create a fulfillment.
|
||||||
*
|
*
|
||||||
* @param {CreateFulfillmentDTO} data - The fulfillment to be created.
|
* @param {CreateFulfillmentDTO} data - The fulfillment to be created.
|
||||||
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
|
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
|
||||||
@@ -2405,6 +2405,45 @@ export interface IFulfillmentModuleService extends IModuleService {
|
|||||||
sharedContext?: Context
|
sharedContext?: Context
|
||||||
): Promise<FulfillmentDTO>
|
): Promise<FulfillmentDTO>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method creates a fulfillment and call the provider to create a return.
|
||||||
|
*
|
||||||
|
* @param {CreateFulfillmentDTO} data - The fulfillment to be created.
|
||||||
|
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
|
||||||
|
* @returns {Promise<FulfillmentDTO>} The created fulfillment.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const fulfillment =
|
||||||
|
* await fulfillmentModuleService.createReturnFulfillment({
|
||||||
|
* location_id: "loc_123",
|
||||||
|
* provider_id: "webshipper",
|
||||||
|
* delivery_address: {
|
||||||
|
* address_1: "4120 Auto Park Cir",
|
||||||
|
* country_code: "us",
|
||||||
|
* },
|
||||||
|
* items: [
|
||||||
|
* {
|
||||||
|
* title: "Shirt",
|
||||||
|
* sku: "SHIRT",
|
||||||
|
* quantity: 1,
|
||||||
|
* barcode: "ABCED",
|
||||||
|
* },
|
||||||
|
* ],
|
||||||
|
* labels: [
|
||||||
|
* {
|
||||||
|
* tracking_number: "1234567",
|
||||||
|
* tracking_url: "https://example.com/tracking",
|
||||||
|
* label_url: "https://example.com/label",
|
||||||
|
* },
|
||||||
|
* ],
|
||||||
|
* order: {},
|
||||||
|
* })
|
||||||
|
*/
|
||||||
|
createReturnFulfillment(
|
||||||
|
data: CreateFulfillmentDTO,
|
||||||
|
sharedContext?: Context
|
||||||
|
): Promise<FulfillmentDTO>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method updates an existing fulfillment.
|
* This method updates an existing fulfillment.
|
||||||
*
|
*
|
||||||
|
|||||||
+4
@@ -14,6 +14,10 @@ export class FulfillmentProviderServiceFixtures extends AbstractFulfillmentProvi
|
|||||||
async getFulfillmentOptions(): Promise<any> {
|
async getFulfillmentOptions(): Promise<any> {
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async createReturnFulfillment(fulfillment): Promise<any> {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const services = [FulfillmentProviderServiceFixtures]
|
export const services = [FulfillmentProviderServiceFixtures]
|
||||||
|
|||||||
+57
@@ -137,6 +137,63 @@ moduleIntegrationTestRunner({
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should create a return fulfillment", async () => {
|
||||||
|
const shippingProfile = await service.createShippingProfiles({
|
||||||
|
name: "test",
|
||||||
|
type: "default",
|
||||||
|
})
|
||||||
|
const fulfillmentSet = await service.create({
|
||||||
|
name: "test",
|
||||||
|
type: "test-type",
|
||||||
|
})
|
||||||
|
const serviceZone = await service.createServiceZones({
|
||||||
|
name: "test",
|
||||||
|
fulfillment_set_id: fulfillmentSet.id,
|
||||||
|
})
|
||||||
|
|
||||||
|
const shippingOption = await service.createShippingOptions(
|
||||||
|
generateCreateShippingOptionsData({
|
||||||
|
provider_id: providerId,
|
||||||
|
service_zone_id: serviceZone.id,
|
||||||
|
shipping_profile_id: shippingProfile.id,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
const fulfillment = await service.createReturnFulfillment(
|
||||||
|
generateCreateFulfillmentData({
|
||||||
|
provider_id: providerId,
|
||||||
|
shipping_option_id: shippingOption.id,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(fulfillment).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: expect.any(String),
|
||||||
|
packed_at: null,
|
||||||
|
shipped_at: null,
|
||||||
|
delivered_at: null,
|
||||||
|
canceled_at: null,
|
||||||
|
data: null,
|
||||||
|
provider_id: providerId,
|
||||||
|
shipping_option_id: shippingOption.id,
|
||||||
|
metadata: null,
|
||||||
|
delivery_address: expect.objectContaining({
|
||||||
|
id: expect.any(String),
|
||||||
|
}),
|
||||||
|
items: [
|
||||||
|
expect.objectContaining({
|
||||||
|
id: expect.any(String),
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
labels: [
|
||||||
|
expect.objectContaining({
|
||||||
|
id: expect.any(String),
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("on cancel", () => {
|
describe("on cancel", () => {
|
||||||
|
|||||||
@@ -193,9 +193,7 @@ export default class FulfillmentModuleService<
|
|||||||
|
|
||||||
return await this.baseRepository_.serialize<
|
return await this.baseRepository_.serialize<
|
||||||
FulfillmentTypes.ShippingOptionDTO[]
|
FulfillmentTypes.ShippingOptionDTO[]
|
||||||
>(shippingOptions, {
|
>(shippingOptions)
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager("baseRepository_")
|
@InjectManager("baseRepository_")
|
||||||
@@ -211,10 +209,7 @@ export default class FulfillmentModuleService<
|
|||||||
)
|
)
|
||||||
|
|
||||||
return await this.baseRepository_.serialize<FulfillmentTypes.FulfillmentDTO>(
|
return await this.baseRepository_.serialize<FulfillmentTypes.FulfillmentDTO>(
|
||||||
fulfillment,
|
fulfillment
|
||||||
{
|
|
||||||
populate: true,
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,9 +227,7 @@ export default class FulfillmentModuleService<
|
|||||||
|
|
||||||
return await this.baseRepository_.serialize<
|
return await this.baseRepository_.serialize<
|
||||||
FulfillmentTypes.FulfillmentDTO[]
|
FulfillmentTypes.FulfillmentDTO[]
|
||||||
>(fulfillments, {
|
>(fulfillments)
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectManager("baseRepository_")
|
@InjectManager("baseRepository_")
|
||||||
@@ -251,10 +244,7 @@ export default class FulfillmentModuleService<
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
await this.baseRepository_.serialize<FulfillmentTypes.FulfillmentDTO[]>(
|
await this.baseRepository_.serialize<FulfillmentTypes.FulfillmentDTO[]>(
|
||||||
fulfillments,
|
fulfillments
|
||||||
{
|
|
||||||
populate: true,
|
|
||||||
}
|
|
||||||
),
|
),
|
||||||
count,
|
count,
|
||||||
]
|
]
|
||||||
@@ -283,9 +273,7 @@ export default class FulfillmentModuleService<
|
|||||||
|
|
||||||
return await this.baseRepository_.serialize<
|
return await this.baseRepository_.serialize<
|
||||||
FulfillmentTypes.FulfillmentSetDTO | FulfillmentTypes.FulfillmentSetDTO[]
|
FulfillmentTypes.FulfillmentSetDTO | FulfillmentTypes.FulfillmentSetDTO[]
|
||||||
>(createdFulfillmentSets, {
|
>(createdFulfillmentSets)
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager("baseRepository_")
|
@InjectTransactionManager("baseRepository_")
|
||||||
@@ -351,9 +339,7 @@ export default class FulfillmentModuleService<
|
|||||||
|
|
||||||
return await this.baseRepository_.serialize<
|
return await this.baseRepository_.serialize<
|
||||||
FulfillmentTypes.ServiceZoneDTO | FulfillmentTypes.ServiceZoneDTO[]
|
FulfillmentTypes.ServiceZoneDTO | FulfillmentTypes.ServiceZoneDTO[]
|
||||||
>(createdServiceZones, {
|
>(createdServiceZones)
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager("baseRepository_")
|
@InjectTransactionManager("baseRepository_")
|
||||||
@@ -410,9 +396,7 @@ export default class FulfillmentModuleService<
|
|||||||
|
|
||||||
return await this.baseRepository_.serialize<
|
return await this.baseRepository_.serialize<
|
||||||
FulfillmentTypes.ShippingOptionDTO | FulfillmentTypes.ShippingOptionDTO[]
|
FulfillmentTypes.ShippingOptionDTO | FulfillmentTypes.ShippingOptionDTO[]
|
||||||
>(createdShippingOptions, {
|
>(createdShippingOptions)
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager("baseRepository_")
|
@InjectTransactionManager("baseRepository_")
|
||||||
@@ -469,9 +453,7 @@ export default class FulfillmentModuleService<
|
|||||||
return await this.baseRepository_.serialize<
|
return await this.baseRepository_.serialize<
|
||||||
| FulfillmentTypes.ShippingProfileDTO
|
| FulfillmentTypes.ShippingProfileDTO
|
||||||
| FulfillmentTypes.ShippingProfileDTO[]
|
| FulfillmentTypes.ShippingProfileDTO[]
|
||||||
>(createdShippingProfiles, {
|
>(createdShippingProfiles)
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager("baseRepository_")
|
@InjectTransactionManager("baseRepository_")
|
||||||
@@ -523,10 +505,7 @@ export default class FulfillmentModuleService<
|
|||||||
)
|
)
|
||||||
|
|
||||||
return await this.baseRepository_.serialize<FulfillmentTypes.GeoZoneDTO[]>(
|
return await this.baseRepository_.serialize<FulfillmentTypes.GeoZoneDTO[]>(
|
||||||
Array.isArray(data) ? createdGeoZones : createdGeoZones[0],
|
Array.isArray(data) ? createdGeoZones : createdGeoZones[0]
|
||||||
{
|
|
||||||
populate: true,
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -557,9 +536,7 @@ export default class FulfillmentModuleService<
|
|||||||
return await this.baseRepository_.serialize<
|
return await this.baseRepository_.serialize<
|
||||||
| FulfillmentTypes.ShippingOptionRuleDTO
|
| FulfillmentTypes.ShippingOptionRuleDTO
|
||||||
| FulfillmentTypes.ShippingOptionRuleDTO[]
|
| FulfillmentTypes.ShippingOptionRuleDTO[]
|
||||||
>(createdShippingOptionRules, {
|
>(createdShippingOptionRules)
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager("baseRepository_")
|
@InjectTransactionManager("baseRepository_")
|
||||||
@@ -627,10 +604,43 @@ export default class FulfillmentModuleService<
|
|||||||
}
|
}
|
||||||
|
|
||||||
return await this.baseRepository_.serialize<FulfillmentTypes.FulfillmentDTO>(
|
return await this.baseRepository_.serialize<FulfillmentTypes.FulfillmentDTO>(
|
||||||
fulfillment,
|
fulfillment
|
||||||
{
|
)
|
||||||
populate: true,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@InjectManager("baseRepository_")
|
||||||
|
async createReturnFulfillment(
|
||||||
|
data: FulfillmentTypes.CreateFulfillmentDTO,
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
): Promise<FulfillmentTypes.FulfillmentDTO> {
|
||||||
|
const { order, ...fulfillmentDataToCreate } = data
|
||||||
|
|
||||||
|
const fulfillment = await this.fulfillmentService_.create(
|
||||||
|
fulfillmentDataToCreate,
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
|
||||||
|
let fulfillmentThirdPartyData!: any
|
||||||
|
try {
|
||||||
|
fulfillmentThirdPartyData =
|
||||||
|
await this.fulfillmentProviderService_.createReturn(
|
||||||
|
fulfillment.provider_id,
|
||||||
|
fulfillment as Record<any, any>
|
||||||
|
)
|
||||||
|
await this.fulfillmentService_.update(
|
||||||
|
{
|
||||||
|
id: fulfillment.id,
|
||||||
|
data: fulfillmentThirdPartyData ?? {},
|
||||||
|
},
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
} catch (error) {
|
||||||
|
await this.fulfillmentService_.delete(fulfillment.id, sharedContext)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
|
||||||
|
return await this.baseRepository_.serialize<FulfillmentTypes.FulfillmentDTO>(
|
||||||
|
fulfillment
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -654,9 +664,7 @@ export default class FulfillmentModuleService<
|
|||||||
|
|
||||||
return await this.baseRepository_.serialize<
|
return await this.baseRepository_.serialize<
|
||||||
FulfillmentTypes.FulfillmentSetDTO | FulfillmentTypes.FulfillmentSetDTO[]
|
FulfillmentTypes.FulfillmentSetDTO | FulfillmentTypes.FulfillmentSetDTO[]
|
||||||
>(updatedFulfillmentSets, {
|
>(updatedFulfillmentSets)
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager("baseRepository_")
|
@InjectTransactionManager("baseRepository_")
|
||||||
@@ -865,9 +873,7 @@ export default class FulfillmentModuleService<
|
|||||||
|
|
||||||
return await this.baseRepository_.serialize<
|
return await this.baseRepository_.serialize<
|
||||||
FulfillmentTypes.ServiceZoneDTO | FulfillmentTypes.ServiceZoneDTO[]
|
FulfillmentTypes.ServiceZoneDTO | FulfillmentTypes.ServiceZoneDTO[]
|
||||||
>(toReturn, {
|
>(toReturn)
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager("baseRepository_")
|
@InjectTransactionManager("baseRepository_")
|
||||||
@@ -1110,9 +1116,7 @@ export default class FulfillmentModuleService<
|
|||||||
|
|
||||||
const serialized = await this.baseRepository_.serialize<
|
const serialized = await this.baseRepository_.serialize<
|
||||||
FulfillmentTypes.ShippingOptionDTO | FulfillmentTypes.ShippingOptionDTO[]
|
FulfillmentTypes.ShippingOptionDTO | FulfillmentTypes.ShippingOptionDTO[]
|
||||||
>(updatedShippingOptions, {
|
>(updatedShippingOptions)
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
return isString(idOrSelector) ? serialized[0] : serialized
|
return isString(idOrSelector) ? serialized[0] : serialized
|
||||||
}
|
}
|
||||||
@@ -1359,9 +1363,7 @@ export default class FulfillmentModuleService<
|
|||||||
|
|
||||||
const serialized = await this.baseRepository_.serialize<
|
const serialized = await this.baseRepository_.serialize<
|
||||||
FulfillmentTypes.GeoZoneDTO[]
|
FulfillmentTypes.GeoZoneDTO[]
|
||||||
>(updatedGeoZones, {
|
>(updatedGeoZones)
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
return Array.isArray(data) ? serialized : serialized[0]
|
return Array.isArray(data) ? serialized : serialized[0]
|
||||||
}
|
}
|
||||||
@@ -1393,9 +1395,7 @@ export default class FulfillmentModuleService<
|
|||||||
return await this.baseRepository_.serialize<
|
return await this.baseRepository_.serialize<
|
||||||
| FulfillmentTypes.ShippingOptionRuleDTO
|
| FulfillmentTypes.ShippingOptionRuleDTO
|
||||||
| FulfillmentTypes.ShippingOptionRuleDTO[]
|
| FulfillmentTypes.ShippingOptionRuleDTO[]
|
||||||
>(updatedShippingOptionRules, {
|
>(updatedShippingOptionRules)
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager("baseRepository_")
|
@InjectTransactionManager("baseRepository_")
|
||||||
@@ -1434,10 +1434,7 @@ export default class FulfillmentModuleService<
|
|||||||
|
|
||||||
const serialized =
|
const serialized =
|
||||||
await this.baseRepository_.serialize<FulfillmentTypes.FulfillmentDTO>(
|
await this.baseRepository_.serialize<FulfillmentTypes.FulfillmentDTO>(
|
||||||
fulfillment,
|
fulfillment
|
||||||
{
|
|
||||||
populate: true,
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return Array.isArray(serialized) ? serialized[0] : serialized
|
return Array.isArray(serialized) ? serialized[0] : serialized
|
||||||
@@ -1478,9 +1475,7 @@ export default class FulfillmentModuleService<
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await this.baseRepository_.serialize(fulfillment, {
|
const result = await this.baseRepository_.serialize(fulfillment)
|
||||||
populate: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
return Array.isArray(result) ? result[0] : result
|
return Array.isArray(result) ? result[0] : result
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,4 +101,12 @@ export default class FulfillmentProviderService extends ModulesSdkUtils.internal
|
|||||||
const provider = this.retrieveProviderRegistration(providerId)
|
const provider = this.retrieveProviderRegistration(providerId)
|
||||||
return await provider.cancelFulfillment(fulfillment)
|
return await provider.cancelFulfillment(fulfillment)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async createReturn(
|
||||||
|
providerId: string,
|
||||||
|
fulfillment: Record<string, unknown>,
|
||||||
|
) {
|
||||||
|
const provider = this.retrieveProviderRegistration(providerId)
|
||||||
|
return await provider.createReturnFulfillment(fulfillment)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Modules } from "@medusajs/modules-sdk"
|
import { Modules } from "@medusajs/modules-sdk"
|
||||||
import { ModuleJoinerConfig } from "@medusajs/types"
|
import { ModuleJoinerConfig } from "@medusajs/types"
|
||||||
import { MapToConfig } from "@medusajs/utils"
|
import { MapToConfig, pluralize } from "@medusajs/utils"
|
||||||
import { LineItem, ReturnReason } from "@models"
|
import { LineItem, ReturnReason } from "@models"
|
||||||
import Order from "./models/order"
|
import Order from "./models/order"
|
||||||
|
|
||||||
@@ -37,6 +37,7 @@ export const joinerConfig: ModuleJoinerConfig = {
|
|||||||
name: ["return_reason", "return_reasons"],
|
name: ["return_reason", "return_reasons"],
|
||||||
args: {
|
args: {
|
||||||
entity: ReturnReason.name,
|
entity: ReturnReason.name,
|
||||||
|
methodSuffix: pluralize(ReturnReason.name),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -29,16 +29,20 @@ export class ManualFulfillmentService extends AbstractFulfillmentProviderService
|
|||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
async validateOption(data: Record<string, unknown>): Promise<boolean> {
|
async validateOption(data: Record<string, any>): Promise<boolean> {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
async createFulfillment(): Promise<Record<string, unknown>> {
|
async createFulfillment(): Promise<Record<string, any>> {
|
||||||
// No data is being sent anywhere
|
// No data is being sent anywhere
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
|
||||||
async cancelFulfillment(fulfillment: Record<string, unknown>): Promise<any> {
|
async cancelFulfillment(): Promise<any> {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
|
||||||
|
async createReturnFulfillment(): Promise<any> {
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user