浏览代码

update

master
CANCERYS\kw093 2 个月前
父节点
当前提交
8ca9c0a205
共有 4 个文件被更改,包括 79 次插入75 次删除
  1. +3
    -3
      src/components/FinishedGoodSearch/FGPickOrderCard.tsx
  2. +21
    -22
      src/components/FinishedGoodSearch/FinishedGoodSearch.tsx
  3. +41
    -49
      src/components/FinishedGoodSearch/GoodPickExecutiondetail.tsx
  4. +14
    -1
      src/i18n/zh/pickOrder.json

+ 3
- 3
src/components/FinishedGoodSearch/FGPickOrderCard.tsx 查看文件

@@ -20,7 +20,7 @@ const FGPickOrderCard: React.FC<Props> = ({ fgOrder, onQrCodeClick }) => {
<Grid container spacing={2} columns={{ xs: 6, sm: 12 }}> <Grid container spacing={2} columns={{ xs: 6, sm: 12 }}>
<Grid item xs={6}> <Grid item xs={6}>
<TextField <TextField
label={t("Delivery No.")}
label={t("Delivery Code")}
fullWidth fullWidth
disabled={true} disabled={true}
value={fgOrder.deliveryNo} value={fgOrder.deliveryNo}
@@ -28,7 +28,7 @@ const FGPickOrderCard: React.FC<Props> = ({ fgOrder, onQrCodeClick }) => {
</Grid> </Grid>
<Grid item xs={6}> <Grid item xs={6}>
<TextField <TextField
label={t("FG Pick Order No.")}
label={t("Pick Order Code")}
fullWidth fullWidth
disabled={true} disabled={true}
value={fgOrder.pickOrderCode} value={fgOrder.pickOrderCode}
@@ -37,7 +37,7 @@ const FGPickOrderCard: React.FC<Props> = ({ fgOrder, onQrCodeClick }) => {
</Grid> </Grid>
<Grid item xs={6}> <Grid item xs={6}>
<TextField <TextField
label={t("Shop PO No.")}
label={t("Shop PO Code")}
fullWidth fullWidth
disabled={true} disabled={true}
value={fgOrder.shopPoNo} value={fgOrder.shopPoNo}


+ 21
- 22
src/components/FinishedGoodSearch/FinishedGoodSearch.tsx 查看文件

@@ -57,39 +57,38 @@ const PickOrderSearch: React.FC<Props> = ({ pickOrders }) => {
console.error("Missing user id in session"); console.error("Missing user id in session");
return; return;
} }
const res = await autoAssignAndReleasePickOrderByStore(currentUserId, storeId);
console.log("Assign by store result:", res);
// Optionally show toast/refresh list here
};
// ✅ Manual assignment handler - uses the action function
const handleManualAssign = useCallback(async () => {
if (!currentUserId || isAssigning) return;
setIsAssigning(true); setIsAssigning(true);
try { try {
console.log("🎯 Manual assignment triggered for user:", currentUserId);
// ✅ Use the action function instead of direct fetch
const result = await autoAssignAndReleasePickOrder(currentUserId);
console.log("✅ Manual assignment result:", result);
const res = await autoAssignAndReleasePickOrderByStore(currentUserId, storeId);
console.log("Assign by store result:", res);
if (result.code === "SUCCESS") {
console.log("✅ Successfully assigned pick order manually");
// Trigger refresh of the PickExecution component
// ✅ Handle different response codes
if (res.code === "SUCCESS") {
console.log("✅ Successfully assigned pick order to store", storeId);
// ✅ Trigger refresh to show newly assigned data
window.dispatchEvent(new CustomEvent('pickOrderAssigned')); window.dispatchEvent(new CustomEvent('pickOrderAssigned'));
} else if (result.code === "EXISTS") {
console.log("ℹ️ User already has active pick orders");
// Still trigger refresh to show existing orders
} else if (res.code === "USER_BUSY") {
console.warn("⚠️ User already has pick orders in progress:", res.message);
// ✅ Show warning but still refresh to show existing orders
alert(`Warning: ${res.message}`);
window.dispatchEvent(new CustomEvent('pickOrderAssigned')); window.dispatchEvent(new CustomEvent('pickOrderAssigned'));
} else if (res.code === "NO_ORDERS") {
console.log("ℹ️ No available pick orders for store", storeId);
alert(`Info: ${res.message}`);
} else { } else {
console.log("ℹ️ No available pick orders or other status:", result.message);
console.log("ℹ️ Assignment result:", res.message);
alert(`Info: ${res.message}`);
} }
} catch (error) { } catch (error) {
console.error("❌ Error in manual assignment:", error);
console.error("❌ Error assigning by store:", error);
alert("Error occurred during assignment");
} finally { } finally {
setIsAssigning(false); setIsAssigning(false);
} }
}, [currentUserId, isAssigning]);
};
// ✅ Manual assignment handler - uses the action function



const handleTabChange = useCallback<NonNullable<TabsProps["onChange"]>>( const handleTabChange = useCallback<NonNullable<TabsProps["onChange"]>>(
(_e, newValue) => { (_e, newValue) => {
@@ -316,7 +315,7 @@ const PickOrderSearch: React.FC<Props> = ({ pickOrders }) => {
borderBottom: '1px solid #e0e0e0' borderBottom: '1px solid #e0e0e0'
}}> }}>
<Tabs value={tabIndex} onChange={handleTabChange} variant="scrollable"> <Tabs value={tabIndex} onChange={handleTabChange} variant="scrollable">
<Tab label={t("Pick Execution")} iconPosition="end" />
<Tab label={t("Pick Order Detail")} iconPosition="end" />
<Tab label={t("Pick Execution Detail")} iconPosition="end" /> <Tab label={t("Pick Execution Detail")} iconPosition="end" />
</Tabs> </Tabs>


+ 41
- 49
src/components/FinishedGoodSearch/GoodPickExecutiondetail.tsx 查看文件

@@ -15,6 +15,7 @@ import {
TableHead, TableHead,
TableRow, TableRow,
Paper, Paper,
Checkbox,
TablePagination, TablePagination,
Modal, Modal,
} from "@mui/material"; } from "@mui/material";
@@ -490,25 +491,21 @@ const PickExecution: React.FC<Props> = ({ filterArgs }) => {
console.log(`✅ Stock out line already exists for line ${matchingLot.pickOrderLineId}`); console.log(`✅ Stock out line already exists for line ${matchingLot.pickOrderLineId}`);
existsCount++; existsCount++;
} else { } else {
const stockOutLineData: CreateStockOutLine = {
consoCode: matchingLot.pickOrderConsoCode,
pickOrderLineId: matchingLot.pickOrderLineId,
inventoryLotLineId: matchingLot.lotId,
qty: 0.0
};
const stockOutLineUpdate = await updateStockOutLineStatus({
id: selectedLotForQr.stockOutLineId,
status: 'checked',
qty: selectedLotForQr.stockOutLineQty || 0
});
console.log(`Create stock out line result for line ${matchingLot.pickOrderLineId}:`,stockOutLineUpdate);
console.log(`Creating stock out line for pick order line ${matchingLot.pickOrderLineId}:`, stockOutLineData);
const result = await createStockOutLine(stockOutLineData);
console.log(`Create stock out line result for line ${matchingLot.pickOrderLineId}:`, result);
if (result && result.code === "EXISTS") {
if (stockOutLineUpdate && stockOutLineUpdate.code === "EXISTS") {
console.log(`✅ Stock out line already exists for line ${matchingLot.pickOrderLineId}`); console.log(`✅ Stock out line already exists for line ${matchingLot.pickOrderLineId}`);
existsCount++; existsCount++;
} else if (result && result.code === "SUCCESS") {
} else if (stockOutLineUpdate && stockOutLineUpdate.code === "SUCCESS") {
console.log(`✅ Stock out line created successfully for line ${matchingLot.pickOrderLineId}`); console.log(`✅ Stock out line created successfully for line ${matchingLot.pickOrderLineId}`);
successCount++; successCount++;
} else { } else {
console.error(`❌ Failed to create stock out line for line ${matchingLot.pickOrderLineId}:`, result);
console.error(`❌ Failed to create stock out line for line ${matchingLot.pickOrderLineId}:`, stockOutLineUpdate);
errorCount++; errorCount++;
} }
} }
@@ -567,16 +564,15 @@ const PickExecution: React.FC<Props> = ({ filterArgs }) => {
const lotId = selectedLotForQr.lotId; const lotId = selectedLotForQr.lotId;
// Create stock out line // Create stock out line
const stockOutLineData: CreateStockOutLine = {
consoCode: selectedLotForQr.pickOrderConsoCode, // ✅ Use pickOrderConsoCode instead of pickOrderCode
pickOrderLineId: selectedLotForQr.pickOrderLineId,
inventoryLotLineId: selectedLotForQr.lotId,
qty: 0.0
};

try { try {
await createStockOutLine(stockOutLineData);
console.log("Stock out line created successfully!");
const stockOutLineUpdate = await updateStockOutLineStatus({
id: selectedLotForQr.stockOutLineId,
status: 'checked',
qty: selectedLotForQr.stockOutLineQty || 0
});
console.log("Stock out line updated successfully!");
// Close modal // Close modal
setQrModalOpen(false); setQrModalOpen(false);
@@ -907,30 +903,12 @@ const PickExecution: React.FC<Props> = ({ filterArgs }) => {
}, []); }, []);


// Pagination data with sorting by routerIndex // 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 sortedData.slice(startIndex, endIndex);
}, [combinedLotData, paginationController]);
// Remove the sorting logic and just do pagination
const paginatedData = useMemo(() => {
const startIndex = paginationController.pageNum * paginationController.pageSize;
const endIndex = startIndex + paginationController.pageSize;
return combinedLotData.slice(startIndex, endIndex); // ✅ No sorting needed
}, [combinedLotData, paginationController]);


return ( return (
<FormProvider {...formProps}> <FormProvider {...formProps}>
@@ -980,7 +958,7 @@ const PickExecution: React.FC<Props> = ({ filterArgs }) => {
<strong>{t("Shop Name")}:</strong> {fgPickOrders[0].shopName || '-'} <strong>{t("Shop Name")}:</strong> {fgPickOrders[0].shopName || '-'}
</Typography> </Typography>
<Typography variant="subtitle1"> <Typography variant="subtitle1">
<strong>{t("Delivery Date")}:</strong> {(fgPickOrders[0].deliveryDate || '-').split('T')[0]}
<strong>{t("Pick Order Code")}:</strong>{fgPickOrders[0].pickOrderCode || '-'}
</Typography> </Typography>
<Typography variant="subtitle1"> <Typography variant="subtitle1">
<strong>{t("Departure Time")}:</strong> {fgPickOrders[0].DepartureTime || '-'} <strong>{t("Departure Time")}:</strong> {fgPickOrders[0].DepartureTime || '-'}
@@ -1015,6 +993,7 @@ const PickExecution: React.FC<Props> = ({ filterArgs }) => {
{/* <TableCell align="right">{t("Original Available Qty")}</TableCell> */} {/* <TableCell align="right">{t("Original Available Qty")}</TableCell> */}
<TableCell align="center">{t("Lot Actual Pick Qty")}</TableCell> <TableCell align="center">{t("Lot Actual Pick Qty")}</TableCell>
{/* <TableCell align="right">{t("Remaining Available Qty")}</TableCell> */} {/* <TableCell align="right">{t("Remaining Available Qty")}</TableCell> */}
<TableCell align="right">{t("Finish Scan?")}</TableCell>
<TableCell align="center">{t("Action")}</TableCell> <TableCell align="center">{t("Action")}</TableCell>
</TableRow> </TableRow>
</TableHead> </TableHead>
@@ -1041,7 +1020,7 @@ const PickExecution: React.FC<Props> = ({ filterArgs }) => {
> >
<TableCell> <TableCell>
<Typography variant="body2" fontWeight="bold"> <Typography variant="body2" fontWeight="bold">
{lot.routerIndex || index + 1}
{index + 1}
</Typography> </Typography>
</TableCell> </TableCell>
<TableCell> <TableCell>
@@ -1070,7 +1049,7 @@ const PickExecution: React.FC<Props> = ({ filterArgs }) => {
const inQty = lot.inQty || 0; const inQty = lot.inQty || 0;
const outQty = lot.outQty || 0; const outQty = lot.outQty || 0;
const result = inQty - outQty; const result = inQty - outQty;
return result.toLocaleString();
return result.toLocaleString()+'('+lot.stockUnit+')';
})()} })()}
</TableCell> </TableCell>
<TableCell align="center"> <TableCell align="center">
@@ -1102,7 +1081,7 @@ const PickExecution: React.FC<Props> = ({ filterArgs }) => {
{t("Scan")} {t("Scan")}
</Button> </Button>
) : ( ) : (
// ✅ When stockOutLineId exists, show TextField + Issue button
<Stack direction="row" spacing={1} alignItems="center"> <Stack direction="row" spacing={1} alignItems="center">
<TextField <TextField
type="number" type="number"
@@ -1162,6 +1141,19 @@ const PickExecution: React.FC<Props> = ({ filterArgs }) => {
return result.toLocaleString(); return result.toLocaleString();
})()} })()}
</TableCell> */} </TableCell> */}
<TableCell align="center">
<Checkbox
checked={lot.stockOutLineStatus?.toLowerCase() !== 'pending'}
disabled={true}
readOnly={true}
sx={{
color: lot.stockOutLineStatus?.toLowerCase() !== 'pending' ? 'success.main' : 'grey.400',
'&.Mui-checked': {
color: 'success.main',
},
}}
/>
</TableCell>
<TableCell align="center"> <TableCell align="center">
<Stack direction="column" spacing={1} alignItems="center"> <Stack direction="column" spacing={1} alignItems="center">
<Button <Button


+ 14
- 1
src/i18n/zh/pickOrder.json 查看文件

@@ -242,5 +242,18 @@
"Max":"最大值", "Max":"最大值",
"Route":"路線", "Route":"路線",
"Index":"編號", "Index":"編號",
"No FG pick orders found":"沒有成品提料單"
"No FG pick orders found":"沒有成品提料單",
"Finish Scan?":"完成掃描?",
"Delivery Code":"出倉單編號",
"Shop PO Code":"訂單編號",
"Shop ID":"商店編號",
"Truck No.":"車輛編號",
"Departure Time":"車輛出發時間",
"Shop Name":"商店名稱",
"Shop Address":"商店地址",
"Delivery Date":"目標日期",
"Pick Execution 2/F":"進行提料 2/F",
"Pick Execution 4/F":"進行提料 4/F",
"Pick Execution Detail":"進行提料詳情"
} }

正在加载...
取消
保存