import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { quantity } from '@/types/inventory'; import { controlClass } from '@/components/procurement'; export type CountInput = { lot_id: number | null; new_key: string | null; quantity: string; code: string; expires_on: string; no_expiry: boolean; }; export type LotCountSource = { stock_item_id: number; warehouse_id: number; hash: string; lots: { lot_id: number; metadata_id: number; quantity_milli: number; code: string | null; expires_on: string | null; no_expiry: boolean; }[]; }; export function countTotal(rows: CountInput[]): string | null { let total = 0; for (const row of rows) { if (!/^\d{1,9}(\.\d{1,3})?$/.test(row.quantity)) return null; const [whole, fraction = ''] = row.quantity.split('.'); total += Number(whole) * 1000 + Number(fraction.padEnd(3, '0')); } return `${Math.floor(total / 1000)}.${String(total % 1000).padStart(3, '0')}`; } export function LotCountFields({ source, rows, setRows, }: { source: LotCountSource; rows: CountInput[]; setRows: (rows: CountInput[]) => void; }) { const change = (index: number, update: Partial) => setRows( rows.map((row, i) => (i === index ? { ...row, ...update } : row)), ); const exhausted = source.lots.filter( (lot) => lot.quantity_milli === 0 && !rows.some((row) => row.lot_id === lot.lot_id), ); return (
Conferência física por lote

Registe apenas o que contou. O total é calculado; identificação, validade e saldo de referência vêm do registo existente. A contagem não altera existências nem liberta qualidade.

{rows.map((row, index) => { const known = source.lots.find( (lot) => lot.lot_id === row.lot_id, ); return (

{known ? `${known.code ?? `Lote #${known.lot_id}`} · Saldo: ${quantity(known.quantity_milli)} · Validade: ${known.expires_on ?? (known.no_expiry ? 'Sem prazo confirmado' : 'Por confirmar')}` : 'Lote encontrado sem identidade anterior neste local'}

{!known && ( <> )}
); })} {exhausted.length > 0 && ( )}

Total contado: {countTotal(rows) ?? 'Complete as quantidades'}

Quantidades encontradas a mais ficam em quarentena após o ajuste, mesmo num lote anteriormente libertado. A aplicação exige conferência independente da contagem.

); }