|
|
|
@@ -26,6 +26,13 @@ import { |
|
|
|
updateStockOutLineStatus, |
|
|
|
createStockOutLine, |
|
|
|
recordPickExecutionIssue, |
|
|
|
fetchFGPickOrders, // ✅ Add this import |
|
|
|
FGPickOrderResponse, |
|
|
|
autoAssignAndReleasePickOrder, |
|
|
|
AutoAssignReleaseResponse, |
|
|
|
checkPickOrderCompletion, |
|
|
|
PickOrderCompletionResponse, |
|
|
|
checkAndCompletePickOrderByConsoCode |
|
|
|
} from "@/app/api/pickOrder/actions"; |
|
|
|
import { fetchNameList, NameList } from "@/app/api/user/actions"; |
|
|
|
import { |
|
|
|
@@ -39,16 +46,9 @@ import QrCodeIcon from '@mui/icons-material/QrCode'; |
|
|
|
import { useQrCodeScannerContext } from '../QrCodeScannerProvider/QrCodeScannerProvider'; |
|
|
|
import { useSession } from "next-auth/react"; |
|
|
|
import { SessionWithTokens } from "@/config/authConfig"; |
|
|
|
import { |
|
|
|
autoAssignAndReleasePickOrder, |
|
|
|
AutoAssignReleaseResponse, |
|
|
|
checkPickOrderCompletion, |
|
|
|
PickOrderCompletionResponse, |
|
|
|
checkAndCompletePickOrderByConsoCode |
|
|
|
} from "@/app/api/pickOrder/actions"; |
|
|
|
import { fetchStockInLineInfo } from "@/app/api/po/actions"; |
|
|
|
import GoodPickExecutionForm from "./GoodPickExecutionForm"; |
|
|
|
|
|
|
|
import FGPickOrderCard from "./FGPickOrderCard"; |
|
|
|
interface Props { |
|
|
|
filterArgs: Record<string, any>; |
|
|
|
} |
|
|
|
@@ -73,7 +73,7 @@ const QrCodeModal: React.FC<{ |
|
|
|
|
|
|
|
const [processedQrCodes, setProcessedQrCodes] = useState<Set<string>>(new Set()); |
|
|
|
const [scannedQrResult, setScannedQrResult] = useState<string>(''); |
|
|
|
|
|
|
|
const [fgPickOrder, setFgPickOrder] = useState<FGPickOrderResponse | null>(null); |
|
|
|
// Process scanned QR codes |
|
|
|
useEffect(() => { |
|
|
|
if (qrValues.length > 0 && lot && !isProcessingQr && !qrScanSuccess) { |
|
|
|
@@ -347,6 +347,51 @@ const PickExecution: React.FC<Props> = ({ filterArgs }) => { |
|
|
|
// ✅ Add GoodPickExecutionForm states |
|
|
|
const [pickExecutionFormOpen, setPickExecutionFormOpen] = useState(false); |
|
|
|
const [selectedLotForExecutionForm, setSelectedLotForExecutionForm] = useState<any | null>(null); |
|
|
|
const [fgPickOrders, setFgPickOrders] = useState<FGPickOrderResponse[]>([]); |
|
|
|
const [fgPickOrdersLoading, setFgPickOrdersLoading] = useState(false); |
|
|
|
const fetchFgPickOrdersData = useCallback(async () => { |
|
|
|
if (!currentUserId) return; |
|
|
|
|
|
|
|
setFgPickOrdersLoading(true); |
|
|
|
try { |
|
|
|
// Get all pick order IDs from combinedLotData |
|
|
|
const pickOrderIds = Array.from(new Set(combinedLotData.map(lot => lot.pickOrderId))); |
|
|
|
|
|
|
|
if (pickOrderIds.length === 0) { |
|
|
|
setFgPickOrders([]); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// Fetch FG pick orders for each pick order ID |
|
|
|
const fgPickOrdersPromises = pickOrderIds.map(pickOrderId => |
|
|
|
fetchFGPickOrders(pickOrderId) |
|
|
|
); |
|
|
|
|
|
|
|
const fgPickOrdersResults = await Promise.all(fgPickOrdersPromises); |
|
|
|
|
|
|
|
// Flatten the results (each fetchFGPickOrders returns an array) |
|
|
|
const allFgPickOrders = fgPickOrdersResults.flat(); |
|
|
|
|
|
|
|
setFgPickOrders(allFgPickOrders); |
|
|
|
console.log("✅ Fetched FG pick orders:", allFgPickOrders); |
|
|
|
} catch (error) { |
|
|
|
console.error("❌ Error fetching FG pick orders:", error); |
|
|
|
setFgPickOrders([]); |
|
|
|
} finally { |
|
|
|
setFgPickOrdersLoading(false); |
|
|
|
} |
|
|
|
}, [currentUserId, combinedLotData]); |
|
|
|
useEffect(() => { |
|
|
|
if (combinedLotData.length > 0) { |
|
|
|
fetchFgPickOrdersData(); |
|
|
|
} |
|
|
|
}, [combinedLotData, fetchFgPickOrdersData]); |
|
|
|
|
|
|
|
// ✅ Handle QR code button click |
|
|
|
const handleQrCodeClick = (pickOrderId: number) => { |
|
|
|
console.log(`QR Code clicked for pick order ID: ${pickOrderId}`); |
|
|
|
// TODO: Implement QR code functionality |
|
|
|
}; |
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
startScan(); |
|
|
|
@@ -850,11 +895,30 @@ const PickExecution: React.FC<Props> = ({ filterArgs }) => { |
|
|
|
}); |
|
|
|
}, []); |
|
|
|
|
|
|
|
// Pagination data |
|
|
|
// Pagination data with sorting by routerIndex |
|
|
|
const paginatedData = useMemo(() => { |
|
|
|
// ✅ Sort by routerIndex first, then by other criteria |
|
|
|
const sortedData = [...combinedLotData].sort((a, b) => { |
|
|
|
const aIndex = a.routerIndex || 0; |
|
|
|
const bIndex = b.routerIndex || 0; |
|
|
|
|
|
|
|
// Primary sort: by routerIndex |
|
|
|
if (aIndex !== bIndex) { |
|
|
|
return aIndex - bIndex; |
|
|
|
} |
|
|
|
|
|
|
|
// Secondary sort: by pickOrderCode if routerIndex is the same |
|
|
|
if (a.pickOrderCode !== b.pickOrderCode) { |
|
|
|
return a.pickOrderCode.localeCompare(b.pickOrderCode); |
|
|
|
} |
|
|
|
|
|
|
|
// Tertiary sort: by lotNo if everything else is the same |
|
|
|
return (a.lotNo || '').localeCompare(b.lotNo || ''); |
|
|
|
}); |
|
|
|
|
|
|
|
const startIndex = paginationController.pageNum * paginationController.pageSize; |
|
|
|
const endIndex = startIndex + paginationController.pageSize; |
|
|
|
return combinedLotData.slice(startIndex, endIndex); |
|
|
|
return sortedData.slice(startIndex, endIndex); |
|
|
|
}, [combinedLotData, paginationController]); |
|
|
|
|
|
|
|
return ( |
|
|
|
@@ -862,11 +926,35 @@ const PickExecution: React.FC<Props> = ({ filterArgs }) => { |
|
|
|
<Stack spacing={2}> |
|
|
|
{/* Search Box */} |
|
|
|
<Box> |
|
|
|
<SearchBox |
|
|
|
criteria={searchCriteria} |
|
|
|
onSearch={handleSearch} |
|
|
|
onReset={handleReset} |
|
|
|
/> |
|
|
|
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2 }}> |
|
|
|
<Typography variant="h6" gutterBottom sx={{ mb: 0 }}> |
|
|
|
{t("FG Pick Orders")} |
|
|
|
</Typography> |
|
|
|
</Box> |
|
|
|
|
|
|
|
{fgPickOrdersLoading ? ( |
|
|
|
<Box sx={{ display: 'flex', justifyContent: 'center', p: 3 }}> |
|
|
|
<CircularProgress /> |
|
|
|
</Box> |
|
|
|
) : ( |
|
|
|
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}> |
|
|
|
{fgPickOrders.length === 0 ? ( |
|
|
|
<Box sx={{ p: 3, textAlign: 'center' }}> |
|
|
|
<Typography variant="body2" color="text.secondary"> |
|
|
|
{t("No FG pick orders found")} |
|
|
|
</Typography> |
|
|
|
</Box> |
|
|
|
) : ( |
|
|
|
fgPickOrders.map((fgOrder) => ( |
|
|
|
<FGPickOrderCard |
|
|
|
key={fgOrder.pickOrderId} |
|
|
|
fgOrder={fgOrder} |
|
|
|
onQrCodeClick={handleQrCodeClick} |
|
|
|
/> |
|
|
|
)) |
|
|
|
)} |
|
|
|
</Box> |
|
|
|
)} |
|
|
|
</Box> |
|
|
|
|
|
|
|
|
|
|
|
@@ -887,8 +975,8 @@ const PickExecution: React.FC<Props> = ({ filterArgs }) => { |
|
|
|
<Table> |
|
|
|
<TableHead> |
|
|
|
<TableRow> |
|
|
|
<TableCell>{t("Pick Order Code")}</TableCell> |
|
|
|
<TableCell>{t("Item Code")}</TableCell> |
|
|
|
<TableCell>{t("Index")}</TableCell> |
|
|
|
<TableCell>{t("Route")}</TableCell> |
|
|
|
<TableCell>{t("Item Name")}</TableCell> |
|
|
|
<TableCell>{t("Lot#")}</TableCell> |
|
|
|
<TableCell>{t("Target Date")}</TableCell> |
|
|
|
@@ -921,8 +1009,16 @@ const PickExecution: React.FC<Props> = ({ filterArgs }) => { |
|
|
|
} |
|
|
|
}} |
|
|
|
> |
|
|
|
<TableCell>{lot.pickOrderCode}</TableCell> |
|
|
|
<TableCell>{lot.itemCode}</TableCell> |
|
|
|
<TableCell> |
|
|
|
<Typography variant="body2" fontWeight="bold"> |
|
|
|
{lot.routerIndex || index + 1} |
|
|
|
</Typography> |
|
|
|
</TableCell> |
|
|
|
<TableCell> |
|
|
|
<Typography variant="body2"> |
|
|
|
{lot.routerRoute || '-'} |
|
|
|
</Typography> |
|
|
|
</TableCell> |
|
|
|
<TableCell>{lot.itemName}</TableCell> |
|
|
|
<TableCell> |
|
|
|
<Box> |
|
|
|
@@ -933,18 +1029,7 @@ const PickExecution: React.FC<Props> = ({ filterArgs }) => { |
|
|
|
}} |
|
|
|
> |
|
|
|
{lot.lotNo} |
|
|
|
|
|
|
|
</Typography> |
|
|
|
{/* |
|
|
|
{lot.lotAvailability !== 'available' && ( |
|
|
|
<Typography variant="caption" color="error" display="block"> |
|
|
|
({lot.lotAvailability === 'expired' ? 'Expired' : |
|
|
|
lot.lotAvailability === 'insufficient_stock' ? 'Insufficient' : |
|
|
|
lot.lotAvailability === 'rejected' ? 'Rejected' : |
|
|
|
'Unavailable'}) |
|
|
|
</Typography> |
|
|
|
|
|
|
|
)*/} |
|
|
|
</Box> |
|
|
|
</TableCell> |
|
|
|
<TableCell>{lot.pickOrderTargetDate}</TableCell> |
|
|
|
|