Skip to content

Commit 9e1e708

Browse files
authored
feat(core-flows,order,medusa,types): update item metadata on item_update change action (#14570)
## Summary **What** — What changes are introduced in this PR? Allow to update item `metadata` on `ITEM_UPDATE` order change action. **Why** — Why are these changes relevant or necessary? You are unable to update a draft order item `metadata`. **How** — How have these changes been implemented? Update item `metadata` if specified in the order change action details when the `ITEM_UPDATE` processing handler gets executed. **Testing** — How have these changes been tested, or how can the reviewer test the feature? Integration tests. --- ## Examples Provide examples or code snippets that demonstrate how this feature works, or how it can be used in practice. This helps with documentation and ensures maintainers can quickly understand and verify the change. ```ts // Example usage ``` --- ## Checklist Please ensure the following before requesting a review: - [x] I have added a **changeset** for this PR - Every non-breaking change should be marked as a **patch** - To add a changeset, run `yarn changeset` and follow the prompts - [x] The changes are covered by relevant **tests** - [x] I have verified the code works as intended locally - [x] I have linked the related issue(s) if applicable --- ## Additional Context Add any additional context, related issues, or references that might help the reviewer understand this PR. closes #14481 --- > [!NOTE] > Adds support for updating item `metadata` during draft order item updates. > > - Core flow `update-draft-order-item` now includes `metadata` in action `details` for `ITEM_UPDATE` > - Order processing merges provided `metadata` into both `item.detail.metadata` and `item.metadata` > - Types expanded to include optional `metadata` for new/existing items and related inputs > - Admin validators allow `metadata` in draft order item update payloads > - Order transform maps `detail.metadata` to exposed item `metadata` > - Integration test added to verify metadata update behavior > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 350a79e. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup>
1 parent 843dbfe commit 9e1e708

File tree

16 files changed

+174
-13
lines changed

16 files changed

+174
-13
lines changed

.changeset/seven-windows-brake.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
"@medusajs/core-flows": patch
3+
"@medusajs/order": patch
4+
"@medusajs/types": patch
5+
"@medusajs/medusa": patch
6+
---
7+
8+
feat(core-flows,order,medusa,types): update item metadata on item_update change action

integration-tests/http/__tests__/draft-order/admin/draft-order.spec.ts

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -807,6 +807,97 @@ medusaIntegrationTestRunner({
807807

808808
expect(reservations.length).toBe(0)
809809
})
810+
811+
it("should update item metadata", async () => {
812+
// Create edit
813+
await api.post(
814+
`/admin/draft-orders/${testDraftOrder.id}/edit`,
815+
{},
816+
adminHeaders
817+
)
818+
819+
// Add item with initial metadata
820+
let orderPreview = (
821+
await api.post(
822+
`/admin/draft-orders/${testDraftOrder.id}/edit/items`,
823+
{
824+
items: [
825+
{
826+
variant_id: product.variants.find(
827+
(v) => v.title === "L shirt"
828+
).id,
829+
quantity: 1,
830+
metadata: { initial: "value", custom_field: "original" },
831+
},
832+
],
833+
},
834+
adminHeaders
835+
)
836+
).data.draft_order_preview
837+
838+
const itemToUpdate = orderPreview.items.find(
839+
(i) => i.subtitle === "L shirt"
840+
)
841+
expect(itemToUpdate.metadata).toEqual({
842+
initial: "value",
843+
custom_field: "original",
844+
})
845+
846+
await api.post(
847+
`/admin/draft-orders/${testDraftOrder.id}/edit/confirm`,
848+
{},
849+
adminHeaders
850+
)
851+
852+
await api.post(
853+
`/admin/draft-orders/${testDraftOrder.id}/edit`,
854+
{},
855+
adminHeaders
856+
)
857+
858+
// Update item with new metadata
859+
orderPreview = (
860+
await api.post(
861+
`/admin/draft-orders/${testDraftOrder.id}/edit/items/item/${itemToUpdate.id}`,
862+
{
863+
quantity: 2,
864+
metadata: { updated: "metadata", custom_field: "modified" },
865+
},
866+
adminHeaders
867+
)
868+
).data.draft_order_preview
869+
870+
const updatedItem = orderPreview.items.find(
871+
(i) => i.subtitle === "L shirt"
872+
)
873+
expect(updatedItem.quantity).toBe(2)
874+
expect(updatedItem.metadata).toEqual({
875+
updated: "metadata",
876+
initial: "value",
877+
custom_field: "modified",
878+
})
879+
880+
await api.post(
881+
`/admin/draft-orders/${testDraftOrder.id}/edit/confirm`,
882+
{},
883+
adminHeaders
884+
)
885+
886+
const order = (
887+
await api.get(
888+
`/admin/draft-orders/${testDraftOrder.id}`,
889+
adminHeaders
890+
)
891+
).data.draft_order
892+
893+
expect(
894+
order.items.find((i) => i.subtitle === "L shirt").metadata
895+
).toEqual({
896+
updated: "metadata",
897+
initial: "value",
898+
custom_field: "modified",
899+
})
900+
})
810901
})
811902

812903
describe("POST /draft-orders/:id/edit/promotions", () => {

packages/core/core-flows/src/draft-order/workflows/update-draft-order-item.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ export const updateDraftOrderItemWorkflow = createWorkflow(
107107
unit_price: item.unit_price,
108108
compare_at_unit_price: item.compare_at_unit_price,
109109
quantity_diff: quantityDiff,
110+
metadata: item.metadata,
110111
},
111112
}
112113
})

packages/core/core-flows/src/order/workflows/claim/claim-item.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,14 @@ export type OrderClaimItemValidationStepInput = {
4545
/**
4646
* This step validates that claim items can be added to a claim. If the
4747
* order or claim is canceled, or the order change is not active, the step will throw an error.
48-
*
48+
*
4949
* :::note
50-
*
50+
*
5151
* You can retrieve an order, order claim, and order change details using [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query),
5252
* or [useQueryGraphStep](https://docs.medusajs.com/resources/references/medusa-workflows/steps/useQueryGraphStep).
53-
*
53+
*
5454
* :::
55-
*
55+
*
5656
* @example
5757
* const data = orderClaimItemValidationStep({
5858
* order: {
@@ -88,12 +88,12 @@ export const orderClaimItemValidationStep = createStep(
8888

8989
export const orderClaimItemWorkflowId = "claim-item"
9090
/**
91-
* This workflow adds order items to a claim as claim items. It's used by the
91+
* This workflow adds order items to a claim as claim items. It's used by the
9292
* [Add Claim Items Admin API Route](https://docs.medusajs.com/api/admin#claims_postclaimsidclaimitems).
93-
*
93+
*
9494
* You can use this workflow within your customizations or your own custom workflows, allowing you to add items to a claim
9595
* for an order in your custom flows.
96-
*
96+
*
9797
* @example
9898
* const { result } = await orderClaimItemWorkflow(container)
9999
* .run({
@@ -107,9 +107,9 @@ export const orderClaimItemWorkflowId = "claim-item"
107107
* ]
108108
* }
109109
* })
110-
*
110+
*
111111
* @summary
112-
*
112+
*
113113
* Add order items to a claim as claim items.
114114
*/
115115
export const orderClaimItemWorkflow = createWorkflow(
@@ -172,6 +172,7 @@ export const orderClaimItemWorkflow = createWorkflow(
172172
reference_id: item.id,
173173
reason: item.reason,
174174
quantity: item.quantity,
175+
metadata: item.metadata,
175176
},
176177
}))
177178
}

packages/core/core-flows/src/order/workflows/order-edit/order-edit-update-item-quantity.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ export const orderEditUpdateItemQuantityWorkflow = createWorkflow(
182182
unit_price: item.unit_price,
183183
compare_at_unit_price: item.compare_at_unit_price,
184184
quantity_diff: quantityDiff,
185+
metadata: item.metadata,
185186
},
186187
}
187188
})

packages/core/types/src/http/claim/admin/payloads.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ interface AdminClaimAddItems {
3030
* An internal note viewed by admin users only.
3131
*/
3232
internal_note?: string
33+
/**
34+
* Key-value pairs of custom data.
35+
*/
36+
metadata?: Record<string, unknown> | null
3337
}[]
3438
}
3539

@@ -120,13 +124,15 @@ export interface AdminCreateClaim {
120124
}
121125

122126
export interface AdminAddClaimItems extends AdminClaimAddItems {}
123-
export interface AdminUpdateClaimItem extends Omit<AdminClaimUpdateItem, "description"> {}
127+
export interface AdminUpdateClaimItem
128+
extends Omit<AdminClaimUpdateItem, "description"> {}
124129

125130
export interface AdminAddClaimInboundItems extends AdminClaimAddItems {}
126131
export interface AdminUpdateClaimInboundItem extends AdminClaimUpdateItem {}
127132

128133
export interface AdminAddClaimOutboundItems extends AdminClaimAddItems {}
129-
export interface AdminUpdateClaimOutboundItem extends Omit<AdminClaimUpdateItem, "description"> {}
134+
export interface AdminUpdateClaimOutboundItem
135+
extends Omit<AdminClaimUpdateItem, "description"> {}
130136

131137
export interface AdminClaimAddInboundShipping
132138
extends AdminClaimAddShippingMethod {}

packages/core/types/src/workflow/order/items.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ interface ExistingItem {
5959
* A note viewed by admins only related to the item.
6060
*/
6161
internal_note?: string | null
62+
/**
63+
* Custom key-value pairs to store additional information about the item.
64+
*/
65+
metadata?: Record<string, any> | null
6266
}
6367

6468
/**

packages/medusa/src/api/admin/claims/validators.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ export const AdminPostClaimItemsReqSchema = z.object({
164164
reason: z.nativeEnum(ClaimReason).optional(),
165165
description: z.string().optional(),
166166
internal_note: z.string().optional(),
167+
metadata: z.record(z.string(), z.unknown()).nullish(),
167168
})
168169
),
169170
})
@@ -212,4 +213,6 @@ export type AdminPostClaimsConfirmRequestReqSchemaType = z.infer<
212213

213214
export const AdminDeleteClaimItemActionSchema = createSelectParams()
214215

215-
export type AdminDeleteClaimItemActionSchemaType = z.infer<typeof AdminDeleteClaimItemActionSchema>
216+
export type AdminDeleteClaimItemActionSchemaType = z.infer<
217+
typeof AdminDeleteClaimItemActionSchema
218+
>

packages/medusa/src/api/admin/draft-orders/validators.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ export const AdminUpdateDraftOrderItem = z.object({
137137
unit_price: z.number().nullish(),
138138
compare_at_unit_price: z.number().nullish(),
139139
internal_note: z.string().optional(),
140+
metadata: z.record(z.string(), z.unknown()).nullish(),
140141
})
141142

142143
export type AdminUpdateDraftOrderActionItemType = z.infer<

packages/medusa/src/api/admin/order-edits/validators.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ export const AdminPostOrderEditsUpdateItemQuantityReqSchema = z.object({
6666
unit_price: z.number().nullish(),
6767
compare_at_unit_price: z.number().nullish(),
6868
internal_note: z.string().nullish().optional(),
69+
metadata: z.record(z.string(), z.unknown()).nullish(),
6970
})
7071

7172
export type AdminPostOrderEditsUpdateItemQuantityReqSchemaType = z.infer<

0 commit comments

Comments
 (0)