Compare commits

...

16 Commits

Author SHA1 Message Date
90610c4ce2 feat(servers): cru added in to the server and dynamically updates vms036 2025-10-07 06:46:02 -05:00
d49c8807d0 chore(auth): cleanup unused imports 2025-10-07 06:45:12 -05:00
e31552374e fix(forecast button): added in energizer forcast 2025-10-07 06:44:37 -05:00
e16b26e313 chore(lstv2): cleanup to the main file 2025-10-07 06:44:11 -05:00
265dd8ca7a fix(printers): when reverting back to 90 seconds had a typo on what var to call 2025-10-07 06:43:47 -05:00
62e78d2a30 refactor(savexml): changes to the date section to look more clean 2025-10-07 06:43:17 -05:00
68e577c476 refactor(lots): rounded the time needed to print due to a weird issue with a decimal 2025-10-07 06:42:48 -05:00
2a05046bfd fix(labelprocessing): some strange lot issues to catch 2025-10-07 06:40:34 -05:00
6f4e987ec4 fix(xml saving): if the stirng has
\r we now flatten it so its proper and not create a new folder
2025-10-03 15:00:14 -05:00
92043d8118 fix(gp data): parsed the av instead of passing over as a string 2025-10-03 14:59:11 -05:00
63e09347bf refactor(printer delays): reduced the time formula from .9 to .7 to give a little more freedom 2025-10-03 14:58:40 -05:00
a7e1fcd3be feat(printer delay): printer delay option to grab the delay based off cycle time 2025-10-03 14:57:57 -05:00
356dd5a578 fix(ti imports): correction to the xml data with incorrect symbols passed over 2025-10-03 14:57:24 -05:00
7ed29e7432 feat(lstv2): energizer forecast added with new format 2025-10-02 08:58:43 -05:00
7e1a93512b fix(lottransfer): error in timing it would only allow for a 3min window 2025-10-02 07:48:33 -05:00
71713937c7 refactor(histoircal data): cahnge to not look at yestrday 2025-10-01 10:17:12 -05:00
35 changed files with 671 additions and 76 deletions

View File

@@ -0,0 +1,30 @@
meta {
name: Login
type: http
seq: 1
}
post {
url: {{urlv2}}/api/auth/login
body: json
auth: inherit
}
headers {
Content-Type: application/json
}
body:json {
{
"username": "matthes01",
"password": "{{v2Password}}"
}
}
script:post-response {
bru.setEnvVar("jwtV2",res.body.token)
}
settings {
encodeUrl: true
}

View File

@@ -0,0 +1,8 @@
meta {
name: Auth
seq: 2
}
auth {
mode: inherit
}

View File

@@ -0,0 +1,20 @@
meta {
name: Forecast
type: http
seq: 1
}
post {
url: {{urlv2}}/api/logistics/postforecastin
body: multipartForm
auth: inherit
}
body:multipart-form {
postForecast: @file(C:\Users\matthes01\Downloads\Rolling Forecast .xlsx)
fileType: energizer
}
settings {
encodeUrl: true
}

View File

@@ -0,0 +1,8 @@
meta {
name: DM
seq: 1
}
auth {
mode: inherit
}

View File

@@ -0,0 +1,15 @@
meta {
name: Active notifications
type: http
seq: 1
}
get {
url: {{urlv2}}/api/notify/activenotifications
body: none
auth: inherit
}
settings {
encodeUrl: true
}

View File

@@ -0,0 +1,8 @@
meta {
name: Notifcations
seq: 3
}
auth {
mode: inherit
}

View File

@@ -0,0 +1,12 @@
meta {
name: LstV2
seq: 3
}
auth {
mode: bearer
}
auth:bearer {
token: {{jwtV2}}
}

View File

@@ -10,12 +10,16 @@ post {
auth: inherit
}
headers {
Cookie: {{session_cookie}}
}
body:json {
{
"name": "Test Server",
"serverDNS": "USMCD1VMS036",
"plantToken": "test3",
"ipAddress": "10.193.0.56",
"name": "Bethlehem",
"serverDNS": "USBET1VMS006",
"plantToken": "usbet1",
"ipAddress": "10.204.0.26",
"greatPlainsPlantCode": 0,
"lstServerPort": 4000,
"serverLoc": "E$\\LST"

View File

@@ -5,11 +5,22 @@ meta {
}
patch {
url: {{url}}/lst/api/admin/server
body: none
url: {{url}}/lst/api/admin/server/:token
body: json
auth: inherit
}
params:path {
token: usbet1
}
body:json {
{
"zipcode": 45247
}
}
settings {
encodeUrl: true
}

View File

@@ -1,4 +1,9 @@
vars {
url: https://usmcd1vms036.alpla.net
url: http://localhost:4200
session_cookie:
urlv2: http://usksc1vms006:3000
jwtV2:
}
vars:secret [
v2Password
]

View File

@@ -1,3 +1,4 @@
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
import express from "express";
import morgan from "morgan";
import { createServer } from "http";

View File

@@ -5,9 +5,13 @@ import { requireAuth } from "../../pkg/middleware/authMiddleware.js";
import users from "./routes/getUserRoles.js";
import grantRoles from "./routes/grantRole.js";
import servers from "./routes/servers/serverRoutes.js";
import { restrictToHosts } from "../../pkg/middleware/restrictToHosts.js";
export const setupAdminRoutes = (app: Express, basePath: string) => {
app.use(
basePath + "/api/admin/server", // will pass bc system admin but this is just telling us we need this
servers
);
app.use(
basePath + "/api/admin/users",
requireAuth("user", ["systemAdmin"]), // will pass bc system admin but this is just telling us we need this
@@ -18,11 +22,4 @@ export const setupAdminRoutes = (app: Express, basePath: string) => {
requireAuth("user", ["systemAdmin", "admin"]), // will pass bc system admin but this is just telling us we need this
grantRoles
);
app.use(
basePath + "/api/admin/server",
requireAuth("user", ["systemAdmin", "admin"]), // will pass bc system admin but this is just telling us we need this
restrictToHosts(["usmcd1vms036", "USMCD1VMS036"]), // what servers are allowed to see the server section
servers
);
};

View File

@@ -9,6 +9,7 @@ import { tryCatch } from "../../../../pkg/utils/tryCatch.js";
import type { DrizzleError } from "drizzle-orm";
import axios from "axios";
import { createLogger } from "../../../../pkg/logger/logger.js";
import https from "https";
const router = Router();
@@ -43,6 +44,28 @@ router.post("/", async (req: Request, res: Response) => {
if (req.hostname === "localhost" && process.env.MAIN_SERVER) {
log.info({}, "Running in dev server about to add in a new server");
const axiosInstance = axios.create({
httpsAgent: new https.Agent({ rejectUnauthorized: false }),
baseURL: process.env.MAIN_SERVER, // e.g. "https://example.com"
withCredentials: true,
});
const loginRes = await axiosInstance.post(
`${process.env.MAIN_SERVER}/lst/api/auth/sign-in/username`,
{
username: process.env.MAIN_SERVER_USERNAME,
password: process.env.MAIN_SERVER_PASSWORD,
},
{
headers: { "Content-Type": "application/json" },
}
);
const setCookie = loginRes.headers["set-cookie"];
if (!setCookie) {
throw new Error("Did not receive a Set-Cookie header from login");
}
const { data, error } = await tryCatch(
axios.post(
`${process.env.MAIN_SERVER}/lst/api/admin/server`,
@@ -50,7 +73,7 @@ router.post("/", async (req: Request, res: Response) => {
{
headers: {
"Content-Type": "application/json",
Cookie: req.headers.cookie ?? "",
Cookie: setCookie.join("; "),
},
withCredentials: true,
}
@@ -63,7 +86,10 @@ router.post("/", async (req: Request, res: Response) => {
"There was an error adding the server to Main Server"
);
}
log.info({ stack: data }, "A new Server was just added to the server.");
log.info(
{ stack: data?.data },
"A new Server was just added to the server."
);
}
return res

View File

@@ -8,11 +8,21 @@ import { and, asc, eq } from "drizzle-orm";
const router = Router();
router.get("/", async (req: Request, res: Response) => {
const token = req.query.token;
const conditions = [];
if (token !== undefined) {
conditions.push(eq(serverData.plantToken, `${token}`));
}
conditions.push(eq(serverData.active, true));
const { data, error } = await tryCatch(
db
.select()
.from(serverData)
.where(eq(serverData.active, true))
.where(and(...conditions))
.orderBy(asc(serverData.name))
);

View File

@@ -2,11 +2,31 @@ import { Router } from "express";
import addServer from "./addServer.js";
import getServers from "./getServers.js";
import updateServer from "./updateServer.js";
import { restrictToHosts } from "../../../../pkg/middleware/restrictToHosts.js";
import { requireAuth } from "../../../../pkg/middleware/authMiddleware.js";
const router = Router();
router.get("/", getServers);
router.post("/", addServer);
router.patch("/", updateServer);
router.use("/", getServers);
router.use(
"/",
requireAuth("user", ["systemAdmin", "admin"]),
restrictToHosts([
"usmcd1vms036",
"USMCD1VMS036",
"https://usmcd1vms036.alpla.net",
]),
addServer
);
router.use(
"/",
requireAuth("user", ["systemAdmin", "admin"]),
restrictToHosts([
"usmcd1vms036",
"USMCD1VMS036",
"https://usmcd1vms036.alpla.net",
]),
updateServer
);
export default router;

View File

@@ -1,11 +1,135 @@
import { Router } from "express";
import type { Request, Response } from "express";
import { db } from "../../../../pkg/db/db.js";
import { serverData } from "../../../../pkg/db/schema/servers.js";
import { eq } from "drizzle-orm";
import { tryCatch } from "../../../../pkg/utils/tryCatch.js";
import axios from "axios";
import { createLogger } from "../../../../pkg/logger/logger.js";
import https from "https";
const router = Router();
router.patch("/", async (req: Request, res: Response) => {
router.patch("/:token", async (req: Request, res: Response) => {
const log = createLogger({ module: "admin", subModule: "update server" });
// when a server is updated and is posted from localhost or 127.0.0.1 we also want to post it to the test server so we can see it from there, we want to insert with update on conflict.
res.status(200).json({ message: "Server added" });
const token = req.params.token;
const updates: Record<string, any> = {};
if (req.body?.name !== undefined) {
updates.name = req.body.name;
}
if (req.body?.serverDNS !== undefined) {
updates.serverDNS = req.body.serverDNS;
}
if (req.body?.ipAddress !== undefined) {
updates.ipAddress = req.body.ipAddress;
}
if (req.body?.greatPlainsPlantCode !== undefined) {
updates.greatPlainsPlantCode = req.body.greatPlainsPlantCode;
}
if (req.body?.lstServerPort !== undefined) {
updates.lstServerPort = req.body.lstServerPort;
}
if (req.body?.serverLoc !== undefined) {
updates.serverLoc = req.body.serverLoc;
}
if (req.body?.streetAddress !== undefined) {
updates.streetAddress = req.body.streetAddress;
}
if (req.body?.cityState !== undefined) {
updates.cityState = req.body.cityState;
}
if (req.body?.zipcode !== undefined) {
updates.zipcode = req.body.zipcode;
}
if (req.body?.contactEmail !== undefined) {
updates.contactEmail = req.body.contactEmail;
}
if (req.body?.contactPhone !== undefined) {
updates.contactPhone = req.body.contactPhone;
}
if (req.body?.customerTiAcc !== undefined) {
updates.customerTiAcc = req.body.customerTiAcc;
}
if (req.body?.active !== undefined) {
updates.active = req.body.active;
}
try {
if (Object.keys(updates).length > 0) {
await db
.update(serverData)
.set(updates)
.where(eq(serverData.plantToken, token));
}
if (req.hostname === "localhost" && process.env.MAIN_SERVER) {
log.info({}, "Running in dev server about to add in a new server");
const axiosInstance = axios.create({
httpsAgent: new https.Agent({ rejectUnauthorized: false }),
baseURL: process.env.MAIN_SERVER,
withCredentials: true,
});
const loginRes = await axiosInstance.post(
`${process.env.MAIN_SERVER}/lst/api/auth/sign-in/username`,
{
username: process.env.MAIN_SERVER_USERNAME,
password: process.env.MAIN_SERVER_PASSWORD,
},
{
headers: { "Content-Type": "application/json" },
}
);
const setCookie = loginRes.headers["set-cookie"];
if (!setCookie) {
throw new Error(
"Did not receive a Set-Cookie header from login"
);
}
const { data, error } = await tryCatch(
axios.post(
`${process.env.MAIN_SERVER}/lst/api/admin/server/${token}`,
updates,
{
headers: {
"Content-Type": "application/json",
Cookie: setCookie.join("; "),
},
withCredentials: true,
}
)
);
if (error) {
log.error(
{ stack: error },
"There was an error adding the server to Main Server"
);
}
log.info(
{ stack: data?.data },
"A new Server was just added to the server."
);
}
res.status(200).json({ message: `${token} Server was just updated` });
} catch (error) {
console.log(error);
res.status(400).json({ message: "Error Server updated", error });
}
});
export default router;

View File

@@ -1,12 +1,8 @@
import { Router } from "express";
import type { Request, Response } from "express";
import z from "zod";
import { db } from "../../../pkg/db/db.js";
import { userRoles } from "../../../pkg/db/schema/user_roles.js";
import { DrizzleError, eq } from "drizzle-orm";
import { requireAuth } from "../../../pkg/middleware/authMiddleware.js";
import { auth } from "../../../pkg/auth/auth.js";
import { authClient } from "../../../pkg/auth/auth-client.js";
const router = Router();

View File

@@ -23,6 +23,10 @@ export default function DMButtons() {
/>
<ForecastImport fileType={"loreal"} name={"VMI Import"} />
<ForecastImport fileType={"pg"} name={"P&G"} />
<ForecastImport
fileType={"energizer"}
name={"Energizer Forecast"}
/>
</div>
)}
{plantToken[0]?.value === "usday1" && (
@@ -35,6 +39,10 @@ export default function DMButtons() {
fileType={"energizer"}
name={"Energizer Truck List"}
/>
<ForecastImport
fileType={"energizer"}
name={"Energizer Forecast"}
/>
</div>
)}
{plantToken[0]?.value === "usflo1" && (

View File

@@ -19,10 +19,7 @@ import rfid from "./services/rfid/rfidService.js";
import printers from "./services/printers/printerService.js";
import loggerService from "./services/logger/loggerService.js";
import ocpService from "./services/ocp/ocpService.js";
import { db } from "../database/dbclient.js";
import { settings } from "../database/schema/settings.js";
import os from "os";
import { tryCatch } from "./globalUtils/tryCatch.js";
import { sendEmail } from "./services/notifications/controller/sendMail.js";
import notify from "./services/notifications/notifyService.js";
import eom from "./services/eom/eomService.js";
@@ -33,7 +30,6 @@ import {
getSettings,
serverSettings,
} from "./services/server/controller/settings/getSettings.js";
import type { Settings } from "./types/settings.js";
// create the main prodlogin here
const username = "lst_user";

View File

@@ -26,7 +26,7 @@ export const historicalInvIMmport = async () => {
}
// check if we have data already for today this way we dont duplicate anything.
const today = new Date();
today.setDate(today.getDate() - 1);
//today.setDate(today.getDate() - 1);
const dateCheck = data?.filter(
(i: any) => i.histDate === format(today, "yyyy-MM-dd")
@@ -62,7 +62,8 @@ export const historicalInvIMmport = async () => {
const importInv = inv.data ? inv.data : [];
const eomImportData = importInv.map((i: any) => {
return {
histDate: sql`(NOW() - INTERVAL '1 day')::date`,
//histDate: sql`(NOW() - INTERVAL '1 day')::date`,
histDate: sql`(NOW())::date`,
plantToken: plantToken[0].value,
article: i.av,
articleDescription: i.Alias,

View File

@@ -1,3 +1,4 @@
import { energizerForecast } from "./mappings/energizer.js";
import { lorealForecast } from "./mappings/loralForecast.js";
import { pNgForecast } from "./mappings/pNgForecast.js";
import { standardForecast } from "./mappings/standardForcast.js";
@@ -40,6 +41,14 @@ export const forecastIn = async (data: any, user: any) => {
orderData = pg.data;
}
if (data["fileType"] === "energizer") {
//run the standard forecast in
const eg = await energizerForecast(data["postForecast"], user);
success = eg.success ?? false;
message = eg.message ?? "Error posting standard forecast";
orderData = eg.data;
}
return {
success,
message,

View File

@@ -0,0 +1,95 @@
import { db } from "../../../../../../../database/dbclient.js";
import { settings } from "../../../../../../../database/schema/settings.js";
import { tryCatch } from "../../../../../../globalUtils/tryCatch.js";
import XLSX from "xlsx";
import { postForecast } from "../postForecast.js";
import { query } from "../../../../../sqlServer/prodSqlServer.js";
import { activeArticle } from "../../../../../sqlServer/querys/dataMart/article.js";
import { addDays } from "date-fns";
import { sendEmail } from "../../../../../notifications/controller/sendMail.js";
import { createLog } from "../../../../../logger/logger.js";
export const energizerForecast = async (data: any, user: any) => {
/**
* Post a standard forecast based on the standard template.
*/
const { data: s, error: e } = await tryCatch(db.select().from(settings));
if (e) {
return {
success: false,
message: `Error getting settings`,
data: e,
};
}
const plantToken = s.filter((s) => s.name === "plantToken");
const arrayBuffer = await data.arrayBuffer();
const buffer = Buffer.from(arrayBuffer);
const workbook = XLSX.read(buffer, { type: "buffer" });
const sheet: any = workbook.Sheets["Sheet1"];
const range = XLSX.utils.decode_range(sheet["!ref"]);
const headers = [
"CustomerArticleNumber",
"Quantity",
"RequirementDate",
"CustomerID",
];
// formatting the data
const rows = XLSX.utils.sheet_to_json(sheet, { header: 1 }) as any;
const posting: any = [];
const customerId = 44;
for (let i = 1; i < rows.length; i++) {
const row: any = rows[i];
const material = row[0];
if (material == undefined) continue;
for (let j = 1; j < row.length; j++) {
const qty = row[j];
if (qty && qty !== 0) {
const requirementDate = rows[0][j]; // first row is dates
posting.push({
customerArticleNo: material,
quantity: qty,
requirementDate: new Date(requirementDate),
});
}
}
}
// the predefined data that will never change
const predefinedObject = {
receivingPlantId: plantToken[0].value,
documentName: `ForecastFromLST-${new Date(Date.now()).toLocaleString(
"en-US"
)}`,
sender: user.username || "lst-system",
customerId: customerId,
positions: [],
};
// add the new forecast to the predefined data
let updatedPredefinedObject = {
...predefinedObject,
positions: [...predefinedObject.positions, ...posting],
};
//post it
const forecastData: any = await postForecast(updatedPredefinedObject, user);
return {
success: forecastData.success,
message: forecastData.message,
data: forecastData.data,
};
};

View File

@@ -8,6 +8,7 @@ export const postForecast = async (data: any, user: any) => {
);
//console.log(endpoint);
//console.log(req.body.orders[0]);
try {
const results = await axios({

View File

@@ -55,7 +55,7 @@ export const consumeMaterial = async (data: Data) => {
"Content-Type": "application/json",
},
});
//console.log(results);
const { data: commandL, error: ce } = await tryCatch(
db.insert(commandLog).values({
commandUsed: "consumeMaterial",
@@ -68,6 +68,7 @@ export const consumeMaterial = async (data: Data) => {
status: results.status,
};
} catch (error: any) {
console.log(error);
return {
success: false,
status: 200,

View File

@@ -1,4 +1,5 @@
import { freightClass } from "../../../../../globalUtils/freightClass.js";
import { escapeXml } from "../../../utils/xmlCharFixes.js";
export const loadItems = async (data: any) => {
let itemGroups = "";
@@ -21,7 +22,9 @@ export const loadItems = async (data: any) => {
data[i].pkgHeight / 25.4
).toFixed(2)}</Dimension>
</Dimensions>
<Description>${`av ${data[i].article} ${data[i].articleAlias}`}</Description>
<Description>${`av ${data[i].article} ${escapeXml(
data[i].articleAlias
)}`}</Description>
<FreightClasses>
<FreightClass type="">${freightClass(
data[i].pkgWeight,

View File

@@ -14,6 +14,7 @@ import { loadItems } from "./loadItems.js";
import { dateCorrection } from "./dateCorrection.js";
import { scacCheck } from "./scacCodeCheck.js";
import { postToTi } from "./postToTI.js";
import { escapeXml } from "../../../utils/xmlCharFixes.js";
export const tiImport = async () => {
// get the plant token
@@ -224,21 +225,39 @@ export const tiImport = async () => {
// shipper info
payload = payload
.replaceAll("[plantName]", `Alpla ${plantI[0]?.sName!}`)
.replaceAll("[plantStreetAddress]", plantI[0]?.streetAddress!)
.replaceAll("[plantCity]", plantI[0]?.cityState!.split(",")[0])
.replaceAll("[plantState]", plantI[0]?.cityState!.split(",")[1])
.replaceAll("[plantZipCode]", plantI[0]?.zipcode!)
.replaceAll("[contactNum]", plantI[0]?.contactPhone!)
.replaceAll("[contactEmail]", plantI[0]?.contactEmail!)
.replaceAll("[plantName]", escapeXml(`Alpla ${plantI[0]?.sName!}`))
.replaceAll(
"[plantStreetAddress]",
escapeXml(plantI[0]?.streetAddress!)
)
.replaceAll(
"[plantCity]",
escapeXml(plantI[0]?.cityState!.split(",")[0])
)
.replaceAll(
"[plantState]",
escapeXml(plantI[0]?.cityState!.split(",")[1])
)
.replaceAll("[plantZipCode]", escapeXml(plantI[0]?.zipcode!))
.replaceAll("[contactNum]", escapeXml(plantI[0]?.contactPhone!))
.replaceAll("[contactEmail]", escapeXml(plantI[0]?.contactEmail!))
// customer info
.replaceAll("[customerName]", orderData[0].addressAlias)
.replaceAll("[customerStreetAddress]", orderData[0].streetAddress)
.replaceAll("[customerCity]", orderData[0].city.split(",")[0])
.replaceAll("[customerState]", orderData[0].city.split(",")[1])
.replaceAll("[customerZip]", orderData[0].zipCode)
.replaceAll("[customerPO]", orderData[0].Header)
.replaceAll("[customerName]", escapeXml(orderData[0].addressAlias))
.replaceAll(
"[customerStreetAddress]",
escapeXml(orderData[0].streetAddress)
)
.replaceAll(
"[customerCity]",
escapeXml(orderData[0].city.split(",")[0])
)
.replaceAll(
"[customerState]",
escapeXml(orderData[0].city.split(",")[1])
)
.replaceAll("[customerZip]", escapeXml(orderData[0].zipCode))
.replaceAll("[customerPO]", escapeXml(orderData[0].Header))
// .replaceAll(
// "[glCoding]",
// `52410-${

View File

@@ -2,21 +2,27 @@ import fs from "fs";
import path from "path";
import { createLog } from "../../logger/logger.js";
const cleanStringForFilename = (str: string) => {
// Remove CRLF and LF newlines
return str.replace(/(\r\n|\n|\r)/gm, " "); // or "" if you want no space at all
};
/**
* Save XML string to /xml/ with timestamp in name
* @param xmlContent The XML string
* @param prefix File prefix (ex: request or response)
*/
export const saveXml = (xmlContent: string, prefix: string = "request") => {
export const saveXml = (xmlContent: string, nameString: string = "request") => {
const prefix = cleanStringForFilename(nameString);
try {
const now = new Date();
// Format YYYYMMDDHHmm
const timestamp = `${now.getFullYear()}${String(
const timestamp = `${now.getFullYear()}-${String(
now.getMonth() + 1
).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")}-${String(
now.getHours()
).padStart(2, "0")}-${String(now.getMinutes()).padStart(2, "0")}`;
).padStart(2, "0")}${String(now.getMinutes()).padStart(2, "0")}`;
// Ensure xml folder path is always relative to project root
const xmlDir = path.resolve(process.cwd(), "xml");

View File

@@ -0,0 +1,9 @@
export const escapeXml = (str: string) => {
if (!str) return "";
return str
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&apos;");
};

View File

@@ -62,7 +62,7 @@ export const labelingProcess = async ({
(l: any) => l.MachineID === macId[0]?.HumanReadableId
);
if (filteredLot.length === 0) {
if (filteredLot?.length === 0) {
createLog(
"error",
"labeling",
@@ -85,7 +85,7 @@ export const labelingProcess = async ({
(l: any) => l.MachineID === macId[0]?.HumanReadableId
);
if (!filteredLot || filteredLot.length === 0) {
if (!filteredLot || filteredLot?.length === 0) {
createLog(
"error",
"labeling",
@@ -138,7 +138,7 @@ export const labelingProcess = async ({
let dualPrinting = settingData.filter((d) => d.name === "dualPrinting")[0]
?.value;
if (filteredLot.length > 1 && dualPrinting === "0") {
if (filteredLot?.length > 1 && dualPrinting === "0") {
createLog(
"error",
"labeling",
@@ -151,7 +151,7 @@ export const labelingProcess = async ({
};
}
if (filteredLot.length > 1 && dualPrinting === "1") {
if (filteredLot?.length > 1 && dualPrinting === "1") {
// send over for dual printing processing
createLog(
"info",
@@ -193,7 +193,7 @@ export const labelingProcess = async ({
}
// check if we actaully have a lot passed over so we do not error out again.
if (filteredLot.length === 0) {
if (filteredLot?.length === 0) {
createLog(
"error",
"labeling",
@@ -234,8 +234,8 @@ export const labelingProcess = async ({
// do we want to over run
if (
filteredLot[0].overPrinting === "no" &&
filteredLot[0].Remaining <= 0
filteredLot[0]?.overPrinting === "no" &&
filteredLot[0]?.Remaining <= 0
) {
createLog(
"error",

View File

@@ -88,7 +88,7 @@ export const lotMaterialTransfer = async (data: NewLotData) => {
// shift split
const shiftTimeSplit = shift?.data[0]?.shiftChange.split(":");
//console.log(shiftTimeSplit);
console.log(parseInt(shiftTimeSplit[0]) - 1);
// Current time
const now = new Date();
@@ -97,12 +97,14 @@ export const lotMaterialTransfer = async (data: NewLotData) => {
now.getFullYear(),
now.getMonth(),
1, //now.getDate(),
shiftTimeSplit.length > 0 ? parseInt(shiftTimeSplit[0]) - 1 : 5, // this will parse the hour to remove teh zero
shiftTimeSplit.length > 0 ? parseInt(shiftTimeSplit[1]) + 3 : 3,
shiftTimeSplit.length > 0 ? parseInt(shiftTimeSplit[0]) : 5, // this will parse the hour to remove teh zero
shiftTimeSplit.length > 0 ? parseInt(shiftTimeSplit[1]) : 3,
0,
0
);
console.log("target", target.toLocaleString(), "Now", now.toLocaleString());
// to early time
const early = new Date(
now.getFullYear(),
@@ -114,6 +116,8 @@ export const lotMaterialTransfer = async (data: NewLotData) => {
0
);
console.log("early", early.toLocaleString(), "Now", now.toLocaleString());
// next month just to be here
const nextMonth = new Date(
now.getFullYear(),
@@ -125,6 +129,13 @@ export const lotMaterialTransfer = async (data: NewLotData) => {
0
);
console.log(
"nextMonth",
nextMonth.toLocaleString(),
"Now",
now.toLocaleString()
);
// console.log(early, target);
// if we are to early return early only if we are sending over eom
if (data.type === "eom" && (early > now || target < now)) {

View File

@@ -6,11 +6,13 @@ import { tryCatch } from "../../../globalUtils/tryCatch.js";
import { getLots } from "../controller/lots/lots.js";
import { getPrinters } from "../controller/printers/getPrinters.js";
import { createLog } from "../../logger/logger.js";
import { printerDelayByLot } from "./printerDelayByLot.js";
export const assignedPrinters = async () => {
createLog("debug", "ocp", "ocp", "Lot assignment check");
const { data: lot, error: lotError } = await tryCatch(getLots());
const l: any = lot;
if (lotError) {
return {
success: false,
@@ -41,6 +43,9 @@ export const assignedPrinters = async () => {
data: [],
};
}
// update the printers if we have the setting checked
printerDelayByLot(l.data);
const { data: print, error: printerError } = await tryCatch(getPrinters());
if (printerError) {

View File

@@ -0,0 +1,111 @@
import { eq, sql } from "drizzle-orm";
import { db } from "../../../../database/dbclient.js";
import { printerData } from "../../../../database/schema/printers.js";
import { settings } from "../../../../database/schema/settings.js";
import { tryCatch } from "../../../globalUtils/tryCatch.js";
import { createLog } from "../../logger/logger.js";
import { delay } from "../../../globalUtils/delay.js";
import { getPrinters } from "../controller/printers/getPrinters.js";
//**The logic here will be when the setting is active to utilize the lots times it will update the printDelay in the printer data table */
export const printerDelayByLot = async (lot: any) => {
const { data: settingData, error: settingError } = await tryCatch(
db.select().from(settings)
);
if (settingError) {
return {
success: false,
message: "There was an error getting the settings.",
settingError,
};
}
// get the plantToken
const printDelay = settingData.filter((n) => n.name === "lotPrintDelay");
const ignorePrinters = [
"Autolabeler",
"pdf24",
"PDF24",
"zecchetti_1",
"zecchetti2",
];
const printers = (await getPrinters()) as any;
const p = printers.data;
if (printDelay[0].value === "0") {
for (let i = 0; i < p.length; i++) {
if (p[i].printDelay > 90) {
if (ignorePrinters.includes(p[i].name)) continue;
const { data, error } = await tryCatch(
db
.update(printerData)
.set({
printDelay: "90",
upd_date: sql`NOW()`,
})
.where(
eq(printerData.humanReadableId, lot[i].printerID)
)
);
// if (data) {
// createLog(
// "info",
// "printers",
// "ocp",
// `${printerData.name} had its delay time updated to 90 seconds `
// );
// }
// if (error) {
// createLog(
// "error",
// "printers",
// "ocp",
// `${printerData.name} encountered an error updating the printer delay time `
// );
// }
await delay(500);
}
}
}
if (printDelay[0].value === "1") {
for (let i = 0; i < lot.length; i++) {
if (ignorePrinters.includes(lot[i].PrinterName)) continue;
const { data, error } = await tryCatch(
db
.update(printerData)
.set({
printDelay: lot[i].timeTOmakeInSeconds,
upd_date: sql`NOW()`,
})
.where(eq(printerData.humanReadableId, lot[i].printerID))
);
// if (data) {
// createLog(
// "info",
// "printers",
// "ocp",
// `${lot[i].PrinterName} had its delay time updated to ${lot[
// i
// ].timeTOmakeInSeconds.toFixed(2)} seconds `
// );
// }
// if (error) {
// createLog(
// "error",
// "printers",
// "ocp",
// `${lot[i].PrinterName} encountered an error updating the printer delay time `
// );
// }
await delay(500);
}
}
};

View File

@@ -280,6 +280,14 @@ const newSettings = [
serviceBelowsTo: "admin",
roleToChange: "admin",
},
{
name: "lotPrintDelay",
value: `0`,
description:
"Changes the print delay to be based on the pallet completion time",
serviceBelowsTo: "admin",
roleToChange: "admin",
},
];
export const areSettingsIn = async () => {
// get the roles

View File

@@ -81,10 +81,11 @@ export const runGPQuery = async (gpCheck: GPCheck) => {
PO: n.PO.trim(),
Supplier: n.Supplier.trim(),
Item: n.Item.trim(),
article:
n.Item.split("-").length > 1
? n.Item.split("-")[1].trim()
: "No article",
// article:
// n.Item.split("-").length > 1
// ? n.Item.split("-")[1].trim()
// : 0,
article: Number.parseInt(n.Item.split("-")[1]) || 0,
Type: n.Type.trim(),
Location: n.Location.trim(),
Date_Recived: format(n.Date_Recived, "M/d/yyyy"),

View File

@@ -1,14 +1,14 @@
export const lotQuery = `
select IdMaschinen_ProdPlanung as LabelOnlineID,
IdMaschine as machineID,
x.IdMaschine as machineID,
MaschinenStandort as MachineLocation,
MaschinenBez as MachineDescription,
IdProdPlanung as lot,
x.IdProdPlanung as lot,
prolink.lot as ProlinkLot,
IdArtikelvarianten as AV,
ArtikelVariantenBez as Alias,
convert(varchar, add_date, 20) as Add_Date,
Add_user,
x.IdArtikelvarianten as AV,
x.ArtikelVariantenBez as Alias,
convert(varchar, x.add_date, 20) as Add_Date,
x.Add_user,
idEtikettenDrucker as printerID,
b.name as PrinterName,
CAST(TotalPlannedLoadingUnits as float) as PlannedQTY,
@@ -23,21 +23,26 @@ select IdMaschinen_ProdPlanung as LabelOnlineID,
else 'no' end as overPrinting,
CustomerHumanReadableId as CustomerId,
CustomerName as CustomerName,
idMaschine as MachineID,
x.idMaschine as MachineID,
prolink.lastProlinkUpdate as lastProlinkUpdate,
IdEtikettenLayoutPalette as palletLabel,
AnzahlKopienPalette as pallerCopies,
IdEtikettenLayoutKarton as cartonLabel,
AnzahlKopienKarton as cartonCopies,
IsTechnicallyReleased
IsTechnicallyReleased,
DruckStatus as allowPrinting,
p.MaschZyklus as cycleTime,
x.StueckzahlJePalette,
p.WerkzeugKavität,
ROUND((((x.StueckzahlJePalette /p.WerkzeugKavität) * p.MaschZyklus) * (p.MaschAuslastung/100)) * .75,0) as timeTOmakeInSeconds
--*
from AlplaPROD_test1.dbo.V_Maschinen_ProdPlanungen x (nolock)
join
[test1_AlplaPROD2.0_Read].[productionControlling].[ProducedLot] on
[test1_AlplaPROD2.0_Read].[productionControlling].[ProducedLot](nolock) on
x.IdProdPlanung =
[test1_AlplaPROD2.0_Read].[productionControlling].[ProducedLot].ProductionLotHumanReadableId
left join
[test1_AlplaPROD2.0_Read].masterData.Printer as b on
[test1_AlplaPROD2.0_Read].masterData.Printer (nolock) as b on
x.IdEtikettenDrucker = b.HumanReadableId
-- adding in prolink lot
left join
@@ -51,5 +56,16 @@ select IdMaschinen_ProdPlanung as LabelOnlineID,
) as prolink on
x.idMaschine = prolink.prolinkMachineId
where IsTechnicallyReleased = 1
----packagin info
--left join
--[test1_AlplaPROD2.0_Read].[masterData].[PackagingInstruction] (nolock) pkg on
--pkg.HumanReadableId = x.IdVpkVorschrift
-- cycle time info
left join
AlplaPROD_test1.dbo.V_ProdPlanung (nolock) as p on
p.IdProdPlanung = x.IdProdPlanung
where IsTechnicallyReleased = 1 and DruckStatus = 1
`;