fix(dashboard, js-sdk): undefined RMA activity items (#9649)
**What** - fix for showing removed items in rma flows --- DEPENDS ON https://github.com/medusajs/medusa/pull/9646 FIXES CC-597
This commit is contained in:
1 parent
6fa98b6a4d
commit
24a1b81fb2
7 files changed
+155
-35
No files matched your search
@@ -56,6 +56,10 @@ export const useRequestOrderEdit = (
|
|||||||
queryClient.invalidateQueries({
|
queryClient.invalidateQueries({
|
||||||
queryKey: ordersQueryKeys.changes(id),
|
queryKey: ordersQueryKeys.changes(id),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
queryClient.invalidateQueries({
|
||||||
|
queryKey: ordersQueryKeys.lineItems(id),
|
||||||
|
})
|
||||||
options?.onSuccess?.(data, variables, context)
|
options?.onSuccess?.(data, variables, context)
|
||||||
},
|
},
|
||||||
...options,
|
...options,
|
||||||
@@ -85,6 +89,10 @@ export const useConfirmOrderEdit = (
|
|||||||
queryKey: ordersQueryKeys.changes(id),
|
queryKey: ordersQueryKeys.changes(id),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
queryClient.invalidateQueries({
|
||||||
|
queryKey: ordersQueryKeys.lineItems(id),
|
||||||
|
})
|
||||||
|
|
||||||
queryClient.invalidateQueries({
|
queryClient.invalidateQueries({
|
||||||
queryKey: reservationItemsQueryKeys.lists(),
|
queryKey: reservationItemsQueryKeys.lists(),
|
||||||
})
|
})
|
||||||
@@ -121,6 +129,10 @@ export const useCancelOrderEdit = (
|
|||||||
queryClient.invalidateQueries({
|
queryClient.invalidateQueries({
|
||||||
queryKey: ordersQueryKeys.changes(orderId),
|
queryKey: ordersQueryKeys.changes(orderId),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
queryClient.invalidateQueries({
|
||||||
|
queryKey: ordersQueryKeys.lineItems(id),
|
||||||
|
})
|
||||||
options?.onSuccess?.(data, variables, context)
|
options?.onSuccess?.(data, variables, context)
|
||||||
},
|
},
|
||||||
...options,
|
...options,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { FetchError } from "@medusajs/js-sdk"
|
import { FetchError } from "@medusajs/js-sdk"
|
||||||
import { HttpTypes } from "@medusajs/types"
|
import { AdminOrderItemsFilters, HttpTypes } from "@medusajs/types"
|
||||||
import {
|
import {
|
||||||
QueryKey,
|
QueryKey,
|
||||||
useMutation,
|
useMutation,
|
||||||
@@ -12,13 +12,10 @@ import { queryClient } from "../../lib/query-client"
|
|||||||
import { queryKeysFactory, TQueryKey } from "../../lib/query-key-factory"
|
import { queryKeysFactory, TQueryKey } from "../../lib/query-key-factory"
|
||||||
|
|
||||||
const ORDERS_QUERY_KEY = "orders" as const
|
const ORDERS_QUERY_KEY = "orders" as const
|
||||||
const _orderKeys = queryKeysFactory(ORDERS_QUERY_KEY) as TQueryKey<
|
const _orderKeys = queryKeysFactory(ORDERS_QUERY_KEY) as TQueryKey<"orders"> & {
|
||||||
"orders",
|
|
||||||
any,
|
|
||||||
string
|
|
||||||
> & {
|
|
||||||
preview: (orderId: string) => any
|
preview: (orderId: string) => any
|
||||||
changes: (orderId: string) => any
|
changes: (orderId: string) => any
|
||||||
|
lineItems: (orderId: string) => any
|
||||||
}
|
}
|
||||||
|
|
||||||
_orderKeys.preview = function (id: string) {
|
_orderKeys.preview = function (id: string) {
|
||||||
@@ -29,6 +26,10 @@ _orderKeys.changes = function (id: string) {
|
|||||||
return [this.detail(id), "changes"]
|
return [this.detail(id), "changes"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_orderKeys.lineItems = function (id: string) {
|
||||||
|
return [this.detail(id), "lineItems"]
|
||||||
|
}
|
||||||
|
|
||||||
export const ordersQueryKeys = _orderKeys
|
export const ordersQueryKeys = _orderKeys
|
||||||
|
|
||||||
export const useOrder = (
|
export const useOrder = (
|
||||||
@@ -97,7 +98,7 @@ export const useOrderChanges = (
|
|||||||
options?: Omit<
|
options?: Omit<
|
||||||
UseQueryOptions<
|
UseQueryOptions<
|
||||||
HttpTypes.AdminOrderChangesResponse,
|
HttpTypes.AdminOrderChangesResponse,
|
||||||
Error,
|
FetchError,
|
||||||
HttpTypes.AdminOrderChangesResponse,
|
HttpTypes.AdminOrderChangesResponse,
|
||||||
QueryKey
|
QueryKey
|
||||||
>,
|
>,
|
||||||
@@ -113,6 +114,28 @@ export const useOrderChanges = (
|
|||||||
return { ...data, ...rest }
|
return { ...data, ...rest }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const useOrderLineItems = (
|
||||||
|
id: string,
|
||||||
|
query?: HttpTypes.AdminOrderItemsFilters,
|
||||||
|
options?: Omit<
|
||||||
|
UseQueryOptions<
|
||||||
|
HttpTypes.AdminOrderLineItemsListResponse,
|
||||||
|
FetchError,
|
||||||
|
HttpTypes.AdminOrderLineItemsListResponse,
|
||||||
|
QueryKey
|
||||||
|
>,
|
||||||
|
"queryFn" | "queryKey"
|
||||||
|
>
|
||||||
|
) => {
|
||||||
|
const { data, ...rest } = useQuery({
|
||||||
|
queryFn: async () => sdk.admin.order.listLineItems(id, query),
|
||||||
|
queryKey: ordersQueryKeys.lineItems(id),
|
||||||
|
...options,
|
||||||
|
})
|
||||||
|
|
||||||
|
return { ...data, ...rest }
|
||||||
|
}
|
||||||
|
|
||||||
export const useCreateOrderFulfillment = (
|
export const useCreateOrderFulfillment = (
|
||||||
orderId: string,
|
orderId: string,
|
||||||
options?: UseMutationOptions<
|
options?: UseMutationOptions<
|
||||||
|
|||||||
+5
-9
@@ -54,7 +54,7 @@ function ActivityItems(props: ActivityItemsProps) {
|
|||||||
<Popover.Content
|
<Popover.Content
|
||||||
align="center"
|
align="center"
|
||||||
side="top"
|
side="top"
|
||||||
className="bg-ui-bg-component p-0 max-w-[200px] focus-visible:outline-none"
|
className="bg-ui-bg-component max-w-[200px] p-0 focus-visible:outline-none"
|
||||||
>
|
>
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
{!!itemsToSend?.length && (
|
{!!itemsToSend?.length && (
|
||||||
@@ -73,12 +73,10 @@ function ActivityItems(props: ActivityItemsProps) {
|
|||||||
{item.quantity}x
|
{item.quantity}x
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<Thumbnail
|
<Thumbnail src={originalItem?.thumbnail} />
|
||||||
src={originalItem?.variant?.product?.thumbnail}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Text className="txt-compact-small text-ui-fg-subtle truncate">
|
<Text className="txt-compact-small text-ui-fg-subtle truncate">
|
||||||
{`${originalItem?.variant?.title} · ${originalItem?.variant?.product?.title}`}
|
{`${originalItem?.variant_title} · ${originalItem?.product_title}`}
|
||||||
</Text>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
@@ -105,12 +103,10 @@ function ActivityItems(props: ActivityItemsProps) {
|
|||||||
{item.quantity}x
|
{item.quantity}x
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<Thumbnail
|
<Thumbnail src={originalItem?.thumbnail} />
|
||||||
src={originalItem?.variant?.product?.thumbnail}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Text className="txt-compact-small text-ui-fg-subtle truncate">
|
<Text className="txt-compact-small text-ui-fg-subtle truncate">
|
||||||
{`${originalItem?.variant?.title} · ${originalItem?.variant?.product?.title}`}
|
{`${originalItem?.variant_title} · ${originalItem?.product_title}`}
|
||||||
</Text>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
+75
-19
@@ -16,7 +16,7 @@ import {
|
|||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
|
|
||||||
import { AdminOrderLineItem } from "@medusajs/types"
|
import { AdminOrderLineItem } from "@medusajs/types"
|
||||||
import { useOrderChanges } from "../../../../../hooks/api"
|
import { useOrderChanges, useOrderLineItems } from "../../../../../hooks/api"
|
||||||
import { useCancelClaim, useClaims } from "../../../../../hooks/api/claims"
|
import { useCancelClaim, useClaims } from "../../../../../hooks/api/claims"
|
||||||
import {
|
import {
|
||||||
useCancelExchange,
|
useCancelExchange,
|
||||||
@@ -112,14 +112,36 @@ type Activity = {
|
|||||||
const useActivityItems = (order: AdminOrder): Activity[] => {
|
const useActivityItems = (order: AdminOrder): Activity[] => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const itemsMap = useMemo(
|
const { order_changes: orderChanges = [] } = useOrderChanges(order.id, {
|
||||||
() => new Map(order?.items?.map((i) => [i.id, i])),
|
change_type: ["edit", "claim", "exchange", "return"],
|
||||||
[order.items]
|
})
|
||||||
|
|
||||||
|
const missingLineItemIds = getMissingLineItemIds(order, orderChanges)
|
||||||
|
const { order_items: removedLineItems = [] } = useOrderLineItems(
|
||||||
|
order.id,
|
||||||
|
|
||||||
|
{
|
||||||
|
fields: "+quantity",
|
||||||
|
item_id: missingLineItemIds,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
enabled: !!orderChanges.length,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const { order_changes: orderChanges = [] } = useOrderChanges(order.id, {
|
const itemsMap = useMemo(() => {
|
||||||
change_type: "edit",
|
const _itemsMap = new Map(order?.items?.map((i) => [i.id, i]))
|
||||||
})
|
|
||||||
|
for (const id of missingLineItemIds) {
|
||||||
|
const i = removedLineItems.find((i) => i.item.id === id)
|
||||||
|
|
||||||
|
if (i) {
|
||||||
|
_itemsMap.set(id, { ...i.item, quantity: i.quantity }) // copy quantity from OrderItem to OrderLineItem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _itemsMap
|
||||||
|
}, [order.items, removedLineItems, missingLineItemIds])
|
||||||
|
|
||||||
const { returns = [] } = useReturns({
|
const { returns = [] } = useReturns({
|
||||||
order_id: order.id,
|
order_id: order.id,
|
||||||
@@ -226,9 +248,7 @@ const useActivityItems = (order: AdminOrder): Activity[] => {
|
|||||||
items.push({
|
items.push({
|
||||||
title: t("orders.activity.events.fulfillment.delivered"),
|
title: t("orders.activity.events.fulfillment.delivered"),
|
||||||
timestamp: fulfillment.delivered_at,
|
timestamp: fulfillment.delivered_at,
|
||||||
children: (
|
children: <FulfillmentCreatedBody fulfillment={fulfillment} />,
|
||||||
<FulfillmentCreatedBody fulfillment={fulfillment} />
|
|
||||||
),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,7 +354,7 @@ const useActivityItems = (order: AdminOrder): Activity[] => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const edit of orderChanges) {
|
for (const edit of orderChanges.filter((oc) => oc.change_type === "edit")) {
|
||||||
const isConfirmed = edit.status === "confirmed"
|
const isConfirmed = edit.status === "confirmed"
|
||||||
const isPending = edit.status === "pending"
|
const isPending = edit.status === "pending"
|
||||||
|
|
||||||
@@ -390,7 +410,16 @@ const useActivityItems = (order: AdminOrder): Activity[] => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return [...sortedActivities, createdAt]
|
return [...sortedActivities, createdAt]
|
||||||
}, [order, payments, returns, exchanges, orderChanges, notes, isLoading])
|
}, [
|
||||||
|
order,
|
||||||
|
payments,
|
||||||
|
returns,
|
||||||
|
exchanges,
|
||||||
|
orderChanges,
|
||||||
|
notes,
|
||||||
|
isLoading,
|
||||||
|
itemsMap,
|
||||||
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
type OrderActivityItemProps = PropsWithChildren<{
|
type OrderActivityItemProps = PropsWithChildren<{
|
||||||
@@ -813,14 +842,13 @@ const OrderEditBody = ({
|
|||||||
itemsMap,
|
itemsMap,
|
||||||
}: {
|
}: {
|
||||||
edit: AdminOrderChange
|
edit: AdminOrderChange
|
||||||
isRequested: boolean
|
itemsMap: Map<string, AdminOrderLineItem>
|
||||||
itemsMap: Record<string, AdminOrderLineItem>
|
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const [itemsAdded, itemsRemoved] = useMemo(
|
const [itemsAdded, itemsRemoved] = useMemo(
|
||||||
() => countItemsChange(edit.actions, itemsMap),
|
() => countItemsChange(edit.actions, itemsMap),
|
||||||
[edit]
|
[edit, itemsMap]
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -840,21 +868,24 @@ const OrderEditBody = ({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns count of added and removed item quantity
|
||||||
|
*/
|
||||||
function countItemsChange(
|
function countItemsChange(
|
||||||
actions: AdminOrderChange["actions"],
|
actions: AdminOrderChange["actions"],
|
||||||
itemsMap: Record<string, AdminOrderLineItem>
|
itemsMap: Map<string, AdminOrderLineItem>
|
||||||
) {
|
) {
|
||||||
let added = 0
|
let added = 0
|
||||||
let removed = 0
|
let removed = 0
|
||||||
|
|
||||||
actions.forEach((action) => {
|
actions.forEach((action) => {
|
||||||
if (action.action === "ITEM_ADD") {
|
if (action.action === "ITEM_ADD") {
|
||||||
added += action.details.quantity
|
added += action.details!.quantity as number
|
||||||
}
|
}
|
||||||
if (action.action === "ITEM_UPDATE") {
|
if (action.action === "ITEM_UPDATE") {
|
||||||
const newQuantity: number = action.details!.quantity
|
const newQuantity = action.details!.quantity as number
|
||||||
const originalQuantity: number | undefined = itemsMap.get(
|
const originalQuantity: number | undefined = itemsMap.get(
|
||||||
action.details!.reference_id
|
action.details!.reference_id as string
|
||||||
)?.quantity
|
)?.quantity
|
||||||
|
|
||||||
if (typeof originalQuantity === "number") {
|
if (typeof originalQuantity === "number") {
|
||||||
@@ -872,3 +903,28 @@ function countItemsChange(
|
|||||||
|
|
||||||
return [added, removed]
|
return [added, removed]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get IDs of missing line items that were removed from the order.
|
||||||
|
*/
|
||||||
|
function getMissingLineItemIds(order: AdminOrder, changes: AdminOrderChange[]) {
|
||||||
|
if (!changes?.length) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
const retIds = new Set<string>()
|
||||||
|
const existingItemsMap = new Map(order.items.map((item) => [item.id, true]))
|
||||||
|
|
||||||
|
changes.forEach((change) => {
|
||||||
|
change.actions.forEach((action) => {
|
||||||
|
if (
|
||||||
|
(action.details!.reference_id as string).startsWith("ordli_") &&
|
||||||
|
!existingItemsMap.has(action.details!.reference_id as string)
|
||||||
|
) {
|
||||||
|
retIds.add(action.details!.reference_id as string)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return Array.from(retIds)
|
||||||
|
}
|
||||||
@@ -148,4 +148,17 @@ export class Order {
|
|||||||
headers,
|
headers,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async listLineItems(
|
||||||
|
id: string,
|
||||||
|
queryParams?: FindParams & HttpTypes.AdminOrderItemsFilters,
|
||||||
|
headers?: ClientHeaders
|
||||||
|
) {
|
||||||
|
return await this.client.fetch<
|
||||||
|
PaginatedResponse<HttpTypes.AdminOrderLineItemsListResponse>
|
||||||
|
>(`/admin/orders/${id}/line-items`, {
|
||||||
|
query: queryParams,
|
||||||
|
headers,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -39,6 +39,19 @@ export interface AdminOrderChange
|
|||||||
actions: AdminOrderChangeAction[]
|
actions: AdminOrderChangeAction[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AdminOrderItem {
|
||||||
|
order_id: string
|
||||||
|
item_id: string
|
||||||
|
version: number
|
||||||
|
history: {
|
||||||
|
version: {
|
||||||
|
from: number
|
||||||
|
to: number
|
||||||
|
}
|
||||||
|
}
|
||||||
|
item: AdminOrderLineItem
|
||||||
|
}
|
||||||
|
|
||||||
export interface AdminOrderChangeAction
|
export interface AdminOrderChangeAction
|
||||||
extends Omit<BaseOrderChangeAction, "order_change" | "order"> {
|
extends Omit<BaseOrderChangeAction, "order_change" | "order"> {
|
||||||
order_change: AdminOrderChange
|
order_change: AdminOrderChange
|
||||||
|
|||||||
@@ -14,6 +14,13 @@ export interface AdminOrderFilters extends FindParams, BaseOrderFilters {
|
|||||||
updated_at?: OperatorMap<string>
|
updated_at?: OperatorMap<string>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AdminOrderItemsFilters extends FindParams {
|
||||||
|
id?: string[] | string
|
||||||
|
item_id?: string[] | string
|
||||||
|
order_id?: string[] | string
|
||||||
|
version?: number[] | number
|
||||||
|
}
|
||||||
|
|
||||||
export interface AdminOrderChangesFilters extends BaseOrderChangesFilters {}
|
export interface AdminOrderChangesFilters extends BaseOrderChangesFilters {}
|
||||||
|
|
||||||
export interface AdminOrderItemsFilters extends FindParams {
|
export interface AdminOrderItemsFilters extends FindParams {
|
||||||
|
|||||||
Reference in new issue
Block a user