feat(adshboard,types,medusa): enable adding notes/return reason to inbound claims (#8488)

* wip: setup UI

* wip: rendering modal, adding claim items, create checks

* fix: make form work after merge

* fix: continuation of claim edit

* chore: ability to add and remove items to claim inbound

* chore: minor fixes

* chore: add toast messages on actions

* feat(adshboard,types,medusa): enable adding notes/return reason to inbound items

* chore: fix types in a bunch of places

* chore: add conditional for actions

* Update packages/admin-next/dashboard/src/routes/orders/order-create-claim/components/claim-create-form/claim-create-form.tsx

Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>

---------

Co-authored-by: fPolic <mainacc.polic@gmail.com>
Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
authored and GitHub committed 2024-08-07 19:32:07 +02:00
1 parent c017be2a54
commit d50161fa32
13 files changed
+393 -88

No files matched your search

@@ -6,10 +6,10 @@ import {
UseQueryOptions, UseQueryOptions,
} from "@tanstack/react-query" } from "@tanstack/react-query"
import { HttpTypes } from "@medusajs/types"
import { sdk } from "../../lib/client"
import { queryClient } from "../../lib/query-client" import { queryClient } from "../../lib/query-client"
import { queryKeysFactory } from "../../lib/query-key-factory" import { queryKeysFactory } from "../../lib/query-key-factory"
import { sdk } from "../../lib/client"
import { HttpTypes } from "@medusajs/types"
const ORDERS_QUERY_KEY = "orders" as const const ORDERS_QUERY_KEY = "orders" as const
const _orderKeys = queryKeysFactory(ORDERS_QUERY_KEY) const _orderKeys = queryKeysFactory(ORDERS_QUERY_KEY)
@@ -40,7 +40,12 @@ export const useOrder = (
export const useOrderPreview = ( export const useOrderPreview = (
id: string, id: string,
options?: Omit< options?: Omit<
UseQueryOptions<any, Error, any, QueryKey>, UseQueryOptions<
HttpTypes.AdminOrderPreviewResponse,
Error,
HttpTypes.AdminOrderPreviewResponse,
QueryKey
>,
"queryFn" | "queryKey" "queryFn" | "queryKey"
> >
) => { ) => {
@@ -886,7 +886,12 @@
"create": "Create Claim", "create": "Create Claim",
"outbound": "Outbound", "outbound": "Outbound",
"refundAmount": "Estimated difference", "refundAmount": "Estimated difference",
"activeChangeError": "There is an active order change on this order. Please finish or discard the previous change." "activeChangeError": "There is an active order change on this order. Please finish or discard the previous change.",
"actions": {
"cancelClaim": {
"successToast": "Claim was successfully canceled."
}
}
}, },
"reservations": { "reservations": {
"allocatedLabel": "Allocated", "allocatedLabel": "Allocated",
@@ -1,6 +1,11 @@
import { zodResolver } from "@hookform/resolvers/zod" import { zodResolver } from "@hookform/resolvers/zod"
import { PencilSquare } from "@medusajs/icons" import { PencilSquare } from "@medusajs/icons"
import { AdminClaim, AdminOrder, InventoryLevelDTO } from "@medusajs/types" import {
AdminClaim,
AdminOrder,
AdminOrderPreview,
InventoryLevelDTO,
} from "@medusajs/types"
import { import {
Alert, Alert,
Button, Button,
@@ -46,7 +51,7 @@ import { currencies } from "../../../../../lib/data/currencies"
type ReturnCreateFormProps = { type ReturnCreateFormProps = {
order: AdminOrder order: AdminOrder
claim: AdminClaim claim: AdminClaim
preview: AdminOrder preview: AdminOrderPreview
} }
let itemsToAdd: string[] = [] let itemsToAdd: string[] = []
@@ -134,14 +139,14 @@ export const ClaimCreateForm = ({
*/ */
const previewItems = useMemo( const previewItems = useMemo(
() => () =>
preview.items.filter( preview?.items?.filter(
(i) => !!i.actions?.find((a) => a.claim_id === claim.id) (i) => !!i.actions?.find((a) => a.claim_id === claim.id)
), ),
[preview.items] [preview.items]
) )
const itemsMap = useMemo( const itemsMap = useMemo(
() => new Map(order.items.map((i) => [i.id, i])), () => new Map(order?.items?.map((i) => [i.id, i])),
[order.items] [order.items]
) )
@@ -161,14 +166,18 @@ export const ClaimCreateForm = ({
) )
return Promise.resolve({ return Promise.resolve({
inbound_items: previewItems.map((i) => ({ inbound_items: previewItems.map((i) => {
const returnAction = i.actions?.find(
(a) => a.action === "RETURN_ITEM"
)
return {
item_id: i.id, item_id: i.id,
quantity: i.detail.return_requested_quantity, quantity: i.detail.return_requested_quantity,
note: i.actions?.find((a) => a.action === "RETURN_ITEM") note: returnAction?.internal_note,
?.internal_note, reason_id: returnAction?.details?.reason_id as string | undefined,
reason_id: i.actions?.find((a) => a.action === "RETURN_ITEM")?.details }
?.reason_id, }),
})),
inbound_option_id: method ? method.shipping_option_id : "", inbound_option_id: method ? method.shipping_option_id : "",
location_id: "", location_id: "",
send_notification: false, send_notification: false,
@@ -188,7 +197,7 @@ export const ClaimCreateForm = ({
}) })
useEffect(() => { useEffect(() => {
const existingItemsMap = {} const existingItemsMap: Record<string, boolean> = {}
previewItems.forEach((i) => { previewItems.forEach((i) => {
const ind = items.findIndex((field) => field.item_id === i.id) const ind = items.findIndex((field) => field.item_id === i.id)
@@ -205,7 +214,7 @@ export const ClaimCreateForm = ({
...items[ind], ...items[ind],
quantity: i.detail.return_requested_quantity, quantity: i.detail.return_requested_quantity,
note: returnItemAction?.internal_note, note: returnItemAction?.internal_note,
reason_id: returnItemAction?.details?.reason_id, reason_id: returnItemAction?.details?.reason_id as string,
}) })
} }
} else { } else {
@@ -226,13 +235,13 @@ export const ClaimCreateForm = ({
) )
if (method) { if (method) {
form.setValue("option_id", method.shipping_option_id) form.setValue("inbound_option_id", method.shipping_option_id)
} }
}, [preview.shipping_methods]) }, [preview.shipping_methods])
const showPlaceholder = !items.length const showPlaceholder = !items.length
const locationId = form.watch("location_id") const locationId = form.watch("location_id")
const shippingOptionId = form.watch("option_id") const shippingOptionId = form.watch("inbound_option_id")
const handleSubmit = form.handleSubmit(async (data) => { const handleSubmit = form.handleSubmit(async (data) => {
try { try {
@@ -242,19 +251,25 @@ export const ClaimCreateForm = ({
} catch (e) { } catch (e) {
toast.error(t("general.error"), { toast.error(t("general.error"), {
description: e.message, description: e.message,
dismissLabel: t("actions.close"),
}) })
} }
}) })
const onItemsSelected = async () => { const onItemsSelected = async () => {
itemsToAdd.length && itemsToAdd.length &&
(await addInboundItem({ (await addInboundItem(
{
items: itemsToAdd.map((id) => ({ items: itemsToAdd.map((id) => ({
id, id,
quantity: 1, quantity: 1,
})), })),
})) },
{
onError: (error) => {
toast.error(error.message)
},
}
))
for (const itemToRemove of itemsToRemove) { for (const itemToRemove of itemsToRemove) {
const actionId = previewItems const actionId = previewItems
@@ -262,14 +277,18 @@ export const ClaimCreateForm = ({
?.actions?.find((a) => a.action === "RETURN_ITEM")?.id ?.actions?.find((a) => a.action === "RETURN_ITEM")?.id
if (actionId) { if (actionId) {
await removeInboundItem(actionId) await removeInboundItem(actionId, {
onError: (error) => {
toast.error(error.message)
},
})
} }
} }
setIsOpen("items", false) setIsOpen("items", false)
} }
const onLocationChange = async (selectedLocationId: string) => { const onLocationChange = async (selectedLocationId?: string | null) => {
await updateClaimRequest({ location_id: selectedLocationId }) await updateClaimRequest({ location_id: selectedLocationId })
} }
@@ -281,12 +300,19 @@ export const ClaimCreateForm = ({
await Promise.all(promises) await Promise.all(promises)
await addInboundShipping({ shipping_option_id: selectedOptionId }) await addInboundShipping(
{ shipping_option_id: selectedOptionId },
{
onError: (error) => {
toast.error(error.message)
},
}
)
} }
useEffect(() => { useEffect(() => {
if (isShippingPriceEdit) { if (isShippingPriceEdit) {
document.getElementById("js-shipping-input").focus() document.getElementById("js-shipping-input")?.focus()
} }
}, [isShippingPriceEdit]) }, [isShippingPriceEdit])
@@ -298,7 +324,7 @@ export const ClaimCreateForm = ({
const allItemsHaveLocation = items const allItemsHaveLocation = items
.map((_i) => { .map((_i) => {
const item = itemsMap.get(_i.item_id) const item = itemsMap.get(_i.item_id)
if (!item?.variant_id) { if (!item?.variant_id || !item?.variant) {
return true return true
} }
@@ -326,11 +352,12 @@ export const ClaimCreateForm = ({
;( ;(
await Promise.all( await Promise.all(
items.map(async (_i) => { items.map(async (_i) => {
const item = itemsMap.get(_i.item_id) const item = itemsMap.get(_i.item_id)!
if (!item.variant_id) { if (!item.variant_id || !item.variant?.product) {
return undefined return undefined
} }
return await sdk.admin.product.retrieveVariant( return await sdk.admin.product.retrieveVariant(
item.variant.product.id, item.variant.product.id,
item.variant_id, item.variant_id,
@@ -339,8 +366,9 @@ export const ClaimCreateForm = ({
}) })
) )
) )
.filter((it) => it?.variant) .filter((it) => !!it?.variant)
.forEach((item) => { .forEach((item) => {
const { variant } = item const { variant } = item
const levels = variant.inventory[0]?.location_levels const levels = variant.inventory[0]?.location_levels
@@ -365,23 +393,30 @@ export const ClaimCreateForm = ({
*/ */
return () => { return () => {
if (IS_CANCELING) { if (IS_CANCELING) {
cancelClaimRequest() cancelClaimRequest(undefined, {
onSuccess: () => {
toast.success(t("orders.claims.actions.cancelClaim.successToast"))
},
onError: (error) => {
toast.error(error.message)
},
})
// TODO: add this on ESC press // TODO: add this on ESC press
IS_CANCELING = false IS_CANCELING = false
} }
} }
}, []) }, [])
const returnTotal = preview.return_requested_total
const shippingTotal = useMemo(() => { const shippingTotal = useMemo(() => {
const method = preview.shipping_methods.find( const method = preview.shipping_methods.find(
(sm) => !!sm.actions?.find((a) => a.action === "SHIPPING_ADD") (sm) => !!sm.actions?.find((a) => a.action === "SHIPPING_ADD")
) )
return method?.total || 0 return (method?.total as number) || 0
}, [preview.shipping_methods]) }, [preview.shipping_methods])
const returnTotal = preview.return_requested_total
const refundAmount = returnTotal - shippingTotal const refundAmount = returnTotal - shippingTotal
return ( return (
@@ -473,7 +508,11 @@ export const ClaimCreateForm = ({
?.actions?.find((a) => a.action === "RETURN_ITEM")?.id ?.actions?.find((a) => a.action === "RETURN_ITEM")?.id
if (actionId) { if (actionId) {
removeInboundItem(actionId) removeInboundItem(actionId, {
onError: (error) => {
toast.error(error.message)
},
})
} }
}} }}
onUpdate={(payload) => { onUpdate={(payload) => {
@@ -482,7 +521,14 @@ export const ClaimCreateForm = ({
?.actions?.find((a) => a.action === "RETURN_ITEM")?.id ?.actions?.find((a) => a.action === "RETURN_ITEM")?.id
if (actionId) { if (actionId) {
updateInboundItem({ ...payload, actionId }) updateInboundItem(
{ ...payload, actionId },
{
onError: (error) => {
toast.error(error.message)
},
}
)
} }
}} }}
index={index} index={index}
@@ -543,16 +589,16 @@ export const ClaimCreateForm = ({
{/*TODO: WHAT IF THE RETURN OPTION HAS COMPUTED PRICE*/} {/*TODO: WHAT IF THE RETURN OPTION HAS COMPUTED PRICE*/}
<Form.Field <Form.Field
control={form.control} control={form.control}
name="option_id" name="inbound_option_id"
render={({ field: { value, onChange, ...field } }) => { render={({ field: { value, onChange, ...field } }) => {
return ( return (
<Form.Item> <Form.Item>
<Form.Control> <Form.Control>
<Combobox <Combobox
value={value} value={value ?? undefined}
onChange={(v) => { onChange={(val) => {
onChange(v) onChange(val)
onShippingOptionChange(v) val && onShippingOptionChange(val)
}} }}
{...field} {...field}
options={(shipping_options ?? []) options={(shipping_options ?? [])
@@ -640,13 +686,20 @@ export const ClaimCreateForm = ({
}) })
if (actionId) { if (actionId) {
updateInboundShipping({ updateInboundShipping(
{
actionId, actionId,
custom_price: custom_price:
typeof customShippingAmount === "string" typeof customShippingAmount === "string"
? null ? null
: customShippingAmount, : customShippingAmount,
}) },
{
onError: (error) => {
toast.error(error.message)
},
}
)
} }
setIsShippingPriceEdit(false) setIsShippingPriceEdit(false)
}} }}
@@ -656,7 +709,7 @@ export const ClaimCreateForm = ({
} }
code={order.currency_code} code={order.currency_code}
onValueChange={(value) => onValueChange={(value) =>
setCustomShippingAmount(value ? parseInt(value) : "") value && setCustomShippingAmount(parseInt(value))
} }
value={customShippingAmount} value={customShippingAmount}
disabled={showPlaceholder} disabled={showPlaceholder}
@@ -1,16 +1,14 @@
import { useTranslation } from "react-i18next" import { ChatBubble, DocumentText, XCircle, XMark } from "@medusajs/icons"
import { AdminOrderLineItem, HttpTypes } from "@medusajs/types"
import React from "react"
import { IconButton, Input, Text } from "@medusajs/ui" import { IconButton, Input, Text } from "@medusajs/ui"
import { UseFormReturn } from "react-hook-form" import { UseFormReturn } from "react-hook-form"
import { HttpTypes, AdminOrderLineItem } from "@medusajs/types" import { useTranslation } from "react-i18next"
import { ChatBubble, DocumentText, XCircle, XMark } from "@medusajs/icons"
import { Thumbnail } from "../../../../../components/common/thumbnail"
import { MoneyAmountCell } from "../../../../../components/table/table-cells/common/money-amount-cell"
import { Form } from "../../../../../components/common/form"
import { ActionMenu } from "../../../../../components/common/action-menu" import { ActionMenu } from "../../../../../components/common/action-menu"
import { Form } from "../../../../../components/common/form"
import { Thumbnail } from "../../../../../components/common/thumbnail"
import { Combobox } from "../../../../../components/inputs/combobox" import { Combobox } from "../../../../../components/inputs/combobox"
import { MoneyAmountCell } from "../../../../../components/table/table-cells/common/money-amount-cell"
import { useReturnReasons } from "../../../../../hooks/api/return-reasons" import { useReturnReasons } from "../../../../../hooks/api/return-reasons"
type OrderEditItemProps = { type OrderEditItemProps = {
@@ -35,11 +33,9 @@ function ClaimInboundItem({
index, index,
}: OrderEditItemProps) { }: OrderEditItemProps) {
const { t } = useTranslation() const { t } = useTranslation()
const { return_reasons = [] } = useReturnReasons({ fields: "+label" }) const { return_reasons = [] } = useReturnReasons({ fields: "+label" })
const formItem = form.watch(`inbound_items.${index}`) const formItem = form.watch(`inbound_items.${index}`)
const showReturnReason = typeof formItem.reason_id === "string" const showReturnReason = typeof formItem.reason_id === "string"
const showNote = typeof formItem.note === "string" const showNote = typeof formItem.note === "string"
@@ -48,15 +44,17 @@ function ClaimInboundItem({
<div className="flex flex-col items-center gap-x-2 gap-y-2 border-b p-3 text-sm md:flex-row"> <div className="flex flex-col items-center gap-x-2 gap-y-2 border-b p-3 text-sm md:flex-row">
<div className="flex flex-1 items-center gap-x-3"> <div className="flex flex-1 items-center gap-x-3">
<Thumbnail src={item.thumbnail} /> <Thumbnail src={item.thumbnail} />
<div className="flex flex-col"> <div className="flex flex-col">
<div> <div>
<Text className="txt-small" as="span" weight="plus"> <Text className="txt-small" as="span" weight="plus">
{item.title}{" "} {item.title}{" "}
</Text> </Text>
{item.variant.sku && <span>({item.variant.sku})</span>}
{item.variant?.sku && <span>({item.variant.sku})</span>}
</div> </div>
<Text as="div" className="text-ui-fg-subtle txt-small"> <Text as="div" className="text-ui-fg-subtle txt-small">
{item.variant.product.title} {item.variant?.product?.title}
</Text> </Text>
</div> </div>
</div> </div>
@@ -71,19 +69,18 @@ function ClaimInboundItem({
<Form.Item> <Form.Item>
<Form.Control> <Form.Control>
<Input <Input
{...field}
className="bg-ui-bg-base txt-small w-[67px] rounded-lg" className="bg-ui-bg-base txt-small w-[67px] rounded-lg"
min={1} min={1}
max={item.quantity} max={item.quantity}
type="number" type="number"
{...field} onBlur={(e) => {
onChange={(e) => {
const val = e.target.value const val = e.target.value
const payload = val === "" ? null : Number(val) const payload = val === "" ? null : Number(val)
field.onChange(payload) field.onChange(payload)
if (payload) { if (payload) {
// todo: move on blur
onUpdate({ quantity: payload }) onUpdate({ quantity: payload })
} }
}} }}
@@ -178,8 +175,9 @@ function ClaimInboundItem({
className="flex-shrink" className="flex-shrink"
variant="transparent" variant="transparent"
onClick={() => { onClick={() => {
onUpdate({ reason_id: null }) // TODO BE: we should be able to set to unset reason here form.setValue(`inbound_items.${index}.reason_id`, null)
form.setValue(`inbound_items.${index}.reason_id`, "")
onUpdate({ reason_id: null })
}} }}
> >
<XMark className="text-ui-fg-muted" /> <XMark className="text-ui-fg-muted" />
@@ -202,17 +200,17 @@ function ClaimInboundItem({
<div className="flex-grow"> <div className="flex-grow">
<Form.Field <Form.Field
control={form.control} control={form.control}
name={`items.${index}.note`} name={`inbound_items.${index}.note`}
render={({ field: { ref, onChange, ...field } }) => { render={({ field: { ref, ...field } }) => {
return ( return (
<Form.Item> <Form.Item>
<Form.Control> <Form.Control>
<Input <Input
onChange={onChange}
{...field} {...field}
onBlur={() => onBlur={() => {
field.onChange(field.value)
onUpdate({ internal_note: field.value }) onUpdate({ internal_note: field.value })
} }}
className="bg-ui-bg-field-component hover:bg-ui-bg-field-component-hover" className="bg-ui-bg-field-component hover:bg-ui-bg-field-component-hover"
/> />
</Form.Control> </Form.Control>
@@ -222,15 +220,14 @@ function ClaimInboundItem({
}} }}
/> />
</div> </div>
<IconButton <IconButton
type="button" type="button"
className="flex-shrink" className="flex-shrink"
variant="transparent" variant="transparent"
onClick={() => { onClick={() => {
form.setValue(`items.${index}.note`, { form.setValue(`inbound_items.${index}.note`, null)
shouldDirty: true,
shouldTouch: true,
})
onUpdate({ internal_note: null }) onUpdate({ internal_note: null })
}} }}
> >
@@ -5,18 +5,19 @@ export const ClaimCreateSchema = z.object({
z.object({ z.object({
item_id: z.string(), item_id: z.string(),
quantity: z.number(), quantity: z.number(),
reason_id: z.string().optional().nullable(), reason_id: z.string().nullish(),
note: z.string().optional().nullable(), note: z.string().nullish(),
})
),
outbound_items: z.array(
z.object({
item_id: z.string(), // TODO: variant id?
quantity: z.number(),
}) })
), ),
// TODO: Bring back when introducing outbound items
// outbound_items: z.array(
// z.object({
// item_id: z.string(), // TODO: variant id?
// quantity: z.number(),
// })
// ),
location_id: z.string().optional(), location_id: z.string().optional(),
inbound_option_id: z.string(), inbound_option_id: z.string().nullish(),
send_notification: z.boolean().optional(), send_notification: z.boolean().optional(),
}) })
+1 -1
View File
@@ -24,7 +24,7 @@ export class Order {
} }
async retrievePreview(id: string, headers?: ClientHeaders) { async retrievePreview(id: string, headers?: ClientHeaders) {
return await this.client.fetch<{ order: HttpTypes.AdminOrder }>( return await this.client.fetch<HttpTypes.AdminOrderPreviewResponse>(
`/admin/orders/${id}/preview`, `/admin/orders/${id}/preview`,
{ {
headers, headers,
@@ -17,9 +17,9 @@ interface AdminClaimAddItems {
interface AdminClaimUpdateItem { interface AdminClaimUpdateItem {
quantity?: number quantity?: number
reason_id?: ClaimReason reason_id?: string | null
description?: string description?: string
internal_note?: string internal_note?: string | null
} }
interface AdminClaimAddShippingMethod { interface AdminClaimAddShippingMethod {
@@ -31,7 +31,7 @@ interface AdminClaimAddShippingMethod {
} }
interface AdminClaimUpdateShippingMethod { interface AdminClaimUpdateShippingMethod {
custom_price?: number custom_price?: number | null
internal_note?: string internal_note?: string
metadata?: Record<string, unknown> | null metadata?: Record<string, unknown> | null
} }
@@ -1,5 +1,6 @@
import { GeoZoneType } from "../../../fulfillment" import { GeoZoneType } from "../../../fulfillment"
import { AdminShippingOption } from "../../shipping-option" import { AdminShippingOption } from "../../shipping-option"
import { AdminStockLocation } from "../../stock-locations"
export interface AdminGeoZone { export interface AdminGeoZone {
id: string id: string
@@ -17,6 +18,7 @@ export interface AdminServiceZone {
id: string id: string
name: string name: string
fulfillment_set_id: string fulfillment_set_id: string
fulfillment_set: AdminFulfillmentSet
geo_zones: AdminGeoZone[] geo_zones: AdminGeoZone[]
shipping_options: AdminShippingOption[] shipping_options: AdminShippingOption[]
created_at: string created_at: string
@@ -28,6 +30,7 @@ export interface AdminFulfillmentSet {
id: string id: string
name: string name: string
type: string type: string
location: AdminStockLocation
service_zones: AdminServiceZone[] service_zones: AdminServiceZone[]
created_at: string created_at: string
updated_at: string updated_at: string
@@ -2,6 +2,8 @@ import { AdminPaymentCollection } from "../payment/admin"
import { import {
BaseOrder, BaseOrder,
BaseOrderAddress, BaseOrderAddress,
BaseOrderChange,
BaseOrderChangeAction,
BaseOrderFilters, BaseOrderFilters,
BaseOrderLineItem, BaseOrderLineItem,
BaseOrderShippingMethod, BaseOrderShippingMethod,
@@ -45,3 +47,19 @@ export interface AdminCreateOrderShipment {
export interface AdminCancelOrderFulfillment { export interface AdminCancelOrderFulfillment {
no_notification?: boolean no_notification?: boolean
} }
// Order Preview
export interface AdminOrderPreview
extends Omit<AdminOrder, "items" | "shipping_methods"> {
return_requested_total: number
order_change: BaseOrderChange
items: (BaseOrderLineItem & { actions?: BaseOrderChangeAction[] })[]
shipping_methods: (BaseOrderShippingMethod & {
actions?: BaseOrderChangeAction[]
})[]
}
export interface AdminOrderPreviewResponse {
order: AdminOrderPreview
}
+223 -1
View File
@@ -1,5 +1,6 @@
import { BaseFilterable, OperatorMap } from "../../dal" import { BaseFilterable, OperatorMap } from "../../dal"
import { BigNumberValue } from "../../totals" import { BigNumberValue } from "../../totals"
import { BaseClaim } from "../claim/common"
import { BasePaymentCollection } from "../payment/common" import { BasePaymentCollection } from "../payment/common"
import { BaseProduct, BaseProductVariant } from "../product/common" import { BaseProduct, BaseProductVariant } from "../product/common"
@@ -116,7 +117,7 @@ export interface BaseOrderLineItem {
title: string title: string
subtitle: string | null subtitle: string | null
thumbnail: string | null thumbnail: string | null
variant?: BaseProductVariant variant?: BaseProductVariant | null
variant_id: string | null variant_id: string | null
product?: BaseProduct product?: BaseProduct
product_id: string | null product_id: string | null
@@ -305,3 +306,224 @@ export interface BaseOrderFilters extends BaseFilterable<BaseOrderFilters> {
id?: string[] | string | OperatorMap<string | string[]> id?: string[] | string | OperatorMap<string | string[]>
status?: string[] | string | OperatorMap<string | string[]> status?: string[] | string | OperatorMap<string | string[]>
} }
export interface BaseOrderChange {
/**
* The ID of the order change
*/
id: string
/**
* The version of the order change
*/
version: number
/**
* The type of the order change
*/
change_type?: "return" | "exchange" | "claim" | "edit"
/**
* The ID of the associated order
*/
order_id: string
/**
* The ID of the associated return order
*/
return_id: string
/**
* The ID of the associated exchange order
*/
exchange_id: string
/**
* The ID of the associated claim order
*/
claim_id: string
/**
* The associated order
*
* @expandable
*/
order: BaseOrder
/**
* The associated return order
*
* @expandable
*/
return_order: any
/**
* The associated exchange order
*
* @expandable
*/
exchange: any
/**
* The associated claim order
*
* @expandable
*/
claim: BaseClaim
/**
* The actions of the order change
*
* @expandable
*/
actions: BaseOrderChangeAction[]
/**
* The status of the order change
*/
status: string
/**
* The requested by of the order change
*/
requested_by: string | null
/**
* When the order change was requested
*/
requested_at: Date | string | null
/**
* The confirmed by of the order change
*/
confirmed_by: string | null
/**
* When the order change was confirmed
*/
confirmed_at: Date | string | null
/**
* The declined by of the order change
*/
declined_by: string | null
/**
* The declined reason of the order change
*/
declined_reason: string | null
/**
* The metadata of the order change
*/
metadata: Record<string, unknown> | null
/**
* When the order change was declined
*/
declined_at: Date | string | null
/**
* The canceled by of the order change
*/
canceled_by: string | null
/**
* When the order change was canceled
*/
canceled_at: Date | string | null
/**
* When the order change was created
*/
created_at: Date | string
/**
* When the order change was updated
*/
updated_at: Date | string
}
/**
* The order change action details.
*/
export interface BaseOrderChangeAction {
/**
* The ID of the order change action
*/
id: string
/**
* The ID of the associated order change
*/
order_change_id: string | null
/**
* The associated order change
*
* @expandable
*/
order_change: BaseOrderChange | null
/**
* The ID of the associated order
*/
order_id: string | null
/**
* The ID of the associated return.
*/
return_id: string | null
/**
* The ID of the associated claim.
*/
claim_id: string | null
/**
* The ID of the associated exchange.
*/
exchange_id: string | null
/**
* The associated order
*
* @expandable
*/
order: BaseOrder | null
/**
* The reference of the order change action
*/
reference: string
/**
* The ID of the reference
*/
reference_id: string
/**
* The action of the order change action
*/
action: string
/**
* The details of the order change action
*/
details: Record<string, unknown> | null
/**
* The internal note of the order change action
*/
internal_note: string | null
/**
* When the order change action was created
*/
created_at: Date | string
/**
* When the order change action was updated
*/
updated_at: Date | string
}
+2 -2
View File
@@ -56,8 +56,8 @@ export interface AdminAddReturnItems {
export interface AdminUpdateReturnItems { export interface AdminUpdateReturnItems {
quantity?: number quantity?: number
internal_note?: string internal_note?: string | null
reason_id?: string reason_id?: string | null
} }
export interface AdminAddReturnShipping { export interface AdminAddReturnShipping {
@@ -86,7 +86,7 @@ export interface UpdateClaimItemWorkflowInput {
action_id: string action_id: string
data: { data: {
quantity?: BigNumberInput quantity?: BigNumberInput
reason_id?: ClaimReason reason_id?: string | null
internal_note?: string | null internal_note?: string | null
} }
} }
@@ -44,6 +44,7 @@ export const AdminPostOrderClaimsReqSchema = z.object({
order_id: z.string(), order_id: z.string(),
description: z.string().optional(), description: z.string().optional(),
internal_note: z.string().optional(), internal_note: z.string().optional(),
reason_id: z.string().nullish(),
metadata: z.record(z.unknown()).nullish(), metadata: z.record(z.unknown()).nullish(),
}) })
export type AdminPostOrderClaimsReqSchemaType = z.infer< export type AdminPostOrderClaimsReqSchemaType = z.infer<
@@ -173,7 +174,7 @@ export type AdminPostClaimItemsReqSchemaType = z.infer<
export const AdminPostClaimsRequestItemsActionReqSchema = z.object({ export const AdminPostClaimsRequestItemsActionReqSchema = z.object({
quantity: z.number().optional(), quantity: z.number().optional(),
internal_note: z.string().nullish().optional(), internal_note: z.string().nullish().optional(),
reason: z.nativeEnum(ClaimReason).nullish().optional(), reason_id: z.string().nullish(),
metadata: z.record(z.unknown()).nullish().optional(), metadata: z.record(z.unknown()).nullish().optional(),
}) })
@@ -183,7 +184,7 @@ export type AdminPostClaimsRequestItemsActionReqSchemaType = z.infer<
export const AdminPostClaimsItemsActionReqSchema = z.object({ export const AdminPostClaimsItemsActionReqSchema = z.object({
quantity: z.number().optional(), quantity: z.number().optional(),
reason: z.nativeEnum(ClaimReason).nullish().optional(), reason_id: z.string().nullish(),
internal_note: z.string().nullish().optional(), internal_note: z.string().nullish().optional(),
}) })