|
|
|
@@ -66,7 +66,7 @@ import GoodPickExecutionForm from "./GoodPickExecutionForm"; |
|
|
|
import FGPickOrderCard from "./FGPickOrderCard"; |
|
|
|
import dayjs from "dayjs"; |
|
|
|
import { OUTPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; |
|
|
|
import { printDN, printDNLabels } from "@/app/api/do/actions"; |
|
|
|
import { printDN, printDNLabels, printDNLabelsReprint } from "@/app/api/do/actions"; |
|
|
|
import Swal from "sweetalert2"; |
|
|
|
|
|
|
|
|
|
|
|
@@ -173,7 +173,20 @@ const GoodPickExecutionRecord: React.FC<Props> = ({ |
|
|
|
confirmButtonColor: "#8dba00", |
|
|
|
cancelButtonColor: "#F04438", |
|
|
|
showLoaderOnConfirm: true, |
|
|
|
allowOutsideClick: () => !Swal.isLoading() |
|
|
|
allowOutsideClick: () => !Swal.isLoading(), |
|
|
|
didOpen: () => { |
|
|
|
const input = Swal.getInput() as HTMLInputElement | null; |
|
|
|
if (input) { |
|
|
|
input.style.outline = "none"; |
|
|
|
input.style.boxShadow = "none"; |
|
|
|
input.style.border = "1px solid #d9d9d9"; |
|
|
|
input.onfocus = () => { |
|
|
|
input.style.outline = "none"; |
|
|
|
input.style.boxShadow = "none"; |
|
|
|
input.style.borderColor = "#d9d9d9"; |
|
|
|
}; |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
if (askNumofCarton.isConfirmed) { |
|
|
|
@@ -209,7 +222,7 @@ const GoodPickExecutionRecord: React.FC<Props> = ({ |
|
|
|
}, [t, a4Printer]); |
|
|
|
|
|
|
|
const handleDNandLabel = useCallback(async (recordId: number) => { |
|
|
|
if (!a4Printer || !labelPrinter) { |
|
|
|
if (!a4Printer) { |
|
|
|
Swal.fire({ |
|
|
|
position: "bottom-end", |
|
|
|
icon: "warning", |
|
|
|
@@ -253,7 +266,20 @@ const GoodPickExecutionRecord: React.FC<Props> = ({ |
|
|
|
confirmButtonColor: "#8dba00", |
|
|
|
cancelButtonColor: "#F04438", |
|
|
|
showLoaderOnConfirm: true, |
|
|
|
allowOutsideClick: () => !Swal.isLoading() |
|
|
|
allowOutsideClick: () => !Swal.isLoading(), |
|
|
|
didOpen: () => { |
|
|
|
const input = Swal.getInput() as HTMLInputElement | null; |
|
|
|
if (input) { |
|
|
|
input.style.outline = "none"; |
|
|
|
input.style.boxShadow = "none"; |
|
|
|
input.style.border = "1px solid #d9d9d9"; |
|
|
|
input.onfocus = () => { |
|
|
|
input.style.outline = "none"; |
|
|
|
input.style.boxShadow = "none"; |
|
|
|
input.style.borderColor = "#d9d9d9"; |
|
|
|
}; |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
if (askNumofCarton.isConfirmed) { |
|
|
|
@@ -307,6 +333,17 @@ const GoodPickExecutionRecord: React.FC<Props> = ({ |
|
|
|
|
|
|
|
const handleLabel = useCallback(async (recordId: number) => { |
|
|
|
console.log(" [Print Label] Button clicked for recordId:", recordId); |
|
|
|
if (!labelPrinter) { |
|
|
|
Swal.fire({ |
|
|
|
position: "bottom-end", |
|
|
|
icon: "warning", |
|
|
|
text: t("Please select a label printer first"), |
|
|
|
showConfirmButton: false, |
|
|
|
timer: 1500 |
|
|
|
}); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
const askNumofCarton = await Swal.fire({ |
|
|
|
title: t("Enter the number of cartons: "), |
|
|
|
icon: "info", |
|
|
|
@@ -331,14 +368,27 @@ const GoodPickExecutionRecord: React.FC<Props> = ({ |
|
|
|
confirmButtonColor: "#8dba00", |
|
|
|
cancelButtonColor: "#F04438", |
|
|
|
showLoaderOnConfirm: true, |
|
|
|
allowOutsideClick: () => !Swal.isLoading() |
|
|
|
allowOutsideClick: () => !Swal.isLoading(), |
|
|
|
didOpen: () => { |
|
|
|
const input = Swal.getInput() as HTMLInputElement | null; |
|
|
|
if (input) { |
|
|
|
input.style.outline = "none"; |
|
|
|
input.style.boxShadow = "none"; |
|
|
|
input.style.border = "1px solid #d9d9d9"; |
|
|
|
input.onfocus = () => { |
|
|
|
input.style.outline = "none"; |
|
|
|
input.style.boxShadow = "none"; |
|
|
|
input.style.borderColor = "#d9d9d9"; |
|
|
|
}; |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
if (askNumofCarton.isConfirmed) { |
|
|
|
const numOfCartons = askNumofCarton.value; |
|
|
|
try{ |
|
|
|
const printRequest = { |
|
|
|
printerId: labelPrinter?.id ?? 0, |
|
|
|
printerId: labelPrinter.id, |
|
|
|
printQty: 1, |
|
|
|
numOfCarton: numOfCartons, |
|
|
|
doPickOrderId: recordId |
|
|
|
@@ -365,6 +415,103 @@ const GoodPickExecutionRecord: React.FC<Props> = ({ |
|
|
|
} |
|
|
|
}, [t, labelPrinter]); |
|
|
|
|
|
|
|
const handleLabelReprint = useCallback(async (doPickOrder: CompletedDoPickOrderResponse) => { |
|
|
|
if (!labelPrinter) { |
|
|
|
Swal.fire({ |
|
|
|
position: "bottom-end", |
|
|
|
icon: "warning", |
|
|
|
text: t("Please select a label printer first"), |
|
|
|
showConfirmButton: false, |
|
|
|
timer: 1500 |
|
|
|
}); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
const defaultTotalCartons = Math.max(1, doPickOrder.numberOfCartons || 1); |
|
|
|
const result = await Swal.fire({ |
|
|
|
title: t("Reprint DN Label"), |
|
|
|
html: ` |
|
|
|
<div style="display:flex;flex-direction:column;gap:10px;text-align:left;"> |
|
|
|
<div style="display:flex;align-items:center;gap:12px;"> |
|
|
|
<label for="swal-from-carton" style="min-width:120px;">${t("From carton")}</label> |
|
|
|
<input id="swal-from-carton" class="swal2-input" type="number" min="1" step="1" value="1" style="margin:0;flex:1;outline:none;box-shadow:none;border:1px solid #d9d9d9;" onfocus="this.style.outline='none';this.style.boxShadow='none';this.style.borderColor='#d9d9d9';" /> |
|
|
|
</div> |
|
|
|
<div style="display:flex;align-items:center;gap:12px;"> |
|
|
|
<label for="swal-to-carton" style="min-width:120px;">${t("To carton")}</label> |
|
|
|
<input id="swal-to-carton" class="swal2-input" type="number" min="1" step="1" value="1" style="margin:0;flex:1;outline:none;box-shadow:none;border:1px solid #d9d9d9;" onfocus="this.style.outline='none';this.style.boxShadow='none';this.style.borderColor='#d9d9d9';" /> |
|
|
|
</div> |
|
|
|
<div style="display:flex;align-items:center;gap:12px;"> |
|
|
|
<label for="swal-total-carton" style="min-width:120px;">${t("Total cartons on shipment")}</label> |
|
|
|
<input id="swal-total-carton" class="swal2-input" type="number" min="1" step="1" value="${defaultTotalCartons}" style="margin:0;flex:1;outline:none;box-shadow:none;border:1px solid #d9d9d9;" onfocus="this.style.outline='none';this.style.boxShadow='none';this.style.borderColor='#d9d9d9';" /> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
`, |
|
|
|
showCancelButton: true, |
|
|
|
confirmButtonText: t("Confirm"), |
|
|
|
cancelButtonText: t("Cancel"), |
|
|
|
confirmButtonColor: "#8dba00", |
|
|
|
cancelButtonColor: "#F04438", |
|
|
|
focusConfirm: false, |
|
|
|
preConfirm: () => { |
|
|
|
const fromCarton = Number((document.getElementById("swal-from-carton") as HTMLInputElement | null)?.value || "0"); |
|
|
|
const toCarton = Number((document.getElementById("swal-to-carton") as HTMLInputElement | null)?.value || "0"); |
|
|
|
const totalCartonsOnShipment = Number((document.getElementById("swal-total-carton") as HTMLInputElement | null)?.value || "0"); |
|
|
|
|
|
|
|
if (!Number.isInteger(fromCarton) || fromCarton < 1) { |
|
|
|
Swal.showValidationMessage(t("From carton must be at least 1")); |
|
|
|
return null; |
|
|
|
} |
|
|
|
if (!Number.isInteger(toCarton) || toCarton < fromCarton) { |
|
|
|
Swal.showValidationMessage(t("To carton must be greater than or equal to from carton")); |
|
|
|
return null; |
|
|
|
} |
|
|
|
if (!Number.isInteger(totalCartonsOnShipment) || totalCartonsOnShipment < 1) { |
|
|
|
Swal.showValidationMessage(t("Total cartons on shipment must be at least 1")); |
|
|
|
return null; |
|
|
|
} |
|
|
|
if (toCarton > totalCartonsOnShipment) { |
|
|
|
Swal.showValidationMessage(t("To carton cannot be greater than total cartons on shipment")); |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
return { |
|
|
|
fromCarton, |
|
|
|
toCarton, |
|
|
|
totalCartonsOnShipment, |
|
|
|
}; |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
if (!result.isConfirmed || !result.value) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
try { |
|
|
|
const response = await printDNLabelsReprint({ |
|
|
|
doPickOrderId: doPickOrder.doPickOrderRecordId, |
|
|
|
printerId: labelPrinter.id, |
|
|
|
printQty: 1, |
|
|
|
fromCarton: result.value.fromCarton, |
|
|
|
toCarton: result.value.toCarton, |
|
|
|
totalCartonsOnShipment: result.value.totalCartonsOnShipment, |
|
|
|
}); |
|
|
|
|
|
|
|
if (response.success) { |
|
|
|
Swal.fire({ |
|
|
|
position: "bottom-end", |
|
|
|
icon: "success", |
|
|
|
text: t("Printed Successfully."), |
|
|
|
showConfirmButton: false, |
|
|
|
timer: 1500 |
|
|
|
}); |
|
|
|
} else { |
|
|
|
console.error("Reprint failed:", response.message); |
|
|
|
} |
|
|
|
} catch (error) { |
|
|
|
console.error("reprint error: ", error); |
|
|
|
} |
|
|
|
}, [labelPrinter, t]); |
|
|
|
|
|
|
|
// 修改:使用新的 API 获取已完成的 DO Pick Orders |
|
|
|
const fetchCompletedDoPickOrdersData = useCallback(async (searchParams?: CompletedDoPickOrderSearchParams) => { |
|
|
|
if (listScope === "mine" && !currentUserId) return; |
|
|
|
@@ -843,6 +990,12 @@ if (showDetailView && selectedDoPickOrder) { |
|
|
|
> |
|
|
|
{t("Print Label")} |
|
|
|
</Button> |
|
|
|
<Button |
|
|
|
variant="contained" |
|
|
|
onClick={() => handleLabelReprint(doPickOrder)} |
|
|
|
> |
|
|
|
{t("Reprint Label(s)")} |
|
|
|
</Button> |
|
|
|
</> |
|
|
|
|
|
|
|
</CardActions> |
|
|
|
|