Compare commits

..

66 Commits

Author SHA1 Message Date
dcfa56bdb9 fix(notify): fixed to plantto plant that would cause multiple emails to be sent and never update 2026-03-11 15:30:53 -05:00
ea92422bb1 feat(notification): plant to plant edi 2026-03-10 08:18:29 -05:00
2111a5fdc9 refactor(sql): changes to improve the job disable 2026-02-18 08:53:19 -06:00
6edd20585f refactor(stats): added in mastermacro version 2026-02-18 08:52:29 -06:00
a9759795c4 fix(scripts): changed the fake scanning to be more readable 2026-02-16 19:15:32 -06:00
32f26a1725 fix(quality): hoping to finally find the bud that kills me everynight 2026-02-16 19:05:41 -06:00
60533beed5 feat(sql): job disabling scripts 2026-02-16 19:05:08 -06:00
24ced97b6d feat(notification): added cycle count check 2026-02-16 19:04:38 -06:00
dc1d342799 fix(scanner): if host or port not sent over stop the connection right away 2026-02-16 19:04:04 -06:00
44d0cb63cf refactor(sql): moved new queries to there own folder to make it more easy to work and migrate 2026-02-16 19:01:23 -06:00
ace73fa919 refactor(sendmail): updated the smtp per alpla needs 2026-02-16 18:59:12 -06:00
316af4233f refactor(stats): added sheet version check in 2026-02-16 18:58:17 -06:00
36a805c652 refactor(scripts): create finance bol 2026-02-16 09:40:19 -06:00
460bc3d24a feat(query selector): queryselector from file based vs cp to ts filesz 2026-02-16 09:40:00 -06:00
ec201fcfb5 refactor(sql): full changes to localhost if on produciton server 2026-02-16 09:39:35 -06:00
914ad46c43 refactor(sql server): changes to look at localhost if in production 2026-02-16 09:38:55 -06:00
b96c546ed3 refactor(notify): changed to only allow max 100 errors in the email 2026-02-16 09:38:31 -06:00
29b3be41a1 build(notification): fixed fifo index ts errors 2026-02-16 09:38:10 -06:00
16edf58025 refactor(eom): changes to hist inv 2026-02-16 09:37:40 -06:00
775627f215 feat(scanner): tcp scanner connection based on env var no more db stuff 2026-02-16 09:37:14 -06:00
4e70fae69b refactor(api docs): added/changed docs 2026-02-16 09:36:44 -06:00
24dd109a21 fix(commandlog): changes to the log table 2026-02-13 16:08:23 -06:00
38b57a00cc refactor(datamart): article changes to add pet-g 2026-02-13 16:03:26 -06:00
f8070db95f fix(sqlserver): changed to proper pool connection 2026-02-13 16:02:43 -06:00
10e9dc430c fix(notification): limited to 1000 max errors 2026-02-13 15:59:38 -06:00
6b669ccd9c fix(labelinfo): corrected the query on label info for external 2026-02-13 14:51:15 -06:00
d9a10d98a1 refactor(sendmail): change the send mail function from noreply to donotreply 2026-02-13 14:50:44 -06:00
e64dc7c013 refactor(ocp): removed zechetti 2 from this silly thing for now 2026-02-13 14:50:07 -06:00
d63138d746 helper scripts 2026-02-03 15:40:51 -06:00
84a28f2d01 added relocate 2026-02-03 15:40:41 -06:00
9be6614972 fix(ocp): more material check work 2026-01-19 07:50:27 -06:00
9d0db71f6a fix(datamart): psiPlanning was looking at thertical but a rare case this would look at last years da
and be missed and not pull correct data, switched to plan end
2026-01-15 13:28:18 -06:00
3cc55436f3 refactor(psi): old planning numbers to revert back to maybe 2026-01-08 20:11:40 -06:00
124fde07e0 refactor(psi): planning numbers refactored to deal with a bad downsync that caused negative numbers 2026-01-08 20:08:31 -06:00
b15d0d7322 refactor(datamart): delivery by date range updates 2026-01-08 20:08:03 -06:00
0680f332fb refactor(manual print): added new option for mulitple tags on pallet 2026-01-08 20:07:28 -06:00
46bf310dce refactor(datamart): changed the getDelbyDateRange to the new 2.0 way 2026-01-05 15:17:15 -06:00
0dda6ae744 fix(notifications): fixed a type in the alert being sent out only showing 1 alert instead of many 2026-01-05 10:27:09 -06:00
1b59cdd3a4 fix(psi): correcrtions to account for the tiem offset in the psi 2026-01-02 11:07:45 -06:00
56934216f7 fix(sql): fix connection issues in the sql connection loosing it 2025-12-31 07:54:26 -06:00
e8a2ef8b85 refactor(ocp): plc reading changes to disconnect and reconnect
it was found that there were some errors that spammed the log and caused the server to actually stop
responding and crash weirdly so added a disconnect and reconnect back. so we can figure out whats
going on.
2025-12-30 10:55:28 -06:00
6cbffa4ac5 feat(notification): error monitoring
if there are more than 10 errors in a 15min window sends email to alert someone
2025-12-30 10:54:09 -06:00
09f16f4e62 refactor(datamart): added in 2 new queroes 2025-12-30 08:43:03 -06:00
461acb2b16 fix(datamart): removed limitation on inhousedelivery 2025-12-30 07:21:40 -06:00
0d05c66a2b fix(quality): changes to the logging to reduce un nessasary logging 2025-12-30 07:13:20 -06:00
096cc18477 refactor(datamart): psi work 2025-12-30 07:12:38 -06:00
f3333ce020 fix(dm): abbott truck time corrections 2025-12-18 08:47:12 -06:00
8e3d2b3d95 fix(dm): new scj custom mapping added for westbend 2025-12-12 10:53:33 -06:00
501709546d feat(dm): abbott trucklist will do orders and forecast now 2025-12-11 15:56:34 -06:00
2b5e77993b test(dm): starts on abbot forecast to be brought over from the original truck list 2025-12-11 14:43:50 -06:00
6efaffbb17 fix(printers): add null case for the printerID 2025-12-11 14:43:22 -06:00
90ddbca2e7 fix(rfid): changes to log all reads and also replace some trailing text from a hex 2025-12-11 14:42:51 -06:00
7a9ea16f48 fix(dm): energizer forecast to correct the date and qty push over 2025-12-11 14:42:22 -06:00
420826de9b fix(frontend): transfer lots style adjustment 2025-12-11 14:41:48 -06:00
dc2d3718fa fix(dm): energizer orders missing remark 2025-12-11 14:41:22 -06:00
5013228384 feat(inhouse): delivery by pallet and lot added 2025-12-08 13:16:23 -06:00
4459742cf0 feat(datamart): inhouse delivery added 2025-12-08 13:15:59 -06:00
070c3ee975 fix(mainmaterial): added missing return 2025-12-08 13:15:37 -06:00
8ac92888ad test(mobile): keyence added 2025-12-08 08:37:25 -06:00
567579ef35 fix(transfers): corrected to be a int vs float 2025-12-08 08:37:07 -06:00
8d90f27514 fix(rfid): corrected the link to reset 2025-12-08 08:36:47 -06:00
722b23a321 fix(rfid): changed the tag reading to have a little more flexable 2025-12-08 08:36:25 -06:00
ba48c5307f style(transfer to next lot): spelling issue 2025-12-08 08:35:22 -06:00
30d2ec0477 fix(materials): if no machine stop the check and fail so it manual needs tried again 2025-12-08 08:34:52 -06:00
d3c6444491 chore(release): 1.9.0 2025-12-02 18:30:54 -06:00
12345c0b64 fix(commands): corrections to allow external labels to be consumed and transfered 2025-12-02 18:29:30 -06:00
112 changed files with 8160 additions and 2295 deletions

View File

@@ -49,12 +49,15 @@
"go.formatTool": "goimports",
"cSpell.words": [
"acitve",
"actaully",
"alpla",
"alplamart",
"alplaprod",
"autoconsume",
"intiallally",
"ppoo",
"prodlabels"
"prodlabels",
"rfid"
],
"gitea.token": "8456def90e1c651a761a8711763d6ef225d6b2db",
"gitea.instanceURL": "https://git.tuffraid.net",

View File

@@ -1,5 +1,37 @@
# All Changes to LST can be found below.
## [1.9.0](https://git.tuffraid.net/cowch/lst/compare/v1.8.0...v1.9.0) (2025-12-03)
### 📝 Chore
* **module updates:** just updated all the modules ([bdb4bfc](https://git.tuffraid.net/cowch/lst/commits/bdb4bfc53d24f37f0e7098ea828cf418d58d5224))
### 🌟 Enhancements
* **datamart:** active article moved over to the new version ([8e7f1eb](https://git.tuffraid.net/cowch/lst/commits/8e7f1eb09811fcf3ea49b95b0ba9a8f55b9c4184))
* **dm:** added article description into the historical data ([7311372](https://git.tuffraid.net/cowch/lst/commits/7311372ba8eb901b51972ca216152bcfc2b009af))
* **swagger:** added in the start of swagger where all the common and useable endpoints will be ([2607fd3](https://git.tuffraid.net/cowch/lst/commits/2607fd3026ed0b5777a5598aa3498ffc67baa012))
### 🛠️ Code Refactor
* **contorller:** only install npm production modules dont install everything ([c1816c0](https://git.tuffraid.net/cowch/lst/commits/c1816c07ff5ac939b0997d314a9da624a4a66b7a))
* **helpercommands:** removed the remove as reusabele ([a3dba6c](https://git.tuffraid.net/cowch/lst/commits/a3dba6cc9db147ff4765fef648867e50878a6ac8))
* **quality:** added a check to monior [#7](https://git.tuffraid.net/cowch/lst/issues/7) as well ([6833dfc](https://git.tuffraid.net/cowch/lst/commits/6833dfc9929741203083b01726b83a6c8d61d308))
* **sql:** some changes to help with sql connection on random disconnect ([320dd47](https://git.tuffraid.net/cowch/lst/commits/320dd47aea017b4ff219b07e363ef87ec8523b82))
* **swagger:** corrected the name displaced ([d605225](https://git.tuffraid.net/cowch/lst/commits/d605225e48bca66f915ce0db448aa61933891986))
### 🐛 Bug fixes
* **commands:** corrections to allow external labels to be consumed and transfered ([12345c0](https://git.tuffraid.net/cowch/lst/commits/12345c0b6442c3abd309f660bb43216def9abb89))
* **dm:** type in customer article number ([f226c56](https://git.tuffraid.net/cowch/lst/commits/f226c5644cc2b93b9d967962bd6f82b3e506c8c0))
* **labeling:** added in a catch to avoid rouge lots ([59c6fd0](https://git.tuffraid.net/cowch/lst/commits/59c6fd011728dff50bfa3233d6095c396d0b1999))
* **lot transfer:** changes to make it so the reprint and return do not happen instantly ([ac27a28](https://git.tuffraid.net/cowch/lst/commits/ac27a286c07733333703d8421cfa525691363e54))
* **lstv2:** added in a close function to stop crashing the server ([712a6ee](https://git.tuffraid.net/cowch/lst/commits/712a6eebdfef0ce2b99155d23422ddc7e5e0daad))
## [1.8.0](https://git.tuffraid.net/cowch/lst/compare/v1.7.0...v1.8.0) (2025-11-25)

View File

@@ -0,0 +1,16 @@
meta {
name: Error logging
type: http
seq: 4
}
get {
url: {{urlv2}}/api/notify/toomanyerrors
body: none
auth: inherit
}
settings {
encodeUrl: true
timeout: 0
}

View File

@@ -0,0 +1,22 @@
meta {
name: sscc
type: http
seq: 4
}
post {
url: {{url}}/lst/old/api/logistics/getsscc
body: json
auth: inherit
}
body:json {
{
"runningNr": ""
}
}
settings {
encodeUrl: true
timeout: 0
}

View File

@@ -0,0 +1,20 @@
meta {
name: PSI - Forecast data
type: http
seq: 1
}
get {
url: {{url}}/lst/old/api/datamart/psiforecastdata?customer=8
body: none
auth: inherit
}
params:query {
customer: 8
}
settings {
encodeUrl: true
timeout: 0
}

View File

@@ -0,0 +1,22 @@
meta {
name: PSI -planning data
type: http
seq: 2
}
get {
url: {{url}}/lst/old/api/datamart/psiplanningdata?avs=118,120&startDate=12/1/2025&endDate=12/31/2026
body: none
auth: inherit
}
params:query {
avs: 118,120
startDate: 12/1/2025
endDate: 12/31/2026
}
settings {
encodeUrl: true
timeout: 0
}

View File

@@ -5,11 +5,22 @@ meta {
}
get {
url:
url: {{url}}/lst/old/api/logger/logs?service=ocp&service=rfid&service=dyco&level=error&level=info&level=warn&hours=12
body: none
auth: inherit
}
params:query {
service: ocp
service: rfid
service: dyco
level: error
level: info
level: warn
hours: 12
}
settings {
encodeUrl: true
timeout: 0
}

View File

@@ -0,0 +1,23 @@
meta {
name: Consume
type: http
seq: 1
}
post {
url: {{url}}/lst/old/api/logistics/consume
body: json
auth: inherit
}
body:json {
{
"lotNum":283559,
"runningNr":19302907
}
}
settings {
encodeUrl: true
timeout: 0
}

View File

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

View File

@@ -0,0 +1,16 @@
meta {
name: SSCC
type: http
seq: 2
}
get {
url: {{url}}/lst/api/logistics/getsscc
body: none
auth: inherit
}
settings {
encodeUrl: true
timeout: 0
}

View File

@@ -1,6 +1,6 @@
{
"version": "1",
"name": "LogisticsSupportTool_API_DOCS",
"name": "lstv2",
"type": "collection",
"ignore": [
"node_modules",

View File

@@ -1,5 +1,5 @@
vars {
url: https://usday1prod.alpla.net
url: http://localhost:5500
session_cookie:
urlv2: http://usbow1vms006:3000
jwtV2:

View File

@@ -0,0 +1,24 @@
meta {
name: bookout
type: http
seq: 2
}
post {
url: {{url}}/lst/old/api/logistics/bookout
body: json
auth: none
}
body:json {
{
"runningNr": "1865027",
"reason": "packer printed premature"
}
}
settings {
encodeUrl: true
timeout: 0
}

View File

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

View File

@@ -0,0 +1,24 @@
meta {
name: relocate
type: http
seq: 1
}
post {
url: {{url}}/lst/old/api/logistics/relocate
body: json
auth: inherit
}
body:json {
{
"runningNr": "56121541",
"laneID": "30006"
}
}
settings {
encodeUrl: true
timeout: 0
}

View File

@@ -0,0 +1,24 @@
meta {
name: removeAsWaste
type: http
seq: 3
}
post {
url: {{url}}/lst/old/api/logistics/removeasreusable
body: json
auth: none
}
body:json {
{
"runningNr": "1865018",
"reason": "validating stockout"
}
}
settings {
encodeUrl: true
timeout: 0
}

View File

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

View File

@@ -0,0 +1,16 @@
meta {
name: tester
type: http
seq: 1
}
post {
url: http://localhost:3000/lst/api/system/prodsql/start
body: none
auth: inherit
}
settings {
encodeUrl: true
timeout: 0
}

View File

@@ -78,7 +78,7 @@ const main = async () => {
// connect to the prod sql
console.log("Connecting to the sql server");
await initializeProdPool();
// express app
const app = express();
@@ -184,7 +184,7 @@ const main = async () => {
// swaggerUi.serve,
// swaggerUi.setup(openapiSpec, swaggerUiOptions),
// );
initializeProdPool();
setupSwagger(app, basePath)
app.use(basePath + "/d", express.static(join(__dirname, "../lstDocs/build")));
app.use(

View File

@@ -58,6 +58,8 @@ router.get("/", async (req, res) => {
memoryUsage: `Heap: ${(used.heapUsed / 1024 / 1024).toFixed(2)} MB / RSS: ${(
used.rss / 1024 / 1024
).toFixed(2)} MB`,
eomFGPkgSheetVersion: 1, // this is the excel file version when we have a change to the macro we want to grab this
masterMacroFile: 1, // this is the excel file version when we have a change to the macro we want to grab this
});
});

View File

@@ -1,13 +1,13 @@
import type { Address } from "nodemailer/lib/mailer/index.js";
import type { Transporter } from "nodemailer";
import type SMTPTransport from "nodemailer/lib/smtp-transport/index.js";
import type Mail from "nodemailer/lib/mailer/index.js";
import os from "os";
import nodemailer from "nodemailer";
import type Mail from "nodemailer/lib/mailer/index.js";
import type { Address } from "nodemailer/lib/mailer/index.js";
import type SMTPTransport from "nodemailer/lib/smtp-transport/index.js";
import hbs from "nodemailer-express-handlebars";
import os from "os";
import path from "path";
import { fileURLToPath } from "url";
import { promisify } from "util";
import hbs from "nodemailer-express-handlebars";
import { createLogger } from "../../logger/logger.js";
interface HandlebarsMailOptions extends Mail.Options {
@@ -27,57 +27,59 @@ export const sendEmail = async (data: EmailData): Promise<any> => {
let transporter: Transporter;
let fromEmail: string | Address;
if (
os.hostname().includes("OLP") &&
process.env.EMAIL_USER &&
process.env.EMAIL_PASSWORD
) {
transporter = nodemailer.createTransport({
service: "gmail",
auth: {
user: process.env.EMAIL_USER,
pass: process.env.EMAIL_PASSWORD,
},
//debug: true,
});
// if (
// os.hostname().includes("OLP") &&
// process.env.EMAIL_USER &&
// process.env.EMAIL_PASSWORD
// ) {
// transporter = nodemailer.createTransport({
// service: "gmail",
// auth: {
// user: process.env.EMAIL_USER,
// pass: process.env.EMAIL_PASSWORD,
// },
// //debug: true,
// });
// update the from email
fromEmail = process.env.EMAIL_USER;
} else {
// convert to the correct plant token.
// // update the from email
// fromEmail = process.env.EMAIL_USER;
// } else {
// // convert to the correct plant token.
let host = `${os.hostname().replace("VMS006", "")}-smtp.alpla.net`;
//let host = `${os.hostname().replace("VMS006", "")}-smtp.alpla.net`;
//const testServers = ["vms036", "VMS036"];
if (os.hostname().includes("VMS036")) {
host = "USMCD1-smtp.alpla.net";
}
// if (os.hostname().includes("VMS036")) {
// host = "USMCD1-smtp.alpla.net";
// }
// if (plantToken[0].value === "usiow2") {
// host = "USIOW1-smtp.alpla.net";
// }
transporter = nodemailer.createTransport({
host: host,
port: 25,
rejectUnauthorized: false,
//secure: false,
// auth: {
// user: "alplaprod",
// pass: "obelix",
// },
host: "smtp.azurecomm.net",
port: 587,
//rejectUnauthorized: false,
tls: {
minVersion: "TLSv1.2",
},
auth: {
user: "donotreply@mail.alpla.com",
pass: process.env.SMTP_PASSWORD,
},
debug: true,
} as SMTPTransport.Options);
// update the from email
fromEmail = `noreply@alpla.com`;
}
fromEmail = `DoNotReply@mail.alpla.com`;
//}
// creating the handlbar options
const viewPath = path.resolve(
path.dirname(fileURLToPath(import.meta.url)),
"./views/"
"./views/",
);
const handlebarOptions = {
@@ -116,7 +118,7 @@ export const sendEmail = async (data: EmailData): Promise<any> => {
log.error(
{ error: err },
`Error sending Email to : ${data.email}`
`Error sending Email to : ${data.email}`,
);
return { success: false, message: "Error sending email.", error: err };
}

View File

@@ -15,7 +15,7 @@ export default function Admin() {
const items: Items[] = [
{
title: "Users",
url: "/lst/app/admin/users",
url: "/admin/users",
icon: User,
role: ["systemAdmin", "admin"],
module: "admin",
@@ -23,7 +23,7 @@ export default function Admin() {
},
{
title: "System",
url: "/lst/app/admin/settings",
url: "/admin/settings",
icon: Settings,
role: ["systemAdmin", "admin"],
module: "admin",
@@ -31,7 +31,7 @@ export default function Admin() {
},
{
title: "Modules",
url: "/lst/app/admin/modules",
url: "/admin/modules",
icon: Settings,
role: ["systemAdmin", "admin"],
module: "admin",
@@ -39,7 +39,7 @@ export default function Admin() {
},
{
title: "Servers",
url: "/lst/app/admin/servers",
url: "/admin/servers",
icon: Server,
role: ["systemAdmin", "admin"],
module: "admin",

View File

@@ -21,7 +21,7 @@ export default function ForkliftSideBar() {
const items: Items[] = [
{
title: "Lease Companies",
url: "/lst/app/forklifts/companies",
url: "/forklifts/companies",
icon: Building2,
role: ["systemAdmin", "admin"],
module: "forklifts",
@@ -29,7 +29,7 @@ export default function ForkliftSideBar() {
},
{
title: "Leases",
url: "/lst/app/forklifts/leases",
url: "/forklifts/leases",
icon: ReceiptText,
role: ["systemAdmin", "admin"],
module: "forklifts",
@@ -37,7 +37,7 @@ export default function ForkliftSideBar() {
},
{
title: "Invoices",
url: "/lst/app/forklifts/invoices",
url: "/forklifts/invoices",
icon: ReceiptText,
role: ["systemAdmin", "admin", "manager"],
module: "forklifts",
@@ -45,7 +45,7 @@ export default function ForkliftSideBar() {
},
{
title: "Repairs",
url: "/lst/app/admin/settings",
url: "/admin/settings",
icon: Wrench,
role: ["systemAdmin", "admin", "manager"],
module: "forklifts",
@@ -53,7 +53,7 @@ export default function ForkliftSideBar() {
},
{
title: "Hours",
url: "/lst/app/admin/settings",
url: "/admin/settings",
icon: Hourglass,
role: ["systemAdmin", "admin", "manager", "supervisor"],
module: "forklifts",
@@ -61,7 +61,7 @@ export default function ForkliftSideBar() {
},
{
title: "Forklifts",
url: "/lst/app/forklifts/forklifts",
url: "/forklifts/forklifts",
icon: Forklift,
role: ["systemAdmin", "admin", "manager", "supervisor"],
module: "forklifts",

View File

@@ -14,36 +14,19 @@ export default function DMButtons() {
{/* dev and testserver sees all */}
{testServers.includes(plantToken[0]?.value) && (
<div className="flex flex-row gap-2">
<OrderImport
fileType={"abbott"}
name={"Abbott truck list"}
/>
<OrderImport
fileType={"energizer"}
name={"Energizer Truck List"}
/>
<OrderImport fileType={"abbott"} name={"Abbott truck list"} />
<OrderImport fileType={"energizer"} name={"Energizer Truck List"} />
<OrderImport fileType={"scj"} name={"SCJ Orders"} />
<ForecastImport fileType={"loreal"} name={"VMI Import"} />
<ForecastImport fileType={"pg"} name={"P&G"} />
<ForecastImport
fileType={"energizer"}
name={"Energizer Forecast"}
/>
<ForecastImport fileType={"energizer"} name={"Energizer Forecast"} />
</div>
)}
{plantToken[0]?.value === "usday1" && (
<div className="flex flex-row gap-2">
<OrderImport
fileType={"abbott"}
name={"Abbott truck list"}
/>
<OrderImport
fileType={"energizer"}
name={"Energizer Truck List"}
/>
<ForecastImport
fileType={"energizer"}
name={"Energizer Forecast"}
/>
<OrderImport fileType={"abbott"} name={"Abbott truck list"} />
<OrderImport fileType={"energizer"} name={"Energizer Truck List"} />
<ForecastImport fileType={"energizer"} name={"Energizer Forecast"} />
</div>
)}
{plantToken[0]?.value === "usflo1" && (
@@ -69,6 +52,11 @@ export default function DMButtons() {
<ForecastImport fileType={"pg"} name={"P&G"} />
</div>
)}
{plantToken[0]?.value === "usweb1" && (
<div className="flex flex-row gap-2">
<OrderImport fileType={"scj"} name={"SCJ Orders"} />
</div>
)}
</div>
);
}

View File

@@ -12,14 +12,15 @@ import { LstCard } from "../../../extendedUi/LstCard";
export default function Relocate() {
const [bookingIn, setBookingIn] = useState(false);
const form = useForm({
defaultValues: { runningNr: " ", lane: "" },
defaultValues: { runningNr: " ", laneID: "" },
onSubmit: async ({ value }) => {
// Do something with form data
setBookingIn(true);
try {
const res = await axios.post("/lst/old/api/ocp/bookin", {
const res = await axios.post("/lst/old/api/logistics/relocate", {
runningNr: parseInt(value.runningNr),
laneID: parseInt(value.laneID),
});
if (res.data.success) {
@@ -27,15 +28,15 @@ export default function Relocate() {
form.reset();
setBookingIn(false);
} else {
console.log(res.data.data.errors);
toast.error(res.data.data.errors[0]?.message);
form.reset();
console.log(res.data.message);
toast.error(res.data.message);
//form.reset();
setBookingIn(false);
}
} catch (error) {
console.log(error);
toast.error(
"There was an error booking in pallet please validate you entered the correct info and try again.",
"There was an error relocating the pallet please validate the data.",
);
setBookingIn(false);
}
@@ -58,7 +59,7 @@ export default function Relocate() {
validators={{
// We can choose between form-wide and field-specific validators
onChange: ({ value }) =>
value.length > 2
value.length > 0
? undefined
: "Please enter a valid running number",
}}
@@ -83,19 +84,17 @@ export default function Relocate() {
}}
/>
<form.Field
name="lane"
name="laneID"
validators={{
// We can choose between form-wide and field-specific validators
onChange: ({ value }) =>
value.length > 2
? undefined
: "Please enter a valid running number",
value.length > 0 ? undefined : "Please enter a valid lane ID",
}}
children={(field) => {
return (
<div className="">
<Label htmlFor="runningNr" className="mb-2">
Enter lane
<Label htmlFor="laneID" className="mb-2">
Enter lane ID
</Label>
<Input
name={field.name}

View File

@@ -6,15 +6,19 @@ export default function HelperPage() {
const url: string = window.location.host.split(":")[0];
return (
<div className="flex flex-wrap m-2 justify-center">
<div className="m-1">
<div className="m-1 ">
<Bookin />
</div>
<div className="w-96 m-1">
<Relocate />
</div>
</div>
<div className="m-1">
{url === "localhost" && (
<div className="m-1">
<RemoveAsNonReusable />
<Relocate />
</div>
)}
</div>

View File

@@ -19,7 +19,7 @@ import { LstCard } from "../../../extendedUi/LstCard";
export default function TransferToNextLot() {
const [gaylordFilled, setGaylordFilled] = useState([0]);
const [actualAmount, setActualAmount] = useState(0);
const [tab, setTab] = useState("esitmate");
const [tab, setTab] = useState("estimate");
const [typeSwitch, setTypeSwitch] = useState(false);
const { settings } = useSettingStore();
@@ -207,7 +207,7 @@ export default function TransferToNextLot() {
<span>"EOM Transfer"</span>
<Tooltip>
<TooltipTrigger>
<Info className="h-[16px] w-[16px]" />
<Info className="h-4 w-4" />
</TooltipTrigger>
<TooltipContent>
<p>
@@ -223,7 +223,7 @@ export default function TransferToNextLot() {
<span>"Lot Transfer"</span>
<Tooltip>
<TooltipTrigger>
<Info className="h-[16px] w-[16px]" />
<Info className="h-4 w-4" />
</TooltipTrigger>
<TooltipContent>
<p>

View File

@@ -30,6 +30,7 @@ import { useSettingStore } from "../../../-lib/store/useSettings";
const printReason = [
{ key: "printerIssue", label: "Printer Related" },
{ key: "missingRfidTag", label: "Missing or incorrect tag" },
{ key: "multipleTags", label: "More than one tag on pallet." },
{ key: "rfidMissScan", label: "Missed Scan from RFID reader" },
{ key: "strapper", label: "Strapper Error" },
{ key: "manualCheck", label: "20th pallet check" },

View File

@@ -112,7 +112,7 @@ export const readerColumns: ColumnDef<Readers>[] = [
const resetReads = async () => {
setReaderReset(true);
try {
const res = await axios.post("/api/rfid/resetRatio", {
const res = await axios.post("/lst/old/api/rfid/resetRatio", {
reader: name,
});

View File

@@ -0,0 +1,2 @@
ALTER TABLE "invHistoricalData" ADD COLUMN "whse_id" text DEFAULT '';--> statement-breakpoint
ALTER TABLE "invHistoricalData" ADD COLUMN "whse_name" text DEFAULT 'missing whseName';

File diff suppressed because it is too large Load Diff

View File

@@ -547,6 +547,13 @@
"when": 1763407463567,
"tag": "0077_lucky_texas_twister",
"breakpoints": true
},
{
"idx": 78,
"version": "7",
"when": 1766514890344,
"tag": "0078_cheerful_the_leader",
"breakpoints": true
}
]
}

View File

@@ -1,4 +1,4 @@
import { text, pgTable, timestamp, uuid, jsonb } from "drizzle-orm/pg-core";
import { jsonb, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
import { z } from "zod";
@@ -9,12 +9,12 @@ export const commandLog = pgTable(
commandUsed: text("commandUsed").notNull(),
bodySent: jsonb("bodySent").default([]),
reasonUsed: text("reasonUsed"),
add_at: timestamp("add_Date").defaultNow(),
addDate: timestamp("add_Date").defaultNow(),
},
(table) => [
// uniqueIndex('emailUniqueIndex').on(sql`lower(${table.email})`),
// uniqueIndex("role_name").on(table.name),
]
],
);
// Schema for inserting a user - can be used to validate API requests

View File

@@ -24,9 +24,11 @@ export const invHistoricalData = pgTable(
lot_Number: text("lot_number"),
consignment: text("consignment"),
location: text("location"),
whseId: text("whse_id").default(""),
whseName: text("whse_name").default("missing whseName"),
upd_user: text("upd_user").default("lst"),
upd_date: timestamp("upd_date").defaultNow(),
}
},
// (table) => [
// // uniqueIndex('emailUniqueIndex').on(sql`lower(${table.email})`),
// uniqueIndex("role_name").on(table.name),

View File

@@ -10,7 +10,8 @@
"dev:dbgen": " drizzle-kit generate --config=drizzle-dev.config.ts",
"dev:dbmigrate": " drizzle-kit migrate --config=drizzle-dev.config.ts",
"build": "npm run build:server",
"build:server": "rimraf dist && tsc --build && npm run copy:scripts && xcopy server\\services\\notifications\\utils\\views\\ dist\\server\\services\\notifications\\utils\\views\\ /E /I /Y ",
"build:server": "rimraf dist && tsc --build && npm run copy:scripts && xcopy server\\services\\notifications\\utils\\views\\ dist\\server\\services\\notifications\\utils\\views\\ /E /I /Y && npm run build:copySql",
"build:copySql": "xcopy server\\services\\sqlServer\\querys\\newQueries dist\\server\\services\\sqlServer\\querys\\newQueries\\ /E /I /Y ",
"build:frontend": "cd frontend && npm run build",
"build:iisNet": "rimraf dotnetwrapper\\bin && xcopy frontend\\dist dotnetwrapper\\wwwroot /E /I /Y && cd dotnetwrapper && dotnet publish lst-wrapper.csproj --configuration Release --output ../prodBuild",
"copy:scripts": "tsx server/scripts/copyScripts.ts",

View File

@@ -0,0 +1,191 @@
/**
* Using this to make a scanner connection to the server.
*/
import net from "net";
interface QueuedCommand {
command: string;
resolve: (value: string) => void;
reject: (reason?: any) => void;
timeout: NodeJS.Timeout;
}
const STX = "\x02";
const ETX = "\x03";
// const prodIP = process.env.SERVER_IP as string;
// const prodPort = parseInt(process.env.SCANNER_PORT || "50000", 10);
// const scannerID = `${process.env.SCANNER_ID}@`;
//const scannerCommand = "AlplaPRODcmd00000042#000028547"; // top of the picksheet
export class ScannerClient {
private socket = new net.Socket();
private connected = false;
private queue: QueuedCommand[] = [];
private processing = false;
private incomingBuffer = "";
constructor(
private host: string,
private port: number,
private scannerId: string,
) {
this.initialize();
}
private initialize() {
if (!this.host || !this.port) {
console.log("Host or port is missing");
return;
}
this.socket.connect(this.port, this.host, () => {
console.info("Connected to scanner");
this.connected = true;
});
this.socket.on("data", (data) => this.handleData(data));
this.socket.on("close", () => {
console.log("Scanner connection closed");
this.connected = false;
});
this.socket.on("error", (err) => {
console.error("Scanner error:", err);
});
}
// ✅ Public method you use
public scan(command: string): Promise<string> {
if (!this.connected) {
return Promise.reject("Scanner not connected");
}
return new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
this.processing = false;
reject("Scanner timeout");
this.processQueue();
}, 5000); // 5s safety timeout
this.queue.push({
command,
resolve,
reject,
timeout,
});
this.processQueue();
});
}
// ✅ Ensures strict FIFO processing
private processQueue() {
if (this.processing) return;
if (this.queue.length === 0) return;
this.processing = true;
const current = this.queue[0];
const message = Buffer.from(
`${STX}${this.scannerId}${current.command}${ETX}`,
"ascii",
);
this.socket.write(message);
}
// ✅ Handles full STX/ETX framed responses
private handleData(data: Buffer) {
console.log(
"ASCII:",
data
.toString("ascii")
.replace(/\x00/g, "") // remove null bytes
.replace(/\x1B\[[0-9;?]*[A-Za-z]/g, "") // remove ANSI escape codes
.trim(),
);
const current = this.queue.shift();
if (current) {
clearTimeout(current.timeout);
current.resolve(data.toString("ascii"));
}
this.processing = false;
this.processQueue();
}
}
export const scanner = new ScannerClient(
process.env.SERVER_IP!,
parseInt(process.env.SCANNER_PORT!, 10),
`${process.env.SCANNER_ID}@`,
);
// export const connectToScanner = () => {
// if (!process.env.SERVER_IP || !process.env.SCANNER_PORT) {
// return {
// success: false,
// message: "Missing ServerIP or ServerPort",
// };
// }
// scanner.connect(prodPort, prodIP, () => {
// console.log("Connected to scanner");
// connected = true;
// });
// };
// export const scan = async (command: string) => {
// if (!connected) {
// return {
// success: false,
// message: "Scanner is not connected, please contact admin",
// };
// }
// if (inScanCommand) {
// bufferCommands.push({ timeStamp: new Date(Date.now()), command: command });
// }
// // we are going to set to scanning
// inScanCommand = true;
// const message = Buffer.from(`${STX}${scannerID}${command}${ETX}`, "ascii");
// scanner.write(message);
// await new Promise((resolve) => setTimeout(resolve, 750));
// inScanCommand = false;
// if (bufferCommands.length > 0) {
// await scan(bufferCommands[0].command);
// bufferCommands.shift();
// }
// return {
// success: true,
// message: "Scan completed",
// };
// };
// scanner.on("data", async (data) => {
// console.log(
// "Response:",
// data
// .toString("ascii")
// .replace(/\x00/g, "") // remove null bytes
// .replace(/\x1B\[[0-9;?]*[A-Za-z]/g, "") // remove ANSI escape codes
// .trim(),
// );
// });
// scanner.on("close", () => {
// console.log("Connection closed");
// });
// scanner.on("error", (err) => {
// console.error("Scanner error:", err);
// });

View File

@@ -1,10 +1,11 @@
import { addDays, format } from "date-fns";
import { formatInTimeZone } from "date-fns-tz";
import { eq } from "drizzle-orm";
import { db } from "../../../../database/dbclient.js";
import { settings } from "../../../../database/schema/settings.js";
import { tryCatch } from "../../../globalUtils/tryCatch.js";
import { query } from "../../sqlServer/prodSqlServer.js";
import { deliveryByDateRange } from "../../sqlServer/querys/dataMart/deleveryByDateRange.js";
import { addDays, format } from "date-fns";
export const getDeliveryByDateRange = async (data: any | null) => {
// const { data: plantToken, error: plantError } = await tryCatch(
@@ -32,18 +33,12 @@ export const getDeliveryByDateRange = async (data: any | null) => {
if (data?.end) {
updatedQuery = updatedQuery.replaceAll("[endDate]", data.end[0]);
} else {
const defaultEndDate = format(
addDays(new Date(Date.now()), 5),
"yyyy-M-d"
);
const defaultEndDate = format(addDays(new Date(Date.now()), 5), "yyyy-M-d");
updatedQuery = updatedQuery.replaceAll("[endDate]", defaultEndDate);
}
try {
const res: any = await query(
updatedQuery,
"Get Delivery by date range"
);
const res: any = await query(updatedQuery, "Get Delivery by date range");
deliverys = res.data;
//console.log(res.data);
} catch (error) {
@@ -55,9 +50,9 @@ export const getDeliveryByDateRange = async (data: any | null) => {
};
}
if (!data) {
deliverys = deliverys.splice(1000, 0);
}
// if (!data) {
// deliverys = deliverys.splice(1000, 0);
// }
// add plant token in
// const pOrders = deliverys.map((item: any) => {
// // const dateCon = new Date(item.loadingDate).toLocaleString("en-US", {
@@ -80,5 +75,21 @@ export const getDeliveryByDateRange = async (data: any | null) => {
// deliveryDate: delDate,
// };
// });
return { success: true, message: "Current open orders", data: deliverys };
return {
success: true,
message: "Current open orders",
data: deliverys.map((i: any) => {
const orderDate = new Date(i.OrderDate);
const delDate = new Date(i.DeliveryDate);
const loadDate = new Date(i.LoadingDate);
return {
...i,
OrderDate: format(orderDate, "yyyy-MM-dd HH:mm"),
DeliveryDate: format(delDate, "yyyy-MM-dd HH:mm"),
LoadingDate: format(loadDate, "yyyy-MM-dd HH:mm"),
dbDate: i.DeliveryDate,
};
}),
};
};

View File

@@ -1,11 +1,11 @@
import { addDays, format } from "date-fns";
import { query } from "../../sqlServer/prodSqlServer.js";
import { deliveryByDateRangeAndAv } from "../../sqlServer/querys/dataMart/deleveryByDateRange.js";
import { addDays, format } from "date-fns";
export const getDeliveryByDateRangeAndAv = async (
avs: string,
startDate: string,
endDate: string
endDate: string,
) => {
// const { data: plantToken, error: plantError } = await tryCatch(
// db.select().from(settings).where(eq(settings.name, "plantToken"))
@@ -32,17 +32,14 @@ export const getDeliveryByDateRangeAndAv = async (
if (endDate) {
updatedQuery = updatedQuery.replaceAll("[endDate]", endDate);
} else {
const defaultEndDate = format(
addDays(new Date(Date.now()), 5),
"yyyy-M-d"
);
const defaultEndDate = format(addDays(new Date(Date.now()), 5), "yyyy-M-d");
updatedQuery = updatedQuery.replaceAll("[endDate]", defaultEndDate);
}
try {
const res: any = await query(
updatedQuery.replace("[articles]", avs),
"Get Delivery by date range"
"Get Delivery by date range",
);
deliverys = res.data;
//console.log(res.data);
@@ -80,5 +77,21 @@ export const getDeliveryByDateRangeAndAv = async (
// deliveryDate: delDate,
// };
// });
return { success: true, message: "Current open orders", data: deliverys };
return {
success: true,
message: "Current open orders",
data: deliverys.map((i: any) => {
const orderDate = new Date(i.OrderDate);
const delDate = new Date(i.DeliveryDate);
const loadDate = new Date(i.LoadingDate);
return {
...i,
OrderDate: format(orderDate, "yyyy-MM-dd HH:mm"),
DeliveryDate: format(delDate, "yyyy-MM-dd HH:mm"),
LoadingDate: format(loadDate, "yyyy-MM-dd HH:mm"),
dbDate: i.DeliveryDate,
};
}),
};
};

View File

@@ -0,0 +1,81 @@
import { addDays, format } from "date-fns";
import { query } from "../../sqlServer/prodSqlServer.js";
import { inhouseDelivery } from "../../sqlServer/querys/dataMart/inhouseDelivery.js";
export const getInhouseDeliveryByDateRange = async (data: any | null) => {
// const { data: plantToken, error: plantError } = await tryCatch(
// db.select().from(settings).where(eq(settings.name, "plantToken"))
// );
// if (plantError) {
// return {
// success: false,
// message: "Error getting Settings",
// data: plantError,
// };
// }
let deliverys: any = [];
let updatedQuery = inhouseDelivery;
// start days can be sent over
if (data?.start) {
updatedQuery = updatedQuery.replaceAll("[startDate]", data.start[0]);
} else {
updatedQuery = updatedQuery.replaceAll("[startDate]", "1990-1-1");
}
// end days can be sent over
if (data?.end) {
updatedQuery = updatedQuery.replaceAll("[endDate]", data.end[0]);
} else {
const defaultEndDate = format(addDays(new Date(Date.now()), 5), "yyyy-M-d");
updatedQuery = updatedQuery.replaceAll("[endDate]", defaultEndDate);
}
try {
const res: any = await query(
updatedQuery,
"Get inhouse Delivery by date range",
);
deliverys = res.data;
//console.log(res.data);
} catch (error) {
console.log(error);
return {
success: false,
message: "All In-House Deliveries within the range.",
data: error,
};
}
if (!data) {
deliverys = deliverys.splice(1000, 0);
}
// add plant token in
// const pOrders = deliverys.map((item: any) => {
// // const dateCon = new Date(item.loadingDate).toLocaleString("en-US", {
// // month: "numeric",
// // day: "numeric",
// // year: "numeric",
// // hour: "2-digit",
// // minute: "2-digit",
// // hour12: false,
// // });
// //const dateCon = new Date(item.loadingDate).toISOString().replace("T", " ").split(".")[0];
// const dateCon = new Date(item.loadingDate).toISOString().split("T")[0];
// //const delDate = new Date(item.deliveryDate).toISOString().replace("T", " ").split(".")[0];
// const delDate = new Date(item.deliveryDate).toISOString().split("T")[0];
// return {
// plantToken: plantToken[0].value,
// ...item,
// loadingDate: dateCon,
// deliveryDate: delDate,
// };
// });
return {
success: true,
message: "Current In-House deliveries by range",
data: deliverys,
};
};

View File

@@ -0,0 +1,52 @@
import { format } from "date-fns-tz/format";
import { tryCatch } from "../../../globalUtils/tryCatch.js";
import { createLog } from "../../logger/logger.js";
import { query } from "../../sqlServer/prodSqlServer.js";
import { forecastData } from "../../sqlServer/querys/psiReport/forecast.js";
// type ArticleData = {
// id: string
// }
export const getGetPSIForecastData = async (customer: string) => {
let articles: any = [];
let queryData = forecastData;
console.log(customer);
if (customer) {
queryData = forecastData.replace("[customer]", customer);
}
const { data, error } = (await tryCatch(
query(queryData, "PSI forecast info"),
)) as any;
if (error) {
createLog(
"error",
"datamart",
"datamart",
`There was an error getting the forecast info: ${JSON.stringify(error)}`,
);
return {
success: false,
messsage: `There was an error getting the forecast info`,
data: error,
};
}
articles = data.data;
return {
success: true,
message: "PSI forecast Data",
data: articles.map((i: any) => {
const requirementDate = new Date(i.requirementDate);
return {
...i,
requirementDate: format(requirementDate, "yyyy-MM-dd"),
dbDate: i.requirementDate,
};
}),
};
};

View File

@@ -1,4 +1,4 @@
import { and, between, inArray, sql } from "drizzle-orm";
import { and, between, inArray, notInArray, sql } from "drizzle-orm";
import { db } from "../../../../database/dbclient.js";
import { invHistoricalData } from "../../../../database/schema/historicalINV.js";
import { tryCatch } from "../../../globalUtils/tryCatch.js";
@@ -10,7 +10,9 @@ import { createLog } from "../../logger/logger.js";
export const psiGetInventory = async (
avs: string,
startDate: string,
endDate: string
endDate: string,
whseToInclude: string,
exludeLanes: string
) => {
let articles: any = [];
@@ -23,28 +25,49 @@ export const psiGetInventory = async (
}
const ids = avs.split(",").map((id) => id.trim());
const whse = whseToInclude
? whseToInclude
.split(",")
.map((w) => w.trim())
.filter(Boolean)
: [];
const { data, error } = (await tryCatch(
db
const locations = exludeLanes
? exludeLanes.split(",").map((l) => l.trim()).filter(Boolean)
: [];
const conditions = [
inArray(invHistoricalData.article, ids),
between(invHistoricalData.histDate, startDate, endDate),
];
// only add the warehouse condition if there are any whse values
if (whse.length > 0) {
console.log("adding whse to include in");
conditions.push(inArray(invHistoricalData.whseId, whse));
}
// locations we dont want in the system
if (locations.length > 0) {
console.log("adding excluded lanes in ",locations);
conditions.push(notInArray(invHistoricalData.location, locations));
}
const query = db
.select()
.from(invHistoricalData)
.where(
and(
inArray(invHistoricalData.article, ids),
between(invHistoricalData.histDate, startDate, endDate)
)
)
//.limit(100)
)) as any;
.where(and(...conditions));
// optional tryCatch or await as you had
const { data, error } = (await tryCatch(query)) as any;
if (error) {
createLog(
"error",
"datamart",
"datamart",
`There was an error getting the planning info: ${JSON.stringify(
error
)}`
`There was an error getting the planning info: ${JSON.stringify(error)}`,
);
return {
success: false,

View File

@@ -2,6 +2,7 @@ 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";
import { improvedPsiPlanningInfo } from "./psiPlanningDataImproved.js";
// type ArticleData = {
// id: string
@@ -9,7 +10,7 @@ import { planningNumbersByAVDate } from "../../sqlServer/querys/psiReport/planni
export const psiGetPlanningData = async (
avs: string,
startDate: string,
endDate: string
endDate: string,
) => {
let articles: any = [];
@@ -27,18 +28,21 @@ export const psiGetPlanningData = async (
.replace("[articles]", avs)
.replace("[startDate]", startDate)
.replace("[endDate]", endDate),
"PSI planning info"
)
"PSI planning info",
),
)) as any;
// improvedPsiPlanningInfo({
// avs,
// startDate,
// endDate,
// });
if (error) {
createLog(
"error",
"datamart",
"datamart",
`There was an error getting the planning info: ${JSON.stringify(
error
)}`
`There was an error getting the planning info: ${JSON.stringify(error)}`,
);
return {
success: false,
@@ -47,17 +51,23 @@ export const psiGetPlanningData = async (
};
}
// TODO: if we are not running planning we no pass the old structure if we are running new planning use the below improved version that makes sure we dont have negative numebrs.
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;
data: await improvedPsiPlanningInfo({
avs,
startDate,
endDate,
}),
// data: articles.map((n: any) => {
// if (n.PalDay) {
// return { ...n, PalDay: n.PalDay.toFixed(2) };
// }
// return n;
// }),
};
};

View File

@@ -0,0 +1,171 @@
import { format } from "date-fns-tz";
import { tryCatch } from "../../../globalUtils/tryCatch.js";
import { query } from "../../sqlServer/prodSqlServer.js";
const improvedQuery = `
DECLARE @StartDate DATE = '[startDate]' -- 2025-1-1
DECLARE @EndDate DATE = '[endDate]' -- 2025-1-31
SELECT
[RunningNumber] as lot
,[ProfitCentreDescription]
,[MachineDescription]
,[ArticleHumanReadableId]
,[ArticleDescription]
,[DeliveryAddressHumanReadableId]
,[DeliveryAddressDescription]
,[MouldHumanReadableId]
,[BlowheadHumanReadableId1]
,[PackagingInstructionHumanReadableId]
,[PackagingInstructionDescription]
,[MainMaterialHumanReadableId]
,[MainMaterialDescription]
,[CompoundHumanReadableId]
,[CompoundDescription]
,[ProductionLotState]
,[PlanType]
,[ProducedQuantityLoadingUnit]
,[ProducedQuantityPieces]
,[PlanStart]
,[PlanEnd]
,[ProdStart]
,[TheoreticEnd]
,[ProdDuration]
,[SetupDuration]
,[StartupDuration]
,[NetEquipmentEfficiency]
,[UtilisationDuration]
,[CycleTime]
,[Cavities]
,[FixedQuantity]
,[ProducedQuantityTrucks]
,[ProducedQuantityTradeUnit]
,[MaxRegrind]
,[Conflict]
,[ProductionOrderHumanReadableId]
,[ProductionDataImportSource]
,[Remark]
,[BlowheadDescription1]
,[MouldDescription]
,[ProcessLossPercentage]
,[SetupTypeNumberOfPersons]
,[UnplannedDowntimePercentage]
,[PlanQuantityLoadingUnit]
,[PlanQuantityPieces]
,[PlanQuantityTradeUnit]
,[PlanQuantityTrucks]
,[PublishState]
,[LastChange]
,[MaterialConsumed]
,[MaterialStaged]
,[MachineLocation]
,[HasPrioritization]
,[ArticleAlias]
FROM [test1_AlplaPROD2.0_Read].[productionScheduling].[ProductionLot] with (nolock)
where PlanEnd between @StartDate and @EndDate
and ArticleHumanReadableId in ([articles])
and PublishState = 1
order by PlanStart
`;
export const improvedPsiPlanningInfo = async (something: any) => {
const { data, error } = (await tryCatch(
query(
improvedQuery
.replace("[articles]", something.avs)
.replace("[startDate]", something.startDate)
.replace("[endDate]", something.endDate),
"PSI planning info",
),
)) as any;
// add error handling in later here
return splitProduction(data.data);
};
const splitProduction = (runs: any) => {
const results: any = [];
const WORKDAY_START_HOUR = 7; // 07:00 start well later get this from the shift def
runs.forEach((e: any) => {
const {
PlanStart,
PlanEnd,
PlanQuantityPieces,
ArticleHumanReadableId,
ProdDuration,
} = e;
const prodStart: any = new Date(PlanStart);
const prodEnd: any = new Date(PlanEnd);
const prodDuration = ProdDuration
? ProdDuration * 60 * 60 * 1000
: prodEnd - prodStart;
// get the prod date the production falls under
function getProdDayStart(date: Date) {
const d = new Date(date);
d.setHours(WORKDAY_START_HOUR, 0, 0, 0);
if (date.getHours() < WORKDAY_START_HOUR) {
// before 07:00, belongs to previous calendar day
d.setDate(d.getDate() - 1);
}
return d;
}
// current pointer starts at the work-day start that contains our start time
let currentStart = new Date(prodStart);
let prodDayStart = getProdDayStart(currentStart);
while (prodDayStart < prodEnd) {
// 1⃣ The next days start = prodDayStart + 1 day at 07:00
const nextProdDayStart = new Date(prodDayStart);
nextProdDayStart.setDate(nextProdDayStart.getDate() + 1);
// 2⃣ Segment end is either the next work-day start or the actual end, whichever is sooner
const segmentEnd = new Date(
Math.min(nextProdDayStart.getTime(), prodEnd.getTime()),
);
// 3⃣ Determine overlap window within (startTime..endTime)
const segStart: any = new Date(
Math.max(prodDayStart.getTime(), prodStart.getTime()),
);
const segEnd: any = segmentEnd;
if (segEnd > segStart) {
const segMs = segEnd - segStart;
const proportion = segMs / prodDuration;
const qty = PlanQuantityPieces * proportion;
const pal = e.PlanQuantityLoadingUnit * proportion;
results.push({
Article: ArticleHumanReadableId,
Description: e.ArticleAlias,
MachineId: e.MachineLocation,
MachineName: e.MachineDescription,
LotNumber: e.lot,
ProductionDay: format(prodDayStart, "M/d/yyyy"),
TotalPlanned: e.PlanQuantityPieces,
// PlanEnd,
// TheoreticEnd,
QTYPerDay: parseInt(qty.toFixed(0)),
PalDay: parseFloat(pal.toFixed(2)),
finished: e.ProductionLotState === 3 ? 1 : 0,
cavities: e.Cavities,
//prodDuration,
});
}
// move to next production-day window
prodDayStart = nextProdDayStart;
}
});
return results;
};

View File

@@ -1,20 +1,23 @@
import { OpenAPIHono } from "@hono/zod-openapi";
import activequerys from "./route/getCurrentQuerys.js";
import getArticles from "./route/getActiveArticles.js";
import currentInv from "./route/getInventory.js";
import getCustomerInv from "./route/getCustomerInv.js";
import getOpenOrders from "./route/getOpenOrders.js";
import getDeliveryByDate from "./route/getDeliveryDateByRange.js";
import fakeEDI from "./route/fakeEDI.js";
import getArticles from "./route/getActiveArticles.js";
import addressCorrections from "./route/getCityStateData.js";
import activequerys from "./route/getCurrentQuerys.js";
import getCustomerInv from "./route/getCustomerInv.js";
import getDeliveryByDate from "./route/getDeliveryDateByRange.js";
import getDeliveryByDateRangeAndAv from "./route/getDeliveryDateByRangeAndAv.js";
import fifoIndex from "./route/getFifoIndex.js";
import financeAudit from "./route/getFinanceAudit.js";
import getForecastByAv from "./route/getForecastDataByAv.js";
import getInhouseDeliveryByDate from "./route/getInHouseDeliveryDateByRange.js";
import currentInv from "./route/getInventory.js";
import getOpenOrders from "./route/getOpenOrders.js";
import psiArticleData from "./route/getPsiArticleData.js";
import psiForecastData from "./route/getPsiForecast.js";
import psiInventory from "./route/getPsiinventory.js";
import psiPlanningData from "./route/getPsiPlanningData.js";
import psiProductionData from "./route/getPsiProductionData.js";
import psiInventory from "./route/getPsiinventory.js";
import getForecastByAv from "./route/getForecastDataByAv.js";
import getDeliveryByDateRangeAndAv from "./route/getDeliveryDateByRangeAndAv.js";
const app = new OpenAPIHono();
const routes = [
@@ -24,6 +27,7 @@ const routes = [
getCustomerInv,
getOpenOrders,
getDeliveryByDate,
getInhouseDeliveryByDate,
getDeliveryByDateRangeAndAv,
getForecastByAv,
fakeEDI,
@@ -34,6 +38,7 @@ const routes = [
psiPlanningData,
psiProductionData,
psiInventory,
psiForecastData,
] as const;
const appRoutes = routes.forEach((route) => {

View File

@@ -1,6 +1,6 @@
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { responses } from "../../../globalUtils/routeDefs/responses.js";
import { apiHit } from "../../../globalUtils/apiHits.js";
import { responses } from "../../../globalUtils/routeDefs/responses.js";
const app = new OpenAPIHono({ strict: false });
const current: any = [
@@ -80,13 +80,21 @@ const current: any = [
criteria: "startDate,endDate", // uncomment this out once the improt process can be faster
},
{
name: "Delivery by date trange",
name: "Delivery by date range",
endpoint: "/api/datamart/deliverybydaterange",
// description: "Returns all inventory, by default excludes running numebrs, also excludes inv locations.",
description:
"Returns all Deliverys in selected date range IE: 1/1/2025 to 1/31/2025",
criteria: "start,end", // uncomment this out once the improt process can be faster
},
{
name: "In House Delivery by date range",
endpoint: "/api/datamart/inhousedeliverybydaterange",
// description: "Returns all inventory, by default excludes running numebrs, also excludes inv locations.",
description:
"Returns all in-house deliveries in selected date range IE: 1/1/2025 to 1/31/2025",
criteria: "start,end", // uncomment this out once the improt process can be faster
},
{
name: "Fake Edi Update",
endpoint: "/api/datamart/fakeediupdate",
@@ -115,8 +123,7 @@ const current: any = [
name: "Finance Audit inv",
endpoint: "/api/datamart/getfinanceaudit",
// description: "Returns all inventory, by default excludes running numebrs, also excludes inv locations.",
description:
"Returns all inventory past the date provided, ie: 5/31/2025",
description: "Returns all inventory past the date provided, ie: 5/31/2025",
criteria: "date", // uncomment this out once the improt process can be faster
},
];
@@ -138,9 +145,9 @@ app.openapi(
return c.json({
success: true,
message: "All Current Active Querys.",
sheetVersion: 2.8,
sheetVersion: 2.8, // TODO: when this gets switched change this
data: current,
});
}
},
);
export default app;

View File

@@ -0,0 +1,54 @@
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { apiHit } from "../../../globalUtils/apiHits.js";
import { responses } from "../../../globalUtils/routeDefs/responses.js";
import { tryCatch } from "../../../globalUtils/tryCatch.js";
import { getInhouseDeliveryByDateRange } from "../controller/getInhouseDeliveryByDateRange.js";
const app = new OpenAPIHono({ strict: false });
const Body = z.object({
includeRunnningNumbers: z.string().openapi({ example: "x" }),
});
app.openapi(
createRoute({
tags: ["dataMart"],
summary: "Returns deliveries by date range.",
method: "get",
path: "/inhousedeliverybydaterange",
request: {
body: {
content: {
"application/json": { schema: Body },
},
},
},
responses: responses(),
}),
async (c) => {
const delivery: any = c.req.queries();
// make sure we have a vaid user being accessed thats really logged in
apiHit(c, { endpoint: "/inhousedeliverybydaterange" });
const { data, error } = await tryCatch(
getInhouseDeliveryByDateRange(delivery ? delivery : null),
);
if (error) {
console.log(error);
return c.json(
{
success: false,
message: "There was an error getting the deliveries.",
data: error,
},
400,
);
}
return c.json({
success: data.success,
message: data.message,
data: data.data,
});
},
);
export default app;

View File

@@ -0,0 +1,65 @@
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { apiHit } from "../../../globalUtils/apiHits.js";
import { responses } from "../../../globalUtils/routeDefs/responses.js";
import { tryCatch } from "../../../globalUtils/tryCatch.js";
import { getGetPSIForecastData } from "../controller/psiForecastData.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 psiforecastdata.",
method: "get",
path: "/psiforecastdata",
request: {
body: {
content: {
"application/json": { schema: Body },
},
},
},
responses: responses(),
}),
async (c) => {
const customer: any = c.req.queries();
// make sure we have a vaid user being accessed thats really logged in
apiHit(c, { endpoint: "/psiforecastdata" });
//console.log(articles["avs"][0]);
let customeArticle = null;
if (customer) {
customeArticle = customer["customer"][0];
}
const { data, error } = await tryCatch(
getGetPSIForecastData(customeArticle),
);
if (error) {
console.log(error);
return c.json(
{
success: false,
message: "There was an error getting the articles.",
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

@@ -1,7 +1,7 @@
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { apiHit } from "../../../globalUtils/apiHits.js";
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 });
@@ -33,8 +33,10 @@ app.openapi(
psiGetInventory(
q["avs"] ? q["avs"][0] : null,
q["startDate"] ? q["startDate"][0] : null,
q["endDate"] ? q["endDate"][0] : null
)
q["endDate"] ? q["endDate"][0] : null,
q["whseToInclude"] ? q["whseToInclude"][0] : null,
q["exludeLanes"] ? q["exludeLanes"][0] : null,
),
);
if (error) {
@@ -45,7 +47,7 @@ app.openapi(
message: "There was an error getting the production.",
data: error,
},
400
400,
);
}
@@ -57,8 +59,8 @@ app.openapi(
message: data.message,
data: data.data,
},
data.success ? 200 : 400
data.success ? 200 : 400,
);
}
},
);
export default app;

View File

@@ -2,21 +2,21 @@ import { OpenAPIHono } from "@hono/zod-openapi";
const app = new OpenAPIHono();
import stats from "./route/stats.js";
import history from "./route/invHistory.js";
import { createJob } from "../notifications/utils/processNotifications.js";
import { historicalInvIMmport } from "./utils/historicalInv.js";
import { tryCatch } from "../../globalUtils/tryCatch.js";
import { createLog } from "../logger/logger.js";
import { createJob } from "../notifications/utils/processNotifications.js";
import { query } from "../sqlServer/prodSqlServer.js";
import { shiftChange } from "../sqlServer/querys/misc/shiftChange.js";
import { createLog } from "../logger/logger.js";
import gpData from "./route/getGpData.js";
import lastPurch from "./route/getLastPurchPrice.js";
import lastSales from "./route/getLastSalesPrice.js";
import gpData from "./route/getGpData.js";
import consumptionData from "./route/getProductionConsumption.js";
import purchased from "./route/getPurchased.js";
import regrind from "./route/getregrind.js";
import soldItems from "./route/getSoldItems.js";
import purchased from "./route/getPurchased.js";
import history from "./route/invHistory.js";
import stats from "./route/stats.js";
import { historicalInvIMmport } from "./utils/historicalInv.js";
const routes = [
stats,
@@ -36,7 +36,7 @@ const appRoutes = routes.forEach((route) => {
setTimeout(async () => {
const { data: shift, error: shiftError } = (await tryCatch(
query(shiftChange, "shift change from material.")
query(shiftChange, "shift change from material."),
)) as any;
if (shiftError) {
@@ -44,7 +44,7 @@ setTimeout(async () => {
"error",
"eom",
"eom",
"There was an error getting the shift times will use fallback times"
"There was an error getting the shift times will use fallback times",
);
}
@@ -63,4 +63,10 @@ setTimeout(async () => {
// the time we want to run the hostircal data should be the same time the historical data run on the server
// getting this from the shift time
//if (process.env.NODE_ENV?.trim() !== "production") {
setTimeout(() => {
historicalInvIMmport();
}, 15 * 1000);
//}
export default app;

View File

@@ -76,7 +76,10 @@ export const historicalInvIMmport = async () => {
coa_QTY: i.COA_QTY,
held_QTY: i.Held_QTY,
consignment: i.Consigment,
lot_Number: i.lot,
lot_Number: i.Lot,
location: i.location,
whseId: i.warehouseID,
whseName: i.warehouseName,
};
});

View File

@@ -0,0 +1,155 @@
import axios from "axios";
import net from "net";
import { db } from "../../../../../database/dbclient.js";
import { commandLog } from "../../../../../database/schema/commandLog.js";
import { createSSCC } from "../../../../globalUtils/createSSCC.js";
import { prodEndpointCreation } from "../../../../globalUtils/createUrl.js";
import { scanner } from "../../../../globalUtils/scannerConnect.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { createLog } from "../../../logger/logger.js";
import { query } from "../../../sqlServer/prodSqlServer.js";
import { sqlQuerySelector } from "../../../sqlServer/utils/querySelector.utils.js";
type Data = {
runningNr: number;
reason: string;
user: string;
};
export const bookOutPallet = async (data: Data) => {
const { runningNr, reason, user } = data;
if (!reason || reason.length < 4) {
return {
success: false,
status: 400,
message: "The reason provided is to short",
data: [],
};
}
const queryCheck = sqlQuerySelector("inventoryInfo.query");
if (!queryCheck.success) {
return {
success: false,
status: 400,
message: queryCheck.message,
data: data,
};
}
const { data: label, error: labelError } = (await tryCatch(
query(
queryCheck.query!.replace("[runningNr]", `${runningNr}`),
"labelQuery",
),
)) as any;
if (labelError) {
return {
success: false,
status: 400,
message: labelError.message,
data: labelError,
};
}
// check if we are in ppoo
if (label.data.length <= 0) {
return {
success: false,
status: 400,
message: `${runningNr} is not currently in ppoo, please move to ppoo before trying to book-out`,
data: [],
};
}
// check if the label is blocked for coa.
if (
label.data[0].blockingReason &&
!label.data[0].blockingReason?.includes("COA")
) {
return {
success: false,
status: 400,
message: `${runningNr} is not currently blocked for coa, to get this pallet booked out please take the label to quality to be released then you can book-out.`,
data: [],
};
}
if (label.data[0].blockingReason) {
await scanner.scan("AlplaPRODcmd89");
await scanner.scan(`${label.data[0].barcode}`);
}
// create the url to post
const url = await prodEndpointCreation(
"/public/v1.1/Manufacturing/ProductionControlling/BookOut",
);
const SSCC = await createSSCC(runningNr);
const bookOutData = {
sscc: SSCC.slice(2),
scannerId: "666",
};
try {
const results = await axios.post(url, bookOutData, {
headers: {
"X-API-Key": process.env.TEC_API_KEY || "",
"Content-Type": "application/json",
},
});
if (results.data.Errors) {
return {
success: false,
status: 400,
message: results.data.Errors.Error.Description,
};
}
// if (results.data.Result !== 0) {
// console.log("stopping here and closing to soon", results);
// return {
// success: false,
// status: 400,
// message: results.data.Message,
// };
// }
const { data: commandL, error: ce } = await tryCatch(
db.insert(commandLog).values({
commandUsed: "book out",
bodySent: data,
reasonUsed: reason,
}),
);
return {
success: true,
message: `${runningNr} was booked out`,
status: results.status,
};
} catch (error: any) {
console.log(bookOutData);
return {
success: false,
status: 400,
message: error.response?.data,
data: error.response?.data,
};
}
// });
/**
* book out the label with
* url /public/v1.1/Manufacturing/ProductionControlling/BookOut
* {
* "sscc": "string",
* "scannerId": "string"
* }
*/
//---------------------------------------------------------------------------------------\\
};

View File

@@ -0,0 +1,96 @@
import axios from "axios";
import { db } from "../../../../../database/dbclient.js";
import { commandLog } from "../../../../../database/schema/commandLog.js";
import { createSSCC } from "../../../../globalUtils/createSSCC.js";
import { prodEndpointCreation } from "../../../../globalUtils/createUrl.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { createLog } from "../../../logger/logger.js";
import { query } from "../../../sqlServer/prodSqlServer.js";
type Data = {
runningNr: number;
laneID: number;
};
export const relatePallet = async (data: Data) => {
const { runningNr, laneID } = data;
// replace the rn
// console.log(data);
// create the url to post
// do we have warehousing turned on?
const { data: feature, error: featureError } = (await tryCatch(
query(
`SELECT [Id]
,[Feature]
,[Enabled]
,[ActivationDate]
FROM [test1_AlplaPROD2.0_Read].[support].[FeatureActivation] where [Feature] = 7`,
"feature switch check",
),
)) as any;
let prodUrl = "/public/v1.0/Warehousing/Relocate";
if (featureError) {
prodUrl = "/public/v1.0/Warehousing/Relocate";
}
if (feature?.data.length > 0) {
prodUrl = "/public/v1.1/Warehousing/Unit/Relocate";
}
// 1.0 "/public/v1.0/Warehousing/AdjustSiloStockLevel","
// 1.1 "/public/v1.1/Warehousing/Lane/AdjustSiloStockLevel"
let url = await prodEndpointCreation(prodUrl);
const SSCC = await createSSCC(runningNr);
const consumeSomething = {
ScannerId: 999,
laneId: laneID,
sscc: SSCC.slice(2),
};
console.log(consumeSomething);
try {
const results = await axios.post(url, consumeSomething, {
headers: {
"X-API-Key": process.env.TEC_API_KEY || "",
"Content-Type": "application/json",
},
});
if (results.data.Errors) {
return {
success: false,
message: results.data.Errors.Error.Description,
};
}
if (results.data.Result !== 0 || results.data.data.length <= 0) {
return {
success: false,
message: results.data.Message,
};
}
const { data: commandL, error: ce } = await tryCatch(
db.insert(commandLog).values({
commandUsed: "relocate",
bodySent: data,
}),
);
return {
success: true,
message: "Pallet Was Relocated",
status: results.status,
};
} catch (error: any) {
console.log(error);
return {
success: false,
status: 200,
message: error.response?.data.errors[0].message,
};
}
};

View File

@@ -1,41 +1,14 @@
import axios from "axios";
import { commandLog } from "../../../../../database/schema/commandLog.js";
import { prodEndpointCreation } from "../../../../globalUtils/createUrl.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { lstAuth } from "../../../../index.js";
import { createSSCC } from "../../../../globalUtils/createSSCC.js";
import { db } from "../../../../../database/dbclient.js";
import net from "net";
import { commandLog } from "../../../../../database/schema/commandLog.js";
import { scanner } from "../../../../globalUtils/scannerConnect.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { query } from "../../../sqlServer/prodSqlServer.js";
import { labelInfo } from "../../../sqlServer/querys/warehouse/labelInfo.js";
import { settings } from "../../../../../database/schema/settings.js";
import { eq } from "drizzle-orm";
import { serverData } from "../../../../../database/schema/serverData.js";
export const removeAsNonReusable = async (data: any) => {
// const removalUrl = await prodEndpointCreation(
// "/public/v1.0/Warehousing/RemoveAsNonReusableMaterial"
// );
// const sscc = await createSSCC(data.runningNr);
// const { data: remove, error } = await tryCatch(
// axios.post(
// removalUrl,
// { scannerId: "500", sscc: sscc.slice(2) },
// {
// headers: { Authorization: `Basic ${lstAuth}` },
// }
// )
// );
// use a scanner tcp connection to trigger this process
const STX = "\x02";
const ETX = "\x03";
const scanner = new net.Socket();
let stage = 0;
// get the label info
const { data: label, error: labelError } = (await tryCatch(
query(labelInfo.replaceAll("[runningNr]", data.runningNr), "Label Info")
query(labelInfo.replaceAll("[runningNr]", data.runningNr), "Label Info"),
)) as any;
if (label.data[0].stockStatus === "notOnStock") {
@@ -46,60 +19,17 @@ export const removeAsNonReusable = async (data: any) => {
};
}
// get the server ip based on the token.
const setting = await db.select().from(settings);
const plantInfo = await db.select().from(serverData);
const plantToken = setting.filter((n: any) => n.name === "plantToken");
const scannerID = setting.filter((n: any) => n.name === "scannerID");
const scannerPort = setting.filter((n: any) => n.name === "scannerPort");
const plantData = plantInfo.filter(
(p: any) => p.plantToken === plantToken[0].value
);
scanner.connect(
parseInt(scannerPort[0].value),
plantData[0].idAddress!,
async () => {
// need to get the ip from the server data and scanner port
//console.log(`connected to scanner`);
scanner.write(`${STX}${scannerID[0].value}@AlplaPRODcmd23${ETX}`);
}
);
scanner.on("data", (data) => {
const response = data.toString();
//console.log("Received:", response.trimStart());
if (stage === 0) {
stage = 1;
scanner.write(
`${STX}${scannerID[0].value}@${label.data[0].Barcode}${ETX}`
);
} else if (stage === 1) {
scanner.end();
}
});
scanner.on("close", () => {
//console.log("Connection closed");
scanner.destroy();
});
scanner.on("error", (err) => {
//console.error("Scanner error:", err);
scanner.destroy();
if (label.data[0].blockingReason) {
return {
success: false,
message: `The label: ${data.runningNr} encountering an error while being removed, please try again`,
status: 400,
message: `${data.runningNr} is currently blocked, to get this pallet removed please take the label to quality to be released then you can remove.`,
data: [],
};
});
}
// if (error) {
// //console.log(error);
// return {
// success: false,
// message: `There was an error removing ${data.runningNr}`,
// data: [],
// };
// }
await scanner.scan("AlplaPRODcmd23");
await scanner.scan(`${label.data[0].barcode}`);
let reason = data.reason || "";
delete data.reason;
@@ -109,7 +39,7 @@ export const removeAsNonReusable = async (data: any) => {
commandUsed: "removeAsNonReusable",
bodySent: data,
reasonUsed: reason,
})
}),
);
return {

View File

@@ -0,0 +1,96 @@
import XLSX from "xlsx";
import { db } from "../../../../../../../database/dbclient.js";
import { settings } from "../../../../../../../database/schema/settings.js";
import { delay } from "../../../../../../globalUtils/delay.js";
import { tryCatch } from "../../../../../../globalUtils/tryCatch.js";
import { excelDateStuff } from "../../../../utils/excelDateStuff.js";
import { postForecast } from "../postForecast.js";
export const abbottForecast = async (sheet: any, user: any) => {
const customerId = 8;
const posting: any = [];
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 customHeaders = [
"date",
"time",
"newton8oz",
"newton10oz",
"E",
"F",
"fDate",
"f8ozqty",
"I",
"J",
"K",
"L",
"M",
"f10ozqty",
];
const forecastData = XLSX.utils.sheet_to_json(sheet, {
range: 5, // Start at row 5 (index 4)
header: customHeaders,
defval: "", // Default value for empty cells
});
for (let i = 1; i < forecastData.length; i++) {
const row: any = forecastData[i];
//console.log(row);
//if (row.fDate == undefined) continue;
if (row.fDate !== "") {
const date = isNaN(row.fDate)
? new Date(row.fDate)
: excelDateStuff(row.fDate);
// for 8oz do
if (row.f8ozqty > 0) {
posting.push({
customerArticleNo: "45300DA",
quantity: row.f8ozqty,
requirementDate: date,
});
}
if (row.f10ozqty > 0) {
posting.push({
customerArticleNo: "43836DA",
quantity: row.f10ozqty,
requirementDate: date,
});
}
}
}
// 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],
};
const forecast: any = await postForecast(updatedPredefinedObject, user);
return {
success: forecast.success,
message: forecast.message,
data: forecast.data,
};
};

View File

@@ -1,13 +1,14 @@
import { addDays } from "date-fns";
import XLSX from "xlsx";
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 { createLog } from "../../../../../logger/logger.js";
import { sendEmail } from "../../../../../notifications/controller/sendMail.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";
import { excelDateStuff } from "../../../../utils/excelDateStuff.js";
import { postForecast } from "../postForecast.js";
export const energizerForecast = async (data: any, user: any) => {
/**
@@ -55,23 +56,29 @@ export const energizerForecast = async (data: any, user: any) => {
for (let j = 1; j < row.length; j++) {
const qty = row[j];
if (qty && qty !== 0) {
if (qty && qty > 0) {
const requirementDate = rows[0][j]; // first row is dates
const date = isNaN(requirementDate)
? new Date(requirementDate)
: excelDateStuff(requirementDate);
console.log(isNaN(requirementDate), requirementDate, date);
posting.push({
customerArticleNo: material,
quantity: qty,
requirementDate: new Date(requirementDate),
requirementDate: date,
});
}
}
}
//console.log(posting);
// the predefined data that will never change
const predefinedObject = {
receivingPlantId: plantToken[0].value,
documentName: `ForecastFromLST-${new Date(Date.now()).toLocaleString(
"en-US"
"en-US",
)}`,
sender: user.username || "lst-system",
customerId: customerId,

View File

@@ -1,12 +1,14 @@
import { addDays, addHours, isAfter, parse, subDays } from "date-fns";
import { format } from "date-fns-tz";
import XLSX from "xlsx";
import { excelDateStuff } from "../../../../utils/excelDateStuff.js";
import { tryCatch } from "../../../../../../globalUtils/tryCatch.js";
import { db } from "../../../../../../../database/dbclient.js";
import { settings } from "../../../../../../../database/schema/settings.js";
import { tryCatch } from "../../../../../../globalUtils/tryCatch.js";
import { query } from "../../../../../sqlServer/prodSqlServer.js";
import { bulkOrderArticleInfo } from "../../../../../sqlServer/querys/dm/bulkOrderArticleInfo.js";
import { addDays, addHours, isAfter, parse } from "date-fns";
import { orderState } from "../../../../../sqlServer/querys/dm/orderState.js";
import { excelDateStuff } from "../../../../utils/excelDateStuff.js";
import { abbottForecast } from "../../forecast/mappings/abbott.js";
import { postOrders } from "../postOrders.js";
// customeris/articles stuff will be in basis once we move to iowa
@@ -32,8 +34,8 @@ export const abbottOrders = async (data: any, user: any) => {
const { data: article, error: ae } = await tryCatch(
query(
bulkOrderArticleInfo.replace("[articles]", articles),
"Get Article data for bulk orders"
)
"Get Article data for bulk orders",
),
);
const a: any = article?.data;
if (ae) {
@@ -46,7 +48,7 @@ export const abbottOrders = async (data: any, user: any) => {
// order state
const { data: o, error: oe } = await tryCatch(
query(orderState, "Gets the next 500 orders that have not been started")
query(orderState, "Gets the next 500 orders that have not been started"),
);
const openOrders: any = o?.data;
@@ -69,6 +71,7 @@ export const abbottOrders = async (data: any, user: any) => {
const sheetName = workbook.SheetNames[0];
const sheet = workbook.Sheets[sheetName];
abbottForecast(sheet, user);
// Define custom headers
const customHeaders = ["date", "time", "newton8oz", "newton10oz"];
const orderData = XLSX.utils.sheet_to_json(sheet, {
@@ -81,58 +84,65 @@ export const abbottOrders = async (data: any, user: any) => {
const predefinedObject = {
receivingPlantId: plantToken[0].value,
documentName: `OrdersFromLST-${new Date(Date.now()).toLocaleString(
"en-US"
"en-US",
)}`,
sender: user.username || "lst-system",
externalRefNo: `OrdersFromLST-${new Date(Date.now()).toLocaleString(
"en-US"
"en-US",
)}`,
orders: [],
};
const oOrders: any = openOrders;
//console.log(orderData);
function trimAll(str: string) {
return str.replace(/\s+/g, "");
}
let correctedOrders: any = orderData
.filter(
(o: any) =>
(o.newton8oz && o.newton8oz.trim() !== "") ||
(o.newton10oz && o.newton10oz.trim() !== "")
(o.newton10oz && o.newton10oz.trim() !== ""),
)
.map((o: any) => ({
date: excelDateStuff(o.date, o.time),
po:
o.newton8oz.replace(/\s+/g, "") !== ""
? o.newton8oz.replace(/\s+/g, "")
: o.newton10oz.replace(/\s+/g, ""),
trimAll(o.newton8oz) !== ""
? trimAll(o.newton8oz)
: o.newton10oz.replace(/[\s\u00A0]+/g, ""),
customerArticlenumber:
o.newton8oz != ""
? a.filter((a: any) => a.av === 118)[0]
.CustomerArticleNumber
: a.filter((a: any) => a.av === 120)[0]
.CustomerArticleNumber,
? a.filter((a: any) => a.av === 118)[0].CustomerArticleNumber
: a.filter((a: any) => a.av === 120)[0].CustomerArticleNumber,
qty:
o.newton8oz != ""
? a.filter((a: any) => a.av === 118)[0].totalTruckLoad
: a.filter((a: any) => a.av === 120)[0].totalTruckLoad,
}));
//console.log(correctedOrders);
// now we want to make sure we only correct orders that or after now
correctedOrders = correctedOrders.filter((o: any) => {
const parsedDate = parse(o.date, "M/d/yyyy, h:mm:ss a", new Date());
return isAfter(o.date, new Date().toISOString());
return isAfter(new Date(o.date), new Date().toISOString());
});
//console.log(correctedOrders);
// last map to remove orders that have already been started
// correctedOrders = correctedOrders.filter((oo: any) =>
// oOrders.some((o: any) => o.CustomerOrderNumber === oo.po)
// );
let postedOrders: any = [];
const filterOrders: any = correctedOrders;
//console.log(filterOrders);
filterOrders.forEach((oo: any) => {
const isMatch = openOrders.some(
(o: any) => String(o.po).trim() === String(oo.po).trim()
(o: any) => String(o.po).trim() === String(oo.po).trim(),
);
//console.log(isMatch, oo.po);
if (!isMatch) {
//console.log(`ok to update: ${oo.po}`);
console.log(`ok to update: ${oo.po}`);
// oo = {
// ...oo,
@@ -147,6 +157,7 @@ export const abbottOrders = async (data: any, user: any) => {
// Map Excel data to predefinedObject format
const orders = filterOrders.map((o: any) => {
//console.log(o.po, " ", o.date, format(o.date, "M/d/yyyy HH:mm"));
return {
customerId: customerID,
invoiceAddressId: invoiceID,
@@ -157,7 +168,7 @@ export const abbottOrders = async (data: any, user: any) => {
deliveryAddressId: 8,
customerArticleNo: o.customerArticlenumber,
quantity: o.qty,
deliveryDate: addHours(addDays(o.date, 1), 1), // adding this in so we can over come the constant 1 day behind thing as a work around
deliveryDate: format(o.date, "M/d/yyyy HH:mm"), // addHours(format(o.date, "M/d/yyyy HH:mm"), 1), //addHours(addDays(o.date, 1), 1), // adding this in so we can over come the constant 1 day behind thing as a work around
customerLineItemNo: 1, // this is how it is currently sent over from abbott
customerReleaseNo: 1, // same as above
},
@@ -165,6 +176,7 @@ export const abbottOrders = async (data: any, user: any) => {
};
});
//console.log(orders);
// combine it all together.
const updatedPredefinedObject = {
...predefinedObject,

View File

@@ -1,11 +1,11 @@
import XLSX from "xlsx";
import { tryCatch } from "../../../../../../globalUtils/tryCatch.js";
import { db } from "../../../../../../../database/dbclient.js";
import { settings } from "../../../../../../../database/schema/settings.js";
import { tryCatch } from "../../../../../../globalUtils/tryCatch.js";
import { query } from "../../../../../sqlServer/prodSqlServer.js";
import { invoiceAddress } from "../../../../../sqlServer/querys/dm/invoiceAddress.js";
import { orderState } from "../../../../../sqlServer/querys/dm/orderState.js";
import { excelDateStuff } from "../../../../utils/excelDateStuff.js";
import { invoiceAddress } from "../../../../../sqlServer/querys/dm/invoiceAddress.js";
import { postOrders } from "../postOrders.js";
export const energizerOrders = async (data: any, user: any) => {
@@ -25,7 +25,7 @@ export const energizerOrders = async (data: any, user: any) => {
// order state
const { data: o, error: oe } = await tryCatch(
query(orderState, "Gets the next 500 orders that have not been started")
query(orderState, "Gets the next 500 orders that have not been started"),
);
const openOrders: any = o?.data;
@@ -40,7 +40,7 @@ export const energizerOrders = async (data: any, user: any) => {
// order state
const { data: invoice, error: ie } = await tryCatch(
query(invoiceAddress, "Gets invoices addresses")
query(invoiceAddress, "Gets invoices addresses"),
);
const i: any = invoice?.data;
@@ -83,11 +83,11 @@ export const energizerOrders = async (data: any, user: any) => {
const predefinedObject = {
receivingPlantId: plantToken[0].value,
documentName: `OrdersFromLST-${new Date(Date.now()).toLocaleString(
"en-US"
"en-US",
)}`,
sender: user.username || "lst-system",
externalRefNo: `OrdersFromLST-${new Date(Date.now()).toLocaleString(
"en-US"
"en-US",
)}`,
orders: [],
};
@@ -97,8 +97,8 @@ export const energizerOrders = async (data: any, user: any) => {
// filter out the orders that have already been started just to reduce the risk of errors.
newOrders.filter((oo: any) =>
openOrders.some(
(o: any) => o.CustomerOrderNumber === oo.CustomerOrderNumber
)
(o: any) => o.CustomerOrderNumber === oo.CustomerOrderNumber,
),
);
// filter out the blanks
@@ -119,7 +119,7 @@ export const energizerOrders = async (data: any, user: any) => {
// // map everything out for each order
const nOrder = newOrders.map((o: any) => {
const invoice = i.filter(
(i: any) => i.deliveryAddress === parseInt(o.CUSTOMERID)
(i: any) => i.deliveryAddress === parseInt(o.CUSTOMERID),
);
if (!invoice) {
return;
@@ -137,7 +137,7 @@ export const energizerOrders = async (data: any, user: any) => {
deliveryDate: o.DELDATE, //excelDateStuff(o.DELDATE),
customerLineItemNo: o.ReleaseNo, // this is how it is currently sent over from abbott
customerReleaseNo: o.ReleaseNo, // same as above
remark: o.remark === "" ? null : o.remark,
remark: o.COMMENTS === "" ? null : o.COMMENTS,
},
],
};

View File

@@ -0,0 +1,166 @@
import XLSX from "xlsx";
import { db } from "../../../../../../../database/dbclient.js";
import { settings } from "../../../../../../../database/schema/settings.js";
import { tryCatch } from "../../../../../../globalUtils/tryCatch.js";
import { query } from "../../../../../sqlServer/prodSqlServer.js";
import { invoiceAddress } from "../../../../../sqlServer/querys/dm/invoiceAddress.js";
import { orderState } from "../../../../../sqlServer/querys/dm/orderState.js";
import { excelDateStuff } from "../../../../utils/excelDateStuff.js";
import { postOrders } from "../postOrders.js";
export const scjOrders = async (data: any, user: any) => {
/**
* Standard orders meaning that we get the standard file exported and fill it out and uplaod to lst.
*/
const customerID = 48;
const { data: s, error: e } = await tryCatch(db.select().from(settings));
if (e) {
return {
sucess: false,
message: `Error getting settings`,
data: e,
};
}
// order state
const { data: o, error: oe } = await tryCatch(
query(orderState, "Gets the next 500 orders that have not been started"),
);
const openOrders: any = o?.data;
if (oe) {
return {
sucess: false,
message: `Error getting article data`,
data: oe,
};
}
// order state
const { data: invoice, error: ie } = await tryCatch(
query(invoiceAddress, "Gets invoices addresses"),
);
const i: any = invoice?.data;
if (ie) {
return {
sucess: false,
message: `Error getting invoice address data`,
data: ie,
};
}
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 sheetName: any = workbook.Sheets["Sheet1"];
const sheet = XLSX.utils.decode_range(sheetName["!ref"]);
// define custom headers
const headers = [
"ItemNo",
"Description",
"DeliveryDate",
"Quantity",
"PO",
"Releases",
"remarks",
];
const orderData = XLSX.utils.sheet_to_json(sheetName, {
defval: "",
header: headers,
range: 1,
});
// the base of the import
const predefinedObject = {
receivingPlantId: plantToken[0].value,
documentName: `OrdersFromLST-${new Date(Date.now()).toLocaleString(
"en-US",
)}`,
sender: user.username || "lst-system",
externalRefNo: `OrdersFromLST-${new Date(Date.now()).toLocaleString(
"en-US",
)}`,
orders: [],
};
let newOrders: any = orderData;
// filter out the orders that have already been started just to reduce the risk of errors.
newOrders.filter((oo: any) =>
openOrders.some(
(o: any) => o.CustomerOrderNumber === oo.CustomerOrderNumber,
),
);
// filter out the blanks
newOrders = newOrders.filter((z: any) => z.ItemNo !== "");
const nOrder = newOrders.map((o: any) => {
const invoice = i.filter((i: any) => i.deliveryAddress === customerID);
if (!invoice) {
return;
}
if (o.Releases === "") {
return;
}
if (o.PO === "") {
return;
}
const date = isNaN(o.DeliveryDate)
? new Date(o.DeliveryDate)
: excelDateStuff(o.DeliveryDate);
return {
customerId: customerID,
invoiceAddressId: invoice[0].invoiceAddress, // matched to the default invoice address
customerOrderNo: o.PO,
orderDate: new Date(Date.now()).toLocaleString("en-US"),
positions: [
{
deliveryAddressId: customerID,
customerArticleNo: o.ItemNo,
quantity: parseInt(o.Quantity),
deliveryDate: date, //excelDateStuff(o.DELDATE),
customerLineItemNo: o.PO, // this is how it is currently sent over from abbott
customerReleaseNo: o.Releases, // same as above
remark: o.remarks === "" ? null : o.remarks,
},
],
};
});
//console.log(nOrder.filter((o: any) => o !== undefined));
// // do that fun combining thing
const updatedPredefinedObject = {
...predefinedObject,
orders: [
...predefinedObject.orders,
...nOrder.filter((o: any) => o !== undefined),
],
};
//console.log(updatedPredefinedObject.orders[0]);
// // post the orders to the server
const posting: any = await postOrders(updatedPredefinedObject, user);
return {
customer: customerID,
//totalOrders: orders?.length(),
success: posting.success,
message: posting.message,
data: posting.data,
};
};

View File

@@ -1,6 +1,7 @@
import { abbottOrders } from "./mappings/abbottTruckList.js";
import { energizerOrders } from "./mappings/energizerOrdersIn.js";
import { macroImportOrders } from "./mappings/macroImport.js";
import { scjOrders } from "./mappings/scj.js";
import { standardOrders } from "./mappings/standardOrders.js";
export const ordersIn = async (data: any, user: any) => {
@@ -53,6 +54,14 @@ export const ordersIn = async (data: any, user: any) => {
orderData = macro.data;
}
if (data["fileType"] === "scj") {
// orders in
const macro = await scjOrders(data["postOrders"], user);
success = macro.success ?? false;
message = macro.message ?? "Error posting Macro Orders";
orderData = macro.data;
}
return {
success,
message,

View File

@@ -1,13 +1,12 @@
import axios from "axios";
import { labelData } from "../../../sqlServer/querys/materialHelpers/labelInfo.js";
import { query } from "../../../sqlServer/prodSqlServer.js";
import { createLog } from "../../../logger/logger.js";
import { prodEndpointCreation } from "../../../../globalUtils/createUrl.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { db } from "../../../../../database/dbclient.js";
import { commandLog } from "../../../../../database/schema/commandLog.js";
import { prodEndpointCreation } from "../../../../globalUtils/createUrl.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { createLog } from "../../../logger/logger.js";
import { query } from "../../../sqlServer/prodSqlServer.js";
import { labelData } from "../../../sqlServer/querys/materialHelpers/labelInfo.js";
import { labelInfo } from "../../../sqlServer/querys/warehouse/labelInfo.js";
type Data = {
runningNr: string;
@@ -17,14 +16,15 @@ export const consumeMaterial = async (data: Data) => {
const { runningNr, lotNum } = data;
// replace the rn
console.log(data);
// console.log(data);
const rnReplace = labelData.replaceAll("[rn]", runningNr);
const rnReplace = labelInfo.replaceAll("[runningNr]", runningNr);
let barcode;
// get the barcode from the running number
try {
const r: any = await query(rnReplace, "labelData");
//console.log(r);
barcode = r?.data;
} catch (error) {
console.log(error);
@@ -40,7 +40,7 @@ export const consumeMaterial = async (data: Data) => {
}
// create the url to post
const url = await prodEndpointCreation(
"/public/v1.0/IssueMaterial/ConsumeNonPreparedManualMaterial"
"/public/v1.0/IssueMaterial/ConsumeNonPreparedManualMaterial",
);
const consumeSomething = {
@@ -60,7 +60,7 @@ export const consumeMaterial = async (data: Data) => {
db.insert(commandLog).values({
commandUsed: "consumeMaterial",
bodySent: data,
})
}),
);
return {
success: true,

View File

@@ -1,6 +1,7 @@
import axios from "axios";
import { prodEndpointCreation } from "../../../../globalUtils/createUrl.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { query } from "../../../sqlServer/prodSqlServer.js";
export const postAdjustment = async (data: any) => {
if (data.warehouseId === undefined) {
@@ -35,9 +36,30 @@ export const postAdjustment = async (data: any) => {
quantity: data.quantity,
};
let url = await prodEndpointCreation(
"/public/v1.0/Warehousing/AdjustSiloStockLevel",
);
// do we have warehousing turned on?
const { data: feature, error: featureError } = (await tryCatch(
query(
`SELECT [Id]
,[Feature]
,[Enabled]
,[ActivationDate]
FROM [test1_AlplaPROD2.0_Read].[support].[FeatureActivation] where [Feature] = 7`,
"feature switch check",
),
)) as any;
let prodUrl = "/public/v1.0/Warehousing/AdjustSiloStockLevel";
if (featureError) {
prodUrl = "/public/v1.0/Warehousing/AdjustSiloStockLevel";
}
if (feature?.data.length > 0) {
prodUrl = "/public/v1.1/Warehousing/Lane/AdjustSiloStockLevel";
}
// 1.0 "/public/v1.0/Warehousing/AdjustSiloStockLevel","
// 1.1 "/public/v1.1/Warehousing/Lane/AdjustSiloStockLevel"
let url = await prodEndpointCreation(prodUrl);
const { data: silo, error } = await tryCatch(
axios.post(url, siloAdjustment, {

View File

@@ -1,7 +1,9 @@
import { OpenAPIHono } from "@hono/zod-openapi";
import { migrateAdjustments } from "./controller/siloAdjustments/migrateAdjustments.js";
import { getLanesToCycleCount } from "./controller/warehouse/cycleCountChecks/cyclecountCheck.js";
import attachSilo from "./route/attachSilo.js";
import bookOutPallet from "./route/bookout.js";
import comsumeMaterial from "./route/consumeMaterial.js";
import detachSilo from "./route/detachSilo.js";
import postBulkOrders from "./route/dm/bulkOrdersIn.js";
@@ -16,6 +18,7 @@ import outbound from "./route/getOutbound.js";
import getPPOO from "./route/getPPOO.js";
import getConnectionType from "./route/getSiloConnectionData.js";
import getSSCC from "./route/getSSCCNumber.js";
import relocate from "./route/relocate.js";
import removeAsNonReable from "./route/removeAsNonReusable.js";
import returnMat from "./route/returnMaterial.js";
import createSiloAdjustment from "./route/siloAdjustments/createSiloAdjustment.js";
@@ -28,7 +31,7 @@ const app = new OpenAPIHono();
const routes = [
comsumeMaterial,
returnMat,
relocate,
// silo
createSiloAdjustment,
postComment,
@@ -55,6 +58,7 @@ const routes = [
// logisitcs
removeAsNonReable,
getSSCC,
bookOutPallet,
] as const;
// app.route("/server", modules);

View File

@@ -0,0 +1,87 @@
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { verify } from "hono/jwt";
import { apiHit } from "../../../globalUtils/apiHits.js";
import { tryCatch } from "../../../globalUtils/tryCatch.js";
//import { authMiddleware } from "../../auth/middleware/authMiddleware.js";
import { bookOutPallet } from "../controller/commands/bookout.js";
const app = new OpenAPIHono();
const responseSchema = z.object({
success: z.boolean().optional().openapi({ example: true }),
message: z.string().optional().openapi({ example: "user access" }),
});
app.openapi(
createRoute({
tags: ["logistics"],
summary: "Consumes material based on its running number",
method: "post",
path: "/bookout",
//middleware: authMiddleware,
description:
"Provided a running number and lot number you can consume material.",
responses: {
200: {
content: { "application/json": { schema: responseSchema } },
description: "stopped",
},
400: {
content: { "application/json": { schema: responseSchema } },
description: "Failed to stop",
},
401: {
content: { "application/json": { schema: responseSchema } },
description: "Failed to stop",
},
},
}),
async (c) => {
const { data, error } = await tryCatch(c.req.json());
if (error) {
return c.json(
{
success: false,
message: "Missing data please try again",
error,
},
400,
);
}
apiHit(c, { endpoint: "/bookout", lastBody: data });
//const authHeader = c.req.header("Authorization");
//const token = authHeader?.split("Bearer ")[1] || "";
//const payload = await verify(token, process.env.JWT_SECRET!);
try {
//return apiReturn(c, true, access?.message, access?.data, 200);
//const pointData = { ...data, user: payload.user };
const bookout = await bookOutPallet(data);
console.log("from booout:", bookout);
return c.json(
{
success: bookout?.success,
message: bookout?.message,
data: bookout.data,
},
200,
);
} catch (error) {
console.log("from error:", 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,
);
}
},
);
export default app;

View File

@@ -0,0 +1,80 @@
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { apiHit } from "../../../globalUtils/apiHits.js";
import { tryCatch } from "../../../globalUtils/tryCatch.js";
import { authMiddleware } from "../../auth/middleware/authMiddleware.js";
import { relatePallet } from "../controller/commands/relocated.js";
const app = new OpenAPIHono();
const responseSchema = z.object({
success: z.boolean().optional().openapi({ example: true }),
message: z.string().optional().openapi({ example: "user access" }),
});
app.openapi(
createRoute({
tags: ["logistics"],
summary: "Consumes material based on its running number",
method: "post",
path: "/relocate",
//middleware: authMiddleware,
description:
"Provided a running number and lot number you can consume material.",
responses: {
200: {
content: { "application/json": { schema: responseSchema } },
description: "stopped",
},
400: {
content: { "application/json": { schema: responseSchema } },
description: "Failed to stop",
},
401: {
content: { "application/json": { schema: responseSchema } },
description: "Failed to stop",
},
},
}),
async (c) => {
const { data, error } = await tryCatch(c.req.json());
if (error) {
return c.json(
{
success: false,
message: "Missing data please try again",
error,
},
400,
);
}
apiHit(c, { endpoint: "/relocate", lastBody: data });
//const authHeader = c.req.header("Authorization");
//const token = authHeader?.split("Bearer ")[1] || "";
//const payload = await verify(token, process.env.JWT_SECRET!);
try {
//return apiReturn(c, true, access?.message, access?.data, 200);
const consume = await relatePallet(data);
console.log(consume);
return c.json(
{ success: consume?.success, message: consume?.message },
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,
);
}
},
);
export default app;

View File

@@ -1,34 +1,60 @@
import { getJsDateFromExcel } from "excel-date-to-js";
export const excelDateStuff = (serial: number, time: any = 0) => {
// console.log(serial);
// add 5 hours or the offset to utc
// export const excelDateStuff = (serial: number, time?: any) => {
// // add 5 hours or the offset to utc
// get the local timezone
const localoffset = new Date().getTimezoneOffset() / 60; // then divide by 60 to get the true number;
// // get the local timezone
// const localoffset = new Date().getTimezoneOffset() / 60; // then divide by 60 to get the true number;
if (serial % 1 === 0) {
time = 800;
}
// if (!time) {
// time = 800;
// }
const addHours = serial + localoffset / 24;
//console.log(getJsDateFromExcel(addHours));
// const addHours = serial + localoffset / 24;
// //console.log(getJsDateFromExcel(addHours));
// if (typeof serial !== "number" || serial <= 0) {
// return "invalid Date";
// }
// const date = getJsDateFromExcel(addHours); // base date from Excel serial
// if (time != 0) {
// // convert the time over to hour and min
// const hours = Math.floor(time / 100);
// const minutes = time % 100;
// date.setHours(hours);
// date.setMinutes(minutes);
// }
// //console.log(date.toLocaleString("en-US"), getJsDateFromExcel(addHours));
// //console.log(serial);
// console.log(date.toISOString(), serial, time);
// return date.toISOString(); //.toLocaleString("en-US"); // or .toISOString() if preferred
// };
export const excelDateStuff = (serial: number, time?: any) => {
if (typeof serial !== "number" || serial <= 0) {
return "invalid Date";
}
const date = getJsDateFromExcel(addHours); // base date from Excel serial
// Default time to 8:00 AM if not provided
if (!time) {
time = 800;
}
if (time != 0) {
// convert the time over to hour and min
// Get base date from Excel serial (this gives you UTC midnight)
const date = getJsDateFromExcel(serial);
const localOffset = new Date().getTimezoneOffset() / 60;
const hours = Math.floor(time / 100);
const minutes = time % 100;
date.setHours(hours);
date.setMinutes(minutes);
}
//console.log(date.toLocaleString("en-US"), getJsDateFromExcel(addHours));
//console.log(serial);
//console.log(date.toISOString());
return date.toISOString(); //.toLocaleString("en-US"); // or .toISOString() if preferred
// Set the time in UTC
date.setUTCHours(hours + localOffset);
date.setUTCMinutes(minutes);
date.setUTCSeconds(0);
date.setUTCMilliseconds(0);
//console.log(date.toISOString(), serial, time);
return date.toISOString();
};

View File

@@ -4,8 +4,8 @@ import { notifications } from "../../../../../database/schema/notifications.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { createLog } from "../../../logger/logger.js";
import { query } from "../../../sqlServer/prodSqlServer.js";
import { sendEmail } from "../sendMail.js";
import { bow2incoming } from "../../../sqlServer/querys/notifications/bow2henkel.js";
import { sendEmail } from "../sendMail.js";
const notification = async (notifyData: any) => {
/**
@@ -19,7 +19,7 @@ const notification = async (notifyData: any) => {
"error",
"reprinting",
"notify",
`There are no emails set for ${notifyData.name}`
`There are no emails set for ${notifyData.name}`,
);
return;
}
@@ -28,12 +28,9 @@ const notification = async (notifyData: any) => {
const { data: l, error: labelError } = await tryCatch(
query(
bow2incoming.replace(
"[time]",
notifyData.notifiySettings.processTime
bow2incoming.replace("[time]", notifyData.notifiySettings.processTime),
"Label Reprints",
),
"Label Reprints"
)
);
const labels: any = l?.data as any;
if (labelError) {
@@ -41,7 +38,7 @@ const notification = async (notifyData: any) => {
"error",
"reprinting",
"notify",
`Failed to get the labels: ${labelError}`
`Failed to get the labels: ${labelError}`,
);
return;
}
@@ -65,7 +62,7 @@ const notification = async (notifyData: any) => {
"error",
"reprinting",
"notify",
"Failed to send email, will try again on next interval"
"Failed to send email, will try again on next interval",
);
return;
}
@@ -88,7 +85,7 @@ const notification = async (notifyData: any) => {
prodID: labels[0].IdEtikettenHistorie,
},
})
.where(eq(notifications.name, notifyData.name))
.where(eq(notifications.name, notifyData.name)),
);
} else {
return;

View File

@@ -0,0 +1,108 @@
import { eq, sql } from "drizzle-orm";
import { db } from "../../../../../database/dbclient.js";
import { notifications } from "../../../../../database/schema/notifications.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { createLog } from "../../../logger/logger.js";
import { query } from "../../../sqlServer/prodSqlServer.js";
import {
type SqlQuery,
sqlQuerySelector,
} from "../../../sqlServer/utils/querySelector.utils.js";
import { sendEmail } from "../sendMail.js";
export interface Labels {
IdEtikettenHistorie?: number;
}
const notification = async (notifyData: any) => {
/**
* Pass the entire notification over
*/
createLog("debug", "reprinting", "notify", `monitoring ${notifyData.name}`);
// validate if there are any emails.
if (notifyData.emails === "") {
createLog(
"error",
"reprinting",
"notify",
`There are no emails set for ${notifyData.name}`,
);
return;
}
const cycleCountCheck = sqlQuerySelector("cycleCountCheck.query") as SqlQuery;
if (!cycleCountCheck.success) {
console.log("Failed to load the query: ", cycleCountCheck.message);
return;
}
const { data: c, error: cError } = await tryCatch(
query(
cycleCountCheck.query.replace("[timeTest]", notifyData.checkInterval),
"Cycle count check",
),
);
const cycle: any = c?.data ?? ([] as any);
//console.log(cycle);
if (cError) {
createLog(
"error",
"reprinting",
"notify",
`Failed to get the labels: ${cError}`,
);
return;
}
if (cycle.length > 0) {
//send the email :D
const emailSetup = {
email: notifyData.emails,
subject: `Alert! RowBlocked for more than ${notifyData.checkInterval} min(s)`,
template: "cycleCountCheck",
context: {
checkTime: notifyData.checkInterval,
items: cycle,
},
};
const sentEmail = await sendEmail(emailSetup);
if (!sentEmail.success) {
createLog(
"error",
"reprinting",
"notify",
"Failed to send email, will try again on next interval",
);
return;
}
// // update the last time we ran and the prod id
// const notifUpdate = {
// prodID: labels[0].IdEtikettenHistorie,
// lastRan: nowDate(),
// };
// update the last time ran
const { data, error } = await tryCatch(
db
.update(notifications)
.set({
lastRan: sql`NOW()`,
// notifiySettings: {
// ...notifyData.notifiySettings,
// prodID: labels[0].IdEtikettenHistorie,
// },
})
.where(eq(notifications.name, notifyData.name)),
);
} else {
return;
}
};
export default notification;

View File

@@ -1,21 +1,21 @@
import { isBefore } from "date-fns";
import { db } from "../../../../../database/dbclient.js";
import { fifoIndex } from "../../../../../database/schema/fifoIndex.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { query } from "../../../sqlServer/prodSqlServer.js";
import { currentInv } from "../../../sqlServer/querys/notifications/fifoIndex/currentInv.js";
import { shippedPallets } from "../../../sqlServer/querys/notifications/fifoIndex/shippedPallets.js";
import { db } from "../../../../../database/dbclient.js";
import { fifoIndex } from "../../../../../database/schema/fifoIndex.js";
export default async function fifoIndexCheck() {
/**
* getting the shipped pallets
*/
const { data: shipped, error: eShipped } = await tryCatch(
query(shippedPallets, "notify shipped pallets")
query(shippedPallets, "notify shipped pallets"),
);
const { data: currentStuff, error: eCurrentInv } = await tryCatch(
query(currentInv, "notify shipped pallets")
query(currentInv, "notify shipped pallets"),
);
// console.log(shipped?.data[2]);
@@ -24,14 +24,14 @@ export default async function fifoIndexCheck() {
/**
* We want to check if the each shippened pallet is out of fifo
*/
const check = shipped?.data.map((n: any) => {
const check: any = shipped?.data.map((n: any) => {
/**
* Returns all data so we know if we are in or out.
*/
//check if there are pallets older than the current one we are mapped on.
const fifoCheck = currentStuff?.data.filter(
(i: any) => isBefore(i.prodDate, n.prodDate) && i.av === n.av
);
(i: any) => isBefore(i.prodDate, n.prodDate) && i.av === n.av,
) as any;
//console.log(fifoCheck.length);
if (fifoCheck.length > 0) {
// console.log("Out of fifo", {
@@ -83,7 +83,7 @@ export default async function fifoIndexCheck() {
/**
* add the data to the db
*/
for (let i = 0; i < check.length; i++) {
for (let i = 0; i < check!.length; i++) {
const { data: dbInsert, error: dbE } = await tryCatch(
db
.insert(fifoIndex)
@@ -95,7 +95,7 @@ export default async function fifoIndexCheck() {
fifoFollowed: check[i].fifoFollowed,
add_Date: check[i].add_Date,
})
.onConflictDoNothing()
.onConflictDoNothing(),
);
}
@@ -105,7 +105,7 @@ export default async function fifoIndexCheck() {
data: {
palletsOut: check,
totalShipped: shipped?.data.length,
inFifo: shipped?.data.length - totalOut,
inFifo: shipped!.data.length - totalOut,
outOfFifoData: outOfFifo,
},
};

View File

@@ -0,0 +1,183 @@
import { eq, sql } from "drizzle-orm";
import { db } from "../../../../../database/dbclient.js";
import { notifications } from "../../../../../database/schema/notifications.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { createLog } from "../../../logger/logger.js";
import { query } from "../../../sqlServer/prodSqlServer.js";
import { sqlQuerySelector } from "../../../sqlServer/utils/querySelector.utils.js";
import { sendEmail } from "../sendMail.js";
let running = false;
export default async function platToPlantEdi(notifyData: any) {
createLog("info", "plantToPlant", "notify", `monitoring ${notifyData.name}`);
if (running) {
createLog(
"info",
"plantToPlant",
"notify",
`Notifcation ${notifyData.name} is already running skipping`,
);
return;
}
running = true;
const { data: noti, error: notiError } = (await tryCatch(
db
.select()
.from(notifications)
.where(eq(notifications.name, notifyData.name)),
)) as any;
if (notiError) {
createLog(
"error",
"edi",
"notify",
"Error in getting the notification data",
);
}
// get the default emails they can be blank if as we will only add these to the end of the email from the full flow
let emails = noti[0]?.email ?? "";
const checkBol = sqlQuerySelector("checkBol.query");
if (!checkBol.success) {
createLog("error", "edi", "notify", "Error in getting the bol query data");
}
const pLinkedB = sqlQuerySelector("palletsLinkedToBol.query");
if (!pLinkedB.success) {
createLog("error", "edi", "notify", "Error in getting the bol query data");
}
let ignoreBols: string[] = noti[0]?.notifiySettings?.processedBol ?? [];
const joinBols = ignoreBols.join(",");
let updateQuery = noti[0]?.notifiySettings?.includeAll
? checkBol?.query?.replace(
"and a.bezeichnung like '%Alpla%'",
"--and a.bezeichnung like '%Alpla%'",
)
: checkBol?.query;
const { data: b, error: bError } = (await tryCatch(
query(
updateQuery
?.replace("[timeCheck]", noti[0]?.checkInterval ?? "30")
.replace("[ignoreBols]", joinBols ?? 500) ?? "",
"Check bol",
),
)) as any;
if (bError) {
return {
success: false,
message: "Error getting newly created bols",
data: bError,
};
}
const planedByBol = new Map<string, string[]>();
for (const row of b.data) {
if (!planedByBol.has(row.bol)) {
planedByBol.set(row.bol, []);
}
planedByBol.get(row.bol)!.push(String(row.idladeplanung));
}
if (b.data.length > 0) {
// loop each bol in the system and get the bols only
for (const [bolNumber, idList] of planedByBol.entries()) {
//for (const bol of b.data) {
// run the process to get the the pallet numbers
const joinedIdLadeplanung = idList.join(",");
//console.log("BOL:", bolNumber);
//console.log("IDLadeplanung string:", joinedIdLadeplanung);
//console.log("IgnoreBols: ", joinBols);
// now get the pallets that are witing the ladeplanning
const { data: pallets, error: pError } = await tryCatch(
query(
pLinkedB?.query?.replace(
"[palLinkedToBol]",
joinedIdLadeplanung ?? "0",
) ?? "",
"Get Pallets linked in the bol",
),
);
//console.log(pallets);
// console.log("Address: ", b.data[0].addressId ?? "0");
if (b.data[0].addressId === "") return;
ignoreBols.push(bolNumber);
if (ignoreBols.length > 15) {
ignoreBols.splice(0, ignoreBols.length - 15);
}
// get the email address.
const checkBol = sqlQuerySelector("addressInfo.query");
const { data: address, error: aError } = (await tryCatch(
query(
checkBol?.query?.replace(
"[customerAddress]",
b.data[0].addressId ?? "0",
) ?? "",
"Get Pallets linked in the bol",
),
)) as any;
if (noti[0]?.emails === "") return; // no default emails
// setup the email to be sent :D
const emailSetup = {
email: `${noti[0]?.emails};${address.data[0].email ?? ""}`,
subject: `New EDI transfer Created for BOL: ${bolNumber}`,
template: "plantToPlantEdi",
context: {
items: pallets?.data ?? [],
bol: bolNumber,
//secondarySetting: notifyData.notifiySettings,
},
};
// send the email
await sendEmail(emailSetup);
// add the bols to be ignored
await db
.update(notifications)
.set({
lastRan: sql`NOW()`,
notifiySettings: {
...noti[0]?.notifiySettings,
processedBol: ignoreBols,
},
})
.where(eq(notifications.name, notifyData.name));
}
running = false;
return {
success: true,
message: "All bols have been processed",
data: [ignoreBols],
};
}
running = false;
return {
success: true,
message: "No new bols have been created",
data: [],
};
}

View File

@@ -0,0 +1,118 @@
// SELECT count(*) FROM V_EtikettenGedruckt where AnzahlGedruckterKopien > 2 and CONVERT(varchar(5), Add_Date,108) not like CONVERT(varchar(5), Upd_Date,108) and Upd_Date > DATEADD(SECOND, -30,getdate()) and VpkVorschriftBez not like '%$%'
import { errorMonitor } from "node:events";
import { eq, sql } from "drizzle-orm";
import { db } from "../../../../../database/dbclient.js";
import { notifications } from "../../../../../database/schema/notifications.js";
import { settings } from "../../../../../database/schema/settings.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { createLog } from "../../../logger/logger.js";
import { sendEmail } from "../sendMail.js";
export interface DownTime {
downTimeId?: number;
machineAlias?: string;
}
export default async function tooManyErrors(notifyData: any) {
// we will over ride this with users that want to sub to this
// a new table will be called subalerts and link to the do a kinda linkn where the user wants it then it dose subId: 1, userID: x, notificationId: y. then in here we look up the userid to get the email :D
// this could then leave the emails in the notificaion blank and let users sub to it.
//console.log(notifyData);
if (notifyData.emails === "") {
createLog(
"error",
"notify",
"notify",
`There are no emails set for ${notifyData.name}`,
);
return;
}
// console.log(data.secondarySetting[0].duration);
const plant = await db
.select()
.from(settings)
.where(eq(settings.name, "plantToken"));
console.log(plant[0].value);
// console.log(
// errorQuery
// .replace("[time]", notifyData.checkInterval)
// .replace("[errorCount]", notifyData.notifiySettings.errorCount),
// errorLogQuery.replace("[time]", notifyData.checkInterval),
// );
let errorLogData: any = [];
try {
const errorData = await db.execute(sql`
SELECT 'error' AS level, COUNT(*) AS error_count
FROM public.logs
WHERE level = 'error'
AND "add_Date" > now() - INTERVAL ${sql.raw(`'${notifyData.checkInterval} minutes'`)}
GROUP BY level
HAVING COUNT(*) >= ${notifyData.notifiySettings.errorCount}
`);
if (
errorData.length > 0
// && downTime[0]?.downTimeId > notifyData.notifiySettings.prodID
) {
const errorLogs = await db.execute(sql`
select* from public.logs where level = 'error' and "add_Date" > now() - INTERVAL ${sql.raw(`'${notifyData.checkInterval} minutes'`)} order by "add_Date" desc;
`);
errorLogData = errorLogs;
//send the email :D
const emailSetup = {
email: notifyData.emails,
subject: `Alert! ${plant[0].value} has encountered ${
errorLogData.length
} ${errorLogData.length > 1 ? "errors" : "error"} in the last ${notifyData.checkInterval} min`,
template: "tooManyErrors",
context: {
data: errorLogData.slice(0, 100),
count: notifyData.notifiySettings.errorCount,
time: notifyData.checkInterval,
},
};
//console.log(emailSetup);
const sentEmail = await sendEmail(emailSetup);
if (!sentEmail.success) {
createLog(
"error",
"notify",
"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",
data: sentEmail,
};
}
}
} catch (err) {
console.log(err);
createLog(
"error",
"notify",
"notify",
`Error from running the downtimeCheck query: ${err}`,
);
return {
success: false,
message: "Error running error data",
data: err,
};
}
return {
success: true,
message: "Error log checking ran",
data: errorLogData ?? [],
};
}

View File

@@ -45,57 +45,57 @@ export const sendEmail = async (data: any): Promise<any> => {
};
}
// get the plantToken
const server = settingData.filter((n) => n.name === "server");
//const server = settingData.filter((n) => n.name === "server");
if (
server[0].value === "localhostx" &&
process.env.EMAIL_USER &&
process.env.EMAIL_PASSWORD
) {
transporter = nodemailer.createTransport({
service: "gmail",
host: "smtp.gmail.com",
port: 465,
auth: {
user: process.env.EMAIL_USER,
pass: process.env.EMAIL_PASSWORD,
},
//debug: true,
});
// update the from email
fromEmail = process.env.EMAIL_USER;
} else {
// convert to the correct plant token.
const plantToken = settingData.filter((s) => s.name === "plantToken");
let host = `${plantToken[0].value}-smtp.alpla.net`;
const testServers = ["test1", "test2", "test3"];
if (testServers.includes(plantToken[0].value)) {
host = "USMCD1-smtp.alpla.net";
}
if (plantToken[0].value === "usiow2") {
host = "USIOW1-smtp.alpla.net";
}
transporter = nodemailer.createTransport({
host: host,
port: 25,
rejectUnauthorized: false,
//secure: false,
// if (
// server[0].value === "localhostx" &&
// process.env.EMAIL_USER &&
// process.env.EMAIL_PASSWORD
// ) {
// transporter = nodemailer.createTransport({
// service: "gmail",
// host: "smtp.gmail.com",
// port: 465,
// auth: {
// user: "alplaprod",
// pass: "obelix",
// user: process.env.EMAIL_USER,
// pass: process.env.EMAIL_PASSWORD,
// },
debug: true,
} as SMTPTransport.Options);
// //debug: true,
// });
// update the from email
fromEmail = `noreply@alpla.com`;
}
// // update the from email
// fromEmail = process.env.EMAIL_USER;
//} else {
// convert to the correct plant token.
//const plantToken = settingData.filter((s) => s.name === "plantToken");
// let host = `${plantToken[0].value}-smtp.alpla.net`;
// const testServers = ["test1", "test2", "test3"];
// if (testServers.includes(plantToken[0].value)) {
// host = "USMCD1-smtp.alpla.net";
// }
// if (plantToken[0].value === "usiow2") {
// host = "USIOW1-smtp.alpla.net";
// }
transporter = nodemailer.createTransport({
host: "smtp.azurecomm.net",
port: 587,
//rejectUnauthorized: false,
tls: {
minVersion: "TLSv1.2",
},
auth: {
user: "donotreply@mail.alpla.com",
pass: process.env.SMTP_PASSWORD,
},
debug: true,
});
fromEmail = `DoNotReply@mail.alpla.com`;
//}
// creating the handlbar options
const viewPath = path.resolve(

View File

@@ -10,7 +10,9 @@ import tiTrigger from "./routes/manualTiggerTi.js";
import materialCheck from "./routes/materialPerDay.js";
import blocking from "./routes/qualityBlocking.js";
import sendemail from "./routes/sendMail.js";
import errorHandling from "./routes/tooManyErrors.js";
import { note, notificationCreate } from "./utils/masterNotifications.js";
import { sqlJobCleanUp } from "./utils/notificationSqlCleanup.js";
import { startNotificationMonitor } from "./utils/processNotifications.js";
const app = new OpenAPIHono();
@@ -23,6 +25,7 @@ const routes = [
notify,
fifoIndex,
materialCheck,
errorHandling,
] as const;
const appRoutes = routes.forEach((route) => {
@@ -55,6 +58,7 @@ if (notesError) {
setTimeout(() => {
notificationCreate();
startNotificationMonitor();
sqlJobCleanUp();
}, 5 * 1000);
export default app;

View File

@@ -0,0 +1,50 @@
// an external way to creating logs
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { eq } from "drizzle-orm";
import { db } from "../../../../database/dbclient.js";
import { notifications } from "../../../../database/schema/notifications.js";
import { apiHit } from "../../../globalUtils/apiHits.js";
import { responses } from "../../../globalUtils/routeDefs/responses.js";
import { tryCatch } from "../../../globalUtils/tryCatch.js";
import { authMiddleware } from "../../auth/middleware/authMiddleware.js";
import hasCorrectRole from "../../auth/middleware/roleCheck.js";
import tooManyErrors from "../controller/notifications/tooManyErrors.js";
import { getAllJobs } from "../utils/processNotifications.js";
const app = new OpenAPIHono({ strict: false });
app.openapi(
createRoute({
tags: ["server"],
summary: "Returns current active notifications.",
method: "get",
path: "/toomanyerrors",
middleware: [authMiddleware, hasCorrectRole(["systemAdmin"], "admin")],
responses: responses(),
}),
async (c) => {
apiHit(c, { endpoint: "/toomanyerrors" });
const { data, error } = await tryCatch(
db
.select()
.from(notifications)
.where(eq(notifications.name, "tooManyErrors")),
);
if (error) {
return c.json({
success: false,
message: "Error Getting Notification Settings.",
data: error,
});
}
const errorData = await tooManyErrors(data[0]);
return c.json({
success: true,
message: "Current Error log data",
data: errorData?.data,
});
},
);
export default app;

View File

@@ -15,8 +15,7 @@ export const note: any = [
},
{
name: "downTimeCheck",
description:
"Checks for specific downtimes that are greater than 105 min.",
description: "Checks for specific downtimes that are greater than 105 min.",
checkInterval: 30,
timeType: "min",
emails: "",
@@ -141,6 +140,40 @@ export const note: any = [
avType: 1,
},
},
{
name: "tooManyErrors",
description:
"Checks to see how many errors in the last x time and sends an email based on this.",
checkInterval: 15,
timeType: "min",
emails: "blake.matthes@alpla.com",
active: true,
notifiySettings: {
errorCount: 10, // change this to something else or leave blank to use the av type
},
},
{
name: "cycleCountCheck",
description:
"Checks if a cycle count has been active for longer than the defined time.",
checkInterval: 60,
timeType: "min",
emails: "",
active: false,
notifiySettings: {
errorCount: 10, // change this to something else or leave blank to use the av type
},
},
{
name: "platToPlantEdi",
description:
"This is the plant to plant edi that will send an edi to the email once it ships, the emails will be for the receiving plants",
checkInterval: 15,
timeType: "min",
emails: "blake.matthes@alpla.com;Maritza.Hernandez@alpla.com",
active: false,
notifiySettings: { processedBol: [500], includeAll: false },
},
];
export const notificationCreate = async () => {
@@ -163,8 +196,8 @@ export const notificationCreate = async () => {
"notify",
"notify",
`There was an error getting the notifications: ${JSON.stringify(
error
)}`
error,
)}`,
);
}
}
@@ -172,6 +205,6 @@ export const notificationCreate = async () => {
"info",
"lst",
"nofity",
"notifications were just added/updated due to server startup"
"notifications were just added/updated due to server startup",
);
};

View File

@@ -0,0 +1,86 @@
import { tryCatch } from "../../../globalUtils/tryCatch.js";
import { query } from "../../sqlServer/prodSqlServer.js";
import {
type SqlQuery,
sqlQuerySelector,
} from "../../sqlServer/utils/querySelector.utils.js";
const cleanUpQuery = `
DECLARE @JobName varchar(max) = '[jobName]'
UPDATE msdb.dbo.sysjobs
SET enabled = 0
WHERE name = @JobName;
`;
// disable the jobs
const jobNames: string[] = [
"monitor_$_lots",
"monitor_$_lots_2",
"monitor$lots",
"Monitor_APO", //listen for people to cry this is no longer a thing
"Monitor_APO2",
"Monitor_AutoConsumeMaterials", // TODO: migrate to lst
"Monitor_AutoConsumeMaterials_iow1",
"Monitor_AutoConsumeMaterials_iow2",
"Monitor_BlockedINV_Loc",
"monitor_inv_cycle",
"monitor_inv_cycle_1",
"monitor_inv_cycle_2",
"monitor_edi_import", // TODO: migrate to lst -- for the query select count(*) from AlplaPROD_test3.dbo.T_EDIDokumente (nolock) where /* IdLieferant > 1 and */ add_date > DATEADD(MINUTE, -30, getdate())
"Monitor_Lot_Progression",
"Monitor_Lots", // TODO: migrate to lst -- this should be the one where we monitor the when a lot is assigned if its missing some data.
"Monitor_MinMax", // TODO:Migrate to lst
"Monitor_MinMax_iow2",
"Monitor_PM",
"Monitor_Purity",
"monitor_wastebookings", // TODO: Migrate
"LastPriceUpdate", // not even sure what this is
"GETLabelsCount", // seems like an old jc job
"jobforpuritycount", // was not even working correctly
"Monitor_EmptyAutoConsumLocations", // not sure who uses this one
"monitor_labelreprint", // Migrated but need to find out who really wants this
"test", // not even sure why this is active
"UpdateLastMoldUsed", // old jc inserts data into a table but not sure what its used for not linked to any other alert
"UpdateWhsePositions3", // old jc inserts data into a table but not sure what its used for not linked to any other alert
"UpdateWhsePositions4",
"delete_print", // i think this was in here for when we was having lag prints in iowa1
"INV_WHSE_1", // something random i wrote long time ago looks like an inv thing to see aged stuff
"INV_WHSE_2",
"laneAgeCheck", // another strange one thats been since moved to lst
"monitor_blocking_2",
"monitor_blocking", // already in lst
"monitor_min_inv", // do we still want this one? it has a description of: this checks m-f the min inventory of materials based on the min level set in stock
"Monitor_MixedLocations",
"Monitor_PM",
"Monitor_PM2",
"wrong_lots_1",
"wrong_lots_2",
"invenotry check", // spelling error one of my stupids
"monitor_hold_monitor",
"Monitor_Silo_adjustments",
"monitor_qualityLocMonitor", // validating with lima this is still needed
];
export const sqlJobCleanUp = async () => {
// running a query to disable jobs that are moved to lst to be better maintained
const sqlQuery = sqlQuerySelector("disableJob.query") as SqlQuery;
if (!sqlQuery.success) {
console.log("Failed to load the query: ", sqlQuery.message);
return;
}
for (const job of jobNames) {
const { data, error } = await tryCatch(
query(
sqlQuery.query.replace("[jobName]", `${job}`),
`Disabling job: ${job}`,
),
);
if (error) {
console.log(error);
}
//console.log(data);
}
};

View File

@@ -0,0 +1,44 @@
<!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 are cycle counts that have been in progress for longer than {{checkTime}} min(s). </p>
<table >
<thead>
<tr>
<th>WarehouseID</th>
<th>Warehouse</th>
<th>LocationID</th>
<th>Location</th>
<th>Cycle count Started</th>
<th>Started by</th>
{{!-- <th>Downtime finish</th> --}}
</tr>
</thead>
<tbody>
{{#each items}}
<tr>
<td>{{idWarehouse}}</td>
<td>{{warehouse}}</td>
<td>{{locationId}}</td>
<td>{{location}}</td>
<td>{{cycleCountStartAt}}</td>
<td>{{blockedBy}}</td>
{{!-- <td>{{dtEnd}}</td> --}}
</tr>
{{/each}}
</tbody>
</table>
<div>
<p>Thank you,</p>
<p>LST Team</p>
</div>
</body>
</html>

View File

@@ -0,0 +1,46 @@
<!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>BOL: {{bol}} was created with the below pallets.</p>
<p>Please head to stock and import the pallets via the normal incoming goods process (now/immediately).</p>
<p>When encountering a discrepancy in pallets/cages received, please correct this after the pallets have been imported.</p>
<p>Due to these being plant to plant shipments, the only way to correct this is to bring them in then undo the incoming goods process.</p>
<br></br>
<table >
<thead>
<tr>
<th>Running Number</th>
<th>AV</th>
<th>Description</th>
<th>Lot number</th>
<th>Quantity</th>
{{!-- <th>Downtime finish</th> --}}
</tr>
</thead>
<tbody>
{{#each items}}
<tr>
<td>{{runningNr}}</td>
<td>{{article}}</td>
<td>{{alias}}</td>
<td>{{lotNumber}}</td>
<td>{{qty}}</td>
{{!-- <td>{{dtEnd}}</td> --}}
</tr>
{{/each}}
</tbody>
</table>
<div>
<p>Thank you,</p>
<p>LST Team</p>
</div>
</body>
</html>

View File

@@ -0,0 +1,42 @@
<!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 plant has encountered more than {{count}} errors in the last {{time}} mins, please see below errors and address as needed. </p>
<table >
<thead>
<tr>
<th>Username</th>
<th>Service</th>
<th>Message</th>
<th>Checked</th>
<th>LogTime</th>
{{!-- <th>Downtime finish</th> --}}
</tr>
</thead>
<tbody>
{{#each data}}
<tr>
<td>{{username}}</td>
<td>{{service}}</td>
<td>{{message}}</td>
<td>{{checked}}</td>
<td>{{add_Date}}</td>
{{!-- <td>{{dtEnd}}</td> --}}
</tr>
{{/each}}
</tbody>
</table>
<div>
<p>Thank you,</p>
<p>LST Team</p>
</div>
</body>
</html>

View File

@@ -168,6 +168,7 @@ export const lotMaterialTransfer = async (data: NewLotData) => {
),
)) as any;
console.log(label);
if (labelError) {
createLog(
"error",
@@ -235,7 +236,8 @@ export const lotMaterialTransfer = async (data: NewLotData) => {
const newQty =
data.amount > 0
? data.amount
: (data.originalAmount * data.level).toFixed(0);
: // : (data.originalAmount * data.level).toFixed(0);
Math.floor(data.originalAmount * data.level);
//console.log(data.amount);
@@ -274,7 +276,7 @@ export const lotMaterialTransfer = async (data: NewLotData) => {
// return the label back to fm1 lane id 10001
const matReturnData = {
barcode: label?.data[0].Barcode,
barcode: label?.data[0].barcode,
laneId: 10001,
};
@@ -300,7 +302,7 @@ export const lotMaterialTransfer = async (data: NewLotData) => {
// consume to the lot provided.
const consumeLot = {
productionLot: data.lotNumber,
barcode: label?.data[0].Barcode,
barcode: label?.data[0].barcode,
};
const delayTimer =

View File

@@ -7,7 +7,10 @@ import { mmQuery } from "../../../sqlServer/querys/ocp/mainMaterial.js";
export const isMainMatStaged = async (lot: any) => {
const set = serverSettings.length === 0 ? [] : serverSettings;
// make staged false by deefault and error logged if theres an issue
const checkColorSetting = set.filter((n) => n.name === "checkColor");
const checkPKGSetting = set.filter((n) => n.name === "checkPKG");
// make staged false by default and error logged if theres an issue
let isStaged = { message: "Material is staged", success: true };
const { data, error } = (await tryCatch(
@@ -20,6 +23,15 @@ export const isMainMatStaged = async (lot: any) => {
const machine = data.data.filter(
(m: any) => m.HumanReadableId === lot.machineID,
);
// just in case we encounter an issue with the machines
if (machine.length === 0) {
createLog("error", "mainMaterial", "ocp", "Invalid machine passed over.");
return {
success: false,
message: "Invalid machine passed over.",
};
}
// we have a check on ksc side to ignore the tetra machine for now as its not updating in 2.0
if (!machine[0].StagingMainMaterialMandatory) {
createLog(
@@ -34,7 +46,7 @@ export const isMainMatStaged = async (lot: any) => {
};
}
// strangly the lot is not always sending over in slc so adding this in for now to see what line is cauing this issue
// strangely the lot is not always sending over in slc so adding this in for now to see what line is cauing this issue
if (!lot) {
createLog("info", "mainMaterial", "ocp", "No lot was passed correctly.");
return isStaged;
@@ -116,7 +128,11 @@ export const isMainMatStaged = async (lot: any) => {
createLog("info", "mainMaterial", "ocp", `Maint material query ran.`);
const mainMaterial = res.find((n: any) => n.IsMainMaterial);
if (mainMaterial?.Staged === 1) {
if (
mainMaterial?.Staged === 1 &&
(checkColorSetting[0].value !== "1" || checkPKGSetting[0].value !== "1")
) {
createLog(
"info",
"mainMaterial",
@@ -143,7 +159,6 @@ export const isMainMatStaged = async (lot: any) => {
// we need to filter the color stuff and then look for includes instead of a standard name. this way we can capture a everything and not a single type
// for manual consume color if active to check colors
const checkColorSetting = set.filter((n) => n.name === "checkColor");
// 2. Auto color
if (checkColorSetting[0].value === "1") {
@@ -153,7 +168,7 @@ export const isMainMatStaged = async (lot: any) => {
results: res,
lot,
filterFn: (n) =>
n.isManual &&
!n.isManual &&
!("noPKGAutoShortage" in n) &&
!("noPKGManualShortage" in n), // pool = non-main, auto
failCondition: (n) => n.autoConsumeCheck === "autoConsumeNOK", // column = autoConsumeCheck
@@ -193,7 +208,7 @@ export const isMainMatStaged = async (lot: any) => {
}
// // if we want to check the packaging
const checkPKGSetting = set.filter((n) => n.name === "checkPKG");
if (checkPKGSetting[0].value === "1") {
const pkgAuto = checkCondition({
results: res,

View File

@@ -0,0 +1,148 @@
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { createLog } from "../../../logger/logger.js";
import { serverSettings } from "../../../server/controller/settings/getSettings.js";
import { query } from "../../../sqlServer/prodSqlServer.js";
import { machineCheck } from "../../../sqlServer/querys/ocp/machineId.js";
import { mmQuery } from "../../../sqlServer/querys/ocp/mainMaterial.js";
export const isMainMatStaged = async (lot: any) => {
const set = serverSettings.length === 0 ? [] : serverSettings;
// make staged false by default and error logged if theres an issue
let isStaged = { message: "Material is staged", success: true };
// validate the machine actaully needs materials to print
const { data, error } = (await tryCatch(
query(
machineCheck.replace("where Active = 1 and [Location] = [loc]", ""),
"check machine needs mm",
),
)) as any;
const machine = data.data.filter(
(m: any) => m.HumanReadableId === lot.machineID,
);
// just in case we encounter an issue with the machines
if (machine.length === 0) {
createLog(
"error",
"mainMaterial",
"ocp-system",
"Invalid machine passed over.",
);
return {
success: false,
message: "Invalid machine passed over.",
};
}
// we have a check on ksc side to ignore the tetra machine for now as its not updating in 2.0
if (!machine[0].StagingMainMaterialMandatory) {
createLog(
"info",
"mainMaterial",
"ocp",
`The machine dose not require mm to print and book in.`,
);
return {
message: "Machine dose not require material to be staged",
success: true,
};
}
// strangely the lot is not always sending over in slc so adding this in for now to see what line is cauing this issue
if (!lot) {
createLog("info", "mainMaterial", "ocp", "No lot was passed correctly.");
return isStaged;
}
if (typeof lot !== "object" || lot === null || Array.isArray(lot)) {
createLog(
"info",
"mainMaterial",
"ocp",
`The lot sent over is not an object: ${JSON.stringify(lot)}`,
);
return isStaged;
}
// get the materials needed for the passed over lot
const { data: material, error: errorMat } = (await tryCatch(
query(mmQuery.replaceAll("[lotNumber]", lot.lot), "Main Material Check"),
)) as any;
if (errorMat) {
return { message: "Failed to get lot info", success: false };
}
const mat = material.data;
const mainMaterial = mat.find((n: any) => n.IsMainMaterial);
const checkColorSetting = set.filter((n) => n.name === "checkColor");
const checkPKGSetting = set.filter((n) => n.name === "checkPKG");
// if we only care about having the check for mm staged and dont care about the rules we just let it fly by.
// risk here is getting $Shortage if there really is nothing
if (
mainMaterial?.Staged === 1 &&
(checkColorSetting[0].value !== "1" || checkPKGSetting[0].value !== "1")
) {
createLog(
"info",
"mainMaterial",
"ocp",
`Main material: ${mainMaterial.MaterialHumanReadableId} - ${mainMaterial.MaterialDescription}: is staged for ${lot.lot}`,
);
return {
message: `Main material: ${mainMaterial.MaterialHumanReadableId} - ${mainMaterial.MaterialDescription}: is staged for ${lot.lot}`,
success: true,
};
}
// do we have enough main material for the next pallet
if (mainMaterial?.noMMShortage === "noMM") {
createLog(
"info",
"mainMaterial",
"ocp",
`Main material: ${mainMaterial.MaterialHumanReadableId} - ${mainMaterial.MaterialDescription}: is not staged for ${lot.lot}`,
);
return {
message: `Main material: ${mainMaterial.MaterialHumanReadableId} - ${mainMaterial.MaterialDescription}: is not staged for ${lot.lot}`,
success: false,
};
}
// do we have color to the line
if (checkColorSetting[0].value === "1") {
const autoConsumeColor = mat.find(
(n: any) =>
!n.isManual &&
!("noPKGAutoShortage" in n) &&
!("noPKGManualShortage" in n),
);
if (autoConsumeColor.autoConsumeCheck === "autoConsumeNOK") {
createLog(
"info",
"mainMaterial",
"ocp",
`lot: ${lot.lot}, is missing: ${autoConsumeColor
.map(
(o: any) =>
`${o.MaterialHumanReadableId} - ${o.MaterialDescription}`,
)
.join(",\n ")} for autoconsume`,
);
return {
message: `lot: ${lot.lot}, is missing: ${autoConsumeColor
.map(
(o: any) =>
`${o.MaterialHumanReadableId} - ${o.MaterialDescription}`,
)
.join(",\n ")} for autoconsume`,
success: false,
};
}
}
};

View File

@@ -39,7 +39,7 @@ export const dycoConnect = async () => {
"debug",
"dyco",
"ocp",
"Skipping cycle: previous read still in progress."
"Skipping cycle: previous read still in progress.",
);
return;
}
@@ -62,8 +62,14 @@ export const dycoConnect = async () => {
"error",
"dyco",
"ocp",
`Error reading PLC tag: ${error.message}`
`Error reading PLC tag: ${error.message}`,
);
// if we error out we want to disconnect and reconnect
closeDyco();
setTimeout(() => {
createLog("info", "dyco", "ocp", `Reconnecting to the dyco`);
dycoConnect();
}, 2 * 1000);
} finally {
isReading = false; // Reset flag
}
@@ -74,7 +80,7 @@ export const dycoConnect = async () => {
"error",
"dyco",
"ocp",
`There was an error in the dyco: ${error}`
`There was an error in the dyco: ${error}`,
);
await PLC.disconnect();
isDycoRunning = false;

View File

@@ -11,14 +11,14 @@ export const zechettiConnect = () => {
printerId: 22, // grabbed from 2.0
tags: ["N7[0]"],
},
{
id: "Zecchetti_2",
ip: "192.168.193.111",
slot: 0,
rpi: 100,
printerId: 23,
tags: ["N8[0]"],
},
// {
// id: "Zecchetti_2",
// ip: "192.168.193.111",
// slot: 0,
// rpi: 100,
// printerId: 23,
// tags: ["N8[0]"],
// },
],
};

View File

@@ -47,7 +47,7 @@ export const printerDelayByLot = async (lot: any) => {
})
.where(
and(
eq(printerData.humanReadableId, lot[i].printerID),
eq(printerData.humanReadableId, lot[i]?.printerID),
eq(printerData.printDelayOverride, false),
),
),

View File

@@ -41,7 +41,7 @@ export const qualityCycle = async () => {
message: "There was an error getting quality request data",
};
}
const lstQData: any = data;
const lstQData: any = data ?? [];
// get the pallets that currentStat is moved
// const res = await runQuery(palletMoveCheck, "palletCheck");
@@ -101,7 +101,7 @@ export const qualityCycle = async () => {
.where(eq(qualityRequest.runningNr, lstQData[i].runningNr));
createLog(
"info",
"debug",
"lst",
"quality",
`Pallet ${lstQData[i].runningNr} was updated`,

View File

@@ -1,14 +1,14 @@
//http://usday1vms006:4000/api/v1/zebra/wrapper1
import { z, createRoute, OpenAPIHono } from "@hono/zod-openapi";
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { ConsoleLogWriter } from "drizzle-orm";
import { tagData } from "../controller/tagData.js";
import { apiHit } from "../../../globalUtils/apiHits.js";
import { responses } from "../../../globalUtils/routeDefs/responses.js";
import { tryCatch } from "../../../globalUtils/tryCatch.js";
import { createLog } from "../../logger/logger.js";
import { clearNoReadTimer, noRead } from "../controller/noRead.js";
import { badRead, goodRead } from "../controller/readerControl.js";
import { createLog } from "../../logger/logger.js";
import { tryCatch } from "../../../globalUtils/tryCatch.js";
import { stopRead } from "../controller/readTags.js";
import { apiHit } from "../../../globalUtils/apiHits.js";
import { tagData } from "../controller/tagData.js";
const app = new OpenAPIHono();
@@ -46,11 +46,17 @@ app.openapi(
return c.json({ success: false, message: "missing data" }, 400);
}
//console.log(`Tag: ${Buffer.from(body.idHex, "hex").toString("utf-8")}, ${body[key].data.idHex}`);
createLog(
"info",
"rfid-tag",
"rfid",
`Tag Data from ${reader}: ${JSON.stringify(body)}`,
);
for (let i = 0; i < body.length; i++) {
const tag = Buffer.from(body[i].data.idHex, "hex").toString(
"utf-8"
);
const tag = Buffer.from(body[i].data.idHex, "hex")
.toString("utf-8")
.replace("\x00\x00", "");
// console.log(
// "Raw value:",
// body[i].data.peakRssi,
@@ -59,7 +65,7 @@ app.openapi(
// );
if (
tag.includes("ALPLA") &&
parseInt(body[i].data.peakRssi) < -30
parseInt(body[i].data.peakRssi) >= -80 // anything strong than this go ahead and read it
) {
tagdata = [
...tagdata,
@@ -80,19 +86,16 @@ app.openapi(
// badRead(reader);
return c.json(
{ success: false, message: `There were no tags scanned.` },
200
200,
);
} else {
tagData(tagdata);
goodRead(reader);
clearNoReadTimer();
return c.json(
{ success: true, message: `New info from ${reader}` },
200
);
}
return c.json({ success: true, message: `New info from ${reader}` }, 200);
}
},
);
export default app;

View File

@@ -1,14 +1,14 @@
import { eq } from "drizzle-orm";
import sql from "mssql";
import { prodSqlConfig } from "./utils/prodServerConfig.js";
import { createLog } from "../logger/logger.js";
import { db } from "../../../database/dbclient.js";
import { settings } from "../../../database/schema/settings.js";
import { eq } from "drizzle-orm";
import { installed } from "../../index.js";
import { checkHostnamePort } from "../../globalUtils/pingServer.js";
import { installed } from "../../index.js";
import { createLog } from "../logger/logger.js";
import { serverSettings } from "../server/controller/settings/getSettings.js";
import { prodSqlConfig } from "./utils/prodServerConfig.js";
let pool: any;
let pool: sql.ConnectionPool;
let connected: boolean = false;
export const initializeProdPool = async () => {
if (!installed) {
@@ -16,7 +16,7 @@ export const initializeProdPool = async () => {
"info",
"lst",
"sqlProd",
"The server was not installed will reconnect in 5 seconds"
"The server was not installed will reconnect in 5 seconds",
);
setTimeout(() => {
initializeProdPool();
@@ -31,18 +31,24 @@ export const initializeProdPool = async () => {
// the move to the go version for settings
const dbServer = serverSettings.filter(
(n: any) => n.name === "dbServer"
(n: any) => n.name === "dbServer",
) as any;
const serverUp = await checkHostnamePort(`${dbServer[0].value}:1433`);
const serverUp = await checkHostnamePort(
`${process.env.NODE_ENV !== "development" ? "localhost" : dbServer[0].value}:1433`,
);
if (!serverUp) {
createLog(
"error",
"lst",
"server",
`The sql ${dbServer[0].value} is not reachable`
`The sql ${dbServer[0].value} is not reachable`,
);
// closePool()
// setTimeout(() => {
// initializeProdPool();
// }, 2*1000);
return {
success: false,
message: `The sql ${dbServer[0].value} is not reachable`,
@@ -57,7 +63,7 @@ export const initializeProdPool = async () => {
// .where(eq(settings.name, "dbServer"));
const serverLoc = serverSettings.filter(
(n: any) => n.name === "dbServer"
(n: any) => n.name === "dbServer",
) as any;
if (
serverLoc[0].value === "localhost" &&
@@ -67,7 +73,7 @@ export const initializeProdPool = async () => {
"error",
"lst",
"sqlProd",
"The server is set to localhost, and you are not in development mode."
"The server is set to localhost, and you are not in development mode.",
);
return {
success: false,
@@ -84,13 +90,14 @@ export const initializeProdPool = async () => {
}
try {
const config = await prodSqlConfig();
pool = await sql.connect(config!);
pool = new sql.ConnectionPool(config!);
await pool.connect();
createLog(
"info",
"lst",
"sqlProd",
`Connected to ${config?.server}, and looking at ${config?.database}`
`Connected to ${config?.server}, and looking at ${config?.database}`,
);
connected = true;
return {
@@ -102,11 +109,18 @@ export const initializeProdPool = async () => {
"error",
"lst",
"sqlProd",
`${JSON.stringify(
error
)}, "There was an error connecting to the pool."`
`${JSON.stringify(error)}, "There was an error connecting to the pool."`,
);
throw new Error("There was an error closing the sql connection");
// closePool()
// setTimeout(() => {
// initializeProdPool();
// }, 2*1000);
return {
success: true,
message: "The sql server connection has been closed",
};
//throw new Error("There was an error closing the sql connection");
}
};
@@ -116,7 +130,7 @@ export const closePool = async () => {
"error",
"lst",
"sqlProd",
"There is no connection a connection."
"There is no connection a connection.",
);
return { success: false, message: "There is already a connection." };
}
@@ -134,8 +148,8 @@ export const closePool = async () => {
"lst",
"sqlProd",
`${JSON.stringify(
error
)}, "There was an error closing the sql connection"`
error,
)}, "There was an error closing the sql connection"`,
);
throw new Error("There was an error closing the sql connection");
}
@@ -151,31 +165,34 @@ export async function query(queryToRun: string, name: string) {
// .where(eq(settings.name, "dbServer"));
const dbServer = serverSettings.filter(
(n: any) => n.name === "dbServer"
(n: any) => n.name === "dbServer",
) as any;
const serverUp = await checkHostnamePort(`${dbServer[0].value}:1433`);
// const serverUp = await checkHostnamePort(
// `${process.env.NODE_ENV !== "development" ? "localhost" : dbServer[0].value}:1433`,
// );
if (!serverUp) {
createLog(
"error",
"lst",
"server",
`The sql ${dbServer[0].value} is not reachable`
);
return {
success: false,
message: `The sql ${dbServer[0].value} is not reachable`,
data: [],
};
}
// if (!serverUp) {
// createLog(
// "error",
// "lst",
// "server",
// `Failed to run query due to ${dbServer[0].value} not being reachable.`,
// );
// return {
// success: false,
// message: `Failed to run query due to ${dbServer[0].value} not being reachable.`,
// data: [],
// };
// }
if (!connected) {
createLog(
"error",
"lst",
"server",
`The sql ${dbServer[0].value} is not connected`
`The sql ${dbServer[0].value} is not connected`,
);
return {
success: false,
message: `The sql ${dbServer[0].value} is not not connected`,
@@ -190,7 +207,7 @@ export async function query(queryToRun: string, name: string) {
// .from(settings)
// .where(eq(settings.name, "plantToken"));
const plantToken = serverSettings.filter(
(n: any) => n.name === "plantToken"
(n: any) => n.name === "plantToken",
) as any;
const query = queryToRun.replaceAll("test1", plantToken[0].value);
@@ -208,9 +225,7 @@ export async function query(queryToRun: string, name: string) {
"error",
"lst",
"sqlProd",
`${JSON.stringify(
error
)}, ${name} did not run due to a timeout.`
`${JSON.stringify(error)}, ${name} did not run due to a timeout.`,
);
//throw new Error(`${name} query did not run due to a timeout.`);
return {

View File

@@ -61,7 +61,8 @@ V_Artikel.ArtikelvariantenTypBez= 'LDPE' or
V_Artikel.ArtikelvariantenTypBez= 'PP' or
V_Artikel.ArtikelvariantenTypBez= 'HDPE' or
V_Artikel.ArtikelvariantenTypBez= 'PET' or
V_Artikel.ArtikelvariantenTypBez= 'PET-P'
V_Artikel.ArtikelvariantenTypBez= 'PET-P' or
V_Artikel.ArtikelvariantenTypBez= 'PET-G'
THEN 'MM'
WHEN
V_Artikel.ArtikelvariantenTypBez='HDPE-Waste' or

View File

@@ -1,83 +1,8 @@
export const deliveryByDateRange = `
use AlplaPROD_test1
DECLARE @StartDate DATE = '[startDate]' -- 2025-1-1
DECLARE @EndDate DATE = '[endDate]' -- 2025-1-31
select * from
(select (select wert from dbo.T_SystemParameter where Bezeichnung = 'Werkskuerzel') as Plant,
AuftragsNummer as OrderNumber,
PositionsNummer as CustomerLineNumber,
AbrufNummer as CustomerReleaseNumber,
CONVERT(date, AbrufLiefertermin) as DeliveryDate,
CONVERT(DATE,JournalDatum) Bol_PrintDate,
AbrufMenge AS OrderQuantity,
AbrufMengeVPK as OrderPallets,
GelieferteMenge AS DeliveredQTY,
GelieferteMengeVPK as DeliverdPallets,
JournalNummer as BOLNum,
ProdArtikelBez AS ProductFamily,
dbo.V_LadePlanungenLadeAuftragAbruf.AbrufIdKundenAdresse AS IdCustomer,
dbo.V_LadePlanungenLadeAuftragAbruf.AdressBez AS CustName,
dbo.T_EAIJournal.IdJournalStatus as bolStatus,
V_TrackerAuftragsAbrufe.IdAuftragsAbruf as releaseNum,
V_LadePlanungenLadeAuftragAbruf.IdLadeAuftrag as truckPostion
,dbo.V_TrackerAuftragsAbrufe.IdArtikelvarianten as av
,dbo.V_TrackerAuftragsAbrufe.ArtikelVariantenAlias as alias
,'Base Plant' as plantType
from dbo.V_TrackerAuftragsAbrufe (nolock)
left join
dbo.V_LadePlanungenLadeAuftragAbruf on V_TrackerAuftragsAbrufe.IdAuftragsAbruf =
dbo.V_LadePlanungenLadeAuftragAbruf.AbrufIdAuftragsAbruf
left join
dbo.T_EAIJournal on dbo.V_LadePlanungenLadeAuftragAbruf.IdLadeAuftrag =
dbo.T_EAIJournal.IdLadeAuftrag
left join
dbo.V_ArtikelKomplett on V_TrackerAuftragsAbrufe.IdArtikelVarianten =
dbo.V_ArtikelKomplett.IdArtikelvarianten
where GelieferteMengeVPK > 0 AND (
AbrufLiefertermin IS NULL
OR CONVERT(date, JournalDatum) BETWEEN @StartDate AND @EndDate
)
/*in house*/
union all
select top (50) (select wert from dbo.T_SystemParameter where Bezeichnung = 'Werkskuerzel') as Plant
,[KundenAuftragsNummer] as OrderNumber
,[KundenPositionsNummer] as CustomerLineNumber
, null as CustomerReleaseNumber
,CONVERT(date, i.Add_Date) as DeliveryDate
,CONVERT(DATE,i.Upd_Date) Bol_PrintDate
,null AS OrderQuantity
,null as OrderPallets
,LieferMengeVereinbart AS DeliveredQTY
,null as DeliverdPallets
,JournalNummer as BOLNum
,null AS ProductFamily
,IdAdresse AS IdCustomer
,null AS CustName
,null as bolStatus
,null as releaseNum
,null as truckPostion
,i.IdArtikelVariante as av
,null as alias
,'In-House' as plantType
--,*
from [dbo].[T_InhouseLieferungen] as i (nolock)
where CONVERT(date, Upd_Date) BETWEEN @StartDate AND @EndDate
) x
order by Bol_PrintDate desc
`;
export const deliveryByDateRangeAndAv = `
use [test1_AlplaPROD2.0_Read]
DECLARE @StartDate DATE = '[startDate]' -- 2025-1-1
DECLARE @EndDate DATE = '[endDate]' -- 2025-1-31
SELECT
r.[ArticleHumanReadableId]
,[ReleaseNumber]
@@ -86,12 +11,15 @@ r.[ArticleHumanReadableId]
,[CustomerReleaseNumber]
,[ReleaseState]
,[DeliveryState]
,ea.JournalNummer
,ea.JournalNummer as BOL_Number
,[ReleaseConfirmationState]
,[PlanningState]
,format(r.[OrderDate], 'yyyy-MM-dd HH:mm') as OrderDate
,FORMAT(r.[DeliveryDate], 'yyyy-MM-dd HH:mm') as DeliveryDate
,FORMAT(r.[LoadingDate], 'yyyy-MM-dd HH:mm') as LoadingDate
--,format(r.[OrderDate], 'yyyy-MM-dd HH:mm') as OrderDate
,r.[OrderDate]
--,FORMAT(r.[DeliveryDate], 'yyyy-MM-dd HH:mm') as DeliveryDate
,r.[DeliveryDate]
--,FORMAT(r.[LoadingDate], 'yyyy-MM-dd HH:mm') as LoadingDate
,r.[LoadingDate]
,[Quantity]
,[DeliveredQuantity]
,r.[AdditionalInformation1]
@@ -108,6 +36,161 @@ r.[ArticleHumanReadableId]
,[Irradiated]
,r.[CreatedByEdi]
,[DeliveryAddressHumanReadableId]
,DeliveryAddressDescription
,[CustomerArtNo]
,[TotalPrice]
,r.[ArticleAlias]
FROM [order].[Release] (nolock) as r
left join
[order].LineItem as x on
r.LineItemId = x.id
left join
[order].Header as h on
x.HeaderId = h.id
--bol stuff
left join
AlplaPROD_test1.dbo.V_LadePlanungenLadeAuftragAbruf (nolock) as zz
on zz.AbrufIdAuftragsAbruf = r.ReleaseNumber
left join
(select * from (SELECT
ROW_NUMBER() OVER (PARTITION BY IdJournal ORDER BY add_date DESC) AS RowNum
,*
FROM [AlplaPROD_test1].[dbo].[T_Lieferungen] (nolock)) x
where RowNum = 1) as ea on
zz.IdLieferschein = ea.IdJournal
where
--r.ArticleHumanReadableId in ([articles])
--r.ReleaseNumber = 1452
r.DeliveryDate between @StartDate AND @EndDate
and DeliveredQuantity > 0
--and Journalnummer = 169386
`;
// export const deliveryByDateRange = `
// use AlplaPROD_test1
// DECLARE @StartDate DATE = '[startDate]' -- 2025-1-1
// DECLARE @EndDate DATE = '[endDate]' -- 2025-1-31
// select * from
// (select (select wert from dbo.T_SystemParameter where Bezeichnung = 'Werkskuerzel') as Plant,
// AuftragsNummer as OrderNumber,
// PositionsNummer as CustomerLineNumber,
// AbrufNummer as CustomerReleaseNumber,
// CONVERT(date, AbrufLiefertermin) as DeliveryDate,
// CONVERT(DATE,JournalDatum) Bol_PrintDate,
// AbrufMenge AS OrderQuantity,
// AbrufMengeVPK as OrderPallets,
// GelieferteMenge AS DeliveredQTY,
// GelieferteMengeVPK as DeliverdPallets,
// JournalNummer as BOLNum,
// ProdArtikelBez AS ProductFamily,
// dbo.V_LadePlanungenLadeAuftragAbruf.AbrufIdKundenAdresse AS IdCustomer,
// dbo.V_LadePlanungenLadeAuftragAbruf.AdressBez AS CustName,
// dbo.T_EAIJournal.IdJournalStatus as bolStatus,
// V_TrackerAuftragsAbrufe.IdAuftragsAbruf as releaseNum,
// V_LadePlanungenLadeAuftragAbruf.IdLadeAuftrag as truckPostion
// ,dbo.V_TrackerAuftragsAbrufe.IdArtikelvarianten as av
// ,dbo.V_TrackerAuftragsAbrufe.ArtikelVariantenAlias as alias
// ,'Base Plant' as plantType
// from dbo.V_TrackerAuftragsAbrufe (nolock)
// left join
// dbo.V_LadePlanungenLadeAuftragAbruf on V_TrackerAuftragsAbrufe.IdAuftragsAbruf =
// dbo.V_LadePlanungenLadeAuftragAbruf.AbrufIdAuftragsAbruf
// left join
// dbo.T_EAIJournal on dbo.V_LadePlanungenLadeAuftragAbruf.IdLadeAuftrag =
// dbo.T_EAIJournal.IdLadeAuftrag
// left join
// dbo.V_ArtikelKomplett on V_TrackerAuftragsAbrufe.IdArtikelVarianten =
// dbo.V_ArtikelKomplett.IdArtikelvarianten
// where GelieferteMengeVPK > 0 AND (
// AbrufLiefertermin IS NULL
// OR CONVERT(date, JournalDatum) BETWEEN @StartDate AND @EndDate
// )
// /*in house*/
// union all
// select top (50) (select wert from dbo.T_SystemParameter where Bezeichnung = 'Werkskuerzel') as Plant
// ,[KundenAuftragsNummer] as OrderNumber
// ,[KundenPositionsNummer] as CustomerLineNumber
// , null as CustomerReleaseNumber
// ,CONVERT(date, i.Add_Date) as DeliveryDate
// ,CONVERT(DATE,i.Upd_Date) Bol_PrintDate
// ,null AS OrderQuantity
// ,null as OrderPallets
// ,LieferMengeVereinbart AS DeliveredQTY
// ,null as DeliverdPallets
// ,JournalNummer as BOLNum
// ,null AS ProductFamily
// ,IdAdresse AS IdCustomer
// ,null AS CustName
// ,null as bolStatus
// ,null as releaseNum
// ,null as truckPostion
// ,i.IdArtikelVariante as av
// ,null as alias
// ,'In-House' as plantType
// --,*
// from [dbo].[T_InhouseLieferungen] as i (nolock)
// where CONVERT(date, Upd_Date) BETWEEN @StartDate AND @EndDate
// ) x
// order by Bol_PrintDate desc
// `;
export const deliveryByDateRangeAndAv = `
use [test1_AlplaPROD2.0_Read]
DECLARE @StartDate DATE = '[startDate]' -- 2025-1-1
DECLARE @EndDate DATE = '[endDate]' -- 2025-1-31
SELECT
r.[ArticleHumanReadableId]
,[ReleaseNumber]
,h.CustomerOrderNumber
,x.CustomerLineItemNumber
,[CustomerReleaseNumber]
,[ReleaseState]
,[DeliveryState]
,ea.JournalNummer as BOL_Number
,[ReleaseConfirmationState]
,[PlanningState]
--,format(r.[OrderDate], 'yyyy-MM-dd HH:mm') as OrderDate
,r.[OrderDate]
--,FORMAT(r.[DeliveryDate], 'yyyy-MM-dd HH:mm') as DeliveryDate
,r.[DeliveryDate]
--,FORMAT(r.[LoadingDate], 'yyyy-MM-dd HH:mm') as LoadingDate
,r.[LoadingDate]
,[Quantity]
,[DeliveredQuantity]
,r.[AdditionalInformation1]
,r.[AdditionalInformation2]
,[TradeUnits]
,[LoadingUnits]
,[Trucks]
,[LoadingToleranceType]
,[SalesPrice]
,[Currency]
,[QuantityUnit]
,[SalesPriceRemark]
,r.[Remark]
,[Irradiated]
,r.[CreatedByEdi]
,[DeliveryAddressHumanReadableId]
,DeliveryAddressDescription
,[CustomerArtNo]
,[TotalPrice]
,r.[ArticleAlias]
@@ -141,8 +224,8 @@ where
r.ArticleHumanReadableId in ([articles])
--r.ReleaseNumber = 1452
and r.DeliveryDate between '[startDate]' and '[endDate]'
order by DeliveryDate desc
and r.DeliveryDate between @StartDate AND @EndDate
--and DeliveredQuantity > 0
--and Journalnummer = 169386
`;

View File

@@ -0,0 +1,18 @@
export const inhouseDelivery = `
declare @shiftStart varchar(max) = (select top(1) CAST(StartDate AS time(0)) from [test1_AlplaPROD2.0_Read].[masterData].[ShiftDefinition] (nolock) order by TeamNumber)
SELECT
ProduktionsLos as lot
,Menge as qty
,Barcode as barcode
,IdArtikelVarianten as av
,ArtikelVariantenAlias as alias
,LieferDatum as deliveryDate
--.*
FROM [AlplaPROD_test1].[dbo].V_LieferBuchungen (nolock)
where Urheber = 1350 and ProduktionsLos > 0
and LieferDatum between '[startDate]' + ' ' + @shiftStart
and '[endDate]' + ' ' + @shiftStart
order by LieferDatum desc
`;

View File

@@ -17,6 +17,10 @@ x.ArtikelVariantenAlias as Alias
,IdProdPlanung as Lot
----,IdAdressen,
,x.AdressBez
,x.IdLagerAbteilung as 'location'
,x.LagerAbteilungKurzBez
,x.IdWarenlager as warehouseID
,x.WarenLagerKurzBez as warehouseName
--,*
from [AlplaPROD_test1].dbo.[V_LagerPositionenBarcodes] (nolock) x
@@ -39,6 +43,10 @@ group by x.idartikelVarianten, ArtikelVariantenAlias, c.Description
--,IdAdressen
,x.AdressBez
,IdProdPlanung
,x.IdLagerAbteilung
,x.LagerAbteilungKurzBez
,x.IdWarenlager
,x.WarenLagerKurzBez
--, x.Lfdnr
order by x.IdArtikelVarianten

View File

@@ -1,5 +1,5 @@
export const orderState = `
SELECT top(10000)
SELECT
CustomerOrderNumber
,r.CustomerReleaseNumber
, OrderState
@@ -21,6 +21,6 @@ CustomerOrderNumber
where
--h.CreatedByEdi = 1
r.ReleaseState > 0
r.ReleaseState >= 1
--and CustomerOrderNumber in ( '2358392')
`;

View File

@@ -0,0 +1,12 @@
export const featureCheck = `
SELECT count(*)
FROM [test2_AlplaPROD2.0_Read].[support].[FeatureActivation]
where feature in (108,7)
`;
/*
as more features get activated and need to have this checked to include the new endpoints add here so we can check this.
108 = waste
7 = warehousing
*/

View File

@@ -0,0 +1,14 @@
use [test1_AlplaPROD2.0_Read]
select
humanreadableId as addressId
,ContactEmail as email
,ContactName
,ContactPhoneNumber
,Name
,Street
,City
,ZipCode
--,*
from [masterData].[Address] (nolock)
where humanreadableid = [customerAddress]

View File

@@ -0,0 +1,43 @@
use AlplaPROD_test1
/**
check if we have any new alpla bols that were created
*/
SELECT
x.idladeplanung
,e.idjournal
,e.journalNummer as bol
,e.idjournalstatus
,e.ladeDatum as loadDate
,e.bemerkung
,e.ereporting_idwerk
,e.journalDatum
,a.idadressen as addressId
,a.bezeichnung as addressDescription
,a.strasse as streetAddress
,a.ort as cityState
,a.plz as zipcode
,idauftrag as releaseNumber
--,*
FROM [dbo].[T_EAIJournal] as e with (nolock)
-- pull in the address so we only pull in florence data
left join
[dbo].[T_EAIJournalAdresse] as a with (nolock) on
a.[IdJournalAdresse] = [IdJournalKundenAdresse]
-- get the table to link the pallets to the bol
left join
[dbo].[T_EAIJournalPosition] as x with (nolock) on
x.idjournal = e.idjournal
where idjournalStatus = 62
--and idadressen = 270
and a.bezeichnung like '%Alpla%' -- we only want to monitor for addresses that are linked to alpla.
and JournalDatum > DATEADD(MINUTE, -[timeCheck], GETDATE())
and e.journalNummer not in ([ignoreBols])
and idauftrag > 1 -- this will ignore all incoming goodsv as we are really only looking for outbound deliveries
order by JournalDatum desc

View File

@@ -0,0 +1,33 @@
/*
checks the age of an inventory dose not exceed x time
*/
use AlplaPROD_test1
DECLARE @timeCheck INT = [timeTest]
select
w.IdWarenLager as idWarehouse
,w.KurzBezeichnung as warehouse
,b.IdLagerAbteilung as locationId
,x.KurzBezeichnung as 'location'
--,case when b.upd_date < Dateadd(minute, -(@timeCheck * 1.5), getdate()) then 'OVERDUE' else 'In-Progress' end as invStatus
,format(b.Upd_Date, 'M/d/yyyy HH:mm') as cycleCountStartAt
,b.Upd_User as blockedBy
--,*
from [dbo].[V_LagerAbteilungenInventuren] (nolock) as b
-- get the loction name
left join
dbo.T_LagerAbteilungen (nolock) as x
on x.IdLagerAbteilung = b.IdLagerAbteilung
-- get the whse
left join
dbo.T_WarenLager (nolock) as w
on x.idWarenLager = w.idWarenLager
where status = 1
and b.Upd_Date < Dateadd(minute, -@timeCheck, getdate())

View File

@@ -0,0 +1,8 @@
/*
disables sql jobs.
*/
EXEC msdb.dbo.sp_update_job @job_name = N'[jobName]', @enabled = 0;
-- DECLARE @JobName varchar(max) = '[jobName]'
-- UPDATE msdb.dbo.sysjobs
-- SET enabled = 0
-- WHERE name = @JobName;

View File

@@ -0,0 +1,78 @@
/*
This query will return a single running number as long as its in stock.
To get all data comment out the lfdnr in the where statmen
*/
use AlplaPROD_test1
DECLARE @runningNumber nvarchar(max) = '[runningNr]' -- when saving in lst should be '[runningNr]'
select x.idartikelVarianten as av,
ArtikelVariantenAlias as alias,
x.Lfdnr as runningNumber,
round(sum(EinlagerungsMengeVPKSum),0) as totalPallets,
sum(EinlagerungsMengeSum) as totalPalletQTY,
round(sum(VerfuegbareMengeVPKSum),0) as avaliblePallets,
sum(VerfuegbareMengeSum) as avaliablePalletQTY,
sum(case when c.Description LIKE '%COA%' then GesperrteMengeVPKSum else 0 end) as coaPallets,
sum(case when c.Description LIKE '%COA%' then GesperrteMengeSum else 0 end) as coaQTY,
sum(case when c.Description NOT LIKE '%COA%' or x.IdMainDefect = -1 then GesperrteMengeVPKSum else 0 end) as heldPallets,
sum(case when c.Description NOT LIKE '%COA%' or x.IdMainDefect = -1 then GesperrteMengeSum else 0 end) as heldQTY
,IdProdPlanung as lot
,IdAdressen as addressID,
x.AdressBez as addressDescription
,x.IdLagerAbteilung as locationId
,x.lagerabteilungkurzbez as location
,lot.machine
,produktionsdatummin as productionDate
,'728'
+ RIGHT(CAST(YEAR(produktionsdatummin) AS varchar(4)), 1)
+ CAST(DATEDIFF(DAY, DATEFROMPARTS(YEAR(produktionsdatummin), 1, 1), produktionsdatummin) + 1 AS varchar(3))
+ CAST(lot.machine AS varchar(10)) as batch
,c.Description as blockingReason
,x.Barcode as barcode
--,*
from dbo.[V_LagerPositionenBarcodes] (nolock) x
left join
dbo.T_EtikettenGedruckt as l(nolock) on
x.Lfdnr = l.Lfdnr AND l.Lfdnr > 1
left join
(SELECT *
FROM [dbo].[T_BlockingDefects] where Active = 1) as c
on x.IdMainDefect = c.IdBlockingDefect
/*
get lot and machine info
*/
left join
(select location as machine,
runningnumber as lot
,planstart
,planend
from [test1_AlplaPROD2.0_Read].[productionScheduling].[ProductionLot] (nolock) x
left join
[test1_AlplaPROD2.0_Read].[masterData].[Machine] (nolock) m on
m.id = x.machineid) as lot on
lot.lot = IdProdPlanung
/*
The data below will be controlled by the user in excel by default everything will be passed over
IdAdressen = 3
*/
where IdArtikelTyp = 1
and x.IdWarenlager in (1) -- the pallet must be in ppoo
and x.Lfdnr = @runningNumber -- comment this out when you want to get everything
group by x.idartikelVarianten, ArtikelVariantenAlias, c.Description, IdAdressen,
x.AdressBez , x.Lfdnr,
IdProdPlanung
,x.IdLagerAbteilung
,x.lagerabteilungkurzbez
,lot.machine
,produktionsdatummin
,x.Barcode
order by x.IdArtikelVarianten

View File

@@ -0,0 +1,37 @@
use AlplaPROD_test1
select * from (SELECT
p.[IdLadePlanung]
,p.[Beleg] as lotNumber
,p.[LfdNrJeArtikelKunde] as runningNr
,p.[Barcode]
,p.[ProduktionsDatum] as productionDate
,p.[Add_User] as scanDate
,p.[Add_Date]
,p.[Upd_User]
,p.[Upd_Date]
,p.[IdJournalWarenPosition]
,p.[LieferMenge] as qty
-- ,av.IdArtikelvarianten as article
-- ,av.Bezeichnung as alias
,av.articlehumanreadableid as article
,av.ArticleDescription as alias
--,[SSCC_ReserveZiffer]
--,ROW_NUMBER() OVER (PARTITION BY p.[LfdNrJeArtikelKunde] ORDER BY p.upd_date DESC) AS RowNum
--,*
FROM [dbo].[T_EAIJournalLieferPosition] as p (nolock)
-- left join
-- dbo.T_ProdPlanung as l on
-- l.IdProdPlanung = p.Beleg
left join
[test1_AlplaPROD2.0_Read].labelling.InternalLabel as av on
av.RunningNumber = p.[LfdNrJeArtikelKunde]
) as a
where idladeplanung in ([palLinkedToBol])
--and RowNum = 1
order by runningNr

View File

@@ -157,3 +157,259 @@ where lot.ProductionLotHumanReadableId = @lot and MaterialDescription not like '
and MaterialDescription NOT LIKE '%bb%'
and MaterialDescription NOT LIKE '%mcg%'
`;
export const something = [
{
MaterialHumanReadableId: 98,
MaterialDescription: "BAN Banding 51544 1cyc",
Staged: 0,
isManual: false,
IsMainMaterial: false,
TotalPlannedLoadingUnits: 88,
TotalProducedLoadingUnits: 0,
remainingPallets: 88,
Provided: 0,
consumption: 0,
totalDemand: 352,
totalNeeded: 66.2904,
noMMShortage: null,
noPKGAutoShortage: "pkgAutoGood",
noPKGManualShortage: "noManPkg",
noManualShortage: null,
autoConsumeCheck: "autoConsumeOk",
invForAutoConsume: 1314200,
Percentage: 0,
QuantityPosition: 4,
"": null,
},
{
MaterialHumanReadableId: 174,
MaterialDescription: "MB PE Ampacet BW 11744",
Staged: 0,
isManual: true,
IsMainMaterial: false,
TotalPlannedLoadingUnits: 88,
TotalProducedLoadingUnits: 0,
remainingPallets: 88,
Provided: 0,
consumption: 0,
totalDemand: 162.728623,
totalNeeded: 1.814699,
noMMShortage: null,
noPKGAutoShortage: null,
noPKGManualShortage: null,
noManualShortage: "noOK",
autoConsumeCheck: "autoConsumeNOK",
invForAutoConsume: null,
Percentage: 2.19,
QuantityPosition: null,
"": 0,
},
{
MaterialHumanReadableId: 99,
MaterialDescription: "TOP Plastic 6040643 44x56x4 w/o CB 30cyc",
Staged: 0,
isManual: false,
IsMainMaterial: false,
TotalPlannedLoadingUnits: 88,
TotalProducedLoadingUnits: 0,
remainingPallets: 88,
Provided: 0,
consumption: 0,
totalDemand: 88,
totalNeeded: 66.2904,
noMMShortage: null,
noPKGAutoShortage: "pkgAutoGood",
noPKGManualShortage: "noManPkg",
noManualShortage: null,
autoConsumeCheck: "autoConsumeOk",
invForAutoConsume: 2048,
Percentage: 0,
QuantityPosition: 1,
"": null,
},
{
MaterialHumanReadableId: 119,
MaterialDescription: "MM HDPE PCR KW Plastics KWR 101-150",
Staged: 1,
isManual: false,
IsMainMaterial: false,
TotalPlannedLoadingUnits: 88,
TotalProducedLoadingUnits: 0,
remainingPallets: 88,
Provided: 53643.717,
consumption: 0,
totalDemand: 3744.977905,
totalNeeded: 41.762952,
noMMShortage: null,
noPKGAutoShortage: null,
noPKGManualShortage: null,
noManualShortage: null,
autoConsumeCheck: "autoConsumeOk",
invForAutoConsume: 53754.112,
Percentage: 50.4,
QuantityPosition: null,
"": 0,
},
{
MaterialHumanReadableId: 504,
MaterialDescription: "LBL IML Label F 1.8L Evolution 1265677",
Staged: 0,
isManual: false,
IsMainMaterial: false,
TotalPlannedLoadingUnits: 88,
TotalProducedLoadingUnits: 0,
remainingPallets: 88,
Provided: 0,
consumption: 0,
totalDemand: 79357.090909,
totalNeeded: 1,
noMMShortage: null,
noPKGAutoShortage: null,
noPKGManualShortage: null,
noManualShortage: null,
autoConsumeCheck: "autoConsumeOk",
invForAutoConsume: 900500,
Percentage: 0,
QuantityPosition: null,
"": 1,
},
{
MaterialHumanReadableId: 176,
MaterialDescription: "MM HDPE Dow DMDF 6230",
Staged: 1,
isManual: false,
IsMainMaterial: true,
TotalPlannedLoadingUnits: 88,
TotalProducedLoadingUnits: 0,
remainingPallets: 88,
Provided: 74063.734,
consumption: 0,
totalDemand: 3522.805744,
totalNeeded: 39.285348,
noMMShortage: "mmGood",
noPKGAutoShortage: null,
noPKGManualShortage: null,
noManualShortage: null,
autoConsumeCheck: "autoConsumeOk",
invForAutoConsume: 182624.771,
Percentage: 47.41,
QuantityPosition: null,
"": 0,
},
{
MaterialHumanReadableId: 397,
MaterialDescription: "STW Film 20x45ga 180567",
Staged: 0,
isManual: false,
IsMainMaterial: false,
TotalPlannedLoadingUnits: 88,
TotalProducedLoadingUnits: 0,
remainingPallets: 88,
Provided: 0,
consumption: 0,
totalDemand: 17.6,
totalNeeded: 66.2904,
noMMShortage: null,
noPKGAutoShortage: "pkgAutoGood",
noPKGManualShortage: "noManPkg",
noManualShortage: null,
autoConsumeCheck: "autoConsumeOk",
invForAutoConsume: 1063.92,
Percentage: 0,
QuantityPosition: 0.2,
"": null,
},
{
MaterialHumanReadableId: 96,
MaterialDescription: "PAL PRA 44x56x5 50cyc",
Staged: 0,
isManual: false,
IsMainMaterial: false,
TotalPlannedLoadingUnits: 88,
TotalProducedLoadingUnits: 0,
remainingPallets: 88,
Provided: 0,
consumption: 0,
totalDemand: 88,
totalNeeded: 66.2904,
noMMShortage: null,
noPKGAutoShortage: "pkgAutoGood",
noPKGManualShortage: "noManPkg",
noManualShortage: null,
autoConsumeCheck: "autoConsumeOk",
invForAutoConsume: 1529,
Percentage: 0,
QuantityPosition: 1,
"": null,
},
{
MaterialHumanReadableId: 505,
MaterialDescription: "LBL IML Label B 1.8L Evolution 1265678",
Staged: 0,
isManual: false,
IsMainMaterial: false,
TotalPlannedLoadingUnits: 88,
TotalProducedLoadingUnits: 0,
remainingPallets: 88,
Provided: 0,
consumption: 0,
totalDemand: 79357.090909,
totalNeeded: 1,
noMMShortage: null,
noPKGAutoShortage: null,
noPKGManualShortage: null,
noManualShortage: null,
autoConsumeCheck: "autoConsumeOk",
invForAutoConsume: 903000,
Percentage: 0,
QuantityPosition: null,
"": 1,
},
{
MaterialHumanReadableId: 97,
MaterialDescription: "SSH Plastic 48100349 44x56x0.06 30cyc",
Staged: 0,
isManual: false,
IsMainMaterial: false,
TotalPlannedLoadingUnits: 88,
TotalProducedLoadingUnits: 0,
remainingPallets: 88,
Provided: 0,
consumption: 0,
totalDemand: 792,
totalNeeded: 66.2904,
noMMShortage: null,
noPKGAutoShortage: "pkgAutoGood",
noPKGManualShortage: "noManPkg",
noManualShortage: null,
autoConsumeCheck: "autoConsumeOk",
invForAutoConsume: 29962,
Percentage: 0,
QuantityPosition: 9,
"": null,
},
{
MaterialHumanReadableId: 169,
MaterialDescription: "LBL Label 4x6 white 9396",
Staged: 0,
isManual: false,
IsMainMaterial: false,
TotalPlannedLoadingUnits: 88,
TotalProducedLoadingUnits: 0,
remainingPallets: 88,
Provided: 0,
consumption: 0,
totalDemand: 264,
totalNeeded: 66.2904,
noMMShortage: null,
noPKGAutoShortage: "pkgAutoGood",
noPKGManualShortage: "noManPkg",
noManualShortage: null,
autoConsumeCheck: "autoConsumeOk",
invForAutoConsume: 55637,
Percentage: 0,
QuantityPosition: 3,
"": null,
},
];

Some files were not shown because too many files have changed in this diff Show More