|
|
|
@@ -58,6 +58,7 @@ import { stockTakeQtyEndAdornment, StockTakeQtyWithUnit } from "./stockTakeQtyAd |
|
|
|
import StockTakeQtyGapHint from "./StockTakeQtyGapHint"; |
|
|
|
import { stockTakeHiddenOnHand, stockTakeQtyGapWarnText } from "./stockTakeQtyGapWarning"; |
|
|
|
import { useStockTakeQtyGapWarnPercent } from "./useStockTakeQtyGapWarnPercent"; |
|
|
|
import { statusChipColor } from "./StockTakeRoundCardList"; |
|
|
|
import { useSession } from "next-auth/react"; |
|
|
|
import { SessionWithTokens } from "@/config/authConfig"; |
|
|
|
import { AUTH } from "@/authorities"; |
|
|
|
@@ -1176,7 +1177,12 @@ const ApproverStockTakeAll: React.FC<ApproverStockTakeAllProps> = ({ |
|
|
|
}; |
|
|
|
/** Word-style: same location grouped under a heading (picker-like). */ |
|
|
|
const locationGroups = useMemo(() => { |
|
|
|
const groups: { key: string; label: string; items: InventoryLotDetailResponse[] }[] = []; |
|
|
|
const groups: { |
|
|
|
key: string; |
|
|
|
label: string; |
|
|
|
sectionLabels: string[]; |
|
|
|
items: InventoryLotDetailResponse[]; |
|
|
|
}[] = []; |
|
|
|
const indexByKey = new Map<string, number>(); |
|
|
|
for (const detail of sortedDetails) { |
|
|
|
const area = detail.warehouseArea?.trim() || ""; |
|
|
|
@@ -1192,9 +1198,17 @@ const ApproverStockTakeAll: React.FC<ApproverStockTakeAllProps> = ({ |
|
|
|
if (idx == null) { |
|
|
|
idx = groups.length; |
|
|
|
indexByKey.set(key, idx); |
|
|
|
groups.push({ key, label, items: [] }); |
|
|
|
groups.push({ key, label, sectionLabels: [], items: [] }); |
|
|
|
} |
|
|
|
groups[idx].items.push(detail); |
|
|
|
const sectionCode = detail.stockTakeSection?.trim() || ""; |
|
|
|
if (sectionCode) { |
|
|
|
const sectionDesc = detail.stockTakeSectionDescription?.trim() || ""; |
|
|
|
const sectionLabel = sectionDesc ? `${sectionCode} (${sectionDesc})` : sectionCode; |
|
|
|
if (!groups[idx].sectionLabels.includes(sectionLabel)) { |
|
|
|
groups[idx].sectionLabels.push(sectionLabel); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return groups; |
|
|
|
}, [sortedDetails]); |
|
|
|
@@ -1252,16 +1266,22 @@ const ApproverStockTakeAll: React.FC<ApproverStockTakeAllProps> = ({ |
|
|
|
{ |
|
|
|
field: "uom", |
|
|
|
headerName: t("UOM"), |
|
|
|
minWidth: 90, |
|
|
|
flex: 0.4, |
|
|
|
minWidth: 140, |
|
|
|
flex: 0.75, |
|
|
|
sortable: false, |
|
|
|
valueGetter: (params) => params.row.uom || "-", |
|
|
|
align: "center", |
|
|
|
headerAlign: "center", |
|
|
|
renderCell: (params) => ( |
|
|
|
<Typography variant="body2" sx={{ width: "100%", textAlign: "center" }}> |
|
|
|
{params.row.uom || "-"} |
|
|
|
</Typography> |
|
|
|
), |
|
|
|
}, |
|
|
|
{ |
|
|
|
field: "qtyBlock", |
|
|
|
headerName: t("Stock Take Qty Data and Variance Analysis"), |
|
|
|
minWidth: 480, |
|
|
|
flex: 3.2, |
|
|
|
minWidth: 420, |
|
|
|
flex: 2.7, |
|
|
|
sortable: false, |
|
|
|
renderCell: (params: GridRenderCellParams<InventoryLotDetailResponse>) => { |
|
|
|
const detail = params.row; |
|
|
|
@@ -1545,24 +1565,20 @@ const ApproverStockTakeAll: React.FC<ApproverStockTakeAllProps> = ({ |
|
|
|
minWidth: 130, |
|
|
|
flex: 0.6, |
|
|
|
sortable: false, |
|
|
|
align: "center", |
|
|
|
headerAlign: "center", |
|
|
|
renderCell: (params) => { |
|
|
|
const raw = params.row.stockTakeRecordStatus; |
|
|
|
const status = String(raw ?? "").trim().toLowerCase(); |
|
|
|
|
|
|
|
const colorMap: Record<string, "success" | "warning" | "info" | "default" | "error"> = { |
|
|
|
completed: "success", |
|
|
|
notmatch: "warning", |
|
|
|
pending: "info", |
|
|
|
"not_match": "warning", |
|
|
|
}; |
|
|
|
|
|
|
|
return ( |
|
|
|
<Chip |
|
|
|
size="small" |
|
|
|
label={t(`${status}`) || "-"} |
|
|
|
color={colorMap[status] ?? "default"} |
|
|
|
variant="outlined" |
|
|
|
/> |
|
|
|
<Box sx={{ width: "100%", display: "flex", justifyContent: "center" }}> |
|
|
|
<Chip |
|
|
|
size="small" |
|
|
|
variant="outlined" |
|
|
|
label={t(`${status}`) || "-"} |
|
|
|
color={statusChipColor(status)} |
|
|
|
/> |
|
|
|
</Box> |
|
|
|
); |
|
|
|
} |
|
|
|
}, |
|
|
|
@@ -1572,7 +1588,13 @@ const ApproverStockTakeAll: React.FC<ApproverStockTakeAllProps> = ({ |
|
|
|
minWidth: 140, |
|
|
|
flex: 0.7, |
|
|
|
sortable: false, |
|
|
|
valueGetter: (params) => params.row.stockTakerName || "-", |
|
|
|
align: "center", |
|
|
|
headerAlign: "center", |
|
|
|
renderCell: (params) => ( |
|
|
|
<Typography variant="body2" sx={{ width: "100%", textAlign: "center" }}> |
|
|
|
{params.row.stockTakerName || "-"} |
|
|
|
</Typography> |
|
|
|
), |
|
|
|
}, |
|
|
|
{ |
|
|
|
field: "actions", |
|
|
|
@@ -1580,6 +1602,8 @@ const ApproverStockTakeAll: React.FC<ApproverStockTakeAllProps> = ({ |
|
|
|
minWidth: 110, |
|
|
|
flex: 0.9, |
|
|
|
sortable: false, |
|
|
|
align: "center", |
|
|
|
headerAlign: "center", |
|
|
|
renderCell: (params) => { |
|
|
|
const detail = params.row; |
|
|
|
const hasSecond = detail.secondStockTakeQty != null && detail.secondStockTakeQty >= 0; |
|
|
|
@@ -1587,7 +1611,7 @@ const ApproverStockTakeAll: React.FC<ApproverStockTakeAllProps> = ({ |
|
|
|
qtySelection[detail.id] || (hasSecond ? "second" : "first"); |
|
|
|
|
|
|
|
return ( |
|
|
|
<Stack direction="column" spacing={1} sx={{ width: "100%" }}> |
|
|
|
<Stack direction="column" spacing={1} sx={{ width: "100%", alignItems: "center" }}> |
|
|
|
{mode === "pending" && ( |
|
|
|
<> |
|
|
|
<Box> |
|
|
|
@@ -2166,6 +2190,9 @@ const ApproverStockTakeAll: React.FC<ApproverStockTakeAllProps> = ({ |
|
|
|
<Box key={group.key} sx={{ width: "100%" }}> |
|
|
|
<Typography variant="subtitle1" fontWeight={700} sx={{ mb: 1, px: 0.5 }}> |
|
|
|
{t("Warehouse Location")}: {group.label} |
|
|
|
{group.sectionLabels.length > 0 |
|
|
|
? ` · ${t("Stock Take Section code")}: ${group.sectionLabels.join(", ")}` |
|
|
|
: ""} |
|
|
|
</Typography> |
|
|
|
<Box |
|
|
|
sx={{ |
|
|
|
@@ -2185,7 +2212,7 @@ const ApproverStockTakeAll: React.FC<ApproverStockTakeAllProps> = ({ |
|
|
|
sx={{ |
|
|
|
backgroundColor: "transparent", |
|
|
|
"& .MuiDataGrid-columnHeaders": { backgroundColor: "#fff" }, |
|
|
|
"& .MuiDataGrid-cell": { py: 1, alignItems: "flex-start" }, |
|
|
|
"& .MuiDataGrid-cell": { py: 1, alignItems: "center" }, |
|
|
|
"& .MuiDataGrid-row": { minHeight: 96 }, |
|
|
|
}} |
|
|
|
/> |
|
|
|
|