From dd4147314f9efafef99d654f454830766a8bd615 Mon Sep 17 00:00:00 2001 From: Riqwan Thamir Date: Mon, 12 Aug 2024 13:09:19 +0200 Subject: [PATCH] feat(core-flows,dashboard,medusa): fixes set of tiny bugs in claims flow (#8551) * feat(types,dashboard): ability to set shipping methods for claim * chore: fix a bunch of stuff * chore: update comment --- .../http/__tests__/claims/claims.spec.ts | 133 ++++++++++++++++-- .../dashboard/src/hooks/api/claims.tsx | 3 +- .../claim-create-form/claim-create-form.tsx | 6 +- .../src/order/steps/update-order-changes.ts | 43 ++++++ .../order/steps/update-shipping-methods.ts | 2 +- .../claim/claim-request-item-return.ts | 12 ++ .../workflows/claim/confirm-claim-request.ts | 19 ++- packages/core/types/src/order/mutations.ts | 5 + packages/core/types/src/order/service.ts | 47 +++++++ 9 files changed, 241 insertions(+), 29 deletions(-) create mode 100644 packages/core/core-flows/src/order/steps/update-order-changes.ts diff --git a/integration-tests/http/__tests__/claims/claims.spec.ts b/integration-tests/http/__tests__/claims/claims.spec.ts index 54c9910305..d370dc9910 100644 --- a/integration-tests/http/__tests__/claims/claims.spec.ts +++ b/integration-tests/http/__tests__/claims/claims.spec.ts @@ -19,6 +19,7 @@ medusaIntegrationTestRunner({ let baseClaim let order, order2 let returnShippingOption + let outboundShippingOption let shippingProfile let fulfillmentSet let returnReason @@ -348,6 +349,37 @@ medusaIntegrationTestRunner({ ], } + const outboundShippingOptionPayload = { + name: "Oubound shipping", + service_zone_id: fulfillmentSet.service_zones[0].id, + shipping_profile_id: shippingProfile.id, + provider_id: shippingProviderId, + price_type: "flat", + type: { + label: "Test type", + description: "Test description", + code: "test-code", + }, + prices: [ + { + currency_code: "usd", + amount: 1000, + }, + ], + rules: [ + { + operator: RuleOperator.EQ, + attribute: "is_return", + value: "false", + }, + { + operator: RuleOperator.EQ, + attribute: "enabled_in_store", + value: "true", + }, + ], + } + returnShippingOption = ( await api.post( "/admin/shipping-options", @@ -356,6 +388,14 @@ medusaIntegrationTestRunner({ ) ).data.shipping_option + outboundShippingOption = ( + await api.post( + "/admin/shipping-options", + outboundShippingOptionPayload, + adminHeaders + ) + ).data.shipping_option + item = order.items[0] await api.post( @@ -411,30 +451,69 @@ medusaIntegrationTestRunner({ const claimId2 = r2.data.claim.id const item2 = order2.items[0] - await api.post( - `/admin/claims/${claimId2}/inbound/items`, - { - items: [ - { - id: item2.id, - quantity: 1, - }, - ], + const { + data: { + order_preview: { + items: [previewItem], + }, }, + } = await api.post( + `/admin/claims/${claimId2}/inbound/items`, + { items: [{ id: item2.id, quantity: 1 }] }, + adminHeaders + ) + + // Delete & recreate again to ensure it works for both delete and create + await api.delete( + `/admin/claims/${claimId2}/inbound/items/${previewItem.actions[0].id}`, + adminHeaders + ) + + const { + data: { return: returnData }, + } = await api.post( + `/admin/claims/${claimId2}/inbound/items`, + { items: [{ id: item2.id, quantity: 1 }] }, + adminHeaders + ) + + await api.post( + `/admin/returns/${returnData.id}`, + { + location_id: location.id, + no_notification: true, + }, + adminHeaders + ) + + const { + data: { + order_preview: { shipping_methods: inboundShippingMethods }, + }, + } = await api.post( + `/admin/claims/${claimId2}/inbound/shipping-method`, + { shipping_option_id: returnShippingOption.id }, + adminHeaders + ) + const inboundShippingMethod = inboundShippingMethods.find( + (m) => m.shipping_option_id == returnShippingOption.id + ) + + // Delete & recreate again to ensure it works for both delete and create + await api.delete( + `/admin/claims/${claimId2}/inbound/shipping-method/${inboundShippingMethod.actions[0].id}`, adminHeaders ) await api.post( `/admin/claims/${claimId2}/inbound/shipping-method`, - { - shipping_option_id: returnShippingOption.id, - }, + { shipping_option_id: returnShippingOption.id }, adminHeaders ) + await api.post(`/admin/claims/${claimId2}/request`, {}, adminHeaders) const claimId = baseClaim.id - const item = order.items[0] let result = await api.post( @@ -453,9 +532,33 @@ medusaIntegrationTestRunner({ await api.post( `/admin/claims/${claimId}/inbound/shipping-method`, - { - shipping_option_id: returnShippingOption.id, + { shipping_option_id: returnShippingOption.id }, + adminHeaders + ) + + const { + data: { + order_preview: { shipping_methods: outboundShippingMethods }, }, + } = await api.post( + `/admin/claims/${claimId}/outbound/shipping-method`, + { shipping_option_id: outboundShippingOption.id }, + adminHeaders + ) + + const outboundShippingMethod = outboundShippingMethods.find( + (m) => m.shipping_option_id == outboundShippingOption.id + ) + + // Delete & recreate again to ensure it works for both delete and create + await api.delete( + `/admin/claims/${claimId}/outbound/shipping-method/${outboundShippingMethod.actions[0].id}`, + adminHeaders + ) + + await api.post( + `/admin/claims/${claimId}/outbound/shipping-method`, + { shipping_option_id: outboundShippingOption.id }, adminHeaders ) diff --git a/packages/admin-next/dashboard/src/hooks/api/claims.tsx b/packages/admin-next/dashboard/src/hooks/api/claims.tsx index d148598b89..8212de51f8 100644 --- a/packages/admin-next/dashboard/src/hooks/api/claims.tsx +++ b/packages/admin-next/dashboard/src/hooks/api/claims.tsx @@ -486,8 +486,9 @@ export const useDeleteClaimOutboundShipping = ( }) } -export const useRequestClaim = ( +export const useClaimConfirmRequest = ( id: string, + orderId: string, options?: UseMutationOptions< HttpTypes.AdminClaimResponse, Error, diff --git a/packages/admin-next/dashboard/src/routes/orders/order-create-claim/components/claim-create-form/claim-create-form.tsx b/packages/admin-next/dashboard/src/routes/orders/order-create-claim/components/claim-create-form/claim-create-form.tsx index c220f7603d..6d1294c795 100644 --- a/packages/admin-next/dashboard/src/routes/orders/order-create-claim/components/claim-create-form/claim-create-form.tsx +++ b/packages/admin-next/dashboard/src/routes/orders/order-create-claim/components/claim-create-form/claim-create-form.tsx @@ -41,6 +41,7 @@ import { useAddClaimInboundItems, useAddClaimInboundShipping, useCancelClaimRequest, + useClaimConfirmRequest, useDeleteClaimInboundShipping, useRemoveClaimInboundItem, useUpdateClaimInboundItem, @@ -86,7 +87,8 @@ export const ClaimCreateForm = ({ * MUTATIONS */ // TODO: implement confirm claim request - const { mutateAsync: confirmClaimRequest, isPending: isConfirming } = {} // useConfirmClaimRequest(claim.id, order.id) + const { mutateAsync: confirmClaimRequest, isPending: isConfirming } = + useClaimConfirmRequest(claim.id, order.id) const { mutateAsync: cancelClaimRequest, isPending: isCanceling } = useCancelClaimRequest(claim.id, order.id) @@ -94,7 +96,7 @@ export const ClaimCreateForm = ({ // TODO: implement update claim request const { mutateAsync: updateReturn, isPending: isUpdating } = useUpdateReturn( - claim.return_id!, + preview?.order_change?.return_id!, order.id ) diff --git a/packages/core/core-flows/src/order/steps/update-order-changes.ts b/packages/core/core-flows/src/order/steps/update-order-changes.ts new file mode 100644 index 0000000000..5bb7f507ba --- /dev/null +++ b/packages/core/core-flows/src/order/steps/update-order-changes.ts @@ -0,0 +1,43 @@ +import { IOrderModuleService, UpdateOrderChangeDTO } from "@medusajs/types" +import { + ModuleRegistrationName, + getSelectsAndRelationsFromObjectArray, +} from "@medusajs/utils" +import { StepResponse, createStep } from "@medusajs/workflows-sdk" + +export const updateOrderChangesStepId = "update-order-shopping-methods" +/** + * This step updates order change. + */ +export const updateOrderChangesStep = createStep( + updateOrderChangesStepId, + async (data: UpdateOrderChangeDTO[], { container }) => { + const service = container.resolve( + ModuleRegistrationName.ORDER + ) + + const { selects, relations } = getSelectsAndRelationsFromObjectArray(data, { + objectFields: ["metadata"], + }) + + const dataBeforeUpdate = await service.listOrderChanges( + { id: data.map((d) => d.id) }, + { relations, select: selects } + ) + + const updated = await service.updateOrderChanges(data) + + return new StepResponse(updated, dataBeforeUpdate) + }, + async (dataBeforeUpdate, { container }) => { + if (!dataBeforeUpdate?.length) { + return + } + + const service = container.resolve( + ModuleRegistrationName.ORDER + ) + + await service.updateOrderChanges(dataBeforeUpdate as UpdateOrderChangeDTO[]) + } +) diff --git a/packages/core/core-flows/src/order/steps/update-shipping-methods.ts b/packages/core/core-flows/src/order/steps/update-shipping-methods.ts index 18644f0ce7..2790d31ac5 100644 --- a/packages/core/core-flows/src/order/steps/update-shipping-methods.ts +++ b/packages/core/core-flows/src/order/steps/update-shipping-methods.ts @@ -10,7 +10,7 @@ import { StepResponse, createStep } from "@medusajs/workflows-sdk" export const updateOrderShippingMethodsStepId = "update-order-shopping-methods" /** - * This step updats order shipping methods. + * This step updates order shipping methods. */ export const updateOrderShippingMethodsStep = createStep( updateOrderShippingMethodsStepId, diff --git a/packages/core/core-flows/src/order/workflows/claim/claim-request-item-return.ts b/packages/core/core-flows/src/order/workflows/claim/claim-request-item-return.ts index 045c3bd053..014ec41a90 100644 --- a/packages/core/core-flows/src/order/workflows/claim/claim-request-item-return.ts +++ b/packages/core/core-flows/src/order/workflows/claim/claim-request-item-return.ts @@ -19,6 +19,7 @@ import { updateOrderClaimsStep } from "../../steps/claim/update-order-claims" import { createOrderChangeActionsStep } from "../../steps/create-order-change-actions" import { previewOrderChangeStep } from "../../steps/preview-order-change" import { createReturnsStep } from "../../steps/return/create-returns" +import { updateOrderChangesStep } from "../../steps/update-order-changes" import { throwIfIsCancelled, throwIfItemsDoesNotExistsInOrder, @@ -121,6 +122,17 @@ export const orderClaimRequestItemReturnWorkflow = createWorkflow( name: "order-change-query", }) + when({ createdReturn }, ({ createdReturn }) => { + return !!createdReturn?.length + }).then(() => { + updateOrderChangesStep([ + { + id: orderChange.id, + return_id: createdReturn?.[0]?.id, + }, + ]) + }) + orderClaimRequestItemReturnValidationStep({ order, items: input.items, diff --git a/packages/core/core-flows/src/order/workflows/claim/confirm-claim-request.ts b/packages/core/core-flows/src/order/workflows/claim/confirm-claim-request.ts index 8ff3c686ea..57fb85ffbc 100644 --- a/packages/core/core-flows/src/order/workflows/claim/confirm-claim-request.ts +++ b/packages/core/core-flows/src/order/workflows/claim/confirm-claim-request.ts @@ -84,11 +84,11 @@ function prepareFulfillmentData({ order.items!.map((i) => [i.id, i]) ) const fulfillmentItems = items.map((i) => { - const orderItem = orderItemsMap.get(i.item_id) ?? i.item + const orderItem = orderItemsMap.get(i.id) ?? i.item + return { line_item_id: i.item_id, - quantity: !isReturn ? i.quantity : undefined, - return_quantity: isReturn ? i.quantity : undefined, + quantity: i.quantity, title: orderItem.variant_title ?? orderItem.title, sku: orderItem.variant_sku || "", barcode: orderItem.variant_barcode || "", @@ -160,7 +160,7 @@ function extractShippingOption({ orderPreview, orderClaim, returnId }) { for (const action of modifiedShippingMethod_.actions) { if (action.action === ChangeActionType.SHIPPING_ADD) { - if (action.return_id === returnId) { + if (action.return?.id === returnId) { returnShippingMethod = shippingMethod } else if (action.claim_id === orderClaim.id) { claimShippingMethod = shippingMethod @@ -181,7 +181,9 @@ export const confirmClaimRequestWorkflowId = "confirm-claim-request" */ export const confirmClaimRequestWorkflow = createWorkflow( confirmClaimRequestWorkflowId, - function (input: ConfirmClaimRequestWorkflowInput): WorkflowResponse { + function ( + input: ConfirmClaimRequestWorkflowInput + ): WorkflowResponse { const orderClaim: OrderClaimDTO = useRemoteQueryStep({ entry_point: "order_claim", fields: ["id", "status", "order_id", "canceled_at"], @@ -196,11 +198,8 @@ export const confirmClaimRequestWorkflow = createWorkflow( "id", "version", "canceled_at", - "items.id", - "items.title", - "items.variant_title", - "items.variant_sku", - "items.variant_barcode", + "items.*", + "items.item.id", "shipping_address.*", ], variables: { id: orderClaim.order_id }, diff --git a/packages/core/types/src/order/mutations.ts b/packages/core/types/src/order/mutations.ts index cf24e4adab..94283e4168 100644 --- a/packages/core/types/src/order/mutations.ts +++ b/packages/core/types/src/order/mutations.ts @@ -922,6 +922,11 @@ export interface UpdateOrderChangeDTO { */ description?: string + /** + * The associated return's ID. + */ + return_id?: string | null + /** * The internal note of the order change. */ diff --git a/packages/core/types/src/order/service.ts b/packages/core/types/src/order/service.ts index f7d67e0d68..b125e3e1bb 100644 --- a/packages/core/types/src/order/service.ts +++ b/packages/core/types/src/order/service.ts @@ -5,6 +5,7 @@ import { Context } from "../shared-context" import { FilterableOrderAddressProps, FilterableOrderChangeActionProps, + FilterableOrderChangeProps, FilterableOrderClaimProps, FilterableOrderExchangeProps, FilterableOrderLineItemAdjustmentProps, @@ -2254,6 +2255,52 @@ export interface IOrderModuleService extends IModuleService { ): Promise // Order Change + /** + * This method retrieves a paginated list of order changes based on optional filters and configuration. + * + * @param {FilterableOrderChangeProps} filters - The filters to apply on the retrieved order changes. + * @param {FindConfig} config - The configurations determining how the order exchange is retrieved. Its properties, such as `select` or `relations`, accept the + * attributes or relations associated with a order exchange. + * @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module. + * @returns {Promise} The list of order changes. + * + * @example + * To retrieve a list of order changes using their IDs: + * + * ```ts + * const orderChanges = await orderModuleService.listOrderChanges({ + * id: ["123", "321"] + * }) + * ``` + * + * To specify relations that should be retrieved within the exchange: + * + * ```ts + * const orderChanges = await orderModuleService.listOrderChanges({ + * id: ["123", "321"] + * }, { + * relations: ["actions"] + * }) + * ``` + * + * By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter: + * + * ```ts + * const orderChanges = await orderModuleService.listOrderChanges({ + * id: ["123", "321"] + * }, { + * relations: ["actions"], + * take: 20, + * skip: 2 + * }) + * ``` + */ + listOrderChanges( + filters?: FilterableOrderChangeProps, + config?: FindConfig, + sharedContext?: Context + ): Promise + /** * This method retrieves an order change by its ID. *