feat(ocp): materials contorls and transfer to next lot logic
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
export default function MaterialCheck() {
|
||||||
|
return <div>MaterialCheck</div>;
|
||||||
|
}
|
||||||
211
frontend/src/components/eom/materialsData/MaterialData.tsx
Normal file
211
frontend/src/components/eom/materialsData/MaterialData.tsx
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
import { LstCard } from "@/components/extendedUI/LstCard";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Calendar } from "@/components/ui/calendar";
|
||||||
|
import { Popover, PopoverTrigger } from "@/components/ui/popover";
|
||||||
|
import { Skeleton } from "@/components/ui/skeleton";
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableHeader,
|
||||||
|
TableRow,
|
||||||
|
} from "@/components/ui/table";
|
||||||
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||||
|
import { useSessionStore } from "@/lib/store/sessionStore";
|
||||||
|
import { useModuleStore } from "@/lib/store/useModuleStore";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import { PopoverContent } from "@radix-ui/react-popover";
|
||||||
|
import { Link, useRouter } from "@tanstack/react-router";
|
||||||
|
import { startOfMonth } from "date-fns";
|
||||||
|
import { format } from "date-fns-tz";
|
||||||
|
import { CalendarIcon } from "lucide-react";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
import KFP from "../KFP";
|
||||||
|
|
||||||
|
export default function MaterialData() {
|
||||||
|
const { modules } = useModuleStore();
|
||||||
|
const { user } = useSessionStore();
|
||||||
|
const router = useRouter();
|
||||||
|
const [date, setDate] = useState<Date>();
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
router.navigate({ to: "/" });
|
||||||
|
}
|
||||||
|
const eomMod = modules.filter((m) => m.name === "eom");
|
||||||
|
// the users current role for eom is?
|
||||||
|
const role: any =
|
||||||
|
user?.roles.filter((r) => r.module_id === eomMod[0].module_id) || "";
|
||||||
|
|
||||||
|
const tabs = [
|
||||||
|
{
|
||||||
|
key: "kfp",
|
||||||
|
label: "Key Figures",
|
||||||
|
roles: ["admin", "systemAdmin"],
|
||||||
|
content: <KFP />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "fg",
|
||||||
|
label: "Finished Goods",
|
||||||
|
roles: ["admin", "systemAdmin"],
|
||||||
|
content: <DummyContent />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "mm",
|
||||||
|
label: "Main Material",
|
||||||
|
roles: ["admin", "systemAdmin"],
|
||||||
|
content: <DummyContent />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "mb",
|
||||||
|
label: "Master Batch",
|
||||||
|
roles: ["admin", "systemAdmin"],
|
||||||
|
content: <DummyContent />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "ab",
|
||||||
|
label: "Additive",
|
||||||
|
roles: ["admin", "systemAdmin"],
|
||||||
|
content: <DummyContent />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "pp",
|
||||||
|
label: "Purchased Preforms",
|
||||||
|
roles: ["admin", "systemAdmin"],
|
||||||
|
content: <DummyContent />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "pre",
|
||||||
|
label: "Preforms",
|
||||||
|
roles: ["admin", "systemAdmin"],
|
||||||
|
content: <DummyContent />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "pkg",
|
||||||
|
label: "Packaging",
|
||||||
|
roles: ["admin", "systemAdmin"],
|
||||||
|
content: <DummyContent />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "ui",
|
||||||
|
label: "Undefined Items",
|
||||||
|
roles: ["admin"],
|
||||||
|
content: <DummyContent />,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<div className="m-2 w-screen">
|
||||||
|
<div className="mb-2 flex flex-row">
|
||||||
|
<Popover>
|
||||||
|
<PopoverTrigger asChild>
|
||||||
|
<Button
|
||||||
|
variant={"outline"}
|
||||||
|
className={cn(
|
||||||
|
"w-[280px] justify-start text-left font-normal",
|
||||||
|
!date && "text-muted-foreground"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<CalendarIcon className="mr-2 h-4 w-4" />
|
||||||
|
{date ? (
|
||||||
|
format(date, "PPP")
|
||||||
|
) : (
|
||||||
|
<span>Pick a date</span>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent className="w-auto p-0">
|
||||||
|
<Calendar
|
||||||
|
mode="single"
|
||||||
|
selected={date}
|
||||||
|
onSelect={setDate}
|
||||||
|
initialFocus
|
||||||
|
/>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
<div className="ml-2">
|
||||||
|
<Button
|
||||||
|
onClick={() =>
|
||||||
|
toast.success(
|
||||||
|
`Getting data for ${startOfMonth(date!)}-${date}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<span className="text-sm">Update Data</span>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Tabs defaultValue="mm">
|
||||||
|
<TabsList>
|
||||||
|
{tabs.map((tab) => {
|
||||||
|
if (tab.roles.includes(role[0].role))
|
||||||
|
return (
|
||||||
|
<TabsTrigger value={tab.key}>
|
||||||
|
{tab.label}
|
||||||
|
</TabsTrigger>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</TabsList>
|
||||||
|
{tabs.map((tab) => {
|
||||||
|
if (tab.roles.includes(role[0].role))
|
||||||
|
return (
|
||||||
|
<TabsContent value={tab.key}>
|
||||||
|
{tab.content}
|
||||||
|
</TabsContent>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Tabs>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function DummyContent() {
|
||||||
|
return (
|
||||||
|
<LstCard className="w-5/6">
|
||||||
|
<Table>
|
||||||
|
<TableHeader>
|
||||||
|
<TableRow>
|
||||||
|
<TableHead>Av</TableHead>
|
||||||
|
<TableHead>Description</TableHead>
|
||||||
|
<TableHead>Material Type</TableHead>
|
||||||
|
<TableHead>Waste</TableHead>
|
||||||
|
<TableHead>Loss / Gain $$</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
|
||||||
|
<TableBody>
|
||||||
|
{Array(10)
|
||||||
|
.fill(0)
|
||||||
|
.map((_, i) => (
|
||||||
|
<TableRow key={i}>
|
||||||
|
<TableCell className="font-medium m-2">
|
||||||
|
<Link
|
||||||
|
to="/article/$av"
|
||||||
|
params={{ av: `${i}` }}
|
||||||
|
>
|
||||||
|
{i}
|
||||||
|
</Link>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="font-medium">
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell>
|
||||||
|
{/* <TableCell>
|
||||||
|
<Skeleton className="h-4" />
|
||||||
|
</TableCell> */}
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</LstCard>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,250 @@
|
|||||||
|
import { LstCard } from "@/components/extendedUI/LstCard";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { CardHeader } from "@/components/ui/card";
|
||||||
|
import { useAppForm } from "@/utils/formStuff";
|
||||||
|
import axios from "axios";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
|
||||||
|
export default function TransferToNextLot() {
|
||||||
|
const [gaylordFilled, setGaylordFilled] = useState([0]);
|
||||||
|
|
||||||
|
const form = useAppForm({
|
||||||
|
defaultValues: {
|
||||||
|
runnungNumber: "",
|
||||||
|
lotNumber: "",
|
||||||
|
originalAmount: "",
|
||||||
|
},
|
||||||
|
onSubmit: async ({ value }) => {
|
||||||
|
//console.log(transferData);
|
||||||
|
//toast.success("603468: qty: 361, was transfered to lot:24897");
|
||||||
|
try {
|
||||||
|
const res = await axios.post("/api/ocp/materiallottransfer", {
|
||||||
|
runnungNumber: Number(value.runnungNumber),
|
||||||
|
lotNumber: Number(value.lotNumber),
|
||||||
|
originalAmount: Number(value.originalAmount),
|
||||||
|
level: Number(
|
||||||
|
gaylordFilled.length === 1
|
||||||
|
? 0.25
|
||||||
|
: gaylordFilled.length === 2
|
||||||
|
? 0.5
|
||||||
|
: gaylordFilled.length === 3
|
||||||
|
? 0.75
|
||||||
|
: gaylordFilled.length === 4 && 0.95
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res.data.success) {
|
||||||
|
toast.success(`${res.data.message}`);
|
||||||
|
form.reset();
|
||||||
|
}
|
||||||
|
//console.log(res.data);
|
||||||
|
|
||||||
|
if (!res.data.success) {
|
||||||
|
toast.error(res.data.message);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (error) {
|
||||||
|
console.log(error);
|
||||||
|
//toast.error(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<LstCard>
|
||||||
|
<CardHeader>
|
||||||
|
<p className="text-center text-lg">
|
||||||
|
Material Transfer to Next lot
|
||||||
|
</p>
|
||||||
|
</CardHeader>
|
||||||
|
<div>
|
||||||
|
<div className="flex flex-wrap m-2 gap-2">
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<div>
|
||||||
|
<LstCard className="">
|
||||||
|
<div className="grid columns-1">
|
||||||
|
<button
|
||||||
|
className={`box-border h-16 w-96 border-3 ${
|
||||||
|
gaylordFilled.includes(4)
|
||||||
|
? " bg-green-500"
|
||||||
|
: ""
|
||||||
|
}`}
|
||||||
|
onClick={() =>
|
||||||
|
setGaylordFilled([1, 2, 3, 4])
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<p className="text-center">
|
||||||
|
Almost full
|
||||||
|
</p>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className={`box-border h-16 w-96 border-3 ${
|
||||||
|
gaylordFilled.includes(3)
|
||||||
|
? " bg-green-500"
|
||||||
|
: ""
|
||||||
|
}`}
|
||||||
|
onClick={() =>
|
||||||
|
setGaylordFilled([1, 2, 3])
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<p className="text-center">
|
||||||
|
About 75% full
|
||||||
|
</p>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className={`box-border h-16 w-96 border-3 ${
|
||||||
|
gaylordFilled.includes(2)
|
||||||
|
? " bg-green-500"
|
||||||
|
: ""
|
||||||
|
}`}
|
||||||
|
onClick={() =>
|
||||||
|
setGaylordFilled([1, 2])
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<p className="text-center">
|
||||||
|
Half full
|
||||||
|
</p>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className={`box-border h-16 w-96 border-3 ${
|
||||||
|
gaylordFilled.includes(1)
|
||||||
|
? " bg-green-500"
|
||||||
|
: ""
|
||||||
|
}`}
|
||||||
|
onClick={() =>
|
||||||
|
setGaylordFilled(() => [1])
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<p className="text-center">
|
||||||
|
Almost empty
|
||||||
|
</p>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-end pr-1">
|
||||||
|
<Button
|
||||||
|
onClick={() =>
|
||||||
|
setGaylordFilled([0])
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Reset Gaylord
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</LstCard>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div className="w-96">
|
||||||
|
<LstCard>
|
||||||
|
<form
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
form.handleSubmit();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="mt-3 p-2">
|
||||||
|
<form.AppField
|
||||||
|
name="runnungNumber"
|
||||||
|
children={(field) => (
|
||||||
|
<field.InputField
|
||||||
|
label="Runnung Number"
|
||||||
|
inputType="number"
|
||||||
|
required={true}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mt-3 p-2">
|
||||||
|
<form.AppField
|
||||||
|
name="lotNumber"
|
||||||
|
children={(field) => (
|
||||||
|
<field.InputField
|
||||||
|
label="Lot Number"
|
||||||
|
inputType="number"
|
||||||
|
required={true}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<div className="mt-3 p-2">
|
||||||
|
<form.AppField
|
||||||
|
name="originalAmount"
|
||||||
|
children={(field) => (
|
||||||
|
<field.InputField
|
||||||
|
label="Orignal Quantity"
|
||||||
|
inputType="number"
|
||||||
|
required={true}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-end p-2">
|
||||||
|
<form.AppForm>
|
||||||
|
<form.SubmitButton>
|
||||||
|
Transfer To Lot
|
||||||
|
</form.SubmitButton>
|
||||||
|
</form.AppForm>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</LstCard>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<LstCard className="p-2">
|
||||||
|
<CardHeader>
|
||||||
|
<p className="text-center text-lg">
|
||||||
|
Moving material to the next lot.
|
||||||
|
</p>
|
||||||
|
</CardHeader>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<ol>
|
||||||
|
<li>
|
||||||
|
1. Grab the gaylord running number
|
||||||
|
from the gaylord at the line/next to
|
||||||
|
the tschritter
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
2. Grab the next lot number you are
|
||||||
|
going to be running (or the one that
|
||||||
|
state no Main material prepared)
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
3. Enter the total gaylord weight
|
||||||
|
(this is how much the gaylord
|
||||||
|
weighed when it came in from the
|
||||||
|
supplier.)
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
4. *Click the level of the gaylord
|
||||||
|
(this is just an estimate to move to
|
||||||
|
the next lot.)
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
5. type in running number on the
|
||||||
|
gaylord.
|
||||||
|
</li>
|
||||||
|
<li>6. Type in the new lot number.</li>
|
||||||
|
<li>7. Press "Transfer To Lot"</li>
|
||||||
|
</ol>
|
||||||
|
<br></br>
|
||||||
|
<p>
|
||||||
|
* to reduce the time needed to get the
|
||||||
|
lot going we will use an estimate of how
|
||||||
|
full the gaylord is.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
NOTE: This is not the return process,
|
||||||
|
this process will just get the gaylord
|
||||||
|
to the next lot.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</LstCard>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</LstCard>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -170,20 +170,15 @@ export const labelingProcess = async ({
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// check mm is good
|
// check the material... mm,color (auto and manual combined), pkg
|
||||||
const mmStaged = await isMainMatStaged(filteredLot[0]);
|
const mmStaged = await isMainMatStaged(filteredLot[0]);
|
||||||
|
|
||||||
if (!mmStaged) {
|
if (!mmStaged.success) {
|
||||||
createLog(
|
createLog("error", "labeling", "ocp", mmStaged.message);
|
||||||
"error",
|
|
||||||
"labeling",
|
|
||||||
"ocp",
|
|
||||||
`Main material is not prepaired for lot ${filteredLot[0].lot}`
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
message: `Main material is not prepaired for lot ${filteredLot[0].lot}`,
|
message: mmStaged.message,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
206
server/services/ocp/controller/materials/lotTransfer.ts
Normal file
206
server/services/ocp/controller/materials/lotTransfer.ts
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
import { eq } from "drizzle-orm";
|
||||||
|
import { db } from "../../../../../database/dbclient.js";
|
||||||
|
import { printerData } from "../../../../../database/schema/printers.js";
|
||||||
|
import { runProdApi } from "../../../../globalUtils/runProdApi.js";
|
||||||
|
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
||||||
|
import { createLog } from "../../../logger/logger.js";
|
||||||
|
import { query } from "../../../sqlServer/prodSqlServer.js";
|
||||||
|
import { labelInfo } from "../../../sqlServer/querys/warehouse/labelInfo.js";
|
||||||
|
|
||||||
|
type NewLotData = {
|
||||||
|
runnungNumber: number;
|
||||||
|
lotNumber: number;
|
||||||
|
originalAmount: number;
|
||||||
|
level: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move manual material to a new lot.
|
||||||
|
*
|
||||||
|
* The data sent over should be
|
||||||
|
* Running number
|
||||||
|
* Lot number
|
||||||
|
* Orignal Quantity
|
||||||
|
* level of gaylord
|
||||||
|
*/
|
||||||
|
export const lotMaterialTransfer = async (data: NewLotData) => {
|
||||||
|
// get the barcode, and layoutID from the running number
|
||||||
|
const { data: label, error: labelError } = (await tryCatch(
|
||||||
|
query(
|
||||||
|
labelInfo.replace("[runningNr]", `${data.runnungNumber}`),
|
||||||
|
"Get label info"
|
||||||
|
)
|
||||||
|
)) as any;
|
||||||
|
|
||||||
|
if (labelError) {
|
||||||
|
createLog(
|
||||||
|
"error",
|
||||||
|
"materials",
|
||||||
|
"ocp",
|
||||||
|
"There was an error getting the label info"
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "There was an error getting the label info",
|
||||||
|
data: labelError,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (
|
||||||
|
// label.data[0]?.stockStatus === "notOnStock" ||
|
||||||
|
// label.data.length === 0
|
||||||
|
// ) {
|
||||||
|
// createLog(
|
||||||
|
// "error",
|
||||||
|
// "materials",
|
||||||
|
// "ocp",
|
||||||
|
// `${data.runnungNumber}: dose not exist or no longer in stock.`
|
||||||
|
// );
|
||||||
|
// return {
|
||||||
|
// success: false,
|
||||||
|
// message: `${data.runnungNumber}: dose not exist or no longer in stock.`,
|
||||||
|
// data: [],
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (label.data[0]?.stockStatus === "onStock") {
|
||||||
|
createLog(
|
||||||
|
"error",
|
||||||
|
"materials",
|
||||||
|
"ocp",
|
||||||
|
`${data.runnungNumber}: currently in stock and not consumed to a lot.`
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: `${data.runnungNumber}: currently in stock and not consumed to a lot.`,
|
||||||
|
data: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the pdf24 printer id
|
||||||
|
const { data: printer, error: printerError } = (await tryCatch(
|
||||||
|
db.select().from(printerData).where(eq(printerData.name, "PDF24"))
|
||||||
|
)) as any;
|
||||||
|
|
||||||
|
if (printerError) {
|
||||||
|
createLog(
|
||||||
|
"error",
|
||||||
|
"materials",
|
||||||
|
"ocp",
|
||||||
|
"There was an error the printer info"
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "There was an error the printer info",
|
||||||
|
data: printerError,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// calculate the remaining amount bascially it will be orignal number * level sent over
|
||||||
|
// level should be sent in a decimal .25 .5 .75 .95 the 95 will allow basically the what looks to be a full gaylord but we always want to consume something
|
||||||
|
const newQty = (data.originalAmount * data.level).toFixed(0);
|
||||||
|
|
||||||
|
// reprint the label and send it to pdf24
|
||||||
|
const reprintData = {
|
||||||
|
clientId: 999,
|
||||||
|
runningNo: label?.data[0].runnungNumber,
|
||||||
|
printerId: printer[0].humanReadableId,
|
||||||
|
layoutId: label?.data[0].labelLayout,
|
||||||
|
noOfCopies: 0,
|
||||||
|
quantity: newQty,
|
||||||
|
} as any;
|
||||||
|
|
||||||
|
const { data: reprint, error: reprintError } = (await tryCatch(
|
||||||
|
runProdApi({
|
||||||
|
endpoint: "/public/v1.0/ProductionLabelling/ReprintLabel",
|
||||||
|
data: [reprintData],
|
||||||
|
})
|
||||||
|
)) as any;
|
||||||
|
|
||||||
|
if (!reprint.success) {
|
||||||
|
createLog(
|
||||||
|
"error",
|
||||||
|
"materials",
|
||||||
|
"ocp",
|
||||||
|
`RN:${data.runnungNumber}, Error: ${reprint.data.data.message}`
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: `RN:${data.runnungNumber}, Error: ${reprint.data.data.message}`,
|
||||||
|
data: reprint,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// return the label back to fm1 lane id 10001
|
||||||
|
|
||||||
|
const matReturnData = {
|
||||||
|
barcode: label?.data[0].Barcode,
|
||||||
|
laneId: 10001,
|
||||||
|
};
|
||||||
|
const { data: matReturn, error: matReturError } = (await tryCatch(
|
||||||
|
runProdApi({
|
||||||
|
endpoint:
|
||||||
|
"/public/v1.0/IssueMaterial/ReturnPartiallyConsumedManualMaterial",
|
||||||
|
data: [matReturnData],
|
||||||
|
})
|
||||||
|
)) as any;
|
||||||
|
|
||||||
|
if (!matReturn.success) {
|
||||||
|
createLog(
|
||||||
|
"error",
|
||||||
|
"materials",
|
||||||
|
"ocp",
|
||||||
|
`RN:${data.runnungNumber}, Error ${matReturn.data.data.errors[0].message}`
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: `RN:${data.runnungNumber}, Error ${matReturn.data.data.errors[0].message}`,
|
||||||
|
data: matReturn,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// consume to the lot provided.
|
||||||
|
const consumeLot = {
|
||||||
|
productionLot: data.lotNumber,
|
||||||
|
barcode: label?.data[0].Barcode,
|
||||||
|
};
|
||||||
|
const { data: matConsume, error: matConsumeError } = (await tryCatch(
|
||||||
|
runProdApi({
|
||||||
|
endpoint:
|
||||||
|
"/public/v1.0/IssueMaterial/ConsumeNonPreparedManualMaterial",
|
||||||
|
data: [consumeLot],
|
||||||
|
})
|
||||||
|
)) as any;
|
||||||
|
|
||||||
|
if (!matConsume.success) {
|
||||||
|
createLog(
|
||||||
|
"error",
|
||||||
|
"materials",
|
||||||
|
"ocp",
|
||||||
|
`RN:${data.runnungNumber}, Error ${matConsume.data.data.errors[0].message}`
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: `RN:${data.runnungNumber}, Error ${matConsume.data.data.errors[0].message}`,
|
||||||
|
data: matConsume,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
createLog(
|
||||||
|
"info",
|
||||||
|
"materials",
|
||||||
|
"ocp",
|
||||||
|
`RN:${data.runnungNumber}: qty: ${newQty}, was transfered to lot:${data.lotNumber}`
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: `RN:${data.runnungNumber}: qty: ${newQty}, was transfered to lot:${data.lotNumber}`,
|
||||||
|
data: [],
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// setTimeout(async () => {
|
||||||
|
// lotMaterialTransfer({
|
||||||
|
// runnungNumber: 603468,
|
||||||
|
// lotNumber: 24897,
|
||||||
|
// originalAmount: 380,
|
||||||
|
// level: 0.95,
|
||||||
|
// });
|
||||||
|
// }, 5000);
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
||||||
import { createLog } from "../../../logger/logger.js";
|
import { createLog } from "../../../logger/logger.js";
|
||||||
|
import { serverSettings } from "../../../server/controller/settings/getSettings.js";
|
||||||
import { query } from "../../../sqlServer/prodSqlServer.js";
|
import { query } from "../../../sqlServer/prodSqlServer.js";
|
||||||
import { machineCheck } from "../../../sqlServer/querys/ocp/machineId.js";
|
import { machineCheck } from "../../../sqlServer/querys/ocp/machineId.js";
|
||||||
import { mmQuery } from "../../../sqlServer/querys/ocp/mainMaterial.js";
|
import { mmQuery } from "../../../sqlServer/querys/ocp/mainMaterial.js";
|
||||||
|
|
||||||
export const isMainMatStaged = async (lot: any) => {
|
export const isMainMatStaged = async (lot: any) => {
|
||||||
|
const set = serverSettings.length === 0 ? [] : serverSettings;
|
||||||
// make staged false by deefault and error logged if theres an issue
|
// make staged false by deefault and error logged if theres an issue
|
||||||
let isStaged = false;
|
let isStaged = { message: "Material is staged", success: true };
|
||||||
|
|
||||||
const { data, error } = (await tryCatch(
|
const { data, error } = (await tryCatch(
|
||||||
query(
|
query(
|
||||||
@@ -26,7 +28,10 @@ export const isMainMatStaged = async (lot: any) => {
|
|||||||
"ocp",
|
"ocp",
|
||||||
`The machine dose not require mm to print and book in.`
|
`The machine dose not require mm to print and book in.`
|
||||||
);
|
);
|
||||||
return true;
|
return {
|
||||||
|
message: "Machine dose not require material to be staged",
|
||||||
|
success: true,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// strangly the lot is not always sending over in slc so adding this in for now to see what line is cauing this issue
|
// strangly the lot is not always sending over in slc so adding this in for now to see what line is cauing this issue
|
||||||
@@ -51,20 +56,101 @@ export const isMainMatStaged = async (lot: any) => {
|
|||||||
|
|
||||||
const res: any = r.data;
|
const res: any = r.data;
|
||||||
|
|
||||||
createLog(
|
// if (res[0].Staged >= 1) {
|
||||||
"info",
|
|
||||||
"mainMaterial",
|
|
||||||
"ocp",
|
|
||||||
`MainMaterial results: ${JSON.stringify(res)}`
|
|
||||||
);
|
|
||||||
|
|
||||||
if (res[0].Staged >= 1) {
|
|
||||||
isStaged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (res[0].noShortage === "good") {
|
|
||||||
// isStaged = true;
|
// isStaged = true;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
createLog("info", "mainMaterial", "ocp", `Maint material query ran.`);
|
||||||
|
|
||||||
|
const mainMateiral = res.filter((n: any) => n.IsMainMaterial);
|
||||||
|
|
||||||
|
if (mainMateiral[0]?.noMaterialShortage === "no") {
|
||||||
|
isStaged = {
|
||||||
|
message: `Main material: ${mainMateiral[0].MaterialHumanReadableId} - ${mainMateiral[0].MaterialDescription}: is not staged for ${lot.lot} `,
|
||||||
|
success: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// we need to filter the color stuff and then look for includes instead of a standard name. this way we can capture a everything and not a single type
|
||||||
|
// for manual consume color if active to check colors
|
||||||
|
const checkColorSetting = set.filter((n) => n.name === "checkColor");
|
||||||
|
|
||||||
|
if (checkColorSetting[0].value === "1") {
|
||||||
|
const autoConsumeColor = res.filter(
|
||||||
|
(n: any) => !n.IsMainMaterial && !n.isManual
|
||||||
|
);
|
||||||
|
if (
|
||||||
|
autoConsumeColor.some(
|
||||||
|
(n: any) => n.autoConsumeCheck === "autoConsumeNOK"
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
const onlyNOK = autoConsumeColor.filter(
|
||||||
|
(n: any) => n.autoConsumeCheck === "autoConsumeNOK"
|
||||||
|
);
|
||||||
|
isStaged = {
|
||||||
|
message: `lot: ${lot.lot}, is missing: ${onlyNOK
|
||||||
|
.map(
|
||||||
|
(o: any) =>
|
||||||
|
`${o.MaterialHumanReadableId} - ${o.MaterialDescription}`
|
||||||
|
)
|
||||||
|
.join(",\n ")} for autoconsume`,
|
||||||
|
success: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// // for manual consume color
|
||||||
|
const manualConsumeColor = res.filter(
|
||||||
|
(n: any) => !n.IsMainMaterial && n.isManual
|
||||||
|
);
|
||||||
|
if (
|
||||||
|
manualConsumeColor.some(
|
||||||
|
(n: any) => n.noMaterialShortage === "yes"
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
isStaged = {
|
||||||
|
message: `lot: ${lot.lot}, is missing: ${manualConsumeColor
|
||||||
|
.map(
|
||||||
|
(o: any) =>
|
||||||
|
`${o.MaterialHumanReadableId} - ${o.MaterialDescription}`
|
||||||
|
)
|
||||||
|
.join(",\n ")} for manual Material`,
|
||||||
|
success: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
createLog(
|
||||||
|
"info",
|
||||||
|
"mainMaterial",
|
||||||
|
"ocp",
|
||||||
|
"Color check is not active."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// // if we want to check the packaging
|
||||||
|
const checkPKGSetting = set.filter((n) => n.name === "checkPKG");
|
||||||
|
if (checkPKGSetting[0].value === "1") {
|
||||||
|
const packagingCheck = res.filter(
|
||||||
|
(n: any) => !n.IsMainMaterial && n.isManual
|
||||||
|
);
|
||||||
|
if (packagingCheck.some((n: any) => n.noPKGShortage === "noPkg")) {
|
||||||
|
isStaged = {
|
||||||
|
message: `lot: ${lot.lot}, is missing: ${packagingCheck
|
||||||
|
.map(
|
||||||
|
(o: any) =>
|
||||||
|
`${o.MaterialHumanReadableId} - ${o.MaterialDescription}`
|
||||||
|
)
|
||||||
|
.join(",\n ")} for pkg`,
|
||||||
|
success: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
createLog(
|
||||||
|
"info",
|
||||||
|
"mainMaterial",
|
||||||
|
"ocp",
|
||||||
|
"PKG check is not active."
|
||||||
|
);
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
createLog(
|
createLog(
|
||||||
"error",
|
"error",
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import { deleteLabels } from "../../globalUtils/dbCleanUp/labelCleanUp.js";
|
|||||||
import bookInLabel from "./routes/labeling/bookIn.js";
|
import bookInLabel from "./routes/labeling/bookIn.js";
|
||||||
import labelRatio from "./routes/labeling/getLabelRatio.js";
|
import labelRatio from "./routes/labeling/getLabelRatio.js";
|
||||||
import resetRatio from "./routes/labeling/resetLabelRatio.js";
|
import resetRatio from "./routes/labeling/resetLabelRatio.js";
|
||||||
|
import materialTransferLot from "./routes/materials/lotTransfer.js";
|
||||||
|
|
||||||
const app = new OpenAPIHono();
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
@@ -47,6 +48,8 @@ const routes = [
|
|||||||
//dyco
|
//dyco
|
||||||
dycoCon,
|
dycoCon,
|
||||||
dycoClose,
|
dycoClose,
|
||||||
|
// materials
|
||||||
|
materialTransferLot,
|
||||||
] as const;
|
] as const;
|
||||||
const setting = await db.select().from(settings);
|
const setting = await db.select().from(settings);
|
||||||
|
|
||||||
@@ -101,4 +104,5 @@ setInterval(() => {
|
|||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
updatePrinters();
|
updatePrinters();
|
||||||
}, 1000 * 60 * 60 * 24);
|
}, 1000 * 60 * 60 * 24);
|
||||||
|
|
||||||
export default app;
|
export default app;
|
||||||
|
|||||||
64
server/services/ocp/routes/materials/lotTransfer.ts
Normal file
64
server/services/ocp/routes/materials/lotTransfer.ts
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
// an external way to creating logs
|
||||||
|
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||||
|
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
|
||||||
|
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
||||||
|
import { apiHit } from "../../../../globalUtils/apiHits.js";
|
||||||
|
|
||||||
|
import { lotMaterialTransfer } from "../../controller/materials/lotTransfer.js";
|
||||||
|
|
||||||
|
const app = new OpenAPIHono({ strict: false });
|
||||||
|
|
||||||
|
const LotTransfer = z.object({
|
||||||
|
runnungNumber: z.number().openapi({ example: 1234 }),
|
||||||
|
lotNumber: z.number().openapi({ example: 1235 }),
|
||||||
|
originalAmount: z.number().openapi({ example: 457 }),
|
||||||
|
level: z.number().openapi({ examples: [0.24, 0.5, 0.75, 0.95] }),
|
||||||
|
});
|
||||||
|
|
||||||
|
app.openapi(
|
||||||
|
createRoute({
|
||||||
|
tags: ["ocp"],
|
||||||
|
summary: "Transfers a gaylord of material to provided lot",
|
||||||
|
method: "post",
|
||||||
|
path: "/materiallottransfer",
|
||||||
|
request: {
|
||||||
|
body: { content: { "application/json": { schema: LotTransfer } } },
|
||||||
|
},
|
||||||
|
responses: responses(),
|
||||||
|
}),
|
||||||
|
async (c) => {
|
||||||
|
//const hours = c.req.query("hours");
|
||||||
|
const { data: bodyData, error: bodyError } = await tryCatch(
|
||||||
|
c.req.json()
|
||||||
|
);
|
||||||
|
apiHit(c, { endpoint: "/materiallottransfer", lastBody: bodyData });
|
||||||
|
|
||||||
|
if (bodyError) {
|
||||||
|
return c.json({
|
||||||
|
success: false,
|
||||||
|
message: "You are missing data",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: transferMaterial, error: transferError } = await tryCatch(
|
||||||
|
lotMaterialTransfer(bodyData)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (transferError) {
|
||||||
|
console.log(transferError);
|
||||||
|
return c.json({
|
||||||
|
success: false,
|
||||||
|
message:
|
||||||
|
"There was an error transfering the material to the next lot.",
|
||||||
|
data: transferError,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.json({
|
||||||
|
success: transferMaterial.success,
|
||||||
|
message: transferMaterial.message,
|
||||||
|
data: transferMaterial.data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
export default app;
|
||||||
@@ -245,6 +245,20 @@ const newSettings = [
|
|||||||
roleToChange: "admin",
|
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: "checkColor",
|
||||||
|
value: `0`,
|
||||||
|
description: "Checks autoconsume and manual consume color",
|
||||||
|
serviceBelowsTo: "admin",
|
||||||
|
roleToChange: "admin",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "checkPKG",
|
||||||
|
value: `0`,
|
||||||
|
description: "Checks checks if we have enough packaging or not",
|
||||||
|
serviceBelowsTo: "admin",
|
||||||
|
roleToChange: "admin",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "siloAdjMigrations",
|
name: "siloAdjMigrations",
|
||||||
value: `0`,
|
value: `0`,
|
||||||
|
|||||||
@@ -1,22 +1,117 @@
|
|||||||
|
// export const mmQuery = `
|
||||||
|
// SELECT lot.ProductionLotHumanReadableId,
|
||||||
|
// case when SourcingState in (1, 2) then 1
|
||||||
|
// when x.ProvidedAmount > 0 then 1
|
||||||
|
// when x.EffectiveConsumption > 0 then 1
|
||||||
|
// else 0 end as Staged,
|
||||||
|
// x.ProvidedAmount as Provided,
|
||||||
|
// x.EffectiveConsumption as consumption,
|
||||||
|
// x.TotalDemand as totalNeeded,
|
||||||
|
// /* remaining needed to complete the lot */
|
||||||
|
// x.TotalDemand - x.EffectiveConsumption as remainingNeeded,
|
||||||
|
// /* do we have enough staged or scanned to the lot? */
|
||||||
|
// case when (case when x.ProvidedAmount <> 0 then x.ProvidedAmount else x.EffectiveConsumption end) > x.TotalDemand then 'good' else 'bad' end as noShortage ,
|
||||||
|
// x.IsManualProcess as isManual,
|
||||||
|
// MaterialHumanReadableId
|
||||||
|
// FROM [test1_AlplaPROD2.0_Read].[issueMaterial].[MaterialDemand] x (nolock)
|
||||||
|
// left join
|
||||||
|
// [test1_AlplaPROD2.0_Read].[issueMaterial].[ProductionLot] as lot on
|
||||||
|
// x.ProductionLotId = lot.Id
|
||||||
|
// where lot.ProductionLotHumanReadableId = [lotNumber]
|
||||||
|
// and IsMainMaterial = 1
|
||||||
|
// `;
|
||||||
|
|
||||||
export const mmQuery = `
|
export const mmQuery = `
|
||||||
SELECT lot.ProductionLotHumanReadableId,
|
use [test1_AlplaPROD2.0_Read]
|
||||||
case when SourcingState in (1, 2) then 1
|
/*
|
||||||
when x.ProvidedAmount > 0 then 1
|
checks all needed material including pkg
|
||||||
when x.EffectiveConsumption > 0 then 1
|
|
||||||
else 0 end as Staged,
|
we only want to monitor the manual materials and the mm materail to make sure they are good.
|
||||||
x.ProvidedAmount as Provided,
|
|
||||||
x.EffectiveConsumption as consumption,
|
for auto consume materails this will be compared with another query.
|
||||||
x.TotalDemand as totalNeeded,
|
|
||||||
|
*/
|
||||||
|
SELECT lot.ProductionLotHumanReadableId
|
||||||
|
,MaterialHumanReadableId
|
||||||
|
,MaterialDescription
|
||||||
|
--IsMainMaterial,
|
||||||
|
--case when SourcingState in (1, 2) then 1
|
||||||
|
--when x.ProvidedAmount > 0 then 1
|
||||||
|
--when x.EffectiveConsumption > 0 then 1
|
||||||
|
--else 0 end as Staged,
|
||||||
|
,x.ProvidedAmount as Provided
|
||||||
|
,x.EffectiveConsumption as consumption
|
||||||
|
,x.TotalDemand as totalDemand ,
|
||||||
|
case when cp.Pieces = 1 then (lot.TotalProducedLoadingUnits+1) * p.LoadingUnitPieces else
|
||||||
|
(a.Weight *(cp.Percentage / 100) * ((lot.TotalProducedLoadingUnits+1) * p.LoadingUnitPieces)) / 1000 end totalNeeded
|
||||||
|
,l.qty as invForAutoConsume
|
||||||
/* remaining needed to complete the lot */
|
/* remaining needed to complete the lot */
|
||||||
x.TotalDemand - x.EffectiveConsumption as remainingNeeded,
|
--,x.TotalDemand - x.EffectiveConsumption as remainingNeeded
|
||||||
/* do we have enough staged or scanned to the lot? */
|
/* do we have enough staged or scanned to the lot? */
|
||||||
case when (case when x.ProvidedAmount <> 0 then x.ProvidedAmount else x.EffectiveConsumption end) > x.TotalDemand then 'good' else 'bad' end as noShortage ,
|
,case when (case when x.ProvidedAmount <> 0
|
||||||
x.IsManualProcess as isManual,
|
then x.ProvidedAmount else x.EffectiveConsumption end) >
|
||||||
MaterialHumanReadableId
|
case when cp.Pieces = 1 then (lot.TotalProducedLoadingUnits+1) * p.LoadingUnitPieces else
|
||||||
FROM [test1_AlplaPROD2.0_Read].[issueMaterial].[MaterialDemand] x (nolock)
|
(a.Weight *(cp.Percentage / 100) * ((lot.TotalProducedLoadingUnits+1) * p.LoadingUnitPieces)) / 1000 end
|
||||||
|
then 'good'
|
||||||
|
else 'no' end as noMaterialShortage
|
||||||
|
-- pkg check
|
||||||
|
,case when pkg.QuantityPosition is null then null else
|
||||||
|
(case when l.qty > (lot.TotalProducedLoadingUnits+1) * pkg.QuantityPosition then 'pkgGood' else 'noPkg' end) end as noPKGShortage
|
||||||
|
|
||||||
|
,case when cp.Percentage is null then
|
||||||
|
case when l.qty > ((lot.TotalProducedLoadingUnits +1) * pkg.QuantityPosition) then 'autoConsumeOk' else 'autoConsumeNOK' end else
|
||||||
|
(case when l.qty > (a.Weight *(cp.Percentage / 100) * ((lot.TotalProducedLoadingUnits+1) * p.LoadingUnitPieces)) / 1000 and IsManualProcess = 0
|
||||||
|
then 'autoConsumeOk' else 'autoConsumeNOK' end) end as autoConsumeCheck
|
||||||
|
,x.IsManualProcess as isManual
|
||||||
|
,IsMainMaterial
|
||||||
|
,lot.TotalPlannedLoadingUnits
|
||||||
|
,lot.TotalProducedLoadingUnits
|
||||||
|
,lot.TotalPlannedLoadingUnits - lot.TotalProducedLoadingUnits as remainingPallets
|
||||||
|
,cp.Percentage
|
||||||
|
,case when cp.Pieces is not null then cp.Pieces else pkg.QuantityPosition end as peices
|
||||||
|
FROM [issueMaterial].[MaterialDemand] x (nolock)
|
||||||
|
|
||||||
left join
|
left join
|
||||||
[test1_AlplaPROD2.0_Read].[issueMaterial].[ProductionLot] as lot on
|
[productionControlling].[ProducedLot] as lot on
|
||||||
x.ProductionLotId = lot.Id
|
lot.Id = x.ProductionLotId
|
||||||
|
|
||||||
|
/* av data */
|
||||||
|
left join
|
||||||
|
[masterData].[Article] as a on
|
||||||
|
a.id = lot.ArticleId
|
||||||
|
|
||||||
|
/* compound*/
|
||||||
|
left join
|
||||||
|
[masterData].[CompoundPosition] as cp on
|
||||||
|
cp.CompoundId = a.CompoundId
|
||||||
|
and cp.ArticleId = x.MaterialId
|
||||||
|
|
||||||
|
/* packagaing */
|
||||||
|
left join
|
||||||
|
[masterData].[PackagingInstructionPosition] as pkg on
|
||||||
|
pkg.PackagingInstructionId = lot.PackagingId
|
||||||
|
and pkg.ArticleId = x.MaterialId
|
||||||
|
|
||||||
|
-- get the pkg stuff so we have the total amount per pallet.
|
||||||
|
left join
|
||||||
|
[masterData].[PackagingInstruction] as p on
|
||||||
|
p.id = lot.PackagingId
|
||||||
|
|
||||||
|
/* current stock info for auto consumption*/
|
||||||
|
left join
|
||||||
|
(select
|
||||||
|
IdArtikelVarianten
|
||||||
|
,ArtikelVariantenBez
|
||||||
|
,sum(VerfuegbareMengeSum) as qty
|
||||||
|
|
||||||
|
from AlplaPROD_test1.dbo.V_LagerPositionenBarcodes as i (nolock)
|
||||||
|
|
||||||
|
left join
|
||||||
|
AlplaPROD_test1.dbo.V_LagerAbteilungen as l (nolock) on
|
||||||
|
l.IdLagerAbteilung = i.IdLagerAbteilung
|
||||||
|
where autoverbrauch = 1 and aktiv = 1
|
||||||
|
group by IdArtikelVarianten,ArtikelVariantenBez
|
||||||
|
) as l on
|
||||||
|
l.IdArtikelVarianten = MaterialHumanReadableId
|
||||||
where lot.ProductionLotHumanReadableId = [lotNumber]
|
where lot.ProductionLotHumanReadableId = [lotNumber]
|
||||||
and IsMainMaterial = 1
|
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -1,20 +1,36 @@
|
|||||||
export const labelInfo = `
|
export const labelInfo = `
|
||||||
select top(500) e.Barcode,
|
declare @runningNumber nvarchar(max) = [runningNr]
|
||||||
e.IdArtikelvarianten as av,
|
|
||||||
e.lfdnr as rn,
|
select e.Barcode,
|
||||||
IdEtikettenLayout as labelLayout,
|
e.RunningNumber as runnungNumber,
|
||||||
AnzStkJePalette,
|
externalRunningNumber= null,
|
||||||
Sonstiges_9,AnzStkJeKarton
|
e.ArticleHumanReadableId as av,
|
||||||
,case when EinlagerungsMengeSum IS NULL then 'notOnStock' else 'onStock' end as stockStatus
|
e.LabelManagementHumanReadableId as labelLayout,
|
||||||
,EinlagerungsMengeSum
|
case when EinlagerungsMengeSum IS NULL then 'notOnStock' else 'onStock' end as stockStatus
|
||||||
--,*
|
from [test1_AlplaPROD2.0_Read].[labelling].[InternalLabel] (nolock) as e
|
||||||
from [AlplaPROD_test1].dbo.[T_EtikettenGedruckt] e (nolock)
|
|
||||||
|
|
||||||
left join
|
left join
|
||||||
[AlplaPROD_test1].dbo.V_LagerPositionenBarcodes as l on
|
alplaprod_test1.dbo.V_LagerPositionenBarcodes (nolock) as l on
|
||||||
e.LfdNr = l.Lfdnr
|
e.RunningNumber = l.Lfdnr
|
||||||
|
|
||||||
where e.LfdNr in ([runningNr])
|
WHERE e.RunningNumber IN (@runningNumber)
|
||||||
|
|
||||||
order by add_date desc
|
union all
|
||||||
|
|
||||||
|
select ext.Barcode
|
||||||
|
,RunningNumber as runnungNumber
|
||||||
|
,SsccEanRunningNumber as externalRunningNumber
|
||||||
|
,ArticleHumanReadableId
|
||||||
|
,case when LabelManagementHumanReadableId is null then (select HumanReadableId from [test1_AlplaPROD2.0_Read].[masterData].[LabelManagement] (nolock) where LabelMarkerId = 7) else LabelManagementHumanReadableId end as labelLayout
|
||||||
|
,case when EinlagerungsMengeSum IS NULL then 'notOnStock' else 'onStock' end as stockStatus
|
||||||
|
from [test1_AlplaPROD2.0_Read].[labelling].[ExternalLabel] (nolock) as ext
|
||||||
|
|
||||||
|
left join
|
||||||
|
alplaprod_test1.dbo.V_LagerPositionenBarcodes (nolock) as l on
|
||||||
|
ext.RunningNumber = l.Lfdnr
|
||||||
|
|
||||||
|
WHERE ext.SsccEanRunningNumber IN (@runningNumber) and
|
||||||
|
ext.RunningNumber NOT IN (
|
||||||
|
SELECT RunningNumber FROM [test1_AlplaPROD2.0_Read].[labelling].[InternalLabel] WHERE RunningNumber IN (@runningNumber)
|
||||||
|
)
|
||||||
`;
|
`;
|
||||||
|
|||||||
Reference in New Issue
Block a user