Browse Source

update jobmatch

reset-do-picking-order
CANCERYS\kw093 3 weeks ago
parent
commit
eaa9477faa
6 changed files with 70 additions and 61 deletions
  1. +23
    -17
      src/components/Jodetail/JobPickExecutionForm.tsx
  2. +13
    -42
      src/components/Jodetail/JobPickExecutionsecondscan.tsx
  3. +1
    -1
      src/components/Jodetail/JobmatchForm.tsx
  4. +23
    -1
      src/i18n/zh/common.json
  5. +9
    -0
      src/i18n/zh/jo.json
  6. +1
    -0
      src/i18n/zh/pickOrder.json

+ 23
- 17
src/components/Jodetail/JobPickExecutionForm.tsx View File

@@ -91,7 +91,9 @@ const PickExecutionForm: React.FC<PickExecutionFormProps> = ({
const [handlers, setHandlers] = useState<Array<{ id: number; name: string }>>([]); const [handlers, setHandlers] = useState<Array<{ id: number; name: string }>>([]);
const [verifiedQty, setVerifiedQty] = useState<number>(0); const [verifiedQty, setVerifiedQty] = useState<number>(0);
const { data: session } = useSession() as { data: SessionWithTokens | null }; const { data: session } = useSession() as { data: SessionWithTokens | null };
const missSet = formData.missQty != null;
const badItemSet = formData.badItemQty != null;
const badPackageSet = (formData as any).badPackageQty != null;
const calculateRemainingAvailableQty = useCallback((lot: LotPickData) => { const calculateRemainingAvailableQty = useCallback((lot: LotPickData) => {
return lot.availableQty || 0; return lot.availableQty || 0;
}, []); }, []);
@@ -162,9 +164,9 @@ useEffect(() => {
storeLocation: selectedLot.location, storeLocation: selectedLot.location,
requiredQty: selectedLot.requiredQty, requiredQty: selectedLot.requiredQty,
actualPickQty: initialVerifiedQty, actualPickQty: initialVerifiedQty,
missQty: 0,
badItemQty: 0,
badPackageQty: 0, // Bad Package Qty (frontend only)
missQty: undefined,
badItemQty: undefined,
badPackageQty: undefined,
issueRemark: "", issueRemark: "",
pickerName: "", pickerName: "",
handledBy: undefined, handledBy: undefined,
@@ -195,10 +197,10 @@ useEffect(() => {
const newErrors: FormErrors = {}; const newErrors: FormErrors = {};
const ap = Number(verifiedQty) || 0; const ap = Number(verifiedQty) || 0;
const miss = Number(formData.missQty) || 0; const miss = Number(formData.missQty) || 0;
const badItem = Number(formData.badItemQty) || 0;
const badPackage = Number((formData as any).badPackageQty) || 0;
const totalBad = badItem + badPackage;
const total = ap + miss + totalBad;
const badItem = Number(formData.badItemQty) ?? 0;
const badPackage = Number((formData as any).badPackageQty) ?? 0;
const totalBadQty = badItem + badPackage;
const total = ap + miss + totalBadQty;
const availableQty = selectedLot?.availableQty || 0; const availableQty = selectedLot?.availableQty || 0;


// 1. Check actualPickQty cannot be negative // 1. Check actualPickQty cannot be negative
@@ -231,7 +233,7 @@ useEffect(() => {
} }


// 5. At least one field must have a value // 5. At least one field must have a value
if (ap === 0 && miss === 0 && totalBad === 0) {
if (ap === 0 && miss === 0 && totalBadQty === 0) {
newErrors.actualPickQty = t("Enter pick qty or issue qty"); newErrors.actualPickQty = t("Enter pick qty or issue qty");
} }


@@ -288,11 +290,12 @@ useEffect(() => {
const submissionData: PickExecutionIssueData = { const submissionData: PickExecutionIssueData = {
...(formData as PickExecutionIssueData), ...(formData as PickExecutionIssueData),
actualPickQty: verifiedQty, actualPickQty: verifiedQty,
lotId: formData.lotId || selectedLot?.lotId || 0,
lotNo: formData.lotNo || selectedLot?.lotNo || '',
pickOrderCode: formData.pickOrderCode || selectedPickOrderLine?.pickOrderCode || '',
pickerName: session?.user?.name || '',
badItemQty: totalBadQty,
lotId: formData.lotId ?? selectedLot?.lotId ?? 0,
lotNo: formData.lotNo ?? selectedLot?.lotNo ?? '',
pickOrderCode: formData.pickOrderCode ?? selectedPickOrderLine?.pickOrderCode ?? '',
pickerName: session?.user?.name ?? '',
missQty: formData.missQty ?? 0, // 这里:null/undefined → 0
badItemQty: totalBadQty, // totalBadQty 下面用 ?? 0 算
badReason, badReason,
}; };
@@ -397,7 +400,8 @@ useEffect(() => {
pattern: "[0-9]*", pattern: "[0-9]*",
min: 0, min: 0,
}} }}
value={formData.missQty || 0}
disabled={badItemSet || badPackageSet}
value={formData.missQty || ""}
onChange={(e) => { onChange={(e) => {
handleInputChange( handleInputChange(
"missQty", "missQty",
@@ -421,7 +425,7 @@ useEffect(() => {
pattern: "[0-9]*", pattern: "[0-9]*",
min: 0, min: 0,
}} }}
value={formData.badItemQty || 0}
value={formData.badItemQty || ""}
onChange={(e) => { onChange={(e) => {
const newBadItemQty = e.target.value === "" const newBadItemQty = e.target.value === ""
? undefined ? undefined
@@ -429,6 +433,7 @@ useEffect(() => {
handleInputChange('badItemQty', newBadItemQty); handleInputChange('badItemQty', newBadItemQty);
}} }}
error={!!errors.badItemQty} error={!!errors.badItemQty}
disabled={missSet || badPackageSet}
helperText={errors.badItemQty} helperText={errors.badItemQty}
variant="outlined" variant="outlined"
/> />
@@ -444,7 +449,7 @@ useEffect(() => {
pattern: "[0-9]*", pattern: "[0-9]*",
min: 0, min: 0,
}} }}
value={(formData as any).badPackageQty || 0}
value={(formData as any).badPackageQty || ""}
onChange={(e) => { onChange={(e) => {
handleInputChange( handleInputChange(
"badPackageQty", "badPackageQty",
@@ -453,6 +458,7 @@ useEffect(() => {
: Math.max(0, Number(e.target.value) || 0) : Math.max(0, Number(e.target.value) || 0)
); );
}} }}
disabled={missSet || badItemSet}
error={!!errors.badItemQty} error={!!errors.badItemQty}
variant="outlined" variant="outlined"
/> />


+ 13
- 42
src/components/Jodetail/JobPickExecutionsecondscan.tsx View File

@@ -868,7 +868,8 @@ const JobPickExecution: React.FC<Props> = ({ filterArgs, onBack }) => {
qty: submitQty, qty: submitQty,
isMissing: false, isMissing: false,
isBad: false, isBad: false,
reason: undefined
reason: undefined,
userId: currentUserId ?? 0
} }
); );
@@ -881,7 +882,7 @@ const JobPickExecution: React.FC<Props> = ({ filterArgs, onBack }) => {
} catch (error) { } catch (error) {
console.error("Error submitting second scan quantity:", error); console.error("Error submitting second scan quantity:", error);
} }
}, [fetchJobOrderData]);
}, [fetchJobOrderData, currentUserId]);


const handlePickExecutionForm = useCallback((lot: any) => { const handlePickExecutionForm = useCallback((lot: any) => {
console.log("=== Pick Execution Form ==="); console.log("=== Pick Execution Form ===");
@@ -1263,55 +1264,24 @@ const JobPickExecution: React.FC<Props> = ({ filterArgs, onBack }) => {
return requiredQty.toLocaleString()+'('+lot.uomShortDesc+')'; return requiredQty.toLocaleString()+'('+lot.uomShortDesc+')';
})()} })()}
</TableCell> </TableCell>
{/*
<TableCell align="center">
{lot.matchStatus?.toLowerCase() === 'scanned' ||
lot.matchStatus?.toLowerCase() === 'completed' ? (
<Box sx={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
width: '100%',
height: '100%'
}}>
<Checkbox
checked={true}
disabled={true}
readOnly={true}
size="large"
sx={{
color: 'success.main',
'&.Mui-checked': {
color: 'success.main',
},
transform: 'scale(1.3)',
'& .MuiSvgIcon-root': {
fontSize: '1.5rem',
}
}}
/>
</Box>
) : (
<Typography variant="body2" color="text.secondary">
{t(" ")}
</Typography>
)}
</TableCell>
*/}

<TableCell align="center"> <TableCell align="center">
<Box sx={{ display: 'flex', justifyContent: 'center' }}> <Box sx={{ display: 'flex', justifyContent: 'center' }}>
<Stack direction="row" spacing={1} alignItems="center"> <Stack direction="row" spacing={1} alignItems="center">
<Button <Button
variant="contained" variant="contained"
onClick={() => {
onClick={async () => {
const lotKey = `${lot.pickOrderLineId}-${lot.lotId}`; const lotKey = `${lot.pickOrderLineId}-${lot.lotId}`;
const submitQty = lot.requiredQty || lot.pickOrderLineRequiredQty; const submitQty = lot.requiredQty || lot.pickOrderLineRequiredQty;
handlePickQtyChange(lotKey, submitQty); handlePickQtyChange(lotKey, submitQty);
handleSubmitPickQtyWithQty(lot, submitQty);
updateSecondQrScanStatus(lot.pickOrderId, lot.itemId, currentUserId || 0, submitQty);
// 先更新 matching 狀態(可選,依你後端流程)
await updateSecondQrScanStatus(lot.pickOrderId, lot.itemId, currentUserId || 0, submitQty);
// 再提交數量並 await refetch,表格會即時更新提料員
await handleSubmitPickQtyWithQty(lot, submitQty);
}} }}
disabled={ disabled={
//lot.matchStatus !== 'scanned' ||
lot.matchStatus === 'completed' ||
lot.matchStatus == 'scanned' ||
lot.lotAvailability === 'expired' || lot.lotAvailability === 'expired' ||
lot.lotAvailability === 'status_unavailable' || lot.lotAvailability === 'status_unavailable' ||
lot.lotAvailability === 'rejected' lot.lotAvailability === 'rejected'
@@ -1331,7 +1301,8 @@ const JobPickExecution: React.FC<Props> = ({ filterArgs, onBack }) => {
size="small" size="small"
onClick={() => handlePickExecutionForm(lot)} onClick={() => handlePickExecutionForm(lot)}
disabled={ disabled={
lot.matchStatus !== 'scanned' ||
lot.matchStatus === 'completed' ||
lot.matchStatus == 'scanned' ||
lot.lotAvailability === 'expired' || lot.lotAvailability === 'expired' ||
lot.lotAvailability === 'status_unavailable' || lot.lotAvailability === 'status_unavailable' ||
lot.lotAvailability === 'rejected' lot.lotAvailability === 'rejected'


+ 1
- 1
src/components/Jodetail/JobmatchForm.tsx View File

@@ -80,7 +80,7 @@ const PickExecutionForm: React.FC<PickExecutionFormProps> = ({
// onNormalPickSubmit, // onNormalPickSubmit,
// selectedRowId, // selectedRowId,
}) => { }) => {
const { t } = useTranslation();
const { t } = useTranslation('common');
const [formData, setFormData] = useState<Partial<PickExecutionIssueData>>({}); const [formData, setFormData] = useState<Partial<PickExecutionIssueData>>({});
const [errors, setErrors] = useState<FormErrors>({}); const [errors, setErrors] = useState<FormErrors>({});
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);


+ 23
- 1
src/i18n/zh/common.json View File

@@ -457,5 +457,27 @@
"Delete Success": "刪除成功", "Delete Success": "刪除成功",
"Delete Failed": "刪除失敗", "Delete Failed": "刪除失敗",
"Create Printer": "新增列印機", "Create Printer": "新增列印機",
"Report": "報告"
"Report": "報告",
"Issue": "問題",
"Note:": "注意:",
"Required Qty": "需求數量",
"Verified Qty": "確認數量",
"Max": "最大值",
"Min": "最小值",
"Max": "最大值",
"This form is for reporting issues only. You must report either missing items or bad items.": "此表單僅用於報告問題。您必須報告缺少的物品或不良物品。",
"Pick Execution Issue Form": "提料問題表單",
"Missing items": "缺少物品",
"Total (Verified + Bad + Missing) must equal Required quantity": "總數必須等於需求數量",
"Missing item Qty": "缺少物品數量",
"Bad Item Qty": "不良物品數量",
"Issue Remark": "問題備註",
"At least one issue must be reported": "至少需要報告一個問題",
"Qty is required": "數量是必填項",
"Verified quantity cannot exceed received quantity": "確認數量不能超過接收數量",
"Handled By": "處理者",
"submit": "提交",
"Received Qty": "接收數量"

} }

+ 9
- 0
src/i18n/zh/jo.json View File

@@ -557,5 +557,14 @@
"Production Time Remaining": "生產剩餘時間", "Production Time Remaining": "生產剩餘時間",
"Process": "工序", "Process": "工序",
"Start": "開始", "Start": "開始",
"This form is for reporting issues only. You must report either missing items or bad items.": "此表單僅用於報告問題。您必須報告缺少的物品或不良物品。",
"Pick Execution Issue Form": "提料問題表單",
"Missing items": "缺少物品",
"Total (Verified + Bad + Missing) must equal Required quantity": "總數必須等於需求數量",
"Missing item Qty": "缺少物品數量",
"Bad Item Qty": "不良物品數量",
"Issue Remark": "問題備註",
"Handled By": "處理者",
"Finish": "完成" "Finish": "完成"

} }

+ 1
- 0
src/i18n/zh/pickOrder.json View File

@@ -367,6 +367,7 @@
"View Details": "查看詳情", "View Details": "查看詳情",
"No Item": "沒有貨品", "No Item": "沒有貨品",
"None": "沒有", "None": "沒有",
"This form is for reporting issues only. You must report either missing items or bad items.": "此表單僅用於報告問題。您必須報告缺少的物品或不良物品。",
"Add Selected Items to Created Items": "將已選擇的貨品添加到已建立的貨品中", "Add Selected Items to Created Items": "將已選擇的貨品添加到已建立的貨品中",
"All pick orders created successfully": "所有提料單建立成功", "All pick orders created successfully": "所有提料單建立成功",
"Failed to create group": "建立分組失敗", "Failed to create group": "建立分組失敗",


Loading…
Cancel
Save