Compare commits

..

28 Commits

Author SHA1 Message Date
8943407f27 feat(finaly): the final push before moving all to the new lst 2025-09-19 22:16:47 -05:00
0bbe411db0 feat(docs): added in link to the main docs and to the material xfer 2025-09-19 07:56:43 -05:00
99b3ad633c fix(materials): changes for consuming peices vs units 2025-09-18 11:00:54 -05:00
c892348d19 refactor(manual print): added a min length of 10 characters 2025-09-18 11:00:18 -05:00
360549aaf4 fix(consume material): changes made to remove the rest of the auth needs 2025-09-18 10:59:55 -05:00
bdc1e72fc1 refactor(frontend): comment required now when doing manual labels 2025-09-17 20:02:14 -05:00
4cae96b1ee refactor(detach): just a log to monitor better 2025-09-11 06:42:31 -05:00
1cde8ab2e6 fix(mm query): more changes to the material query to please more plants 2025-09-11 06:42:02 -05:00
03e8378213 fix(inhouse): changes to no longer error 2025-09-11 06:39:36 -05:00
275c93dc79 refactor(detach silo): changes to now show the error in the console in the browser 2025-09-11 06:39:07 -05:00
fbb8c21d5c feat(loreal forecast): added in an email to be sent when we are missing skus 2025-09-11 06:38:36 -05:00
dce93d3de2 ci(release): bump build number to 652 2025-09-11 06:32:08 -05:00
faf4e9f9ab ci(release): bump build number to 651 2025-09-11 06:30:48 -05:00
a9783a7d35 ci(release): bump build number to 650 2025-09-10 11:15:07 -05:00
e9ca6dbbb2 ci(release): bump build number to 649 2025-09-10 11:13:59 -05:00
e996f99400 ci(release): bump build number to 648 2025-09-10 06:59:19 -05:00
3b939ff2d3 ci(release): bump build number to 647 2025-09-09 21:21:08 -05:00
a7ff88025e chore(release): 2.27.0 2025-09-09 21:20:39 -05:00
00899a5b77 fix(materials): more fixes to try and please all plants to use this version and not call me 2025-09-09 21:20:23 -05:00
99ecf52218 fix(label query): fixes to only pull in active layouts 2025-09-09 21:19:39 -05:00
a6920d7cd8 ci(release): bump build number to 645 2025-09-09 17:52:15 -05:00
788efdf4b3 ci(release): bump build number to 644 2025-09-09 17:40:05 -05:00
a2a17beeeb ci(release): bump build number to 643 2025-09-09 17:28:29 -05:00
6c793c66a4 ci(release): bump build number to 642 2025-09-09 15:57:41 -05:00
6918a5a7d4 ci(release): bump build number to 641 2025-09-09 09:12:18 -05:00
ddd9b0e372 ci(release): bump build number to 640 2025-09-09 07:48:24 -05:00
41d921756b ci(release): bump build number to 638 2025-09-08 19:16:44 -05:00
d86ca7d3bf ci(release): bump build number to 636 2025-09-08 13:30:05 -05:00
31 changed files with 832 additions and 144 deletions

1
.gitignore vendored
View File

@@ -157,3 +157,4 @@ backend-0.1.3.zip
BulkForecastTemplate BulkForecastTemplate
BulkOrdersTemplate BulkOrdersTemplate
check.json check.json
server/services/ocp/controller/materials/materialcheck.bak

View File

@@ -1,5 +1,36 @@
# All CHanges to LST can be found below. # All CHanges to LST can be found below.
## [2.27.0](https://git.tuffraid.net/cowch/lstV2/compare/v2.26.0...v2.27.0) (2025-09-10)
### 🌟 Enhancements
* **eom:** lastSales, lastPurch added to be pulled with new template ([7cc3778](https://git.tuffraid.net/cowch/lstV2/commits/7cc3778506fc92392ca8431aee0edb203861e10d))
### 🛠️ Code Refactor
* **cosume:** changes to allow non logged in users to use this function ([271cdbd](https://git.tuffraid.net/cowch/lstV2/commits/271cdbdbfa2478ecf56e9b01a4474508acacda2e))
* **mm query:** changes to the query to see pkg and materials properly and not duplicates ([57966ac](https://git.tuffraid.net/cowch/lstV2/commits/57966ac9de72543014451b7ccd75539296ccaa51))
* **rfid:** changes to show all tags vs only 3 if there are more ([b677bc1](https://git.tuffraid.net/cowch/lstV2/commits/b677bc14981faff30c91f6ffe4602319dd3c6016))
* **silo card:** changes to allow viewers to see and able to attach and detach ([796a8dc](https://git.tuffraid.net/cowch/lstV2/commits/796a8dccd2807890abdff7c8dacf8b2246eb265e))
* **sql:** articles added in UOM ([cfed981](https://git.tuffraid.net/cowch/lstV2/commits/cfed981928a56389e09ef428c43ceabc1caec28e))
### 🐛 Bug fixes
* **article check:** corrected the query to not have a specfic plant in it ([79f1f8f](https://git.tuffraid.net/cowch/lstV2/commits/79f1f8f91ba33533de7f4a7cc91503cfd8dd4ce5))
* **bookin:** corrected the bookin in error response ([1f8b8a7](https://git.tuffraid.net/cowch/lstV2/commits/1f8b8a7248c11c7e264c8c5ae7c042c5a0878c46))
* **bookin:** corrections to only show the message on error vs the json ([b3ce767](https://git.tuffraid.net/cowch/lstV2/commits/b3ce767b323c990c0ccf35ad6c2c67136a27272e))
* **db:** changes to the user so it deletes correctly ([932a72b](https://git.tuffraid.net/cowch/lstV2/commits/932a72ba884673471f0056e721cc3f2c8e34b4f3))
* **eomservice:** changes to stop a crash incase the sql returned nothing due to start up ([6caa598](https://git.tuffraid.net/cowch/lstV2/commits/6caa5984e7a3e7b48b119c176835663ffec71151))
* **frontend:** typos ([c6f6ef6](https://git.tuffraid.net/cowch/lstV2/commits/c6f6ef626295f452cdf26f6776b74cfb3b1a10f5))
* **label query:** fixes to only pull in active layouts ([99ecf52](https://git.tuffraid.net/cowch/lstV2/commits/99ecf52218556e048ba9262e74f9b3d020dea31d))
* **main material check:** corrections to properly ignore pkg during color checks ([6910550](https://git.tuffraid.net/cowch/lstV2/commits/6910550de769dce04b1045f96ab19cf7b8d1ef8c))
* **material check:** split manual material out of the mm to properly catch it ([a53915a](https://git.tuffraid.net/cowch/lstV2/commits/a53915ad8cbec5bd8d6ba4643c460ad0162249e2))
* **materials:** more fixes to try and please all plants to use this version and not call me ([00899a5](https://git.tuffraid.net/cowch/lstV2/commits/00899a5b778eab792b350a0b47589de1524d91c8))
* **register:** changes to not give everyone system admin ([415d2e4](https://git.tuffraid.net/cowch/lstV2/commits/415d2e4a1d851cc46ac64ffc814a280a02293bbc))
## [2.26.0](https://git.tuffraid.net/cowch/lstV2/compare/v2.25.0...v2.26.0) (2025-08-28) ## [2.26.0](https://git.tuffraid.net/cowch/lstV2/compare/v2.25.0...v2.26.0) (2025-08-28)

View File

@@ -1,3 +1,7 @@
# THIS VERSION IS NO LONGER BEING UPDATED PLEASE GO TO THE NEW REPO LINK BELOW
[NEW LST REPO](https://git.tuffraid.net/cowch/lst)
# lstV2 # lstV2
Logistics Support Tool V2 Logistics Support Tool V2

View File

@@ -1,26 +1,30 @@
import {LstCard} from "@/components/extendedUI/LstCard"; import { LstCard } from "@/components/extendedUI/LstCard";
import {Button} from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import {CardHeader} from "@/components/ui/card"; import { CardHeader } from "@/components/ui/card";
import {Input} from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import {Label} from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import {useSessionStore} from "@/lib/store/sessionStore";
import axios from "axios";
import {useState} from "react";
import {useForm} from "react-hook-form"; import axios from "axios";
import {toast} from "sonner"; import { useState } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
export default function ConsumeMaterial() { export default function ConsumeMaterial() {
const {register: register1, handleSubmit: handleSubmit1, reset} = useForm(); const {
register: register1,
handleSubmit: handleSubmit1,
reset,
} = useForm();
const [submitting, setSubmitting] = useState(false); const [submitting, setSubmitting] = useState(false);
const {token} = useSessionStore();
const handleConsume = async (data: any) => { const handleConsume = async (data: any) => {
setSubmitting(true); setSubmitting(true);
try { try {
const result = await axios.post(`/api/logistics/consume`, data, { // const result = await axios.post(`/api/logistics/consume`, data, {
headers: {Authorization: `Bearer ${token}`}, // headers: {Authorization: `Bearer ${token}`},
}); // });
const result = await axios.post(`/api/logistics/consume`, data);
if (result.data.success) { if (result.data.success) {
toast.success(result.data.message); toast.success(result.data.message);
setSubmitting(false); setSubmitting(false);
@@ -33,12 +37,14 @@ export default function ConsumeMaterial() {
toast.error(result.data.message); toast.error(result.data.message);
} }
} catch (error: any) { } catch (error: any) {
//console.log(error); console.log(error);
setSubmitting(false); setSubmitting(false);
if (error.status === 401) { if (error.status === 401) {
toast.error("Unauthorized to do this task."); toast.error("Unauthorized to do this task.");
} else { } else {
toast.error("Unexpected error if this continues please constact an admin."); toast.error(
"Unexpected error if this continues please constact an admin."
);
} }
} }
}; };
@@ -53,7 +59,9 @@ export default function ConsumeMaterial() {
<LstCard> <LstCard>
<form onSubmit={handleSubmit1(handleConsume)}> <form onSubmit={handleSubmit1(handleConsume)}>
<div className="m-2"> <div className="m-2">
<Label htmlFor="runningNr">Enter unit running number</Label> <Label htmlFor="runningNr">
Enter unit running number
</Label>
<Input <Input
className="mt-2" className="mt-2"
//defaultValue="634" //defaultValue="634"
@@ -62,7 +70,9 @@ export default function ConsumeMaterial() {
/> />
</div> </div>
<div className="m-2"> <div className="m-2">
<Label htmlFor="lotNum">Enter lot number</Label> <Label htmlFor="lotNum">
Enter lot number
</Label>
<Input <Input
className="mt-2" className="mt-2"
//defaultValue="634" //defaultValue="634"
@@ -71,7 +81,12 @@ export default function ConsumeMaterial() {
/> />
</div> </div>
<Button className="m-2" color="primary" type="submit" disabled={submitting}> <Button
className="m-2"
color="primary"
type="submit"
disabled={submitting}
>
Consume materal Consume materal
</Button> </Button>
</form> </form>
@@ -81,12 +96,19 @@ export default function ConsumeMaterial() {
<LstCard> <LstCard>
<div className="w-96 p-1"> <div className="w-96 p-1">
<ol> <ol>
<li>1. Enter the running number of the material you would like to consume</li> <li>
<li>2. Enter the lot number you will be consuming to</li> 1. Enter the running number of the
material you would like to consume
</li>
<li>
2. Enter the lot number you will be
consuming to
</li>
<li>3. Press consume material</li> <li>3. Press consume material</li>
</ol> </ol>
<p className="text-pretty w-96"> <p className="text-pretty w-96">
*This process is only for barcoded material, if it is set to auto consume you will *This process is only for barcoded material,
if it is set to auto consume you will
encounter and error. encounter and error.
</p> </p>
</div> </div>

View File

@@ -14,13 +14,16 @@ import {
TooltipContent, TooltipContent,
TooltipTrigger, TooltipTrigger,
} from "@/components/ui/tooltip"; } from "@/components/ui/tooltip";
import { useSettingStore } from "@/lib/store/useSettings";
export default function TransferToNextLot() { export default function TransferToNextLot() {
const [gaylordFilled, setGaylordFilled] = useState([0]); const [gaylordFilled, setGaylordFilled] = useState([0]);
const [actualAmount, setActualAmount] = useState(0); const [actualAmount, setActualAmount] = useState(0);
const [tab, setTab] = useState("esitmate"); const [tab, setTab] = useState("esitmate");
const [typeSwitch, setTypeSwitch] = useState(false); const [typeSwitch, setTypeSwitch] = useState(false);
const { settings } = useSettingStore();
const server = settings.filter((n: any) => n.name === "dbServer");
const form = useAppForm({ const form = useAppForm({
defaultValues: { defaultValues: {
runningNumber: "", runningNumber: "",
@@ -111,7 +114,7 @@ export default function TransferToNextLot() {
} }
> >
<p className="text-center"> <p className="text-center">
Almost full Almost full - 95%
</p> </p>
</button> </button>
<button <button
@@ -129,7 +132,7 @@ export default function TransferToNextLot() {
} }
> >
<p className="text-center"> <p className="text-center">
About 75% full About full - 75%
</p> </p>
</button> </button>
<button <button
@@ -145,7 +148,7 @@ export default function TransferToNextLot() {
} }
> >
<p className="text-center"> <p className="text-center">
Half full Half full - 50%
</p> </p>
</button> </button>
<button <button
@@ -163,7 +166,7 @@ export default function TransferToNextLot() {
} }
> >
<p className="text-center"> <p className="text-center">
Almost empty Almost empty - 25%
</p> </p>
</button> </button>
</div> </div>
@@ -218,7 +221,7 @@ export default function TransferToNextLot() {
name="runningNumber" name="runningNumber"
children={(field) => ( children={(field) => (
<field.InputField <field.InputField
label="Runnung Number" label="Running Number"
inputType="number" inputType="number"
required={true} required={true}
/> />
@@ -398,6 +401,19 @@ export default function TransferToNextLot() {
process, this process will just get process, this process will just get
the gaylord to the next lot. the gaylord to the next lot.
</p> </p>
<br />
{settings.length > 0 && (
<p>
For more in depth instructions
please{" "}
<a
href={`https://${server[0].value}.alpla.net/lst/d/docs/ocp/ocp#tranfer-partial-estimated-quantity-to-the-next-lot`}
target="_blank"
>
<em>CLICK HERE</em>
</a>
</p>
)}
</div> </div>
) : ( ) : (
<div> <div>
@@ -437,6 +453,19 @@ export default function TransferToNextLot() {
process, this process will just get process, this process will just get
the gaylord to the next lot. the gaylord to the next lot.
</p> </p>
<br />
{settings.length > 0 && (
<p>
For more in depth instructions
please{" "}
<a
href={`https://${server[0].value}.alpla.net/lst/d/docs/ocp/ocp#tranfer-partial-estimated-quantity-to-the-next-lot`}
target="_blank"
>
<em>CLICK HERE</em>
</a>
</p>
)}
</div> </div>
)} )}
</LstCard> </LstCard>

View File

@@ -48,6 +48,7 @@ export function DetachSilo(props: any) {
); );
if (res.status === 200) { if (res.status === 200) {
console.log(res.data.data);
toast.success(res.data.message); toast.success(res.data.message);
refetch(); refetch();

View File

@@ -243,7 +243,8 @@ export default function ManualPrintForm() {
<Textarea <Textarea
//label="Comments" //label="Comments"
placeholder="add more info as needed." placeholder="add more info as needed."
{...register("additionalComments")} {...(register("additionalComments"),
{ required: true, minLength: 10 })}
/> />
</div> </div>

View File

@@ -28,6 +28,7 @@ import { useLogout } from "@/hooks/useLogout";
import ExportInventoryData from "@/components/logistics/warehouse/ExportInventoryData"; import ExportInventoryData from "@/components/logistics/warehouse/ExportInventoryData";
import { AddCards } from "@/components/dashboard/AddCards"; import { AddCards } from "@/components/dashboard/AddCards";
import DMButtons from "@/components/logistics/dm/DMButtons"; import DMButtons from "@/components/logistics/dm/DMButtons";
import { useSettingStore } from "@/lib/store/useSettings";
//import { AddCards } from "@/components/dashboard/AddCards"; //import { AddCards } from "@/components/dashboard/AddCards";
// same as the layout // same as the layout
@@ -38,6 +39,9 @@ export const Route = createRootRoute({
const { user } = useSessionStore(); const { user } = useSessionStore();
const logout = useLogout(); const logout = useLogout();
const location = useLocation(); const location = useLocation();
const { settings } = useSettingStore();
const server = settings.filter((n: any) => n.name === "dbServer");
return ( return (
<div className="overflow-hidden"> <div className="overflow-hidden">
@@ -61,6 +65,17 @@ export const Route = createRootRoute({
<div className="m-1"> <div className="m-1">
<ModeToggle /> <ModeToggle />
</div> </div>
<div className="mr-1 ml-1">
{settings.length > 0 && (
<a
href={`https://${server[0].value}.alpla.net/lst/d`}
target="_blank"
>
LST - Docs
</a>
)}
</div>
{session ? ( {session ? (
<div className="m-1"> <div className="m-1">
<DropdownMenu> <DropdownMenu>

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "lstv2", "name": "lstv2",
"version": "2.26.0", "version": "2.27.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "lstv2", "name": "lstv2",
"version": "2.26.0", "version": "2.27.0",
"dependencies": { "dependencies": {
"@dotenvx/dotenvx": "^1.45.1", "@dotenvx/dotenvx": "^1.45.1",
"@hono/node-server": "^1.14.4", "@hono/node-server": "^1.14.4",

View File

@@ -1,6 +1,6 @@
{ {
"name": "lstv2", "name": "lstv2",
"version": "2.26.0", "version": "2.27.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "concurrently -n \"server,frontend\" -c \"#007755,#2f6da3\" \"npm run dev:server\" \"cd frontend && npm run dev\"", "dev": "concurrently -n \"server,frontend\" -c \"#007755,#2f6da3\" \"npm run dev:server\" \"cd frontend && npm run dev\"",
@@ -36,7 +36,7 @@
} }
}, },
"admConfig": { "admConfig": {
"build": 633, "build": 661,
"oldBuild": "backend-0.1.3.zip" "oldBuild": "backend-0.1.3.zip"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -0,0 +1,63 @@
import { and, between, inArray, sql } from "drizzle-orm";
import { db } from "../../../../database/dbclient.js";
import { invHistoricalData } from "../../../../database/schema/historicalINV.js";
import { tryCatch } from "../../../globalUtils/tryCatch.js";
import { createLog } from "../../logger/logger.js";
// type ArticleData = {
// id: string
// }
export const psiGetInventory = async (
avs: string,
startDate: string,
endDate: string
) => {
let articles: any = [];
if (!avs) {
return {
success: false,
message: `Missing av's please send at least one over`,
data: [],
};
}
const ids = avs.split(",").map((id) => id.trim());
const { data, error } = (await tryCatch(
db
.select()
.from(invHistoricalData)
.where(
and(
inArray(invHistoricalData.article, ids),
between(invHistoricalData.histDate, startDate, endDate)
)
)
//.limit(100)
)) as any;
if (error) {
createLog(
"error",
"datamart",
"datamart",
`There was an error getting the planning info: ${JSON.stringify(
error
)}`
);
return {
success: false,
messsage: `There was an error getting the planning info`,
data: error,
};
}
articles = data;
console.log(articles.length);
return {
success: true,
message: "PSI planning Data",
data: articles,
};
};

View File

@@ -0,0 +1,63 @@
import { tryCatch } from "../../../globalUtils/tryCatch.js";
import { createLog } from "../../logger/logger.js";
import { query } from "../../sqlServer/prodSqlServer.js";
import { planningNumbersByAVDate } from "../../sqlServer/querys/psiReport/planningNumbersByAv.js";
// type ArticleData = {
// id: string
// }
export const psiGetPlanningData = async (
avs: string,
startDate: string,
endDate: string
) => {
let articles: any = [];
if (!avs) {
return {
success: false,
message: `Missing av's please send at least one over`,
data: [],
};
}
const { data, error } = (await tryCatch(
query(
planningNumbersByAVDate
.replace("[articles]", avs)
.replace("[startDate]", startDate)
.replace("[endDate]", endDate),
"PSI planning info"
)
)) as any;
if (error) {
createLog(
"error",
"datamart",
"datamart",
`There was an error getting the planning info: ${JSON.stringify(
error
)}`
);
return {
success: false,
messsage: `There was an error getting the planning info`,
data: error,
};
}
articles = data.data;
return {
success: true,
message: "PSI planning Data",
data: articles.map((n: any) => {
if (n.PalDay) {
return { ...n, PalDay: n.PalDay.toFixed(2) };
}
return n;
}),
};
};

View File

@@ -0,0 +1,63 @@
import { tryCatch } from "../../../globalUtils/tryCatch.js";
import { createLog } from "../../logger/logger.js";
import { query } from "../../sqlServer/prodSqlServer.js";
import { productionNumbers } from "../../sqlServer/querys/psiReport/prodcuctionNumbers.js";
// type ArticleData = {
// id: string
// }
export const psiGetProductionData = async (
avs: string,
startDate: string,
endDate: string
) => {
let articles: any = [];
if (!avs) {
return {
success: false,
message: `Missing av's please send at least one over`,
data: [],
};
}
const { data, error } = (await tryCatch(
query(
productionNumbers
.replace("[articles]", avs)
.replace("[startDate]", startDate)
.replace("[endDate]", endDate),
"PSI production info"
)
)) as any;
if (error) {
createLog(
"error",
"datamart",
"datamart",
`There was an error getting the planning info: ${JSON.stringify(
error
)}`
);
return {
success: false,
messsage: `There was an error getting the planning info`,
data: error,
};
}
articles = data.data;
return {
success: true,
message: "PSI planning Data",
data: articles.map((n: any) => {
if (n.PalDay) {
return { ...n, PalDay: n.PalDay.toFixed(2) };
}
return n;
}),
};
};

View File

@@ -10,6 +10,9 @@ import addressCorrections from "./route/getCityStateData.js";
import fifoIndex from "./route/getFifoIndex.js"; import fifoIndex from "./route/getFifoIndex.js";
import financeAudit from "./route/getFinanceAudit.js"; import financeAudit from "./route/getFinanceAudit.js";
import psiArticleData from "./route/getPsiArticleData.js"; import psiArticleData from "./route/getPsiArticleData.js";
import psiPlanningData from "./route/getPsiPlanningData.js";
import psiProductionData from "./route/getPsiProductionData.js";
import psiInventory from "./route/getPsiinventory.js";
const app = new OpenAPIHono(); const app = new OpenAPIHono();
@@ -25,6 +28,9 @@ const routes = [
fifoIndex, fifoIndex,
financeAudit, financeAudit,
psiArticleData, psiArticleData,
psiPlanningData,
psiProductionData,
psiInventory,
] as const; ] as const;
const appRoutes = routes.forEach((route) => { const appRoutes = routes.forEach((route) => {

View File

@@ -0,0 +1,64 @@
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 { psiGetPlanningData } from "../controller/psiGetPlanningData.js";
const app = new OpenAPIHono({ strict: false });
const Body = z.object({
includeRunnningNumbers: z.string().openapi({ example: "x" }),
});
app.openapi(
createRoute({
tags: ["dataMart"],
summary: "Returns the psiarticleData.",
method: "get",
path: "/psiplanningdata",
request: {
body: {
content: {
"application/json": { schema: Body },
},
},
},
responses: responses(),
}),
async (c) => {
const q: any = c.req.queries();
// make sure we have a vaid user being accessed thats really logged in
apiHit(c, { endpoint: "/psiplanningdata" });
//console.log(articles["avs"][0]);
const { data, error } = await tryCatch(
psiGetPlanningData(
q["avs"] ? q["avs"][0] : null,
q["startDate"] ? q["startDate"][0] : null,
q["endDate"] ? q["endDate"][0] : null
)
);
if (error) {
console.log(error);
return c.json(
{
success: false,
message: "There was an error getting the planning.",
data: error,
},
400
);
}
//console.log(data);
return c.json(
{
success: data.success,
message: data.message,
data: data.data,
},
data.success ? 200 : 400
);
}
);
export default app;

View File

@@ -0,0 +1,64 @@
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 { psiGetProductionData } from "../controller/psiGetProductionData.js";
const app = new OpenAPIHono({ strict: false });
const Body = z.object({
includeRunnningNumbers: z.string().openapi({ example: "x" }),
});
app.openapi(
createRoute({
tags: ["dataMart"],
summary: "Returns the psiproductiondata.",
method: "get",
path: "/psiproductiondata",
request: {
body: {
content: {
"application/json": { schema: Body },
},
},
},
responses: responses(),
}),
async (c) => {
const q: any = c.req.queries();
// make sure we have a vaid user being accessed thats really logged in
apiHit(c, { endpoint: "/psiproductiondata" });
//console.log(articles["avs"][0]);
const { data, error } = await tryCatch(
psiGetProductionData(
q["avs"] ? q["avs"][0] : null,
q["startDate"] ? q["startDate"][0] : null,
q["endDate"] ? q["endDate"][0] : null
)
);
if (error) {
console.log(error);
return c.json(
{
success: false,
message: "There was an error getting the production.",
data: error,
},
400
);
}
//console.log(data);
return c.json(
{
success: data.success,
message: data.message,
data: data.data,
},
data.success ? 200 : 400
);
}
);
export default app;

View File

@@ -0,0 +1,64 @@
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 { psiGetInventory } from "../controller/psiGetInventory.js";
const app = new OpenAPIHono({ strict: false });
const Body = z.object({
includeRunnningNumbers: z.string().openapi({ example: "x" }),
});
app.openapi(
createRoute({
tags: ["dataMart"],
summary: "Returns the getPsiinventory.",
method: "get",
path: "/getpsiinventory",
request: {
body: {
content: {
"application/json": { schema: Body },
},
},
},
responses: responses(),
}),
async (c) => {
const q: any = c.req.queries();
// make sure we have a vaid user being accessed thats really logged in
apiHit(c, { endpoint: "/getpsiinventory" });
//console.log(articles["avs"][0]);
const { data, error } = await tryCatch(
psiGetInventory(
q["avs"] ? q["avs"][0] : null,
q["startDate"] ? q["startDate"][0] : null,
q["endDate"] ? q["endDate"][0] : null
)
);
if (error) {
console.log(error);
return c.json(
{
success: false,
message: "There was an error getting the production.",
data: error,
},
400
);
}
//console.log(data);
return c.json(
{
success: data.success,
message: data.message,
data: data.data,
},
data.success ? 200 : 400
);
}
);
export default app;

View File

@@ -27,7 +27,7 @@ export const deleteHistory = async () => {
.where( .where(
lte( lte(
invHistoricalData.histDate, invHistoricalData.histDate,
sql`(NOW() - INTERVAL '45 day')::date` sql`(NOW() - INTERVAL '365 day')::date`
) )
) )
); );

View File

@@ -7,6 +7,8 @@ import { postForecast } from "../postForecast.js";
import { query } from "../../../../../sqlServer/prodSqlServer.js"; import { query } from "../../../../../sqlServer/prodSqlServer.js";
import { activeArticle } from "../../../../../sqlServer/querys/dataMart/article.js"; import { activeArticle } from "../../../../../sqlServer/querys/dataMart/article.js";
import { addDays } from "date-fns"; import { addDays } from "date-fns";
import { sendEmail } from "../../../../../notifications/controller/sendMail.js";
import { createLog } from "../../../../../logger/logger.js";
let customerID = 4; let customerID = 4;
export const lorealForecast = async (data: any, user: any) => { export const lorealForecast = async (data: any, user: any) => {
@@ -111,6 +113,9 @@ export const lorealForecast = async (data: any, user: any) => {
); );
if (activeAV.length === 0) { if (activeAV.length === 0) {
if (typeof forcast.customerArticleNo === "number") {
missingSku.push(forcast);
}
continue; continue;
} }
@@ -181,6 +186,9 @@ export const lorealForecast = async (data: any, user: any) => {
); );
if (activeAV.length === 0) { if (activeAV.length === 0) {
if (typeof forcast.customerArticleNo === "number") {
missingSku.push(forcast);
}
continue; continue;
} }
@@ -190,6 +198,56 @@ export const lorealForecast = async (data: any, user: any) => {
//console.log(comForecast); //console.log(comForecast);
// email the for the missing ones
const missedGrouped = Object.values(
missingSku.reduce((acc: any, item: any) => {
const key = item.customerArticleNo;
if (!acc[key]) {
// first time we see this customer
acc[key] = item;
} else {
// compare dates and keep the earliest
if (
new Date(item.requirementDate) <
new Date(acc[key].requirementDate)
) {
acc[key] = item;
}
}
return acc;
}, {})
);
const emailSetup = {
email: "Blake.matthes@alpla.com; Stuart.Gladney@alpla.com; Harold.Mccalister@alpla.com; Jenn.Osbourn@alpla.com",
subject:
missedGrouped.length > 0
? `Alert! There are ${missedGrouped.length}, missing skus.`
: `Alert! There is a missing SKU.`,
template: "missingLorealSkus",
context: {
items: missedGrouped,
},
};
const { data: sentEmail, error: sendEmailError } = await tryCatch(
sendEmail(emailSetup)
);
if (sendEmailError) {
createLog(
"error",
"blocking",
"notify",
"Failed to send email, will try again on next interval"
);
return {
success: false,
message: "Failed to send email, will try again on next interval",
};
}
// if the customerarticle number is not matching just ignore it // if the customerarticle number is not matching just ignore it
const predefinedObject = { const predefinedObject = {
receivingPlantId: plantToken[0].value, receivingPlantId: plantToken[0].value,

View File

@@ -13,7 +13,7 @@ type Data = {
runningNr: string; runningNr: string;
lotNum: number; lotNum: number;
}; };
export const consumeMaterial = async (data: Data, prod: any) => { export const consumeMaterial = async (data: Data) => {
const { runningNr, lotNum } = data; const { runningNr, lotNum } = data;
// replace the rn // replace the rn
@@ -28,12 +28,7 @@ export const consumeMaterial = async (data: Data, prod: any) => {
barcode = r?.data; barcode = r?.data;
} catch (error) { } catch (error) {
console.log(error); console.log(error);
createLog( createLog("error", "", "logistics", `Error getting barcode: ${error}`);
"error",
prod.user.username,
"logistics",
`Error getting barcode: ${error}`
);
} }
if (barcode.length === 0) { if (barcode.length === 0) {

View File

@@ -51,33 +51,29 @@ app.openapi(
); );
} }
apiHit(c, { endpoint: "/consume", lastBody: data }); apiHit(c, { endpoint: "/consume", lastBody: data });
const authHeader = c.req.header("Authorization"); //const authHeader = c.req.header("Authorization");
const token = authHeader?.split("Bearer ")[1] || ""; //const token = authHeader?.split("Bearer ")[1] || "";
//const payload = await verify(token, process.env.JWT_SECRET!);
try { try {
const payload = await verify(token, process.env.JWT_SECRET!); //return apiReturn(c, true, access?.message, access?.data, 200);
try {
//return apiReturn(c, true, access?.message, access?.data, 200);
const consume = await consumeMaterial(data, payload); const consume = await consumeMaterial(data);
return c.json( return c.json(
{ success: consume?.success, message: consume?.message }, { success: consume?.success, message: consume?.message },
200 200
); );
} catch (error) {
//console.log(error);
//return apiReturn(c, false, "Error in setting the user access", error, 400);
return c.json(
{
success: false,
message: "Missing data please try again",
error,
},
400
);
}
} catch (error) { } catch (error) {
return c.json({ success: false, message: "Unauthorized" }, 401); //console.log(error);
//return apiReturn(c, false, "Error in setting the user access", error, 400);
return c.json(
{
success: false,
message: "Missing data please try again",
error,
},
400
);
} }
} }
); );

View File

@@ -57,6 +57,7 @@ app.openapi(
}); });
} }
console.log(silo);
return c.json({ return c.json({
success: silo.success, success: silo.success,
message: silo.message, message: silo.message,

View File

@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{{!-- <link rel="stylesheet" href="styles/styles.css" /> --}}
{{> styles}}
</head>
<body>
<p>All,</p>
<p>The below SKU's do not currently have an av and will be ignored in the forcast import.</p>
<p>The date and qty are the first time needed showing from teh vmi report</p>
<table >
<thead>
<tr>
<th>Customer Article Number</th>
<th>First Date Needed</th>
<th>Quantity</th>
</tr>
</thead>
<tbody>
{{#each items}}
<tr>
<td>{{customerArticleNo}}</td>
<td>{{requirementDate}}</td>
<td>{{quantity}}</td>
</tr>
{{/each}}
</tbody>
</table>
<div>
<p>Thank you,</p>
<p>LST Team</p>
</div>
</body>
</html>

View File

@@ -289,11 +289,13 @@ export const labelingProcess = async ({
"error", "error",
"labeling", "labeling",
"ocp", "ocp",
`There was an error booking in the label: ${book.data?.errors[0]?.message}` `There was an error booking in the label: ${JSON.stringify(
book.data
)}`
); );
return { return {
success: false, success: false,
message: `Error Booking in label: ${book.data?.errors[0]?.message}`, message: `Error Booking in label`,
data: book, data: book,
}; };
} }

View File

@@ -60,13 +60,47 @@ export const isMainMatStaged = async (lot: any) => {
// isStaged = true; // isStaged = true;
// } // }
type CheckConditionArgs = {
results: any[];
filterFn: (n: any) => boolean;
failCondition: (n: any) => boolean;
failMessage: string;
successMessage: string;
lot: { lot: string | number };
};
const checkCondition = ({
results,
filterFn,
failCondition,
failMessage,
successMessage,
lot,
}: CheckConditionArgs): { message: string; success: boolean } => {
const subset = results.filter(filterFn);
if (subset.some(failCondition)) {
const failing = subset.filter(failCondition);
return {
message: `lot: ${lot.lot}, is missing: ${failing
.map(
(o: any) =>
`${o.MaterialHumanReadableId} - ${o.MaterialDescription}`
)
.join(",\n ")} ${failMessage}`,
success: false,
};
} else {
return { message: successMessage, success: true };
}
};
createLog("info", "mainMaterial", "ocp", `Maint material query ran.`); createLog("info", "mainMaterial", "ocp", `Maint material query ran.`);
const mainMateiral = res.filter((n: any) => n.IsMainMaterial); const mainMaterial = res.find((n: any) => n.IsMainMaterial);
if (mainMaterial?.noMMShortage === "noMM") {
if (mainMateiral[0]?.noMaterialShortage === "noMM") { return {
isStaged = { message: `Main material: ${mainMaterial.MaterialHumanReadableId} - ${mainMaterial.MaterialDescription}: is not staged for ${lot.lot}`,
message: `Main material: ${mainMateiral[0].MaterialHumanReadableId} - ${mainMateiral[0].MaterialDescription}: is not staged for ${lot.lot} `,
success: false, success: false,
}; };
} }
@@ -75,56 +109,39 @@ export const isMainMatStaged = async (lot: any) => {
// for manual consume color if active to check colors // for manual consume color if active to check colors
const checkColorSetting = set.filter((n) => n.name === "checkColor"); const checkColorSetting = set.filter((n) => n.name === "checkColor");
// 2. Auto color
if (checkColorSetting[0].value === "1") { if (checkColorSetting[0].value === "1") {
const autoConsumeColor = res.filter( // auto check
(n: any) => // 2. Auto color
!n.IsMainMaterial && const autoColor = checkCondition({
!n.isManual && results: res,
n.noPKGShortage !== "pkgGood" && lot,
n.noPKGShortage !== "noPkg" filterFn: (n) =>
); n.isManual &&
if ( !("noPKGAutoShortage" in n) &&
autoConsumeColor.some( !("noPKGManualShortage" in n), // pool = non-main, auto
(n: any) => n.autoConsumeCheck === "autoConsumeNOK" failCondition: (n) => n.autoConsumeCheck === "autoConsumeNOK", // column = autoConsumeCheck
) failMessage: "for autoconsume",
) { successMessage: "auto color is good",
const onlyNOK = autoConsumeColor.filter( });
(n: any) => n.autoConsumeCheck === "autoConsumeNOK" if (!autoColor.success) return autoColor;
); console.log(autoColor);
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 // 3. Manual color
const manualConsumeColor = res.filter( const manualColor = checkCondition({
(n: any) => results: res,
lot,
filterFn: (n) =>
!n.IsMainMaterial && !n.IsMainMaterial &&
n.isManual && n.isManual &&
n.noPKGShortage !== "pkgGood" && !("noPKGAutoShortage" in n) &&
n.noPKGShortage !== "noPkg" !("noPKGManualShortage" in n), // pool = non-main, manual
); failCondition: (n) => n.noManualShortage === "noOK", // column = noManualShortage
if ( failMessage: "for manual material",
manualConsumeColor.some( successMessage: "manual color is good",
(n: any) => n.noManualShortage === "noOK" });
) if (!manualColor.success) return manualColor;
) { console.log(manualColor);
isStaged = {
message: `lot: ${lot.lot}, is missing: ${manualConsumeColor
.map(
(o: any) =>
`${o.MaterialHumanReadableId} - ${o.MaterialDescription}`
)
.join(",\n ")} for manual Material`,
success: false,
};
}
} else { } else {
createLog( createLog(
"info", "info",
@@ -137,11 +154,58 @@ export const isMainMatStaged = async (lot: any) => {
// // if we want to check the packaging // // if we want to check the packaging
const checkPKGSetting = set.filter((n) => n.name === "checkPKG"); const checkPKGSetting = set.filter((n) => n.name === "checkPKG");
if (checkPKGSetting[0].value === "1") { if (checkPKGSetting[0].value === "1") {
const packagingCheck = res.filter( const pkgAuto = checkCondition({
(n: any) => !n.IsMainMaterial && n.isManual results: res,
lot,
filterFn: (n) =>
!n.IsMainMaterial &&
!n.isManual &&
"noPKGAutoShortage" in n,
failCondition: (n) => n.noPKGAutoShortage === "noAutoPkg",
failMessage: "for pkg",
successMessage: "auto PKG is good",
});
if (!pkgAuto.success) return pkgAuto;
console.log(pkgAuto);
// 5. Packaging manual
const pkgManual = checkCondition({
results: res,
lot,
filterFn: (n) =>
!n.IsMainMaterial &&
n.isManual &&
"noPKGManualShortage" in n,
failCondition: (n) => n.noPKGManualShortage === "noManPkg",
failMessage: "for pkg",
successMessage: "manual PKG is good",
});
if (!pkgManual.success) return pkgManual;
console.log(pkgManual);
} else {
createLog(
"info",
"mainMaterial",
"ocp",
"PKG check is not active."
); );
if (packagingCheck.some((n: any) => n.noPKGShortage === "noPkg")) { }
isStaged = {
// manual pkg
if (checkPKGSetting[0].value === "1") {
const packagingCheck = res.filter(
(n: any) =>
!n.IsMainMaterial &&
n.isManual &&
"noPKGManualShortage" in n
);
if (
packagingCheck.some(
(n: any) => n.noPKGManualShortage === "noManPkg"
)
) {
return (isStaged = {
message: `lot: ${lot.lot}, is missing: ${packagingCheck message: `lot: ${lot.lot}, is missing: ${packagingCheck
.map( .map(
(o: any) => (o: any) =>
@@ -149,7 +213,7 @@ export const isMainMatStaged = async (lot: any) => {
) )
.join(",\n ")} for pkg`, .join(",\n ")} for pkg`,
success: false, success: false,
}; });
} }
} else { } else {
createLog( createLog(

View File

@@ -33,13 +33,13 @@ export const delieryInhouse = async (data: any) => {
"error", "error",
"labeling", "labeling",
"ocp", "ocp",
`${data.printer.name}, Error:${res.data.Message}` `${data.printer?.name}, Error:${res.data.Message}`
); );
//printerUpdate(data.printer, 7, "Error while deliverying inhouse."); //printerUpdate(data.printer, 7, "Error while deliverying inhouse.");
return { return {
success: true, success: true,
message: `${data.printer.name} had an error while trying to deliver.`, message: `${data.printer?.name} had an error while trying to deliver.`,
data: res.data, data: res.data,
}; };
} // label was just delivered } // label was just delivered

View File

@@ -23,7 +23,7 @@
export const mmQuery = ` export const mmQuery = `
use [test1_AlplaPROD2.0_Read] use [test1_AlplaPROD2.0_Read]
declare @lot as NVARCHAR(max) = [lotNumber] declare @lot as NVARCHAR(max) = [lotNumber]
/* /*
checks all needed material including pkg checks all needed material including pkg
@@ -52,7 +52,7 @@ MaterialHumanReadableId
,x.EffectiveConsumption as consumption -- this is how much was consummed via cmd 112 ,x.EffectiveConsumption as consumption -- this is how much was consummed via cmd 112
,x.TotalDemand as totalDemand -- the total demand needed to finish the lot out ,x.TotalDemand as totalDemand -- the total demand needed to finish the lot out
,case when cp.Pieces >= 0.001 then (lot.TotalProducedQuantity+1) * cp.Pieces else ,case when cp.Pieces >= 0.001 then (lot.TotalProducedLoadingUnits+1) * cp.Pieces else
(a.Weight *((case when cp.Percentage is null then 80 else cp.Percentage end) / 100) * ((lot.TotalProducedLoadingUnits+1) * p.LoadingUnitPieces)) / 1000 end totalNeeded (a.Weight *((case when cp.Percentage is null then 80 else cp.Percentage end) / 100) * ((lot.TotalProducedLoadingUnits+1) * p.LoadingUnitPieces)) / 1000 end totalNeeded
,case when IsMainMaterial = 1 then ,case when IsMainMaterial = 1 then
@@ -63,9 +63,12 @@ MaterialHumanReadableId
then 'mmGood' then 'mmGood'
else 'noMM' end else null end as noMMShortage else 'noMM' end else null end as noMMShortage
-- pkg check -- pkg check auto
,case when pkg.QuantityPosition is null then null else ,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 l.qty > ((lot.TotalProducedLoadingUnits+1) * pkg.QuantityPosition) and IsManualProcess = 0 then 'pkgAutoGood' else 'noAutoPkg' end) end as noPKGAutoShortage
-- plg check manual
,case when pkg.QuantityPosition is null then null else
(case when x.EffectiveConsumption > ((lot.TotalProducedLoadingUnits+1) * pkg.QuantityPosition) and IsManualProcess = 1 then 'pkgManGood' else 'noManPkg' end) end as noPKGManualShortage
-- manualMateiral -- manualMateiral
,case when IsMainMaterial = 0 and IsManualProcess = 1 then ,case when IsMainMaterial = 0 and IsManualProcess = 1 then
case when (case when x.ProvidedAmount <> 0 case when (case when x.ProvidedAmount <> 0
@@ -131,5 +134,7 @@ group by IdArtikelVarianten,ArtikelVariantenBez
) as l on ) as l on
l.IdArtikelVarianten = MaterialHumanReadableId l.IdArtikelVarianten = MaterialHumanReadableId
where lot.ProductionLotHumanReadableId = @lot where lot.ProductionLotHumanReadableId = @lot and MaterialDescription not like '%nopal%'
and MaterialDescription NOT LIKE '%bb%'
and MaterialDescription NOT LIKE '%mcg%'
`; `;

View File

@@ -1,33 +1,34 @@
export const planningNumbersByAVDate = ` export const planningNumbersByAVDate = `
use AlplaPROD_test1 use AlplaPROD_test1
declare @start_date nvarchar(30) = [startDate] --'2025-01-01' declare @start_date nvarchar(30) = '[startDate]' --'2025-01-01'
declare @end_date nvarchar(30) = [endDate] --'2025-08-09' declare @end_date nvarchar(30) = '[endDate]' --'2025-08-09'
/* /*
articles will need to be passed over as well as the date structure we want to see articles will need to be passed over as well as the date structure we want to see
*/ */
-- planned lots in planning select x.IdArtikelvarianten As Article,
select V_ProdLosProduktionJeProdTag_PLANNING.IdArtikelvarianten As Article,
ProduktionAlias as Description, ProduktionAlias as Description,
standort as MachineId, standort as MachineId,
MaschinenBezeichnung as MachineName, MaschinenBezeichnung as MachineName,
--MaschZyklus as PlanningCycleTime, --MaschZyklus as PlanningCycleTime,
V_ProdLosProduktionJeProdTag_PLANNING.IdProdPlanung as LotNumber, x.IdProdPlanung as LotNumber,
FORMAT(ProdTag, 'MM/dd/yyyy') as ProductionDay, FORMAT(ProdTag, 'MM/dd/yyyy') as ProductionDay,
V_ProdLosProduktionJeProdTag_PLANNING.planMenge as TotalPlanned, x.planMenge as TotalPlanned,
ProduktionMenge as QTYPerDay, ProduktionMenge as QTYPerDay,
round(ProduktionMengeVPK, 2) PalDay, round(ProduktionMengeVPK, 2) PalDay,
Status as finished Status as finished
--MaschStdAuslastung as nee --MaschStdAuslastung as nee
from dbo.V_ProdLosProduktionJeProdTag_PLANNING (nolock) from dbo.V_ProdLosProduktionJeProdTag_PLANNING (nolock) as x
left join left join
dbo.V_ProdPlanung (nolock) on dbo.V_ProdPlanung (nolock) as p on
V_ProdLosProduktionJeProdTag_PLANNING .IdProdPlanung = V_ProdPlanung.IdProdPlanung x.IdProdPlanung = p.IdProdPlanung
where V_ProdLosProduktionJeProdTag_PLANNING.IdArtikelvarianten in ([articles]) and ProdTag between @start_date and @end_date --and IdProdPlanung = 18442 where ProdTag between @start_date and @end_date
and p.IdArtikelvarianten in ([articles])
--and V_ProdLosProduktionJeProdTag_PLANNING.IdKunde = 10
--and IdProdPlanung = 18442
order by ProdTag order by ProdTag desc
`; `;

View File

@@ -1,8 +1,8 @@
export const productionNumbers = ` export const productionNumbers = `
use [test1_AlplaPROD2.0_Reporting] use [test1_AlplaPROD2.0_Reporting]
declare @startDate nvarchar(30) = [startDate] --'2024-12-30' declare @startDate nvarchar(30) = '[startDate]' --'2024-12-30'
declare @endDate nvarchar(30) = [endDate] --'2025-08-09' declare @endDate nvarchar(30) = '[endDate]' --'2025-08-09'
select MachineLocation, select MachineLocation,
ArticleHumanReadableId as article, ArticleHumanReadableId as article,

View File

@@ -0,0 +1,34 @@
export const planningNumbersByAVDate = `
use AlplaPROD_test1
declare @start_date nvarchar(30) = '[startDate]' --'2025-01-01'
declare @end_date nvarchar(30) = '[endDate]' --'2025-08-09'
/*
articles will need to be passed over as well as the date structure we want to see
*/
select x.IdArtikelvarianten As Article,
ProduktionAlias as Description,
standort as MachineId,
MaschinenBezeichnung as MachineName,
--MaschZyklus as PlanningCycleTime,
x.IdProdPlanung as LotNumber,
FORMAT(ProdTag, 'MM/dd/yyyy') as ProductionDay,
x.planMenge as TotalPlanned,
ProduktionMenge as QTYPerDay,
round(ProduktionMengeVPK, 2) PalDay,
Status as finished
--MaschStdAuslastung as nee
from dbo.V_ProdLosProduktionJeProdTag_PLANNING (nolock) as x
left join
dbo.V_ProdPlanung (nolock) as p on
x.IdProdPlanung = p.IdProdPlanung
where ProdTag between @start_date and @end_date
and p.IdArtikelvarianten in ([articles])
--and V_ProdLosProduktionJeProdTag_PLANNING.IdKunde = 10
--and IdProdPlanung = 18442
order by ProdTag desc
`;

View File

@@ -21,7 +21,7 @@ select ext.Barcode
,RunningNumber as runnungNumber ,RunningNumber as runnungNumber
,SsccEanRunningNumber as externalRunningNumber ,SsccEanRunningNumber as externalRunningNumber
,ArticleHumanReadableId ,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 LabelManagementHumanReadableId is null then (select HumanReadableId from [test1_AlplaPROD2.0_Read].[masterData].[LabelManagement] (nolock) where LabelMarkerId = 7 and Active = 1) else LabelManagementHumanReadableId end as labelLayout
,case when EinlagerungsMengeSum IS NULL then 'notOnStock' else 'onStock' end as stockStatus ,case when EinlagerungsMengeSum IS NULL then 'notOnStock' else 'onStock' end as stockStatus
from [test1_AlplaPROD2.0_Read].[labelling].[ExternalLabel] (nolock) as ext from [test1_AlplaPROD2.0_Read].[labelling].[ExternalLabel] (nolock) as ext