Compare commits
16 Commits
373178bf0d
...
90610c4ce2
| Author | SHA1 | Date | |
|---|---|---|---|
| 90610c4ce2 | |||
| d49c8807d0 | |||
| e31552374e | |||
| e16b26e313 | |||
| 265dd8ca7a | |||
| 62e78d2a30 | |||
| 68e577c476 | |||
| 2a05046bfd | |||
| 6f4e987ec4 | |||
| 92043d8118 | |||
| 63e09347bf | |||
| a7e1fcd3be | |||
| 356dd5a578 | |||
| 7ed29e7432 | |||
| 7e1a93512b | |||
| 71713937c7 |
30
LogisticsSupportTool_API_DOCS/LstV2/Auth/Login.bru
Normal file
30
LogisticsSupportTool_API_DOCS/LstV2/Auth/Login.bru
Normal 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
|
||||
}
|
||||
8
LogisticsSupportTool_API_DOCS/LstV2/Auth/folder.bru
Normal file
8
LogisticsSupportTool_API_DOCS/LstV2/Auth/folder.bru
Normal file
@@ -0,0 +1,8 @@
|
||||
meta {
|
||||
name: Auth
|
||||
seq: 2
|
||||
}
|
||||
|
||||
auth {
|
||||
mode: inherit
|
||||
}
|
||||
20
LogisticsSupportTool_API_DOCS/LstV2/DM/Forecast.bru
Normal file
20
LogisticsSupportTool_API_DOCS/LstV2/DM/Forecast.bru
Normal 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
|
||||
}
|
||||
8
LogisticsSupportTool_API_DOCS/LstV2/DM/folder.bru
Normal file
8
LogisticsSupportTool_API_DOCS/LstV2/DM/folder.bru
Normal file
@@ -0,0 +1,8 @@
|
||||
meta {
|
||||
name: DM
|
||||
seq: 1
|
||||
}
|
||||
|
||||
auth {
|
||||
mode: inherit
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
meta {
|
||||
name: Notifcations
|
||||
seq: 3
|
||||
}
|
||||
|
||||
auth {
|
||||
mode: inherit
|
||||
}
|
||||
12
LogisticsSupportTool_API_DOCS/LstV2/folder.bru
Normal file
12
LogisticsSupportTool_API_DOCS/LstV2/folder.bru
Normal file
@@ -0,0 +1,12 @@
|
||||
meta {
|
||||
name: LstV2
|
||||
seq: 3
|
||||
}
|
||||
|
||||
auth {
|
||||
mode: bearer
|
||||
}
|
||||
|
||||
auth:bearer {
|
||||
token: {{jwtV2}}
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
vars {
|
||||
url: https://usmcd1vms036.alpla.net
|
||||
url: http://localhost:4200
|
||||
session_cookie:
|
||||
urlv2: http://usksc1vms006:3000
|
||||
jwtV2:
|
||||
}
|
||||
vars:secret [
|
||||
v2Password
|
||||
]
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
||||
import express from "express";
|
||||
import morgan from "morgan";
|
||||
import { createServer } from "http";
|
||||
|
||||
@@ -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
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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" && (
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
};
|
||||
@@ -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({
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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-${
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
export const escapeXml = (str: string) => {
|
||||
if (!str) return "";
|
||||
return str
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """)
|
||||
.replace(/'/g, "'");
|
||||
};
|
||||
@@ -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",
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
111
lstV2/server/services/ocp/utils/printerDelayByLot.ts
Normal file
111
lstV2/server/services/ocp/utils/printerDelayByLot.ts
Normal 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);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -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
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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
|
||||
`;
|
||||
|
||||
Reference in New Issue
Block a user