Преглед на файлове

Merge branch 'master' of http://svn.2fi-solutions.com:8300/derek/FPSMS-frontend

# Conflicts:
#	src/components/FinishedGoodSearch/FGPickOrderCard.tsx
master
CANCERYS\kw093 преди 2 месеца
родител
ревизия
0715600347
променени са 13 файла, в които са добавени 241 реда и са изтрити 55 реда
  1. +1
    -0
      src/app/api/do/actions.tsx
  2. +2
    -2
      src/components/DoDetail/DoInfoCard.tsx
  3. +2
    -2
      src/components/DoSearch/DoSearch.tsx
  4. +3
    -3
      src/components/JoSave/ActionButtons.tsx
  5. +20
    -6
      src/components/JoSearch/JoSearch.tsx
  6. +2
    -5
      src/components/PoDetail/PutAwayForm.tsx
  7. +45
    -18
      src/components/PoDetail/QcComponent.tsx
  8. +1
    -2
      src/components/PoDetail/QcStockInModal.tsx
  9. +149
    -1
      src/components/PoDetail/dummyQcTemplate.tsx
  10. +4
    -4
      src/i18n/zh/common.json
  11. +10
    -10
      src/i18n/zh/do.json
  12. +1
    -1
      src/i18n/zh/jo.json
  13. +1
    -1
      src/i18n/zh/purchaseOrder.json

+ 1
- 0
src/app/api/do/actions.tsx Целия файл

@@ -19,6 +19,7 @@ export interface DoDetail {
code: string;
supplierCode: string;
shopCode: string;
shopName: string;
currencyCode: string;
orderDate: string;
estimatedArrivalDate: string;


+ 2
- 2
src/components/DoDetail/DoInfoCard.tsx Целия файл

@@ -41,8 +41,8 @@ const DoInfoCard: React.FC<Props> = ({
</Grid>
<Grid item xs={6}>
<TextField
{...register("shopCode")}
label={t("Shop Code")}
{...register("shopName")}
label={t("Shop Name")}
fullWidth
disabled={true}
/>


+ 2
- 2
src/components/DoSearch/DoSearch.tsx Целия файл

@@ -452,14 +452,14 @@ if(orderStartDate != ""){
alignItems="end"
>
<Stack spacing={2} direction="row">
<Button
{/*<Button
name="submit"
variant="contained"
// startIcon={<Check />}
type="submit"
>
{t("Create")}
</Button>
</Button>*/}
{hasSearched && hasResults && (
<Button
name="batch_release"


+ 3
- 3
src/components/JoSave/ActionButtons.tsx Целия файл

@@ -79,13 +79,13 @@ const ActionButtons: React.FC<Props> = ({
variant="outlined"
startIcon={<PlayCircleFilledWhiteIcon />}
onClick={handleStart}
disabled={errors.qtyErr || errors.scanErr || errors.pickErr}
// disabled={errors.qtyErr || errors.scanErr || errors.pickErr}
>
{t("Start Job Order")}
</Button>
{errors.pickErr && (<Typography variant="h3" color="error">{t("Please make sure all required items are picked")}</Typography>)}
{/* {errors.pickErr && (<Typography variant="h3" color="error">{t("Please make sure all required items are picked")}</Typography>)}
{errors.scanErr && (<Typography variant="h3" color="error">{t("Please scan the item qr code")}</Typography>)}
{errors.qtyErr && (<Typography variant="h3" color="error">{t("Please make sure the qty is enough")}</Typography>)}
{errors.qtyErr && (<Typography variant="h3" color="error">{t("Please make sure the qty is enough")}</Typography>)} */}
</Box>
)}
</Stack>


+ 20
- 6
src/components/JoSearch/JoSearch.tsx Целия файл

@@ -28,7 +28,10 @@ interface Props {
bomCombo: BomCombo[]
}

type SearchQuery = Partial<Omit<JobOrder, "id">>;
type SearchQuery = Partial<Omit<JobOrder, "id">> & {
planStartFrom?: string;
planStartTo?: string;
};

type SearchParamNames = keyof SearchQuery;

@@ -46,6 +49,8 @@ const JoSearch: React.FC<Props> = ({ defaultInputs, bomCombo }) => {
const searchCriteria: Criterion<SearchParamNames>[] = useMemo(() => [
{ label: t("Code"), paramName: "code", type: "text" },
{ label: t("Item Name"), paramName: "itemName", type: "text" },
{ label: t("Estimated Production Date From"), paramName: "planStartFrom", type: "date" },
{ label: t("Estimated Production Date To"), paramName: "planStartTo", type: "date" },
], [t])

const columns = useMemo<Column<JobOrder>[]>(
@@ -58,14 +63,14 @@ const JoSearch: React.FC<Props> = ({ defaultInputs, bomCombo }) => {
name: "item",
label: t("Item Code"),
renderCell: (row) => {
return t(row.item.code)
return row.item ? t(row.item.code) : '-'
}
},
{
name: "itemName",
label: t("Item Name"),
renderCell: (row) => {
return t(row.item.name)
return row.item ? t(row.item.name) : '-'
}
},
{
@@ -83,14 +88,22 @@ const JoSearch: React.FC<Props> = ({ defaultInputs, bomCombo }) => {
align: "left",
headerAlign: "left",
renderCell: (row) => {
return t(row.item.uom.udfudesc)
return row.item?.uom ? t(row.item.uom.udfudesc) : '-'
}
},
{
name: "status",
label: t("Status"),
renderCell: (row) => { // TODO improve
return <span style={{color: row.stockInLineStatus == "escalated" ? "red" : "inherit"}}>
{t(upperFirst(row.status))}
</span>
}
},{
name: "planStart",
label: t("Estimated Production Date"),
renderCell: (row) => {
return t(upperFirst(row.status))
return row.planStart ? arrayToDateString(row.planStart, "output") : '-'
}
},
{
@@ -195,7 +208,7 @@ const JoSearch: React.FC<Props> = ({ defaultInputs, bomCombo }) => {
// case "storing": btnSx = {label: t("view putaway"), color:"secondary.main"}; break;
case "storing":
switch (silStatus) {
case "pending": btnSx = {label: t("process epqc"), color:"primary.main"}; break;
case "pending": btnSx = {label: t("process epqc"), color:"success.main"}; break;
case "received": btnSx = {label: t("view putaway"), color:"secondary.main"}; break;
case "escalated":
if (sessionToken?.id == jo.silHandlerId) {
@@ -225,6 +238,7 @@ const JoSearch: React.FC<Props> = ({ defaultInputs, bomCombo }) => {
if (record.stockInLineId != null) {
const data = {
id: record.stockInLineId,
expiryDate: arrayToDateString(dayjs().add(1, "month"), "input"),
}
setModalInfo(data);
setOpenModal(true);


+ 2
- 5
src/components/PoDetail/PutAwayForm.tsx Целия файл

@@ -39,6 +39,7 @@ import { GridEditInputCell } from "@mui/x-data-grid";
import { StockInLine } from "@/app/api/stockIn";
import { WarehouseResult } from "@/app/api/warehouse";
import {
arrayToDateString,
arrayToDateTimeString,
OUTPUT_DATE_FORMAT,
stockInLineStatusMap,
@@ -382,11 +383,7 @@ const PutAwayForm: React.FC<Props> = ({ itemDetail, warehouse=[], disabled, setR
<TextField
label={t("expiryDate")}
fullWidth
value={
// dayjs(itemDetail.expiryDate)
dayjs()
.add(20, "day")
.format(OUTPUT_DATE_FORMAT)}
value={arrayToDateString(itemDetail.expiryDate, "output")}
disabled
/>
</Grid>


+ 45
- 18
src/components/PoDetail/QcComponent.tsx Целия файл

@@ -48,8 +48,10 @@ import { NEXT_PUBLIC_API_URL } from "@/config/api";
import axiosInstance from "@/app/(main)/axios/axiosInstance";
import EscalationComponent from "./EscalationComponent";
import QcDataGrid from "./QCDatagrid";
import { dummyEscalationHistory, dummyQCData } from "./dummyQcTemplate";
import { escape, min } from "lodash";
import { dummyEscalationHistory,
dummyQcData_A1, dummyQcData_E1, dummyQcData_E2,
dummyQcHeader_A1, dummyQcHeader_E1, dummyQcHeader_E2 } from "./dummyQcTemplate";
import { escape, isNull, min } from "lodash";
import { PanoramaSharp } from "@mui/icons-material";
import EscalationLogTable from "../DashboardPage/escalation/EscalationLogTable";
import { EscalationResult } from "@/app/api/escalation";
@@ -389,7 +391,7 @@ const QcComponent: React.FC<Props> = ({ itemDetail, disabled = false }) => {
useEffect(() => {
console.log("%c Qc Record updated:", "color:green", qcRecord);
if (qcRecord.length < 1) { // New QC
const fetchedQcData = dummyQCData; //TODO fetch from DB
const fetchedQcData = dummyQcData; //TODO fetch from DB
setValue("qcResult", fetchedQcData);
} else {
if (itemDetail?.status == "escalated") { // Copy the previous QC data for editing
@@ -470,6 +472,33 @@ const QcComponent: React.FC<Props> = ({ itemDetail, disabled = false }) => {
} else { return 60}
};

// For DEMO
const dummyQcData = useMemo(() => {
const d = itemDetail;
if (d.itemId == 23239 || d.itemNo == "PP2277" || d.itemName == "烚意粉") {
return dummyQcData_E2;
} else {
if (d.jobOrderId === null) {
return dummyQcData_A1;
} else {
return dummyQcData_E1;
}
}
}, [itemDetail])

const dummyQcHeader = useMemo(() => {
const d = itemDetail;console.log("I am checking now", d);
if (d.itemId == 23239 || d.itemNo == "PP2277" || d.itemName == "烚意粉") {
return dummyQcHeader_E2;
} else {
if (d.jobOrderId === null) {
return dummyQcHeader_A1;
} else {
return dummyQcHeader_E1;
}
}
}, [itemDetail])

return (
<>
<Grid container justifyContent="flex-start" alignItems="flex-start">
@@ -498,14 +527,13 @@ const QcComponent: React.FC<Props> = ({ itemDetail, disabled = false }) => {
<Box sx={{ mb: 2, p: 2, backgroundColor: '#f5f5f5', borderRadius: 1 }}>
<Typography variant="h5" component="h2" sx={{ fontWeight: 'bold', color: '#333' }}>
Group A - 急凍貨類 (QCA1-MEAT01)
{dummyQcHeader.name}
</Typography>
<Typography variant="subtitle1" sx={{ color: '#666' }}>
<b>品檢類型</b>:IQC
<b>品檢類型</b>:{dummyQcHeader.type}
</Typography>
<Typography variant="subtitle2" sx={{ color: '#666' }}>
記錄探測溫度的時間,請在1小時内完成卸貨盤點入庫,以保障食品安全<br/>
監察方法:目視檢查、嗅覺檢查和使用適當的食物溫度計,檢查食物溫度是否符合指標
{dummyQcHeader.description}
</Typography>
</Box>
{/* <QcDataGrid<ModalFormInput, QcData, EntryError>
@@ -545,16 +573,15 @@ const QcComponent: React.FC<Props> = ({ itemDetail, disabled = false }) => {
<EscalationLogTable type="qc" items={itemDetail.escResult || []}/>
<CollapsibleCard title={t("QC Record")}>
<Box sx={{ mb: 2, p: 2, backgroundColor: '#f5f5f5', borderRadius: 1 }}>
<Typography variant="h5" component="h2" sx={{ fontWeight: 'bold', color: '#333' }}>
Group A - 急凍貨類 (QCA1-MEAT01)
</Typography>
<Typography variant="subtitle1" sx={{ color: '#666' }}>
<b>品檢類型</b>:IQC
</Typography>
<Typography variant="subtitle2" sx={{ color: '#666' }}>
記錄探測溫度的時間,請在1小時内完成卸貨盤點入庫,以保障食品安全<br/>
監察方法:目視檢查、嗅覺檢查和使用適當的食物溫度計,檢查食物溫度是否符合指標
</Typography>
<Typography variant="h5" component="h2" sx={{ fontWeight: 'bold', color: '#333' }}>
{dummyQcHeader.name}
</Typography>
<Typography variant="subtitle1" sx={{ color: '#666' }}>
<b>品檢類型</b>:{dummyQcHeader.type}
</Typography>
<Typography variant="subtitle2" sx={{ color: '#666' }}>
{dummyQcHeader.description}
</Typography>
</Box>
<StyledDataGrid
columns={qcColumns}
@@ -678,7 +705,7 @@ const QcComponent: React.FC<Props> = ({ itemDetail, disabled = false }) => {
<FormControlLabel disabled={disabled}
value="2" control={<Radio />}
sx={{"& .Mui-checked": {color: "red"}}}
label= {detailMode ? "全部拒絕並退貨" : "不接受並退貨"} />
label= {detailMode ? "全部拒絕並退貨" : "不接受並需要退貨"} />
{(itemDetail.status == "pending" || disabled) && (<>
<FormControlLabel disabled={disabled}


+ 1
- 2
src/components/PoDetail/QcStockInModal.tsx Целия файл

@@ -21,7 +21,6 @@ import { StockInLineRow } from "./PoInputGrid";
import { useTranslation } from "react-i18next";
import StockInForm from "./StockInForm";
import QcComponent from "./QcComponent";
import { dummyPutAwayLine, dummyQCData } from "./dummyQcTemplate";
import PutAwayForm from "./PutAwayForm";
import { GridRowModes, GridRowSelectionModel, useGridApiRef } from "@mui/x-data-grid";
import {msg, submitDialogWithWarning} from "../Swal/CustomAlerts";
@@ -108,7 +107,7 @@ const PoQcStockInModalVer2: React.FC<Props> = ({
const res = await fetchStockInLineInfo(stockInLineId);
if (res) {
console.log("%c Fetched Stock In Line: ", "color:orange", res);
setStockInLineInfo({...inputDetail, ...res});
setStockInLineInfo({...inputDetail, ...res, expiryDate: inputDetail?.expiryDate}); // TODO review to overwrite res with inputDetail instead (revise PO fetching data)
fetchQcResultData(stockInLineId);
} else throw("Result is undefined");


+ 149
- 1
src/components/PoDetail/dummyQcTemplate.tsx Целия файл

@@ -10,7 +10,7 @@ import { QcData } from "@/app/api/qc"
// remarks: string | undefined
// }

export const dummyQCData: QcData[] = [
export const dummyQcData_A1: QcData[] = [
{
id: 1,
qcItemId: 4,
@@ -63,6 +63,154 @@ export const dummyQCData: QcData[] = [
},
]

export const dummyQcHeader_A1: any = {
name: "收貨要求 A1 - 急凍貨類 (QCA1-MEAT01)",
type: "IQC",
description: <>記錄探測溫度的時間,請在1小時内完成卸貨盤點入庫,以保障食品安全<br/>監察方法:目視檢查、嗅覺檢查和使用適當的食物溫度計,檢查食物溫度是否符合指標</>,

}

export const dummyQcHeader_E1: any = {
name: "收貨要求 E1 - 通過加熱製成的醬汁或食物 (QCE1-HEAT01)",
type: "EPQC",
description: "包裝後需用冷卻水池降溫",

}

export const dummyQcHeader_E2: any = {
name: "收貨要求 E2 - 室溫攪拌混合製成的醬汁或食物(無需加熱烹調) (QCA1-MIX01)",
type: "EPQC",
description: "不需使用冷卻水池降溫",

}

// For DEMO 2025/10/03
export const dummyQcData_E1: QcData[] = [
{
id: 1,
qcItemId: 25,
code: "包裝",
description: "包裝不嚴密,液體滲漏。包裝不乾淨,則不合格",
name: "包裝",
qcPassed: undefined,
failQty: undefined,
remarks: undefined,
},
{
id: 2,
qcItemId: 26,
code: "標籤",
description: "標籤名稱或日期錯誤、不清晰或缺失,則不合格",
name: "標籤",
qcPassed: undefined,
failQty: undefined,
remarks: undefined,
},
{
id: 3,
qcItemId: 27,
code: "肉質",
description: "肉質生熟程度不一致,或裁切尺寸不一致,則不合格",
name: "肉質",
qcPassed: undefined,
failQty: undefined,
remarks: undefined,
},
{
id: 4,
qcItemId: 28,
code: "異物",
description: "有異物,無法通過金屬探測器,則不合格",
name: "異物",
qcPassed: undefined,
failQty: undefined,
remarks: undefined,
},
{
id: 5,
qcItemId: 29,
code: "重量",
description: "超過製程要求的誤差+/-5%,則不合格",
name: "重量",
qcPassed: undefined,
failQty: undefined,
remarks: undefined,
},
{
id: 6,
qcItemId: 30,
code: "冷卻水池",
description: "未能於2小時內冷卻至20°C以下。冷卻水池水溫太高,或冷卻池中的成品太多,則不合格",
name: "冷卻水池",
qcPassed: undefined,
failQty: undefined,
remarks: undefined,
},
{
id: 7,
qcItemId: 31,
code: "冷庫",
description: "2小時內,未能及時入冷庫,冷卻至4°C或以下,則不合格",
name: "冷庫",
qcPassed: undefined,
failQty: undefined,
remarks: undefined,
},
]
// For PP2277 - 23293
export const dummyQcData_E2: QcData[] = [
{
id: 1,
qcItemId: 25,
code: "包裝",
description: "包裝不嚴密,液體滲漏。包裝不乾淨,則不合格",
name: "包裝",
qcPassed: undefined,
failQty: undefined,
remarks: undefined,
},
{
id: 2,
qcItemId: 26,
code: "標籤",
description: "標籤名稱或日期錯誤、不清晰或缺失,則不合格",
name: "標籤",
qcPassed: undefined,
failQty: undefined,
remarks: undefined,
},
{
id: 3,
qcItemId: 32,
code: "顔色",
description: "食材有破損、缺口、變質或醬汁有異常顏色狀態,則不合格",
name: "顔色",
qcPassed: undefined,
failQty: undefined,
remarks: undefined,
},
{
id: 4,
qcItemId: 28,
code: "異物",
description: "有異物,無法通過金屬探測器,則不合格",
name: "異物",
qcPassed: undefined,
failQty: undefined,
remarks: undefined,
},
{
id: 5,
qcItemId: 33,
code: "重量",
description: "沒有達到或超出重量要求,則不合格",
name: "重量",
qcPassed: undefined,
failQty: undefined,
remarks: undefined,
},
]

export interface EscalationData {
id: number,
escalation: string,


+ 4
- 4
src/i18n/zh/common.json Целия файл

@@ -18,7 +18,7 @@
"Dashboard": "資訊展示面板",
"Store Management": "原材料",
"Store Management": "倉庫管理",
"Delivery": "交貨單",
"Delivery": "送貨訂單",
"Scheduling": "排程",
"Settings": "設定",
"User": "用戶",
@@ -33,7 +33,7 @@
"Purchase Order":"採購單",
"Demand Forecast":"需求預測",
"Pick Order": "提料單",
"Deliver Order":"交貨單",
"Deliver Order":"送貨訂單",
"Project":"專案",
"Product":"產品",
"Material":"材料",
@@ -46,7 +46,7 @@
"FG":"成品",
"FG & Material Demand Forecast Detail":"成品及材料需求預測詳情",
"View item In-out And inventory Ledger":"查看物料出入庫及庫存日誌",
"Delivery Order":"交貨單",
"Delivery Order":"送貨訂單",
"Detail Scheduling":"詳細排程",
"Customer":"客戶",
"QC Check Item":"QC檢查項目",
@@ -83,7 +83,7 @@
"min": "分鐘",
"mins": "分鐘",
"Job Order": "工單",
"Edit Job Order": "編輯工單",
"Edit Job Order": "工單詳情",
"Production": "生產流程",
"Put Away": "上架",
"Put Away Scan": "上架掃碼",


+ 10
- 10
src/i18n/zh/do.json Целия файл

@@ -1,13 +1,13 @@
{
"Delivery Order": "交貨單",
"Delivery Order": "送貨訂單",
"Shop Name": "店鋪名稱",
"Delivery Order No.": "交貨單編號",
"Delivery Order Date": "交貨單日期",
"Delivery Order Status": "交貨單狀態",
"Delivery Order No.": "送貨訂單編號",
"Delivery Order Date": "送貨訂單日期",
"Delivery Order Status": "送貨訂單狀態",
"Order Date": "訂單日期",
"Estimated Arrival": "預計貨日期",
"Estimated Arrival From": "預計貨日期",
"Estimated Arrival To": "預計貨日期至",
"Estimated Arrival": "預計貨日期",
"Estimated Arrival From": "預計貨日期",
"Estimated Arrival To": "預計貨日期至",
"Status": "來貨狀態",
"Order Date From": "訂單日期",
"Order Date To": "訂單日期至",
@@ -27,7 +27,7 @@
"Releasing": "處理中",
"Shop Code": "店鋪編號",
"Supplier Code": "供應商編號",
"Estimated Arrival Date": "預計貨日期",
"Estimated Arrival Date": "預計貨日期",
"Item No.": "商品編號",
"Item Name": "商品名稱",
"Quantity": "數量",
@@ -43,8 +43,8 @@
"Back": "返回",
"Batch Release": "批量放單",
"Batch release completed successfully.": "已完成批量放單",
"Edit Delivery Order Detail": "編輯交貨單詳情",
"DO released successfully! Pick orders created.": "交貨單放單成功!提料單已建立。",
"Edit Delivery Order Detail": "編輯送貨訂單詳情",
"DO released successfully! Pick orders created.": "送貨訂單放單成功!提料單已建立。",
"Stock Available": "庫存可用",
"row selected": "行已選擇",
"An error has occurred. Please try again later.": "發生錯誤,請稍後再試。",


+ 1
- 1
src/i18n/zh/jo.json Целия файл

@@ -1,7 +1,7 @@
{
"Job Order": "工單",
"Create Job Order": "創建工單",
"Edit Job Order Detail": "編輯工單",
"Edit Job Order Detail": "工單詳情",
"Details": "細節",
"Actions": "操作",
"Code": "工單編號",


+ 1
- 1
src/i18n/zh/purchaseOrder.json Целия файл

@@ -33,7 +33,7 @@
"Item Name": "貨品名稱",
"Item Qty": "貨品數量",
"Item": "貨品",
"Item Accepted Qty": "貨品已收貨數量",
"Item Accepted Qty": "收貨數量",
"Item Purchase UoM": "貨品採購單位",
"qty": "訂單數量",
"uom": "採購單位",


Зареждане…
Отказ
Запис