feat: carry over promotions toggle on exchanges (#14128)

* feat: carry over promotions toggle on exchanges

* fix: inital flag value, return the flag on preview

* fix: validation of allocation type

* fix: revert client changes

* fix: invert condition

* feat: recompute adjustments when outbound item is updated

* fix: condition again

* fix: display more accurate inbound/outbound totals for exchanges

* fix: make exchanges specs green

* feat: more testing cases

* wip: pr feedback

* fix: use plural for the flag on Admin

* fix: schema test, route refactor

* feat: tooltip

* feat: refactor to use update workflow

* feat: display applied promotion per item on order details, show copy sku on hover

* feat: refactor edits and exchanges to have common flag toggle flow

* fix: delete empty file

* fix: exchange_id param query
This commit is contained in:
Frane Polić
2025-11-30 19:31:31 +01:00
committed by GitHub
parent 9d1f09ac7b
commit 5da51064d7
40 changed files with 1367 additions and 214 deletions

View File

@@ -0,0 +1,38 @@
import { updateOrderChangeWorkflow } from "@medusajs/core-flows"
import { HttpTypes, RemoteQueryFunction } from "@medusajs/framework/types"
import {
AuthenticatedMedusaRequest,
MedusaResponse,
} from "@medusajs/framework/http"
import { AdminPostOrderChangesReqSchemaType } from "../validators"
import { ContainerRegistrationKeys } from "@medusajs/framework/utils"
export const POST = async (
req: AuthenticatedMedusaRequest<AdminPostOrderChangesReqSchemaType>,
res: MedusaResponse<HttpTypes.AdminOrderChangeResponse>
) => {
const { id } = req.params
const { carry_over_promotions } = req.validatedBody
const query = req.scope.resolve<RemoteQueryFunction>(
ContainerRegistrationKeys.QUERY
)
const workflow = updateOrderChangeWorkflow(req.scope)
await workflow.run({
input: {
id,
carry_over_promotions,
},
})
const result = await query.graph({
entity: "order_change",
filters: {
...req.filterableFields,
id,
},
fields: req.queryConfig.fields,
})
res.status(200).json({ order_change: result.data[0] })
}

View File

@@ -0,0 +1,24 @@
import { MiddlewareRoute } from "@medusajs/framework/http"
import {
validateAndTransformBody,
validateAndTransformQuery,
} from "@medusajs/framework"
import * as QueryConfig from "./query-config"
import {
AdminPostOrderChangesReqSchema,
AdminOrderChangeParams,
} from "./validators"
export const adminOrderChangesRoutesMiddlewares: MiddlewareRoute[] = [
{
method: ["POST"],
matcher: "/admin/order-changes/:id",
middlewares: [
validateAndTransformBody(AdminPostOrderChangesReqSchema),
validateAndTransformQuery(
AdminOrderChangeParams,
QueryConfig.retrieveTransformQueryConfig
),
],
},
]

View File

@@ -0,0 +1,32 @@
export const defaultAdminRetrieveOrderChangeFields = [
"id",
"order_id",
"return_id",
"claim_id",
"exchange_id",
"version",
"change_type",
"*actions",
"description",
"status",
"internal_note",
"created_by",
"requested_by",
"requested_at",
"confirmed_by",
"confirmed_at",
"declined_by",
"declined_reason",
"metadata",
"declined_at",
"canceled_by",
"canceled_at",
"created_at",
"updated_at",
"carry_over_promotions",
]
export const retrieveTransformQueryConfig = {
defaults: defaultAdminRetrieveOrderChangeFields,
isList: false,
}

View File

@@ -0,0 +1,22 @@
import { z } from "zod"
import { createOperatorMap, createSelectParams } from "../../utils/validators"
export const AdminOrderChangeParams = createSelectParams().merge(
z.object({
id: z.union([z.string(), z.array(z.string())]).optional(),
status: z.union([z.string(), z.array(z.string())]).optional(),
change_type: z.union([z.string(), z.array(z.string())]).optional(),
created_at: createOperatorMap().optional(),
updated_at: createOperatorMap().optional(),
deleted_at: createOperatorMap().optional(),
})
)
export const AdminPostOrderChangesReqSchema = z.object({
carry_over_promotions: z.boolean(),
})
export type AdminPostOrderChangesReqSchemaType = z.infer<
typeof AdminPostOrderChangesReqSchema
>