From 82eedd7e80bf241646a5697a398d17fed426c392 Mon Sep 17 00:00:00 2001 From: "CANCERYS\\kw093" Date: Mon, 30 Mar 2026 17:13:11 +0800 Subject: [PATCH] update --- .../StockTakeManagement/PickerCardList.tsx | 9 ++++-- .../StockTakeManagement/PickerReStockTake.tsx | 28 +++++++++++++++++-- src/config/reportConfig.ts | 21 ++++++++++++-- 3 files changed, 52 insertions(+), 6 deletions(-) diff --git a/src/components/StockTakeManagement/PickerCardList.tsx b/src/components/StockTakeManagement/PickerCardList.tsx index 06980d8..4559c0b 100644 --- a/src/components/StockTakeManagement/PickerCardList.tsx +++ b/src/components/StockTakeManagement/PickerCardList.tsx @@ -19,6 +19,8 @@ import { DialogContentText, DialogActions, } from "@mui/material"; +import { SessionWithTokens } from "@/config/authConfig"; +import { useSession } from "next-auth/react"; import SearchBox, { Criterion } from "@/components/SearchBox/SearchBox"; import { useState, useCallback, useEffect } from "react"; import { useTranslation } from "react-i18next"; @@ -33,7 +35,7 @@ import { import { fetchStockTakeSections } from "@/app/api/warehouse/actions"; import dayjs from "dayjs"; import { OUTPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; - +import { AUTH } from "@/authorities"; const PER_PAGE = 6; interface PickerCardListProps { @@ -59,6 +61,9 @@ const PickerCardList: React.FC = ({ const [loading, setLoading] = useState(false); const [stockTakeSessions, setStockTakeSessions] = useState([]); const [total, setTotal] = useState(0); + const { data: session } = useSession() as { data: SessionWithTokens | null }; + const abilities = session?.abilities ?? session?.user?.abilities ?? []; + const canManageStockTake = abilities.some((a) => a.trim() === AUTH.ADMIN); /** 建立盤點後若仍在 page 0,仍強制重新載入 */ const [listRefreshNonce, setListRefreshNonce] = useState(0); const [creating, setCreating] = useState(false); @@ -303,7 +308,7 @@ const handleResetSearch = () => { variant="contained" color="primary" onClick={() => setOpenConfirmDialog(true)} - disabled={creating} + disabled={creating || !canManageStockTake} > {creating ? : t("Create Stock Take for All Sections")} diff --git a/src/components/StockTakeManagement/PickerReStockTake.tsx b/src/components/StockTakeManagement/PickerReStockTake.tsx index 896b67f..84645a7 100644 --- a/src/components/StockTakeManagement/PickerReStockTake.tsx +++ b/src/components/StockTakeManagement/PickerReStockTake.tsx @@ -123,7 +123,7 @@ const PickerReStockTake: React.FC = ({ setLoadingDetails(false); } }, [selectedSession, total]); - + {/* useEffect(() => { const inputs: Record = {}; inventoryLotDetails.forEach((detail) => { @@ -143,7 +143,31 @@ const PickerReStockTake: React.FC = ({ }); setRecordInputs(inputs); }, [inventoryLotDetails]); - + */} + useEffect(() => { + setRecordInputs((prev) => { + const next: Record = {}; + inventoryLotDetails.forEach((detail) => { + const hasServerFirst = detail.firstStockTakeQty != null; + const hasServerSecond = detail.secondStockTakeQty != null; + const firstTotal = hasServerFirst + ? (detail.firstStockTakeQty! + (detail.firstBadQty ?? 0)).toString() + : ""; + const secondTotal = hasServerSecond + ? (detail.secondStockTakeQty! + (detail.secondBadQty ?? 0)).toString() + : ""; + const existing = prev[detail.id]; + next[detail.id] = { + firstQty: hasServerFirst ? firstTotal : (existing?.firstQty ?? firstTotal), + secondQty: hasServerSecond ? secondTotal : (existing?.secondQty ?? secondTotal), + firstBadQty: hasServerFirst ? (detail.firstBadQty?.toString() || "") : (existing?.firstBadQty ?? ""), + secondBadQty: hasServerSecond ? (detail.secondBadQty?.toString() || "") : (existing?.secondBadQty ?? ""), + remark: hasServerSecond ? (detail.remarks || "") : (existing?.remark ?? detail.remarks ?? ""), + }; + }); + return next; + }); + }, [inventoryLotDetails]); useEffect(() => { loadDetails(page, pageSize); }, [page, pageSize, loadDetails]); diff --git a/src/config/reportConfig.ts b/src/config/reportConfig.ts index e4df646..7a8f8c0 100644 --- a/src/config/reportConfig.ts +++ b/src/config/reportConfig.ts @@ -93,7 +93,7 @@ export const REPORTS: ReportDefinition[] = [ { label: "物料編號 Item Code", name: "itemCode", type: "text", required: false}, ] }, - +/* { id: "rep-012", title: "庫存盤點報告", apiEndpoint: `${NEXT_PUBLIC_API_URL}/report/print-stock-take-variance`, @@ -103,7 +103,24 @@ export const REPORTS: ReportDefinition[] = [ { label: "物料編號 Item Code", name: "itemCode", type: "text", required: false}, ] }, - + */ + { + id: "rep-012", + title: "庫存盤點報告", + apiEndpoint: `${NEXT_PUBLIC_API_URL}/report/print-stock-take-variance-v2`, + fields: [ + { + label: "盤點輪次 Stock Take Round", + name: "stockTakeRoundId", + type: "select", + required: true, + dynamicOptions: true, + dynamicOptionsEndpoint: `${NEXT_PUBLIC_API_URL}/report/stock-take-rounds`, + options: [] + }, + { label: "物料編號 Item Code", name: "itemCode", type: "text", required: false}, + ] + }, { id: "rep-011", title: "庫存明細報告", apiEndpoint: `${NEXT_PUBLIC_API_URL}/report/print-stock-ledger`,