Quellcode durchsuchen

Merge remote-tracking branch 'origin/production' into production

production
B.E.N.S.O.N vor 1 Woche
Ursprung
Commit
3f208b7fb1
12 geänderte Dateien mit 56 neuen und 48 gelöschten Zeilen
  1. +1
    -0
      src/app/api/doworkbench/actions.ts
  2. +5
    -5
      src/app/api/shop/actions.ts
  3. +9
    -2
      src/components/DoWorkbench/WorkbenchFloorLanePanel.tsx
  4. +0
    -1
      src/components/DoWorkbench/WorkbenchGoodPickExecution.tsx
  5. +0
    -1
      src/components/DoWorkbench/WorkbenchGoodPickExecutionDetail.tsx
  6. +4
    -3
      src/components/FinishedGoodSearch/FinishedGoodSearch.tsx
  7. +0
    -1
      src/components/FinishedGoodSearch/GoodPickExecution.tsx
  8. +25
    -24
      src/components/FinishedGoodSearch/GoodPickExecutiondetail.tsx
  9. +3
    -1
      src/components/Jodetail/JoPickOrderList.tsx
  10. +1
    -8
      src/components/NavigationContent/NavigationContent.tsx
  11. +4
    -1
      src/components/Shop/ShopDetail.tsx
  12. +4
    -1
      src/components/Shop/TruckLaneDetail.tsx

+ 1
- 0
src/app/api/doworkbench/actions.ts Datei anzeigen

@@ -252,6 +252,7 @@ export async function assignWorkbenchByLane(data: {
storeId: string;
truckLanceCode: string;
truckDepartureTime?: string;
loadingSequence?: number | null;
requiredDate?: string;
}): Promise<PostPickOrderResponse> {
const res = await serverFetchJson<PostPickOrderResponse>(


+ 5
- 5
src/app/api/shop/actions.ts Datei anzeigen

@@ -25,7 +25,7 @@ export interface ShopAndTruck{
truckLanceCode: String;
DepartureTime: String;
LoadingSequence?: number | null;
districtReference: Number;
districtReference: string | null;
Store_id: Number;
remark?: String | null;
truckId?: number;
@@ -43,7 +43,7 @@ export interface Truck{
truckLanceCode: String;
departureTime: String | number[];
loadingSequence: number;
districtReference: Number;
districtReference: string | null;
storeId: Number | String;
remark?: String | null;
shopName?: String | null;
@@ -55,7 +55,7 @@ export interface SaveTruckLane {
truckLanceCode: string;
departureTime: string;
loadingSequence: number;
districtReference: number;
districtReference: string | null;
storeId: string;
remark?: string | null;
}
@@ -82,7 +82,7 @@ export interface SaveTruckRequest {
shopName: string;
shopCode: string;
loadingSequence: number;
districtReference?: number | null;
districtReference?: string | null;
remark?: string | null;
}

@@ -91,7 +91,7 @@ export interface CreateTruckWithoutShopRequest {
truckLanceCode: string;
departureTime: string;
loadingSequence?: number;
districtReference?: number | null;
districtReference?: string | null;
remark?: string | null;
}



+ 9
- 2
src/components/DoWorkbench/WorkbenchFloorLanePanel.tsx Datei anzeigen

@@ -160,7 +160,13 @@ const WorkbenchFloorLanePanel: React.FC<Props> = ({ onPickOrderAssigned, onSwitc
}, []);

const handleAssignByLane = useCallback(
async (storeId: string, truckDepartureTime: string, truckLanceCode: string, requiredDate: string) => {
async (
storeId: string,
truckDepartureTime: string,
truckLanceCode: string,
loadingSequence: number | null | undefined,
requiredDate: string,
) => {
if (!currentUserId) return;
let dateParam: string | undefined;
if (requiredDate === "today") dateParam = dayjs().format("YYYY-MM-DD");
@@ -173,6 +179,7 @@ const WorkbenchFloorLanePanel: React.FC<Props> = ({ onPickOrderAssigned, onSwitc
storeId,
truckLanceCode,
truckDepartureTime,
loadingSequence,
requiredDate: dateParam,
});
console.log("assignByLane result:", res);
@@ -223,7 +230,7 @@ const WorkbenchFloorLanePanel: React.FC<Props> = ({ onPickOrderAssigned, onSwitc
cancelButtonColor: "#F04438",
});
if (result.isConfirmed) {
await handleAssignByLane(storeId, truckDepartureTime, truckLanceCode, requiredDate);
await handleAssignByLane(storeId, truckDepartureTime, truckLanceCode, loadingSequence, requiredDate);
}
},
[handleAssignByLane, t],


+ 0
- 1
src/components/DoWorkbench/WorkbenchGoodPickExecution.tsx Datei anzeigen

@@ -34,7 +34,6 @@ import {
PickOrderCompletionResponse,
fetchDoPickOrderDetail,
DoPickOrderDetail,
batchQrSubmit,
} from "@/app/api/pickOrder/actions";
import { fetchNameList, NameList } from "@/app/api/user/actions";
import {


+ 0
- 1
src/components/DoWorkbench/WorkbenchGoodPickExecutionDetail.tsx Datei anzeigen

@@ -43,7 +43,6 @@ import {
confirmLotSubstitution,
fetchDoPickOrderDetail, // 必须添加
DoPickOrderDetail, // 必须添加
batchQrSubmit,
batchScan,
BatchScanRequest,
BatchScanLineRequest,


+ 4
- 3
src/components/FinishedGoodSearch/FinishedGoodSearch.tsx Datei anzeigen

@@ -28,7 +28,7 @@ import { fetchPickOrderClient, autoAssignAndReleasePickOrder, autoAssignAndRelea
import Jobcreatitem from "./Jobcreatitem";
import { useSession } from "next-auth/react";
import { SessionWithTokens } from "@/config/authConfig";
import PickExecutionDetail from "./GoodPickExecutiondetail";
//import PickExecutionDetail from "./GoodPickExecutiondetail";
import GoodPickExecutionRecord from "./GoodPickExecutionRecord";
import Swal from "sweetalert2";
import { printDN, printDNLabels } from "@/app/api/do/actions";
@@ -860,13 +860,14 @@ const handleAssignByLane = useCallback(async (
}}
/>
)}
{/*
{tabIndex === 1 && (
<PickExecutionDetail
/*<PickExecutionDetail
filterArgs={filterArgs}
onSwitchToRecordTab={handleSwtitchToRecordTab}
onRefreshReleasedOrderCount={fetchReleasedOrderCount}
/>
) }
) */}
{tabIndex === 2 && (
<GoodPickExecutionRecord
filterArgs={filterArgs}


+ 0
- 1
src/components/FinishedGoodSearch/GoodPickExecution.tsx Datei anzeigen

@@ -35,7 +35,6 @@ import {
checkAndCompletePickOrderByConsoCode,
fetchDoPickOrderDetail,
DoPickOrderDetail,
batchQrSubmit,
} from "@/app/api/pickOrder/actions";
import { fetchNameList, NameList } from "@/app/api/user/actions";
import {


+ 25
- 24
src/components/FinishedGoodSearch/GoodPickExecutiondetail.tsx Datei anzeigen

@@ -1,3 +1,4 @@
/*
"use client";

import {
@@ -52,7 +53,6 @@ import {
fetchDoPickOrderDetail, // 必须添加
DoPickOrderDetail, // 必须添加
fetchFGPickOrdersByUserId,
batchQrSubmit,
batchSubmitList, // 添加:导入 batchSubmitList
batchSubmitListRequest, // 添加:导入类型
batchSubmitListLineRequest,
@@ -105,7 +105,7 @@ type LotConfirmRunContext = {
selectedLotForQr: any; // 與現在一樣:含 pickOrderLineId, stockOutLineId, suggestedPickLotId, itemId…
};

/** 同物料多行时,优先对「有建议批次号」的行做替换,避免误选「无批次/不足」行 */
/** 同物料多行时,优先对「有建议批次号」的行做替换,避免误选「无批次/不足」行
function pickExpectedLotForSubstitution(
activeSuggestedLots: any[],
): any | null {
@@ -630,19 +630,19 @@ const ManualLotConfirmationModal: React.FC<{
);
};

/** 過期批號(未換有效批前):與 noLot 類似——單筆/批量預設提交量為 0,除非 Issue 改數 */
/** 過期批號(未換有效批前):與 noLot 類似——單筆/批量預設提交量為 0,除非 Issue 改數
function isLotAvailabilityExpired(lot: any): boolean {
return String(lot?.lotAvailability || "").toLowerCase() === "expired";
}

/** inventory_lot_line.status = unavailable(API 可能用 lotAvailability 或 lotStatus) */
/** inventory_lot_line.status = unavailable(API 可能用 lotAvailability 或 lotStatus)
function isInventoryLotLineUnavailable(lot: any): boolean {
if (!lot) return false;
if (lot.lotAvailability === "status_unavailable") return true;
return String(lot.lotStatus || "").toLowerCase() === "unavailable";
}

/** Issue「改數」未寫入 SOL,刷新/換頁後需靠 session 還原,否則 Qty will submit 會回到 req */
/** Issue「改數」未寫入 SOL,刷新/換頁後需靠 session 還原,否則 Qty will submit 會回到 req
const FG_ISSUE_PICKED_KEY = (doPickOrderId: number) =>
`fpsms-fg-issuePickedQty:${doPickOrderId}`;

@@ -768,7 +768,7 @@ const PickExecution: React.FC<Props> = ({
const [lotConfirmationError, setLotConfirmationError] = useState<
string | null
>(null);
/** QR 静默换批失败时显示在对应行的 Lot# 列,key = stockOutLineId */
/** QR 静默换批失败时显示在对应行的 Lot# 列,key = stockOutLineId
const [lotSwitchFailByStockOutLineId, setLotSwitchFailByStockOutLineId] =
useState<Record<number, string>>({});
const [expectedLotData, setExpectedLotData] = useState<any>(null);
@@ -1232,7 +1232,7 @@ const PickExecution: React.FC<Props> = ({
pickOrderLinesForDisplay.forEach((line: any) => {
// 用来记录这一行已经通过 lots 出现过的 lotId
const lotIdSet = new Set<number>();
/** 已由有批次建議分配的量(加總後與 pick_order_line.requiredQty 的差額 = 無批次列應顯示的數) */
/** 已由有批次建議分配的量(加總後與 pick_order_line.requiredQty 的差額 = 無批次列應顯示的數)
let lotsAllocatedSumForLine = 0;

// ✅ lots:按 lotId 去重并合并 requiredQty
@@ -4255,7 +4255,7 @@ const PickExecution: React.FC<Props> = ({
handleStopScan();
}
}, [combinedLotData.length, isManualScanning, handleStopScan]);
*/

// Cleanup effect
useEffect(() => {
@@ -4337,9 +4337,9 @@ const PickExecution: React.FC<Props> = ({
successMessage={t("QR code verified.")}
/>
</Box>
{/* DO Header */}
{/* DO Header }

{/* 保留:Combined Lot Table - 包含所有 QR 扫描功能 */}
{/* 保留:Combined Lot Table - 包含所有 QR 扫描功能 }
<Box>
<Box
sx={{
@@ -4355,7 +4355,7 @@ const PickExecution: React.FC<Props> = ({
</Typography>

<Box sx={{ display: "flex", gap: 2, alignItems: "center" }}>
{/* Scanner status indicator (always visible) */}
{/* Scanner status indicator (always visible) }
{/*
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
<QrCodeIcon
@@ -4372,9 +4372,9 @@ const PickExecution: React.FC<Props> = ({
{isManualScanning ? t("Scanner Active") : t("Scanner Inactive")}
</Typography>
</Box>
*/}
}

{/* Pause/Resume button instead of Start/Stop */}
{/* Pause/Resume button instead of Start/Stop }
{isManualScanning ? (
<Button
variant="outlined"
@@ -4397,7 +4397,7 @@ const PickExecution: React.FC<Props> = ({
</Button>
)}

{/* 保留:Submit All Scanned Button */}
{/* 保留:Submit All Scanned Button }
<Button
variant="contained"
color="success"
@@ -4423,7 +4423,7 @@ const PickExecution: React.FC<Props> = ({
{fgPickOrders.length > 0 && (
<Paper sx={{ p: 2, mb: 2 }}>
<Stack spacing={2}>
{/* 基本信息 */}
{/* 基本信息 }
<Stack direction="row" spacing={4} useFlexGap flexWrap="wrap">
<Typography variant="subtitle1">
<strong>{t("Shop Name")}:</strong>{" "}
@@ -4443,9 +4443,9 @@ const PickExecution: React.FC<Props> = ({
</Typography>
</Stack>

{/* 改进:三个字段显示在一起,使用表格式布局 */}
{/* 改进:三个字段合并显示 */}
{/* 改进:表格式显示每个 pick order */}
{/* 改进:三个字段显示在一起,使用表格式布局 }
{/* 改进:三个字段合并显示 }
{/* 改进:表格式显示每个 pick order }
<Box
sx={{
p: 2,
@@ -4844,7 +4844,7 @@ const PickExecution: React.FC<Props> = ({
status === 'completed' ||
(Number(lot.stockOutLineId) > 0 && actionBusyBySolId[Number(lot.stockOutLineId)] === true)
}
*/
disabled={true}
sx={{
fontSize: "0.7rem",
@@ -4889,7 +4889,7 @@ const PickExecution: React.FC<Props> = ({
lot.stockOutLineStatus === 'pending' ||
(Number(lot.stockOutLineId) > 0 && actionBusyBySolId[Number(lot.stockOutLineId)] === true)
}
*/
disabled={true}
sx={{
fontSize: "0.75rem",
@@ -4912,7 +4912,7 @@ const PickExecution: React.FC<Props> = ({
lot.lotAvailability === 'expired' ||
lot.stockOutLineStatus === 'completed' ||
(Number(lot.stockOutLineId) > 0 && actionBusyBySolId[Number(lot.stockOutLineId)] === true)
}*/
}

disabled={true}
sx={{
@@ -4994,7 +4994,7 @@ const PickExecution: React.FC<Props> = ({
</Box>
</Stack>

{/* QR Code Scanner works in background - no modal needed */}
{/* QR Code Scanner works in background - no modal needed }
<ManualLotConfirmationModal
open={manualLotConfirmationOpen}
onClose={() => {
@@ -5005,7 +5005,7 @@ const PickExecution: React.FC<Props> = ({
scannedLot={scannedLotData}
isLoading={isConfirmingLot}
/>
{/* 保留:Lot Confirmation Modal */}
{/* 保留:Lot Confirmation Modal }
{lotConfirmationOpen && expectedLotData && scannedLotData && (
<LotConfirmationModal
open={lotConfirmationOpen}
@@ -5033,7 +5033,7 @@ const PickExecution: React.FC<Props> = ({
/>
)}

{/* 保留:Good Pick Execution Form Modal */}
{/* 保留:Good Pick Execution Form Modal }
{pickExecutionFormOpen && selectedLotForExecutionForm && (
<GoodPickExecutionForm
open={pickExecutionFormOpen}
@@ -5083,3 +5083,4 @@ const PickExecution: React.FC<Props> = ({
};

export default PickExecution;
*/

+ 3
- 1
src/components/Jodetail/JoPickOrderList.tsx Datei anzeigen

@@ -1,3 +1,4 @@
/*
"use client";
import React, { useCallback, useEffect, useState } from "react";
import {
@@ -296,4 +297,5 @@ const JoPickOrderList: React.FC<Props> = ({ onSwitchToRecordTab }) =>{
);
};

export default JoPickOrderList;
export default JoPickOrderList;
*/

+ 1
- 8
src/components/NavigationContent/NavigationContent.tsx Datei anzeigen

@@ -117,14 +117,7 @@ const NavigationContent: React.FC = () => {
requiredAbility: [AUTH.STOCK, AUTH.STOCK_TAKE, AUTH.STOCK_IN_BIND, AUTH.ADMIN],
path: "/putAway",
},
/*
{
icon: <ViewModule />,
label: "Finished Good Order",
requiredAbility: [AUTH.STOCK_FG, AUTH.ADMIN],
path: "/finishedGood",
},
*/

{
icon: <ViewModule />,
label: "Finished Good Management",


+ 4
- 1
src/components/Shop/ShopDetail.tsx Datei anzeigen

@@ -291,7 +291,10 @@ const ShopDetail: React.FC = () => {
shopName: String(shopDetail!.name),
shopCode: String(shopDetail!.code),
loadingSequence: addLoadingSequence,
districtReference: Number(lane.districtReference) || 0,
districtReference:
lane.districtReference != null && String(lane.districtReference).trim() !== ""
? String(lane.districtReference)
: null,
remark: remarkValue,
});


+ 4
- 1
src/components/Shop/TruckLaneDetail.tsx Datei anzeigen

@@ -301,7 +301,10 @@ const TruckLaneDetail: React.FC = () => {
truckLanceCode: String(row.truckLanceCode || ""),
departureTime: departureTimeStr,
loadingSequence: Number(row.loadingSequence) || 0,
districtReference: Number(row.districtReference) || 0,
districtReference:
row.districtReference != null && String(row.districtReference).trim() !== ""
? String(row.districtReference)
: null,
storeId: storeIdStr,
remark: remarkValue,
});


Laden…
Abbrechen
Speichern