Merge pull request 'Add invoice creation mode support to Shop PO flow' (#79) from dev into production

Reviewed-on: #79
This commit was merged in pull request #79.
This commit is contained in:
2026-10-20 14:02:31 +05:30
2 changed files with 37 additions and 6 deletions
@@ -24,9 +24,12 @@ import {
items as itemsApi, items as itemsApi,
priceLists as priceListsApi, priceLists as priceListsApi,
users as usersApi, users as usersApi,
invoiceCreationMode as invoiceCreationModeApi,
DEFAULT_INVOICE_CREATION_MODE,
getApiError, getApiError,
getPaginatedItems, getPaginatedItems,
} from '@/lib/api/index' } from '@/lib/api/index'
import type { InvoiceCreationMode } from '@/lib/api/sys-config'
import type { ItemSummaryResponse, ShopPOResponse, UserResponse } from '@/types/api' import type { ItemSummaryResponse, ShopPOResponse, UserResponse } from '@/types/api'
const lineItemSchema = z.object({ const lineItemSchema = z.object({
@@ -56,6 +59,11 @@ export default function EditShopPOPage() {
const [usersList, setUsersList] = useState<UserResponse[]>([]) const [usersList, setUsersList] = useState<UserResponse[]>([])
const [confirmedByUserId, setConfirmedByUserId] = useState('') const [confirmedByUserId, setConfirmedByUserId] = useState('')
const [confirming, setConfirming] = useState(false) const [confirming, setConfirming] = useState(false)
const [mode, setMode] = useState<InvoiceCreationMode>(DEFAULT_INVOICE_CREATION_MODE)
useEffect(() => {
invoiceCreationModeApi.get().then(setMode).catch(() => {})
}, [])
const form = useForm<FormValues>({ const form = useForm<FormValues>({
resolver: zodResolver(schema), resolver: zodResolver(schema),
@@ -98,9 +106,14 @@ export default function EditShopPOPage() {
if (!po || !confirmedByUserId) return if (!po || !confirmedByUserId) return
setConfirming(true) setConfirming(true)
try { try {
const updated = await shopPosApi.confirm(po.id, confirmedByUserId) const updated = mode === 'ModeA'
? await shopPosApi.confirmAndCreateInvoice(po.id, confirmedByUserId)
: await shopPosApi.confirm(po.id, confirmedByUserId)
setPo(updated) setPo(updated)
toast.add({ title: 'Shop PO confirmed', type: 'success' }) toast.add({
title: mode === 'ModeA' ? 'Shop PO confirmed and invoice created' : 'Shop PO confirmed',
type: 'success',
})
} catch (err) { } catch (err) {
toast.add({ title: 'Failed to confirm Shop PO', description: getApiError(err), type: 'error' }) toast.add({ title: 'Failed to confirm Shop PO', description: getApiError(err), type: 'error' })
} finally { } finally {
@@ -21,7 +21,15 @@ import {
} from '@/components/ui/dialog' } from '@/components/ui/dialog'
import { FieldGroup } from '@/components/ui/field' import { FieldGroup } from '@/components/ui/field'
import { toast } from '@/components/ui/toast' import { toast } from '@/components/ui/toast'
import { shopPos as shopPosApi, users as usersApi, getApiError, getPaginatedItems } from '@/lib/api/index' import {
shopPos as shopPosApi,
users as usersApi,
invoiceCreationMode as invoiceCreationModeApi,
DEFAULT_INVOICE_CREATION_MODE,
getApiError,
getPaginatedItems,
} from '@/lib/api/index'
import type { InvoiceCreationMode } from '@/lib/api/sys-config'
import type { ShopPOResponse, UserResponse } from '@/types/api' import type { ShopPOResponse, UserResponse } from '@/types/api'
const schema = z.object({ const schema = z.object({
@@ -39,6 +47,7 @@ interface ConfirmShopPODialogProps {
export function ConfirmShopPODialog({ open, onClose, onSuccess, po }: ConfirmShopPODialogProps) { export function ConfirmShopPODialog({ open, onClose, onSuccess, po }: ConfirmShopPODialogProps) {
const [usersList, setUsersList] = useState<UserResponse[]>([]) const [usersList, setUsersList] = useState<UserResponse[]>([])
const [mode, setMode] = useState<InvoiceCreationMode>(DEFAULT_INVOICE_CREATION_MODE)
const form = useForm<FormValues>({ const form = useForm<FormValues>({
resolver: zodResolver(schema), resolver: zodResolver(schema),
@@ -51,14 +60,20 @@ export function ConfirmShopPODialog({ open, onClose, onSuccess, po }: ConfirmSho
usersApi.list() usersApi.list()
.then((res) => setUsersList(res)) .then((res) => setUsersList(res))
.catch((err) => toast.add({ title: 'Failed to load users', description: getApiError(err), type: 'error' })) .catch((err) => toast.add({ title: 'Failed to load users', description: getApiError(err), type: 'error' }))
invoiceCreationModeApi.get().then(setMode).catch(() => {})
}, [open]) }, [open])
if (!po) return null if (!po) return null
async function onSubmit(values: FormValues) { async function onSubmit(values: FormValues) {
try { try {
if (mode === 'ModeA') {
await shopPosApi.confirmAndCreateInvoice(po!.id, values.confirmedByUserId)
toast.add({ title: 'Shop PO confirmed and invoice created', type: 'success' })
} else {
await shopPosApi.confirm(po!.id, values.confirmedByUserId) await shopPosApi.confirm(po!.id, values.confirmedByUserId)
toast.add({ title: 'Shop PO confirmed', type: 'success' }) toast.add({ title: 'Shop PO confirmed', type: 'success' })
}
onSuccess() onSuccess()
onClose() onClose()
} catch (err) { } catch (err) {
@@ -71,7 +86,10 @@ export function ConfirmShopPODialog({ open, onClose, onSuccess, po }: ConfirmSho
<DialogContent className="sm:max-w-md"> <DialogContent className="sm:max-w-md">
<DialogHeader> <DialogHeader>
<DialogTitle>Confirm Shop PO</DialogTitle> <DialogTitle>Confirm Shop PO</DialogTitle>
<DialogDescription>{po.storeName} — Rs. {po.totalAmount.toLocaleString()}</DialogDescription> <DialogDescription>
{po.storeName} — Rs. {po.totalAmount.toLocaleString()}
{mode === 'ModeA' && ' · a draft invoice will be created'}
</DialogDescription>
</DialogHeader> </DialogHeader>
<form onSubmit={form.handleSubmit(onSubmit)} className="flex flex-col gap-6"> <form onSubmit={form.handleSubmit(onSubmit)} className="flex flex-col gap-6">