feat(new command): helper command to remove as non reusable pallets
This commit is contained in:
@@ -0,0 +1,138 @@
|
|||||||
|
import { LstCard } from "@/components/extendedUI/LstCard";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { CardContent, CardHeader } from "@/components/ui/card";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
|
import { useForm } from "@tanstack/react-form";
|
||||||
|
import axios from "axios";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
|
||||||
|
export default function RemoveAsNonReusable() {
|
||||||
|
const [stockOut, setStockOut] = useState(false);
|
||||||
|
const form = useForm({
|
||||||
|
defaultValues: { runningNr: " ", reason: " " },
|
||||||
|
onSubmit: async ({ value }) => {
|
||||||
|
// Do something with form data
|
||||||
|
setStockOut(true);
|
||||||
|
|
||||||
|
//console.log(value);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await axios.post(
|
||||||
|
"/api/logistics/removeasreusable",
|
||||||
|
|
||||||
|
value // this is basically the data field
|
||||||
|
);
|
||||||
|
|
||||||
|
if (res.data.success) {
|
||||||
|
toast.success(res.data.message);
|
||||||
|
form.reset();
|
||||||
|
setStockOut(false);
|
||||||
|
} else {
|
||||||
|
console.log(res.data);
|
||||||
|
toast.error(res.data?.message);
|
||||||
|
form.reset();
|
||||||
|
setStockOut(false);
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
console.log(error);
|
||||||
|
toast.error(error.message);
|
||||||
|
setStockOut(false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<LstCard>
|
||||||
|
<CardHeader>
|
||||||
|
<p>Remove a pallet as non reusable</p>
|
||||||
|
</CardHeader>
|
||||||
|
<form
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CardContent>
|
||||||
|
<form.Field
|
||||||
|
name="runningNr"
|
||||||
|
validators={{
|
||||||
|
// We can choose between form-wide and field-specific validators
|
||||||
|
onChange: ({ value }) =>
|
||||||
|
value.length > 2
|
||||||
|
? undefined
|
||||||
|
: "Please enter a valid running number",
|
||||||
|
}}
|
||||||
|
children={(field) => {
|
||||||
|
return (
|
||||||
|
<div className="w-96">
|
||||||
|
<Label htmlFor="runningNr" className="mb-2">
|
||||||
|
Runnning Number
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
name={field.name}
|
||||||
|
value={field.state.value}
|
||||||
|
onBlur={field.handleBlur}
|
||||||
|
required
|
||||||
|
type="number"
|
||||||
|
onChange={(e) =>
|
||||||
|
field.handleChange(e.target.value)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
{field.state.meta.errors.length ? (
|
||||||
|
<em>
|
||||||
|
{field.state.meta.errors.join(",")}
|
||||||
|
</em>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<form.Field
|
||||||
|
name="reason"
|
||||||
|
validators={{
|
||||||
|
// We can choose between form-wide and field-specific validators
|
||||||
|
onChange: ({ value }) =>
|
||||||
|
value.length > 10
|
||||||
|
? undefined
|
||||||
|
: "Please enter a valid reason on why you needed to remove this pallet",
|
||||||
|
}}
|
||||||
|
children={(field) => {
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<Label htmlFor="reason" className="mb-2">
|
||||||
|
Reason for removing
|
||||||
|
</Label>
|
||||||
|
<Textarea
|
||||||
|
name={field.name}
|
||||||
|
value={field.state.value}
|
||||||
|
onBlur={field.handleBlur}
|
||||||
|
//type="number"
|
||||||
|
onChange={(e) =>
|
||||||
|
field.handleChange(e.target.value)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
{field.state.meta.errors.length ? (
|
||||||
|
<div className="text-pretty max-w-96">
|
||||||
|
<em>
|
||||||
|
{field.state.meta.errors.join(
|
||||||
|
","
|
||||||
|
)}
|
||||||
|
</em>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className="flex mt-2 justify-end">
|
||||||
|
<Button onClick={form.handleSubmit} disabled={stockOut}>
|
||||||
|
Remove
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</form>
|
||||||
|
</LstCard>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,9 +1,16 @@
|
|||||||
import Bookin from "./commands/Bookin";
|
import Bookin from "./commands/Bookin";
|
||||||
|
import RemoveAsNonReusable from "./commands/RemoveAsNonReusable";
|
||||||
|
|
||||||
export default function HelperPage() {
|
export default function HelperPage() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className="flex flex-wrap m-2 justify-center">
|
||||||
<Bookin />
|
<div className="m-1">
|
||||||
|
<Bookin />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="m-1">
|
||||||
|
<RemoveAsNonReusable />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,120 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
import { commandLog } from "../../../../../database/schema/commandLog.js";
|
||||||
|
import { prodEndpointCreation } from "../../../../globalUtils/createUrl.js";
|
||||||
|
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
||||||
|
import { lstAuth } from "../../../../index.js";
|
||||||
|
import { createSSCC } from "../../../../globalUtils/createSSCC.js";
|
||||||
|
import { db } from "../../../../../database/dbclient.js";
|
||||||
|
import net from "net";
|
||||||
|
import { query } from "../../../sqlServer/prodSqlServer.js";
|
||||||
|
import { labelInfo } from "../../../sqlServer/querys/warehouse/labelInfo.js";
|
||||||
|
import { settings } from "../../../../../database/schema/settings.js";
|
||||||
|
import { eq } from "drizzle-orm";
|
||||||
|
import { serverData } from "../../../../../database/schema/serverData.js";
|
||||||
|
export const removeAsNonReusable = async (data: any) => {
|
||||||
|
// const removalUrl = await prodEndpointCreation(
|
||||||
|
// "/public/v1.0/Warehousing/RemoveAsNonReusableMaterial"
|
||||||
|
// );
|
||||||
|
|
||||||
|
// const sscc = await createSSCC(data.runningNr);
|
||||||
|
|
||||||
|
// const { data: remove, error } = await tryCatch(
|
||||||
|
// axios.post(
|
||||||
|
// removalUrl,
|
||||||
|
// { scannerId: "500", sscc: sscc.slice(2) },
|
||||||
|
// {
|
||||||
|
// headers: { Authorization: `Basic ${lstAuth}` },
|
||||||
|
// }
|
||||||
|
// )
|
||||||
|
// );
|
||||||
|
|
||||||
|
// use a scanner tcp connection to trigger this process
|
||||||
|
const STX = "\x02";
|
||||||
|
const ETX = "\x03";
|
||||||
|
const scanner = new net.Socket();
|
||||||
|
let stage = 0;
|
||||||
|
// get the label info
|
||||||
|
const { data: label, error: labelError } = (await tryCatch(
|
||||||
|
query(labelInfo.replaceAll("[runningNr]", data.runningNr), "Label Info")
|
||||||
|
)) as any;
|
||||||
|
|
||||||
|
if (label.data[0].stockStatus === "notOnStock") {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: `The label: ${data.runningNr} is not currently in stock`,
|
||||||
|
data: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the server ip based on the token.
|
||||||
|
const setting = await db.select().from(settings);
|
||||||
|
|
||||||
|
const plantInfo = await db.select().from(serverData);
|
||||||
|
const plantToken = setting.filter((n: any) => n.name === "plantToken");
|
||||||
|
const scannerID = setting.filter((n: any) => n.name === "scannerID");
|
||||||
|
const scannerPort = setting.filter((n: any) => n.name === "scannerPort");
|
||||||
|
const plantData = plantInfo.filter(
|
||||||
|
(p: any) => p.plantToken === plantToken[0].value
|
||||||
|
);
|
||||||
|
|
||||||
|
scanner.connect(
|
||||||
|
parseInt(scannerPort[0].value),
|
||||||
|
plantData[0].idAddress!,
|
||||||
|
async () => {
|
||||||
|
// need to get the ip from the server data and scanner port
|
||||||
|
//console.log(`connected to scanner`);
|
||||||
|
scanner.write(`${STX}${scannerID[0].value}@AlplaPRODcmd23${ETX}`);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
scanner.on("data", (data) => {
|
||||||
|
const response = data.toString();
|
||||||
|
//console.log("Received:", response.trimStart());
|
||||||
|
if (stage === 0) {
|
||||||
|
stage = 1;
|
||||||
|
scanner.write(
|
||||||
|
`${STX}${scannerID[0].value}${label.data[0].Barcode}${ETX}`
|
||||||
|
);
|
||||||
|
} else if (stage === 1) {
|
||||||
|
scanner.end();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
scanner.on("close", () => {
|
||||||
|
//console.log("Connection closed");
|
||||||
|
scanner.destroy();
|
||||||
|
});
|
||||||
|
scanner.on("error", (err) => {
|
||||||
|
//console.error("Scanner error:", err);
|
||||||
|
scanner.destroy();
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: `The label: ${data.runningNr} encountering an error while being removed, please try again`,
|
||||||
|
data: [],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// if (error) {
|
||||||
|
// //console.log(error);
|
||||||
|
// return {
|
||||||
|
// success: false,
|
||||||
|
// message: `There was an error removing ${data.runningNr}`,
|
||||||
|
// data: [],
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
|
||||||
|
let reason = data.reason || "";
|
||||||
|
delete data.reason;
|
||||||
|
|
||||||
|
const { data: commandL, error: ce } = await tryCatch(
|
||||||
|
db.insert(commandLog).values({
|
||||||
|
commandUsed: "removeAsNonReusable",
|
||||||
|
bodySent: data,
|
||||||
|
reasonUsed: reason,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: `The label: ${data.runningNr}, was removed`,
|
||||||
|
data: [],
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -19,6 +19,7 @@ import outbound from "./route/getOutbound.js";
|
|||||||
import { runHistoricalData } from "./controller/eom/historicalInv.js";
|
import { runHistoricalData } from "./controller/eom/historicalInv.js";
|
||||||
import intervalChecks from "./route/getActiveLogistics.js";
|
import intervalChecks from "./route/getActiveLogistics.js";
|
||||||
import getActiveLanes from "./route/getActiveLanes.js";
|
import getActiveLanes from "./route/getActiveLanes.js";
|
||||||
|
import removeAsNonReable from "./route/removeAsNonReusable.js";
|
||||||
|
|
||||||
const app = new OpenAPIHono();
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
@@ -45,6 +46,9 @@ const routes = [
|
|||||||
// outbound deliveries
|
// outbound deliveries
|
||||||
outbound,
|
outbound,
|
||||||
intervalChecks,
|
intervalChecks,
|
||||||
|
|
||||||
|
// logisitcs
|
||||||
|
removeAsNonReable,
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
// app.route("/server", modules);
|
// app.route("/server", modules);
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { labelingProcess } from "../../controller/labeling/labelProcess.js";
|
|||||||
import { bookInLabel } from "../../controller/labeling/bookIn.js";
|
import { bookInLabel } from "../../controller/labeling/bookIn.js";
|
||||||
import { createSSCC } from "../../../../globalUtils/createSSCC.js";
|
import { createSSCC } from "../../../../globalUtils/createSSCC.js";
|
||||||
import { apiHit } from "../../../../globalUtils/apiHits.js";
|
import { apiHit } from "../../../../globalUtils/apiHits.js";
|
||||||
|
import { db } from "../../../../../database/dbclient.js";
|
||||||
|
import { commandLog } from "../../../../../database/schema/commandLog.js";
|
||||||
|
|
||||||
const app = new OpenAPIHono({ strict: false });
|
const app = new OpenAPIHono({ strict: false });
|
||||||
|
|
||||||
@@ -49,6 +51,13 @@ app.openapi(
|
|||||||
const newLabel: any = bookinLabel;
|
const newLabel: any = bookinLabel;
|
||||||
//console.log(newLabel);
|
//console.log(newLabel);
|
||||||
|
|
||||||
|
const { data: commandL, error: ce } = await tryCatch(
|
||||||
|
db.insert(commandLog).values({
|
||||||
|
commandUsed: "bookin",
|
||||||
|
bodySent: bodyData,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
return c.json({
|
return c.json({
|
||||||
success: newLabel.success,
|
success: newLabel.success,
|
||||||
message: newLabel.message,
|
message: newLabel.message,
|
||||||
|
|||||||
@@ -222,6 +222,20 @@ const newSettings = [
|
|||||||
serviceBelowsTo: "dm",
|
serviceBelowsTo: "dm",
|
||||||
roleToChange: "admin",
|
roleToChange: "admin",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "scannerID",
|
||||||
|
value: `500`,
|
||||||
|
description: "What scanner id will we be using for the app",
|
||||||
|
serviceBelowsTo: "logistics",
|
||||||
|
roleToChange: "admin",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "scannerPort",
|
||||||
|
value: `50002`,
|
||||||
|
description: "What port instance will we be using?",
|
||||||
|
serviceBelowsTo: "logistics",
|
||||||
|
roleToChange: "admin",
|
||||||
|
},
|
||||||
// temp settings can be deleted at a later date once that code is removed
|
// temp settings can be deleted at a later date once that code is removed
|
||||||
{
|
{
|
||||||
name: "siloAdjMigrations",
|
name: "siloAdjMigrations",
|
||||||
|
|||||||
20
server/services/sqlServer/querys/warehouse/labelInfo.ts
Normal file
20
server/services/sqlServer/querys/warehouse/labelInfo.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
export const labelInfo = `
|
||||||
|
select top(500) e.Barcode,
|
||||||
|
e.IdArtikelvarianten as av,
|
||||||
|
e.lfdnr as rn,
|
||||||
|
IdEtikettenLayout as labelLayout,
|
||||||
|
AnzStkJePalette,
|
||||||
|
Sonstiges_9,AnzStkJeKarton
|
||||||
|
,case when EinlagerungsMengeSum IS NULL then 'notOnStock' else 'onStock' end as stockStatus
|
||||||
|
,EinlagerungsMengeSum
|
||||||
|
--,*
|
||||||
|
from [AlplaPROD_test1].dbo.[T_EtikettenGedruckt] e (nolock)
|
||||||
|
|
||||||
|
left join
|
||||||
|
[AlplaPROD_test1].dbo.V_LagerPositionenBarcodes as l on
|
||||||
|
e.LfdNr = l.Lfdnr
|
||||||
|
|
||||||
|
where e.LfdNr in ([runningNr])
|
||||||
|
|
||||||
|
order by add_date desc
|
||||||
|
`;
|
||||||
Reference in New Issue
Block a user