Compare commits
75 Commits
2607fd3026
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| dcfa56bdb9 | |||
| ea92422bb1 | |||
| 2111a5fdc9 | |||
| 6edd20585f | |||
| a9759795c4 | |||
| 32f26a1725 | |||
| 60533beed5 | |||
| 24ced97b6d | |||
| dc1d342799 | |||
| 44d0cb63cf | |||
| ace73fa919 | |||
| 316af4233f | |||
| 36a805c652 | |||
| 460bc3d24a | |||
| ec201fcfb5 | |||
| 914ad46c43 | |||
| b96c546ed3 | |||
| 29b3be41a1 | |||
| 16edf58025 | |||
| 775627f215 | |||
| 4e70fae69b | |||
| 24dd109a21 | |||
| 38b57a00cc | |||
| f8070db95f | |||
| 10e9dc430c | |||
| 6b669ccd9c | |||
| d9a10d98a1 | |||
| e64dc7c013 | |||
| d63138d746 | |||
| 84a28f2d01 | |||
| 9be6614972 | |||
| 9d0db71f6a | |||
| 3cc55436f3 | |||
| 124fde07e0 | |||
| b15d0d7322 | |||
| 0680f332fb | |||
| 46bf310dce | |||
| 0dda6ae744 | |||
| 1b59cdd3a4 | |||
| 56934216f7 | |||
| e8a2ef8b85 | |||
| 6cbffa4ac5 | |||
| 09f16f4e62 | |||
| 461acb2b16 | |||
| 0d05c66a2b | |||
| 096cc18477 | |||
| f3333ce020 | |||
| 8e3d2b3d95 | |||
| 501709546d | |||
| 2b5e77993b | |||
| 6efaffbb17 | |||
| 90ddbca2e7 | |||
| 7a9ea16f48 | |||
| 420826de9b | |||
| dc2d3718fa | |||
| 5013228384 | |||
| 4459742cf0 | |||
| 070c3ee975 | |||
| 8ac92888ad | |||
| 567579ef35 | |||
| 8d90f27514 | |||
| 722b23a321 | |||
| ba48c5307f | |||
| 30d2ec0477 | |||
| d3c6444491 | |||
| 12345c0b64 | |||
| 6833dfc992 | |||
| ac27a286c0 | |||
| a3dba6cc9d | |||
| 320dd47aea | |||
| 712a6eebdf | |||
| f226c5644c | |||
| d605225e48 | |||
| 8e7f1eb098 | |||
| 59c6fd0117 |
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@@ -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",
|
||||
|
||||
32
CHANGELOG.md
32
CHANGELOG.md
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
22
LogisticsSupportTool_API_DOCS/LstV2/Warehouse/sscc.bru
Normal file
22
LogisticsSupportTool_API_DOCS/LstV2/Warehouse/sscc.bru
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
26
LogisticsSupportTool_API_DOCS/LstV2/ocp/Logs.bru
Normal file
26
LogisticsSupportTool_API_DOCS/LstV2/ocp/Logs.bru
Normal file
@@ -0,0 +1,26 @@
|
||||
meta {
|
||||
name: Logs
|
||||
type: http
|
||||
seq: 2
|
||||
}
|
||||
|
||||
get {
|
||||
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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
meta {
|
||||
name: Consume
|
||||
seq: 5
|
||||
}
|
||||
|
||||
auth {
|
||||
mode: inherit
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"version": "1",
|
||||
"name": "LogisticsSupportTool_API_DOCS",
|
||||
"name": "lstv2",
|
||||
"type": "collection",
|
||||
"ignore": [
|
||||
"node_modules",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
vars {
|
||||
url: https://usflo1prod.alpla.net
|
||||
url: http://localhost:5500
|
||||
session_cookie:
|
||||
urlv2: http://usbow1vms006:3000
|
||||
jwtV2:
|
||||
|
||||
24
LogisticsSupportTool_API_DOCS/logistics/bookout.bru
Normal file
24
LogisticsSupportTool_API_DOCS/logistics/bookout.bru
Normal 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
|
||||
}
|
||||
8
LogisticsSupportTool_API_DOCS/logistics/folder.bru
Normal file
8
LogisticsSupportTool_API_DOCS/logistics/folder.bru
Normal file
@@ -0,0 +1,8 @@
|
||||
meta {
|
||||
name: logistics
|
||||
seq: 7
|
||||
}
|
||||
|
||||
auth {
|
||||
mode: inherit
|
||||
}
|
||||
24
LogisticsSupportTool_API_DOCS/logistics/relocate.bru
Normal file
24
LogisticsSupportTool_API_DOCS/logistics/relocate.bru
Normal 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
|
||||
}
|
||||
24
LogisticsSupportTool_API_DOCS/logistics/removeAsWaste.bru
Normal file
24
LogisticsSupportTool_API_DOCS/logistics/removeAsWaste.bru
Normal 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
|
||||
}
|
||||
8
LogisticsSupportTool_API_DOCS/v3endpoints/folder.bru
Normal file
8
LogisticsSupportTool_API_DOCS/v3endpoints/folder.bru
Normal file
@@ -0,0 +1,8 @@
|
||||
meta {
|
||||
name: v3endpoints
|
||||
seq: 5
|
||||
}
|
||||
|
||||
auth {
|
||||
mode: inherit
|
||||
}
|
||||
16
LogisticsSupportTool_API_DOCS/v3endpoints/tester.bru
Normal file
16
LogisticsSupportTool_API_DOCS/v3endpoints/tester.bru
Normal 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
|
||||
}
|
||||
@@ -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(
|
||||
|
||||
89
app/src/internal/datamart/routes/getActiveAv.ts
Normal file
89
app/src/internal/datamart/routes/getActiveAv.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import { Router, type Request, type Response } from "express";
|
||||
import { prodQuery } from "../../../pkg/prodSql/prodQuery.js";
|
||||
import { tryCatch } from "../../../pkg/utils/tryCatch.js";
|
||||
import { db } from "../../../pkg/db/db.js";
|
||||
import { settings } from "../../../pkg/db/schema/settings.js";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { activeArticle } from "../../../pkg/prodSql/querys/datamart/article.js";
|
||||
|
||||
type Articles = {
|
||||
article: string
|
||||
description: string
|
||||
articleType: string
|
||||
pricePoint:string
|
||||
salesPrice:string
|
||||
typeOfMaterial:string
|
||||
articleIdType:string
|
||||
articleWeight:string
|
||||
idAddress:string
|
||||
addressDescription:string
|
||||
addressType:string
|
||||
profitCenter:String
|
||||
fg: string
|
||||
num_of_cycles:string
|
||||
costsCenterId:string
|
||||
costCenterDescription:string
|
||||
customerArticleNumber:string
|
||||
customerArticleDescription:String
|
||||
cycleTime:string
|
||||
salesAgreement:string
|
||||
productFamily:string
|
||||
uom:string
|
||||
}
|
||||
|
||||
|
||||
const router = Router();
|
||||
|
||||
// GET /health
|
||||
router.get("/", async (req: Request, res: Response) => {
|
||||
|
||||
const includePlantToken = req.params.includePlantToken
|
||||
|
||||
let articles:Articles[] = [];
|
||||
try {
|
||||
const res = await prodQuery(activeArticle, "Get active articles");
|
||||
articles = res?.data;
|
||||
}
|
||||
catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
message:"Error getting articles",
|
||||
error: error
|
||||
};
|
||||
}
|
||||
if (includePlantToken) {
|
||||
const { data, error } = await tryCatch(db.select().from(settings).where(eq(settings.name, "plantToken")))
|
||||
if (error) {
|
||||
|
||||
return {
|
||||
success: false,
|
||||
message:"Error getting settings",
|
||||
error: error
|
||||
};
|
||||
}
|
||||
// return articles.map((n) => {
|
||||
// return {
|
||||
// success: true,
|
||||
// message: "Active articles including plant token",
|
||||
// data:{ plantToken: data[0].value, ...n }};
|
||||
// });
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: "Active articles including plant token",
|
||||
data: articles.map((n) => {
|
||||
return { plantToken: data[0].value, ...n }
|
||||
})
|
||||
}
|
||||
}
|
||||
else {
|
||||
return {
|
||||
success: true,
|
||||
message: "Active articles including plant token",
|
||||
data:articles};
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
export default router;
|
||||
10
app/src/internal/datamart/routes/routes.ts
Normal file
10
app/src/internal/datamart/routes/routes.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import type { Express, Request, Response } from "express";
|
||||
|
||||
//datamart Routes
|
||||
import getActiveAv from './getActiveAv.js'
|
||||
export const setupDataMartRoutes = (app: Express, basePath: string) => {
|
||||
const route = basePath + "/api/datamart"
|
||||
app.use(route + '/activeArticle', getActiveAv);
|
||||
//app.use(basePath + "/api/user/me", requireAuth(), me);
|
||||
|
||||
};
|
||||
@@ -35,20 +35,21 @@ export const forecastEdiData = async (data: ForecastData[]) => {
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const activeAV = article?.data.filter(
|
||||
(c: any) =>
|
||||
c?.CustomerArticleNumber === data[i].customerArticleNo?.toString(),
|
||||
c?.customerArticleNumber === data[i].customerArticleNo?.toString(),
|
||||
);
|
||||
const newData = data[i];
|
||||
//console.log(activeAV[0].IdArtikelvarianten);
|
||||
|
||||
forecaseEDIDATA.push({
|
||||
...newData,
|
||||
article: activeAV[0].IdArtikelvarianten,
|
||||
description: activeAV[0].Bezeichnung, // change this later once we migrate more items
|
||||
article: activeAV.length > 0 ? activeAV[0].article : 0,
|
||||
description:
|
||||
activeAV.length > 0 ? activeAV[0].description : "No Av Created",
|
||||
requirementDate: new Date(newData.requirementDate),
|
||||
});
|
||||
}
|
||||
|
||||
console.log(forecaseEDIDATA[0]);
|
||||
//console.log(forecaseEDIDATA[0]);
|
||||
const { data: f, error: ef } = await tryCatch(
|
||||
db.insert(forecastData).values(forecaseEDIDATA),
|
||||
);
|
||||
|
||||
@@ -5,6 +5,7 @@ import { setupForkliftRoutes } from "../forklifts/routes/routes.js";
|
||||
import { setupLogisticsRoutes } from "../logistics/routes.js";
|
||||
import { setupSystemRoutes } from "../system/routes.js";
|
||||
import { setupMobileRoutes } from "../mobile/route.js";
|
||||
import { setupDataMartRoutes } from "../datamart/routes/routes.js";
|
||||
|
||||
export const setupRoutes = (app: Express, basePath: string) => {
|
||||
// all routes
|
||||
@@ -14,6 +15,7 @@ export const setupRoutes = (app: Express, basePath: string) => {
|
||||
setupLogisticsRoutes(app, basePath);
|
||||
setupForkliftRoutes(app, basePath);
|
||||
setupMobileRoutes(app, basePath);
|
||||
setupDataMartRoutes(app, basePath)
|
||||
|
||||
// always try to go to the app weather we are in dev or in production.
|
||||
app.get(basePath + "/", (req: Request, res: Response) => {
|
||||
|
||||
@@ -1,60 +1,59 @@
|
||||
export const swaggerUiOptions = {
|
||||
explorer: true,
|
||||
customCss: '.swagger-ui .topbar { display: none }',
|
||||
customSiteTitle: 'Your API Documentation',
|
||||
customCss: ".swagger-ui .topbar { display: none }",
|
||||
customSiteTitle: "LST API Documentation",
|
||||
swaggerOptions: {
|
||||
persistAuthorization: true,
|
||||
displayRequestDuration: true,
|
||||
filter: true,
|
||||
syntaxHighlight: {
|
||||
activate: true,
|
||||
theme: 'monokai'
|
||||
}
|
||||
}
|
||||
theme: "monokai",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
export const swaggerConfig = {
|
||||
definition: {
|
||||
openapi: '3.0.0',
|
||||
openapi: "3.0.0",
|
||||
info: {
|
||||
title: 'Logistics Support Tool',
|
||||
version: '1.8.0',
|
||||
description: 'Complete API documentation for lst',
|
||||
title: "Logistics Support Tool",
|
||||
version: "1.8.0",
|
||||
description: "Complete API documentation for lst",
|
||||
contact: {
|
||||
name: 'API Support',
|
||||
email: 'blake.matthes@alpla.com'
|
||||
}
|
||||
name: "API Support",
|
||||
email: "blake.matthes@alpla.com",
|
||||
},
|
||||
},
|
||||
servers: [
|
||||
{
|
||||
url: 'http://localhost:4200',
|
||||
description: 'Development server'
|
||||
url: "http://localhost:4200",
|
||||
description: "Development server",
|
||||
},
|
||||
{
|
||||
url: 'https://api.yourapp.com',
|
||||
description: 'Production server'
|
||||
}
|
||||
url: "https://api.yourapp.com",
|
||||
description: "Production server",
|
||||
},
|
||||
],
|
||||
components: {
|
||||
securitySchemes: {
|
||||
bearerAuth: {
|
||||
type: 'http',
|
||||
scheme: 'bearer',
|
||||
bearerFormat: 'JWT'
|
||||
type: "http",
|
||||
scheme: "bearer",
|
||||
bearerFormat: "JWT",
|
||||
},
|
||||
apiKey: {
|
||||
type: 'apiKey',
|
||||
in: 'header',
|
||||
name: 'X-API-Key'
|
||||
}
|
||||
}
|
||||
type: "apiKey",
|
||||
in: "header",
|
||||
name: "X-API-Key",
|
||||
},
|
||||
},
|
||||
},
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
]
|
||||
bearerAuth: [],
|
||||
},
|
||||
apis: [] // We'll populate this dynamically
|
||||
],
|
||||
},
|
||||
apis: [], // We'll populate this dynamically
|
||||
};
|
||||
|
||||
@@ -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
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import { returnFunc } from "../utils/return.js";
|
||||
import { connected, pool } from "./prodSqlConnect.js";
|
||||
import { validateEnv } from "../utils/envValidator.js";
|
||||
import { returnFunc } from "../utils/return.js";
|
||||
import {
|
||||
closePool,
|
||||
connected,
|
||||
pool,
|
||||
reconnecting,
|
||||
reconnectToSql,
|
||||
} from "./prodSqlConnect.js";
|
||||
|
||||
const env = validateEnv(process.env);
|
||||
/**
|
||||
@@ -12,6 +18,19 @@ const env = validateEnv(process.env);
|
||||
*/
|
||||
export async function prodQuery(queryToRun: string, name: string) {
|
||||
if (!connected) {
|
||||
reconnectToSql();
|
||||
|
||||
if (reconnecting) {
|
||||
return returnFunc({
|
||||
success: false,
|
||||
module: "prodSql",
|
||||
subModule: "query",
|
||||
level: "error",
|
||||
message: `The sql ${env.PROD_PLANT_TOKEN} is trying to reconnect already`,
|
||||
notify: false,
|
||||
data: [],
|
||||
});
|
||||
} else {
|
||||
return returnFunc({
|
||||
success: false,
|
||||
module: "prodSql",
|
||||
@@ -22,6 +41,8 @@ export async function prodQuery(queryToRun: string, name: string) {
|
||||
data: [],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const query = queryToRun.replaceAll("test1", env.PROD_PLANT_TOKEN);
|
||||
try {
|
||||
const result = await pool.request().query(query);
|
||||
@@ -33,6 +54,7 @@ export async function prodQuery(queryToRun: string, name: string) {
|
||||
} catch (error: any) {
|
||||
console.log(error);
|
||||
if (error.code === "ETIMEOUT") {
|
||||
closePool();
|
||||
return returnFunc({
|
||||
success: false,
|
||||
module: "prodSql",
|
||||
@@ -45,6 +67,7 @@ export async function prodQuery(queryToRun: string, name: string) {
|
||||
}
|
||||
|
||||
if (error.code === "EREQUEST") {
|
||||
closePool();
|
||||
return returnFunc({
|
||||
success: false,
|
||||
module: "prodSql",
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import sql from "mssql";
|
||||
import { checkHostnamePort } from "../utils/checkHostNamePort.js";
|
||||
import { sqlConfig } from "./prodSqlConfig.js";
|
||||
import { createLogger } from "../logger/logger.js";
|
||||
import { returnFunc } from "../utils/return.js";
|
||||
import { checkHostnamePort } from "../utils/checkHostNamePort.js";
|
||||
import { validateEnv } from "../utils/envValidator.js";
|
||||
import { returnFunc } from "../utils/return.js";
|
||||
import { sqlConfig } from "./prodSqlConfig.js";
|
||||
|
||||
const env = validateEnv(process.env);
|
||||
|
||||
export let pool: any;
|
||||
export let connected: boolean = false;
|
||||
let reconnecting = false;
|
||||
export let reconnecting = false;
|
||||
|
||||
export const initializeProdPool = async () => {
|
||||
const log = createLogger({ module: "prodSql" });
|
||||
@@ -41,21 +41,19 @@ export const initializeProdPool = async () => {
|
||||
pool = await sql.connect(sqlConfig);
|
||||
|
||||
log.info(
|
||||
`Connected to ${sqlConfig?.server}, using DB: ${sqlConfig?.database}`
|
||||
`Connected to ${sqlConfig?.server}, using DB: ${sqlConfig?.database}`,
|
||||
);
|
||||
connected = true;
|
||||
} catch (error) {
|
||||
log.fatal(
|
||||
`${JSON.stringify(
|
||||
error
|
||||
)}, "There was an error connecting to the pool."`
|
||||
`${JSON.stringify(error)}, "There was an error connecting to the pool."`,
|
||||
);
|
||||
reconnectToSql();
|
||||
// throw new Error("There was an error closing the sql connection");
|
||||
}
|
||||
};
|
||||
|
||||
const reconnectToSql = async () => {
|
||||
export const reconnectToSql = async () => {
|
||||
const log = createLogger({ module: "prodSql" });
|
||||
if (reconnecting) return;
|
||||
reconnecting = true;
|
||||
@@ -67,9 +65,7 @@ const reconnectToSql = async () => {
|
||||
while (!connected && attempts < maxAttempts) {
|
||||
attempts++;
|
||||
log.info(
|
||||
`Reconnect attempt ${attempts}/${maxAttempts} in ${
|
||||
delay / 1000
|
||||
}s...`
|
||||
`Reconnect attempt ${attempts}/${maxAttempts} in ${delay / 1000}s...`,
|
||||
);
|
||||
|
||||
await new Promise((res) => setTimeout(res, delay));
|
||||
@@ -85,15 +81,15 @@ const reconnectToSql = async () => {
|
||||
pool = sql.connect(sqlConfig);
|
||||
|
||||
log.info(
|
||||
`Connected to ${sqlConfig?.server}, and looking at ${sqlConfig?.database}`
|
||||
`Connected to ${sqlConfig?.server}, and looking at ${sqlConfig?.database}`,
|
||||
);
|
||||
reconnecting = false;
|
||||
connected = true;
|
||||
} catch (error) {
|
||||
log.fatal(
|
||||
`${JSON.stringify(
|
||||
error
|
||||
)}, "There was an error connecting to the pool."`
|
||||
error,
|
||||
)}, "There was an error connecting to the pool."`,
|
||||
);
|
||||
delay = Math.min(delay * 2, 30000); // exponential backoff up to 30s
|
||||
// throw new Error("There was an error closing the sql connection");
|
||||
@@ -103,10 +99,10 @@ const reconnectToSql = async () => {
|
||||
if (!connected) {
|
||||
log.fatal(
|
||||
{ notify: true },
|
||||
"Max reconnect attempts reached on the prodSql server. Stopping retries."
|
||||
"Max reconnect attempts reached on the prodSql server. Stopping retries.",
|
||||
);
|
||||
reconnecting = false;
|
||||
// optional: exit process or alert someone here
|
||||
// exit process or alert someone here
|
||||
// process.exit(1);
|
||||
}
|
||||
};
|
||||
@@ -126,11 +122,13 @@ export const closePool = async () => {
|
||||
message: "The sql server connection has been closed",
|
||||
};
|
||||
} catch (error) {
|
||||
log.fatal(
|
||||
{ notify: true },
|
||||
connected = false;
|
||||
log.info(
|
||||
//{ notify: true },
|
||||
{ error: error },
|
||||
`${JSON.stringify(
|
||||
error
|
||||
)}, "There was an error closing the sql connection"`
|
||||
error,
|
||||
)}, "There was an error closing the sql connection"`,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
export const activeArticle = `
|
||||
use AlplaPROD_test1
|
||||
|
||||
SELECT V_Artikel.IdArtikelvarianten,
|
||||
V_Artikel.Bezeichnung,
|
||||
V_Artikel.ArtikelvariantenTypBez,
|
||||
V_Artikel.PreisEinheitBez,
|
||||
SELECT V_Artikel.IdArtikelvarianten as article,
|
||||
V_Artikel.Bezeichnung as description,
|
||||
V_Artikel.ArtikelvariantenTypBez as articleType,
|
||||
V_Artikel.PreisEinheitBez as pricePoint,
|
||||
case when sales.price is null then 0 else sales.price end as salesPrice,
|
||||
TypeOfMaterial=CASE
|
||||
CASE
|
||||
WHEN
|
||||
V_Artikel.ArtikelvariantenTypBez LIKE'%Additive'
|
||||
Then 'AD'
|
||||
@@ -90,14 +90,15 @@ THEN 'Caps'
|
||||
When
|
||||
V_Artikel.ArtikelvariantenTypBez = 'Dummy'
|
||||
THEN 'Not used'
|
||||
ELSE 'Item not defined' END
|
||||
,V_Artikel.IdArtikelvariantenTyp,
|
||||
Round(V_Artikel.ArtikelGewicht, 3) as Article_Weight,
|
||||
IdAdresse,
|
||||
AdressBez,
|
||||
AdressTypBez,
|
||||
ProdBereichBez,
|
||||
FG=case when
|
||||
ELSE 'Item not defined' END as typeOfMaterial
|
||||
|
||||
,V_Artikel.IdArtikelvariantenTyp as articleIdType,
|
||||
Round(V_Artikel.ArtikelGewicht, 3) as articleWeight,
|
||||
IdAdresse as idAddress,
|
||||
AdressBez as addressDescription,
|
||||
AdressTypBez as addressType,
|
||||
ProdBereichBez as profitCenter,
|
||||
case when
|
||||
V_Artikel.ProdBereichBez = 'SBM' or
|
||||
V_Artikel.ProdBereichBez = 'IM-Caps' or
|
||||
V_Artikel.ProdBereichBez = 'IM-PET' or
|
||||
@@ -107,15 +108,16 @@ V_Artikel.ProdBereichBez = 'ISBM' or
|
||||
V_Artikel.ProdBereichBez = 'IM-Finishing'
|
||||
Then 'FG'
|
||||
Else 'not Defined Profit Center'
|
||||
end,
|
||||
end as fg,
|
||||
|
||||
V_Artikel.Umlaeufe as num_of_cycles,
|
||||
V_FibuKonten_BASIS.FibuKontoNr as CostsCenterId,
|
||||
V_FibuKonten_BASIS.Bezeichnung as CostCenterDescription,
|
||||
sales.[KdArtNr] as CustomerArticleNumber,
|
||||
sales.[KdArtBez] as CustomerArticleDescription,
|
||||
round(V_Artikel.Zyklus, 2) as CycleTime,
|
||||
V_FibuKonten_BASIS.FibuKontoNr as costsCenterId,
|
||||
V_FibuKonten_BASIS.Bezeichnung as costCenterDescription,
|
||||
sales.[KdArtNr] as customerArticleNumber,
|
||||
sales.[KdArtBez] as customerArticleDescription,
|
||||
round(V_Artikel.Zyklus, 2) as cycleTime,
|
||||
Sypronummer as salesAgreement,
|
||||
V_Artikel.ProdArtikelBez as ProductFamily
|
||||
V_Artikel.ProdArtikelBez as productFamily
|
||||
--,REPLACE(pur.UOM,'UOM:','')
|
||||
,Case when LEFT(
|
||||
LTRIM(REPLACE(pur.UOM,'UOM:','')),
|
||||
@@ -123,7 +125,7 @@ V_Artikel.ProdArtikelBez as ProductFamily
|
||||
) is null then '1' else LEFT(
|
||||
LTRIM(REPLACE(pur.UOM,'UOM:','')),
|
||||
CHARINDEX(' ', LTRIM(REPLACE(REPLACE(pur.UOM,'UOM:',''), CHAR(13)+CHAR(10), ' ')) + ' ') - 1
|
||||
) end AS UOM
|
||||
) end AS uom
|
||||
--,*
|
||||
FROM dbo.V_Artikel (nolock)
|
||||
|
||||
|
||||
@@ -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 };
|
||||
}
|
||||
|
||||
321
frontend/package-lock.json
generated
321
frontend/package-lock.json
generated
@@ -44,7 +44,6 @@
|
||||
"lucide-react": "^0.554.0",
|
||||
"marked": "^17.0.1",
|
||||
"moment": "^2.30.1",
|
||||
"r": "^0.0.5",
|
||||
"react": "^19.2.0",
|
||||
"react-barcode": "^1.6.1",
|
||||
"react-calendar-timeline": "^0.30.0-beta.4",
|
||||
@@ -52,7 +51,7 @@
|
||||
"react-dom": "^19.2.0",
|
||||
"react-hook-form": "^7.66.1",
|
||||
"react-resizable-panels": "^3.0.6",
|
||||
"recharts": "^3.5.0",
|
||||
"recharts": "^2.15.4",
|
||||
"socket.io-client": "^4.8.1",
|
||||
"sonner": "^2.0.7",
|
||||
"tailwind-merge": "^3.4.0",
|
||||
@@ -1033,6 +1032,7 @@
|
||||
"version": "4.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz",
|
||||
"integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"eslint-visitor-keys": "^3.4.3"
|
||||
@@ -1051,6 +1051,7 @@
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
|
||||
"integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
@@ -1063,6 +1064,7 @@
|
||||
"version": "4.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
|
||||
"integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
|
||||
@@ -1072,6 +1074,7 @@
|
||||
"version": "0.21.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz",
|
||||
"integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@eslint/object-schema": "^2.1.7",
|
||||
@@ -1086,6 +1089,7 @@
|
||||
"version": "0.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz",
|
||||
"integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@eslint/core": "^0.17.0"
|
||||
@@ -1098,6 +1102,7 @@
|
||||
"version": "0.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz",
|
||||
"integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@types/json-schema": "^7.0.15"
|
||||
@@ -1110,6 +1115,7 @@
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz",
|
||||
"integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ajv": "^6.12.4",
|
||||
@@ -1133,6 +1139,7 @@
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
|
||||
"integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
@@ -1145,6 +1152,7 @@
|
||||
"version": "9.39.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz",
|
||||
"integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -1157,6 +1165,7 @@
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz",
|
||||
"integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -1166,6 +1175,7 @@
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz",
|
||||
"integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@eslint/core": "^0.17.0",
|
||||
@@ -1217,6 +1227,7 @@
|
||||
"version": "0.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
|
||||
"integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=18.18.0"
|
||||
@@ -1226,6 +1237,7 @@
|
||||
"version": "0.16.6",
|
||||
"resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz",
|
||||
"integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@humanfs/core": "^0.19.1",
|
||||
@@ -1239,6 +1251,7 @@
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz",
|
||||
"integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=18.18"
|
||||
@@ -1252,6 +1265,7 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
|
||||
"integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=12.22"
|
||||
@@ -1265,6 +1279,7 @@
|
||||
"version": "0.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
|
||||
"integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=18.18"
|
||||
@@ -2702,42 +2717,6 @@
|
||||
"@react-pdf/stylesheet": "^6.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@reduxjs/toolkit": {
|
||||
"version": "2.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.11.0.tgz",
|
||||
"integrity": "sha512-hBjYg0aaRL1O2Z0IqWhnTLytnjDIxekmRxm1snsHjHaKVmIF1HiImWqsq+PuEbn6zdMlkIj9WofK1vR8jjx+Xw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@standard-schema/spec": "^1.0.0",
|
||||
"@standard-schema/utils": "^0.3.0",
|
||||
"immer": "^11.0.0",
|
||||
"redux": "^5.0.1",
|
||||
"redux-thunk": "^3.1.0",
|
||||
"reselect": "^5.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.9.0 || ^17.0.0 || ^18 || ^19",
|
||||
"react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react": {
|
||||
"optional": true
|
||||
},
|
||||
"react-redux": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@reduxjs/toolkit/node_modules/immer": {
|
||||
"version": "11.0.0",
|
||||
"resolved": "https://registry.npmjs.org/immer/-/immer-11.0.0.tgz",
|
||||
"integrity": "sha512-XtRG4SINt4dpqlnJvs70O2j6hH7H0X8fUzFsjMn1rwnETaxwp83HLNimXBjZ78MrKl3/d3/pkzDH0o0Lkxm37Q==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/immer"
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/pluginutils": {
|
||||
"version": "1.0.0-beta.47",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.47.tgz",
|
||||
@@ -3017,12 +2996,6 @@
|
||||
"integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@standard-schema/utils": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz",
|
||||
"integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@swc/core": {
|
||||
"version": "1.13.5",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.13.5.tgz",
|
||||
@@ -4047,6 +4020,7 @@
|
||||
"version": "7.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
@@ -4088,12 +4062,6 @@
|
||||
"@types/react": "^19.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/use-sync-external-store": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz",
|
||||
"integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "8.48.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.48.0.tgz",
|
||||
@@ -4391,6 +4359,7 @@
|
||||
"version": "8.15.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
@@ -4403,6 +4372,7 @@
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
|
||||
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||
@@ -4412,6 +4382,7 @@
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
@@ -4428,6 +4399,7 @@
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1"
|
||||
@@ -4467,6 +4439,7 @@
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||
"dev": true,
|
||||
"license": "Python-2.0"
|
||||
},
|
||||
"node_modules/aria-hidden": {
|
||||
@@ -4528,6 +4501,7 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/base64-js": {
|
||||
@@ -4650,6 +4624,7 @@
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
@@ -4737,6 +4712,7 @@
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
|
||||
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
@@ -4767,6 +4743,7 @@
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
@@ -4873,6 +4850,7 @@
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
@@ -4913,6 +4891,7 @@
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/convert-source-map": {
|
||||
@@ -4932,6 +4911,7 @@
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"path-key": "^3.1.0",
|
||||
@@ -5102,6 +5082,7 @@
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
|
||||
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "^2.1.3"
|
||||
@@ -5125,6 +5106,7 @@
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
|
||||
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/defu": {
|
||||
@@ -5173,6 +5155,16 @@
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-helpers": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
|
||||
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.8.7",
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/dunder-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
@@ -5306,16 +5298,6 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-toolkit": {
|
||||
"version": "1.42.0",
|
||||
"resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.42.0.tgz",
|
||||
"integrity": "sha512-SLHIyY7VfDJBM8clz4+T2oquwTQxEzu263AyhVK4jREOAwJ+8eebaa4wM3nlvnAqhDrMm2EsA6hWHaQsMPQ1nA==",
|
||||
"license": "MIT",
|
||||
"workspaces": [
|
||||
"docs",
|
||||
"benchmarks"
|
||||
]
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.25.9",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz",
|
||||
@@ -5371,6 +5353,7 @@
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
||||
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
@@ -5383,6 +5366,7 @@
|
||||
"version": "9.39.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz",
|
||||
"integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.8.0",
|
||||
@@ -5458,18 +5442,6 @@
|
||||
"eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-react-perf": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react-perf/-/eslint-plugin-react-perf-3.3.3.tgz",
|
||||
"integrity": "sha512-EzPdxsRJg5IllCAH9ny/3nK7sv9251tvKmi/d3Ouv5KzI8TB3zNhzScxL9wnh9Hvv8GYC5LEtzTauynfOEYiAw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.9.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-react-refresh": {
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.24.tgz",
|
||||
@@ -5484,6 +5456,7 @@
|
||||
"version": "8.4.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
|
||||
"integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"esrecurse": "^4.3.0",
|
||||
@@ -5500,6 +5473,7 @@
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
|
||||
"integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
@@ -5512,6 +5486,7 @@
|
||||
"version": "10.4.0",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
|
||||
"integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"acorn": "^8.15.0",
|
||||
@@ -5543,6 +5518,7 @@
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
|
||||
"integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"estraverse": "^5.1.0"
|
||||
@@ -5555,6 +5531,7 @@
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
|
||||
"integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"estraverse": "^5.2.0"
|
||||
@@ -5567,6 +5544,7 @@
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
|
||||
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
@@ -5576,15 +5554,16 @@
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
|
||||
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eventemitter3": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
|
||||
"integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
|
||||
"version": "4.0.7",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
|
||||
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/events": {
|
||||
@@ -5602,22 +5581,34 @@
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-equals": {
|
||||
"version": "5.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.3.3.tgz",
|
||||
"integrity": "sha512-/boTcHZeIAQ2r/tL11voclBHDeP9WPxLt+tyAbVSyyXuUFyh0Tne7gJZTqGbxnvj79TjLdCXLOY7UIPhyG5MTw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-json-stable-stringify": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-levenshtein": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
|
||||
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/file-entry-cache": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
|
||||
"integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"flat-cache": "^4.0.0"
|
||||
@@ -5643,6 +5634,7 @@
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
|
||||
"integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"locate-path": "^6.0.0",
|
||||
@@ -5659,6 +5651,7 @@
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
|
||||
"integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"flatted": "^3.2.9",
|
||||
@@ -5672,6 +5665,7 @@
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
|
||||
"integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
@@ -5823,6 +5817,7 @@
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
|
||||
"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"is-glob": "^4.0.3"
|
||||
@@ -5882,6 +5877,7 @@
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@@ -5968,25 +5964,17 @@
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
||||
"integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/immer": {
|
||||
"version": "10.2.0",
|
||||
"resolved": "https://registry.npmjs.org/immer/-/immer-10.2.0.tgz",
|
||||
"integrity": "sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/immer"
|
||||
}
|
||||
},
|
||||
"node_modules/import-fresh": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
|
||||
"integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"parent-module": "^1.0.0",
|
||||
@@ -6003,6 +5991,7 @@
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
|
||||
"integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.8.19"
|
||||
@@ -6056,6 +6045,7 @@
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
@@ -6065,6 +6055,7 @@
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-extglob": "^2.1.1"
|
||||
@@ -6108,6 +6099,7 @@
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/jay-peg": {
|
||||
@@ -6156,6 +6148,7 @@
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1"
|
||||
@@ -6187,18 +6180,21 @@
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
|
||||
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/json-stable-stringify-without-jsonify": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
|
||||
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/json5": {
|
||||
@@ -6218,6 +6214,7 @@
|
||||
"version": "4.5.4",
|
||||
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
|
||||
"integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"json-buffer": "3.0.1"
|
||||
@@ -6236,6 +6233,7 @@
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
|
||||
"integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"prelude-ls": "^1.2.1",
|
||||
@@ -6517,6 +6515,7 @@
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
||||
"integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"p-locate": "^5.0.0"
|
||||
@@ -6538,6 +6537,7 @@
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/loose-envify": {
|
||||
@@ -6638,6 +6638,7 @@
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
@@ -6698,6 +6699,7 @@
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
|
||||
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/node-releases": {
|
||||
@@ -6739,6 +6741,7 @@
|
||||
"version": "0.9.4",
|
||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
|
||||
"integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"deep-is": "^0.1.3",
|
||||
@@ -6756,6 +6759,7 @@
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
|
||||
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"yocto-queue": "^0.1.0"
|
||||
@@ -6771,6 +6775,7 @@
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
|
||||
"integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"p-limit": "^3.0.2"
|
||||
@@ -6792,6 +6797,7 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"callsites": "^3.0.0"
|
||||
@@ -6810,6 +6816,7 @@
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@@ -6819,6 +6826,7 @@
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@@ -6888,6 +6896,7 @@
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
||||
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
@@ -6936,6 +6945,7 @@
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
@@ -6950,14 +6960,6 @@
|
||||
"inherits": "~2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/r": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/r/-/r-0.0.5.tgz",
|
||||
"integrity": "sha512-rO+FXCKIUiLEVCP4HjIEkq8V5gRHc1N15/2K97GSOE/P5evYj6uOOgvHlINCwMHnEmHouBdeR6PBDzZDqmEH2A==",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/react": {
|
||||
"version": "19.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz",
|
||||
@@ -7051,31 +7053,7 @@
|
||||
"version": "18.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
|
||||
"integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/react-redux": {
|
||||
"version": "9.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz",
|
||||
"integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/use-sync-external-store": "^0.0.6",
|
||||
"use-sync-external-store": "^1.4.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "^18.2.25 || ^19",
|
||||
"react": "^18.0 || ^19",
|
||||
"redux": "^5.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"redux": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/react-remove-scroll": {
|
||||
"version": "2.7.1",
|
||||
@@ -7134,6 +7112,21 @@
|
||||
"react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/react-smooth": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz",
|
||||
"integrity": "sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-equals": "^5.0.1",
|
||||
"prop-types": "^15.8.1",
|
||||
"react-transition-group": "^4.4.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-style-singleton": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
|
||||
@@ -7156,6 +7149,22 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-transition-group": {
|
||||
"version": "4.4.5",
|
||||
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
|
||||
"integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"dom-helpers": "^5.0.1",
|
||||
"loose-envify": "^1.4.0",
|
||||
"prop-types": "^15.6.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.6.0",
|
||||
"react-dom": ">=16.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/readdirp": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||
@@ -7197,49 +7206,35 @@
|
||||
}
|
||||
},
|
||||
"node_modules/recharts": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/recharts/-/recharts-3.5.0.tgz",
|
||||
"integrity": "sha512-jWqBtu8L3VICXWa3g/y+bKjL8DDHSRme7DHD/70LQ/Tk0di1h11Y0kKC0nPh6YJ2oaa0k6anIFNhg6SfzHWdEA==",
|
||||
"version": "2.15.4",
|
||||
"resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.4.tgz",
|
||||
"integrity": "sha512-UT/q6fwS3c1dHbXv2uFgYJ9BMFHu3fwnd7AYZaEQhXuYQ4hgsxLvsUXzGdKeZrW5xopzDCvuA2N41WJ88I7zIw==",
|
||||
"license": "MIT",
|
||||
"workspaces": [
|
||||
"www"
|
||||
],
|
||||
"dependencies": {
|
||||
"@reduxjs/toolkit": "1.x.x || 2.x.x",
|
||||
"clsx": "^2.1.1",
|
||||
"decimal.js-light": "^2.5.1",
|
||||
"es-toolkit": "^1.39.3",
|
||||
"eslint-plugin-react-perf": "^3.3.3",
|
||||
"eventemitter3": "^5.0.1",
|
||||
"immer": "^10.1.1",
|
||||
"react-redux": "8.x.x || 9.x.x",
|
||||
"reselect": "5.1.1",
|
||||
"tiny-invariant": "^1.3.3",
|
||||
"use-sync-external-store": "^1.2.2",
|
||||
"victory-vendor": "^37.0.2"
|
||||
"clsx": "^2.0.0",
|
||||
"eventemitter3": "^4.0.1",
|
||||
"lodash": "^4.17.21",
|
||||
"react-is": "^18.3.1",
|
||||
"react-smooth": "^4.0.4",
|
||||
"recharts-scale": "^0.4.4",
|
||||
"tiny-invariant": "^1.3.1",
|
||||
"victory-vendor": "^36.6.8"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
"node": ">=14"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"react-is": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
"react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/redux": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
|
||||
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/redux-thunk": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz",
|
||||
"integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==",
|
||||
"node_modules/recharts-scale": {
|
||||
"version": "0.4.5",
|
||||
"resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz",
|
||||
"integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"redux": "^5.0.0"
|
||||
"dependencies": {
|
||||
"decimal.js-light": "^2.4.1"
|
||||
}
|
||||
},
|
||||
"node_modules/require-from-string": {
|
||||
@@ -7251,16 +7246,11 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/reselect": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz",
|
||||
"integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/resolve-from": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
|
||||
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
@@ -7394,6 +7384,7 @@
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"shebang-regex": "^3.0.0"
|
||||
@@ -7406,6 +7397,7 @@
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@@ -7559,6 +7551,7 @@
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
|
||||
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@@ -7571,6 +7564,7 @@
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"has-flag": "^4.0.0"
|
||||
@@ -7743,6 +7737,7 @@
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||
"integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"prelude-ls": "^1.2.1"
|
||||
@@ -7886,6 +7881,7 @@
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"punycode": "^2.1.0"
|
||||
@@ -7950,9 +7946,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/victory-vendor": {
|
||||
"version": "37.3.6",
|
||||
"resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-37.3.6.tgz",
|
||||
"integrity": "sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==",
|
||||
"version": "36.9.2",
|
||||
"resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz",
|
||||
"integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==",
|
||||
"license": "MIT AND ISC",
|
||||
"dependencies": {
|
||||
"@types/d3-array": "^3.0.3",
|
||||
@@ -8099,6 +8095,7 @@
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"isexe": "^2.0.0"
|
||||
@@ -8114,6 +8111,7 @@
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
|
||||
"integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
@@ -8159,6 +8157,7 @@
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
"react-dom": "^19.2.0",
|
||||
"react-hook-form": "^7.66.1",
|
||||
"react-resizable-panels": "^3.0.6",
|
||||
"recharts": "^3.5.0",
|
||||
"recharts": "^2.15.4",
|
||||
"socket.io-client": "^4.8.1",
|
||||
"sonner": "^2.0.7",
|
||||
"tailwind-merge": "^3.4.0",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -6,14 +6,22 @@ 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 />
|
||||
</div>
|
||||
<div className="m-1">{url === "localhost" && <Relocate />}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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" },
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
|
||||
|
||||
2
lstV2/database/migrations/0078_cheerful_the_leader.sql
Normal file
2
lstV2/database/migrations/0078_cheerful_the_leader.sql
Normal 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';
|
||||
2298
lstV2/database/migrations/meta/0078_snapshot.json
Normal file
2298
lstV2/database/migrations/meta/0078_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import axios from "axios";
|
||||
import { createLog } from "../services/logger/logger.js";
|
||||
import { prodEndpointCreation } from "./createUrl.js";
|
||||
import { tryCatch } from "./tryCatch.js";
|
||||
import { createLog } from "../services/logger/logger.js";
|
||||
|
||||
type bodyData = any;
|
||||
|
||||
@@ -9,11 +9,13 @@ type Data = {
|
||||
endpoint: string;
|
||||
data: bodyData[];
|
||||
};
|
||||
export const runProdApi = async (data: Data) => {
|
||||
/**
|
||||
* Detachs a silo
|
||||
*
|
||||
* @param data
|
||||
* @param timeoutDelay
|
||||
* @returns
|
||||
*/
|
||||
|
||||
export const runProdApi = async (data: Data) => {
|
||||
let url = await prodEndpointCreation(data.endpoint);
|
||||
|
||||
const { data: d, error } = await tryCatch(
|
||||
@@ -22,7 +24,7 @@ export const runProdApi = async (data: Data) => {
|
||||
"X-API-Key": process.env.TEC_API_KEY || "",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
||||
let e = error as any;
|
||||
@@ -33,11 +35,11 @@ export const runProdApi = async (data: Data) => {
|
||||
"error",
|
||||
"lst",
|
||||
"logistics",
|
||||
`Not autorized: ${JSON.stringify(e.response?.data)}`
|
||||
`Not authorized: ${JSON.stringify(e.response?.data)}`,
|
||||
);
|
||||
const data = {
|
||||
success: false,
|
||||
message: `Not autorized: ${JSON.stringify(e.response?.data)}`,
|
||||
message: `Not authorized: ${JSON.stringify(e.response?.data)}`,
|
||||
data: {
|
||||
status: e.response?.status,
|
||||
statusText: e.response?.statusText,
|
||||
@@ -51,13 +53,13 @@ export const runProdApi = async (data: Data) => {
|
||||
"lst",
|
||||
"logistics",
|
||||
`There was an error processing the endpoint: ${JSON.stringify(
|
||||
e.response?.data
|
||||
)}`
|
||||
e.response?.data,
|
||||
)}`,
|
||||
);
|
||||
return {
|
||||
success: false,
|
||||
message: `There was an error processing the endpoint: ${JSON.stringify(
|
||||
e.response?.data
|
||||
e.response?.data,
|
||||
)}`,
|
||||
data: {
|
||||
status: e.response?.status,
|
||||
|
||||
191
lstV2/server/globalUtils/scannerConnect.ts
Normal file
191
lstV2/server/globalUtils/scannerConnect.ts
Normal 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);
|
||||
// });
|
||||
@@ -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,
|
||||
};
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
};
|
||||
52
lstV2/server/services/dataMart/controller/psiForecastData.ts
Normal file
52
lstV2/server/services/dataMart/controller/psiForecastData.ts
Normal 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,
|
||||
};
|
||||
}),
|
||||
};
|
||||
};
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
// }),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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 day’s 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;
|
||||
};
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
65
lstV2/server/services/dataMart/route/getPsiForecast.ts
Normal file
65
lstV2/server/services/dataMart/route/getPsiForecast.ts
Normal 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;
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
155
lstV2/server/services/logistics/controller/commands/bookout.ts
Normal file
155
lstV2/server/services/logistics/controller/commands/bookout.ts
Normal 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"
|
||||
* }
|
||||
*/
|
||||
//---------------------------------------------------------------------------------------\\
|
||||
};
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
};
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
};
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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, {
|
||||
|
||||
@@ -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);
|
||||
|
||||
87
lstV2/server/services/logistics/route/bookout.ts
Normal file
87
lstV2/server/services/logistics/route/bookout.ts
Normal 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;
|
||||
80
lstV2/server/services/logistics/route/relocate.ts
Normal file
80
lstV2/server/services/logistics/route/relocate.ts
Normal 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;
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
@@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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: [],
|
||||
};
|
||||
}
|
||||
@@ -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 ?? [],
|
||||
};
|
||||
}
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
50
lstV2/server/services/notifications/routes/tooManyErrors.ts
Normal file
50
lstV2/server/services/notifications/routes/tooManyErrors.ts
Normal 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;
|
||||
@@ -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",
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -133,6 +133,14 @@ export const labelingProcess = async ({
|
||||
* The checks we do before we can actually print a label will take place meow.
|
||||
*
|
||||
*/
|
||||
// this will be for the rare case it actually doesn't find a lot properly or has some kinda error.
|
||||
if(!Array.isArray(filteredLot) || filteredLot.length === 0){
|
||||
createLog("error", "labeling", "ocp", `${printer?.name}, dose not apear to have a lot assigned to it.`);
|
||||
return {
|
||||
success: false,
|
||||
message: `${printer?.name}, dose not apear to have a lot assigned to it.`,
|
||||
};
|
||||
}
|
||||
|
||||
// if the plant does not want to have dual printing and we have >2 assigned well return and send error.
|
||||
let dualPrinting = settingData.filter((d) => d.name === "dualPrinting")[0]
|
||||
|
||||
@@ -3,6 +3,7 @@ import { eq } from "drizzle-orm";
|
||||
import { success } from "zod/v4";
|
||||
import { db } from "../../../../../database/dbclient.js";
|
||||
import { printerData } from "../../../../../database/schema/printers.js";
|
||||
import { delay } from "../../../../globalUtils/delay.js";
|
||||
import { runProdApi } from "../../../../globalUtils/runProdApi.js";
|
||||
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
||||
import { createLog } from "../../../logger/logger.js";
|
||||
@@ -158,7 +159,7 @@ export const lotMaterialTransfer = async (data: NewLotData) => {
|
||||
};
|
||||
}
|
||||
|
||||
let timeoutTrans: number = data.type === "lot" ? 30 : 10;
|
||||
let timeoutTrans: number = data.type === "lot" ? 5 : 5;
|
||||
// get the barcode, and layoutID from the running number
|
||||
const { data: label, error: labelError } = (await tryCatch(
|
||||
query(
|
||||
@@ -167,6 +168,7 @@ export const lotMaterialTransfer = async (data: NewLotData) => {
|
||||
),
|
||||
)) as any;
|
||||
|
||||
console.log(label);
|
||||
if (labelError) {
|
||||
createLog(
|
||||
"error",
|
||||
@@ -234,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);
|
||||
|
||||
@@ -273,18 +276,15 @@ 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,
|
||||
};
|
||||
|
||||
//console.log(matReturnData);
|
||||
const { data: matReturn, error: matReturError } = (await tryCatch(
|
||||
runProdApi({
|
||||
endpoint:
|
||||
"/public/v1.0/IssueMaterial/ReturnPartiallyConsumedManualMaterial",
|
||||
data: [matReturnData],
|
||||
}),
|
||||
)) as any;
|
||||
|
||||
// set a delay for when we try to return the label
|
||||
|
||||
const matReturn = await returnMaterial(matReturnData);
|
||||
|
||||
if (!matReturn.success) {
|
||||
createLog(
|
||||
@@ -302,15 +302,15 @@ 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 delay =
|
||||
const delayTimer =
|
||||
data.type === "lot"
|
||||
? timeoutTrans * 1000
|
||||
: target.getTime() - now.getTime();
|
||||
|
||||
const transfer = await transferMaterial(delay, data, consumeLot, newQty);
|
||||
const transfer = await transferMaterial(delayTimer, data, consumeLot, newQty);
|
||||
|
||||
if (!transfer.success) {
|
||||
return {
|
||||
@@ -340,6 +340,22 @@ export const lotMaterialTransfer = async (data: NewLotData) => {
|
||||
}
|
||||
};
|
||||
|
||||
const returnMaterial = async (matReturnData: any) => {
|
||||
console.log("Getting ready to Returning Materials");
|
||||
await delay(5 * 1000);
|
||||
console.log("doing the return");
|
||||
const { data: matReturn, error: matReturError } = (await tryCatch(
|
||||
runProdApi({
|
||||
endpoint:
|
||||
"/public/v1.0/IssueMaterial/ReturnPartiallyConsumedManualMaterial",
|
||||
data: [matReturnData],
|
||||
}),
|
||||
)) as any;
|
||||
|
||||
if (matReturError) return matReturError;
|
||||
return matReturn;
|
||||
};
|
||||
|
||||
const transferMaterial = async (
|
||||
delay: number,
|
||||
data: any,
|
||||
@@ -347,12 +363,13 @@ const transferMaterial = async (
|
||||
newQty: any,
|
||||
) => {
|
||||
//console.log(data);
|
||||
console.log("Transferring the material");
|
||||
if (pendingJobs.has(data.runningNumber)) {
|
||||
createLog(
|
||||
"error",
|
||||
"materials",
|
||||
"ocp",
|
||||
`${data.runningNumber} is pending to be transfered already`,
|
||||
`${data.runningNumber} is pending to be transferred already`,
|
||||
);
|
||||
return {
|
||||
success: false,
|
||||
|
||||
@@ -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,
|
||||
|
||||
148
lstV2/server/services/ocp/controller/materials/materialChecks.ts
Normal file
148
lstV2/server/services/ocp/controller/materials/materialChecks.ts
Normal 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,
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -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;
|
||||
|
||||
@@ -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]"],
|
||||
// },
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
@@ -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),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -26,7 +26,7 @@ export const qualityCycle = async () => {
|
||||
db
|
||||
.select()
|
||||
.from(qualityRequest)
|
||||
.where(inArray(qualityRequest.palletStatus, [1, 4, 5, 6])),
|
||||
.where(inArray(qualityRequest.palletStatus, [1, 4, 5, 6, 7])),
|
||||
);
|
||||
|
||||
if (error) {
|
||||
@@ -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");
|
||||
|
||||
@@ -64,6 +64,9 @@ export const qualityCycle = async () => {
|
||||
let prodData: any =
|
||||
queryData?.data.length === 0 ? [] : queryData.data;
|
||||
|
||||
// if there isnt a pallet just continue
|
||||
if (queryData?.data.length === 0) continue;
|
||||
|
||||
if (
|
||||
lstQData[i]?.locationAtRequest != prodData[0]?.locationAtRequest
|
||||
) {
|
||||
@@ -71,7 +74,7 @@ export const qualityCycle = async () => {
|
||||
const qDataPost = {
|
||||
warehouseMovedTo: prodData[0]?.warehouseAtRequest,
|
||||
locationMovedTo: prodData[0]?.locationAtRequest,
|
||||
// how ling did it take the warehouse to originally move the pallet
|
||||
// how long did it take the warehouse to originally move the pallet
|
||||
durationToMove: warehouse.includes(lstQData[i].palletStatus)
|
||||
? differenceInMinutes(
|
||||
new Date(Date.now()),
|
||||
@@ -98,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`,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -13,6 +13,7 @@ import type { Settings } from "../../../../types/settings.js";
|
||||
import { createLog } from "../../../logger/logger.js";
|
||||
|
||||
export let serverSettings: Settings[] = [];
|
||||
const dbUrl = String(process.env.DATABASE_URL).replace("lst_db", "lst");
|
||||
export const getSettings = async () => {
|
||||
const settingsType = process.env.LST_USE_GO;
|
||||
createLog(
|
||||
@@ -21,14 +22,13 @@ export const getSettings = async () => {
|
||||
"server",
|
||||
`Settings are being grabbed from the app now`,
|
||||
);
|
||||
const client = new Client({
|
||||
connectionString: dbUrl,
|
||||
});
|
||||
|
||||
//if (settingsType !== "true") {
|
||||
try {
|
||||
//serverSettings = (await db.select().from(settings)) as any;
|
||||
const dbUrl = String(process.env.DATABASE_URL).replace("lst_db", "lst");
|
||||
const client = new Client({
|
||||
connectionString: dbUrl,
|
||||
});
|
||||
|
||||
await client.connect();
|
||||
|
||||
@@ -38,7 +38,12 @@ export const getSettings = async () => {
|
||||
|
||||
serverSettings = s.rows;
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
createLog(
|
||||
"error",
|
||||
"lst",
|
||||
"server",
|
||||
`There was an error getting the settings: ${JSON.stringify(e)}`,
|
||||
);
|
||||
}
|
||||
|
||||
// const { data, error } = (await tryCatch(
|
||||
@@ -67,9 +72,16 @@ export const getSettings = async () => {
|
||||
"error",
|
||||
"lst",
|
||||
"server",
|
||||
"There was an error getting the settings",
|
||||
`There was an error getting the settings: ${JSON.stringify(error)}`,
|
||||
);
|
||||
//throw new Error("There was an error getting the settings");
|
||||
} finally {
|
||||
// ✅ Ensure the connection is always closed
|
||||
await client
|
||||
.end()
|
||||
.catch((e) =>
|
||||
createLog("error", "lst", "server", `Error closing DB client: ${e}`),
|
||||
);
|
||||
throw new Error("There was an error getting the settings");
|
||||
}
|
||||
//}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user