Compare commits
12 Commits
2133b94a1d
...
ebe5c0bd5a
| Author | SHA1 | Date | |
|---|---|---|---|
| ebe5c0bd5a | |||
| b8a9aa5132 | |||
| 52089ecdf0 | |||
| d406a92f3d | |||
| 2a6eafa19a | |||
| 00ef72de90 | |||
| 9d9ca63d7c | |||
| f9cfada840 | |||
| c2ae445ea4 | |||
| 2ed6bf4d1f | |||
| 6d27a7aa63 | |||
| 92af7262f6 |
@@ -16,10 +16,10 @@ headers {
|
||||
|
||||
body:json {
|
||||
{
|
||||
"name": "Bowling Green 1",
|
||||
"serverDNS": "USBOW1VS006",
|
||||
"plantToken": "usbow1",
|
||||
"ipAddress": "10.25.0.26",
|
||||
"name": "Dayton",
|
||||
"serverDNS": "USDAY1VS006",
|
||||
"plantToken": "usday1",
|
||||
"ipAddress": "10.44.0.26",
|
||||
"greatPlainsPlantCode": 55,
|
||||
"lstServerPort": 4000,
|
||||
"serverLoc": "E$\\LST"
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
meta {
|
||||
name: RFID Trigger
|
||||
type: http
|
||||
seq: 1
|
||||
}
|
||||
|
||||
post {
|
||||
url: {{url}}/lst/old/api/rfid/manualtrigger/wrapper1
|
||||
body: none
|
||||
auth: inherit
|
||||
}
|
||||
|
||||
settings {
|
||||
encodeUrl: true
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
meta {
|
||||
name: RFID
|
||||
seq: 3
|
||||
}
|
||||
|
||||
auth {
|
||||
mode: inherit
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
meta {
|
||||
name: ForecastData
|
||||
type: http
|
||||
seq: 1
|
||||
}
|
||||
|
||||
post {
|
||||
url: {{url}}/lst/api/logistics/dm/forecastData
|
||||
body: none
|
||||
auth: inherit
|
||||
}
|
||||
|
||||
settings {
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
vars {
|
||||
url: https://usbet1prod.alpla.net
|
||||
url: http://localhost:5500
|
||||
session_cookie:
|
||||
urlv2: http://localhost:3000
|
||||
jwtV2:
|
||||
|
||||
16
app/main.ts
16
app/main.ts
@@ -8,6 +8,8 @@ import { createProxyMiddleware, fixRequestBody } from "http-proxy-middleware";
|
||||
import morgan from "morgan";
|
||||
import os from "os";
|
||||
import { dirname, join } from "path";
|
||||
import swaggerJsdoc from "swagger-jsdoc";
|
||||
import swaggerUi from "swagger-ui-express";
|
||||
import { fileURLToPath } from "url";
|
||||
import { userMigrate } from "./src/internal/auth/controller/userMigrate.js";
|
||||
import { schedulerManager } from "./src/internal/logistics/controller/schedulerManager.js";
|
||||
@@ -15,6 +17,8 @@ import { printers } from "./src/internal/ocp/printers/printers.js";
|
||||
import { setupRoutes } from "./src/internal/routerHandler/routeHandler.js";
|
||||
import { baseModules } from "./src/internal/system/controller/modules/baseModules.js";
|
||||
import { baseSettings } from "./src/internal/system/controller/settings/baseSettings.js";
|
||||
import { addListeners } from "./src/internal/system/utlis/addListeners.js";
|
||||
import { swaggerOptions } from "./src/pkg/apiDocs/swaggerOptions.js";
|
||||
import { auth } from "./src/pkg/auth/auth.js";
|
||||
import { db } from "./src/pkg/db/db.js";
|
||||
import { settings } from "./src/pkg/db/schema/settings.js";
|
||||
@@ -30,7 +34,7 @@ import { setupIoServer } from "./src/ws/server.js";
|
||||
|
||||
const main = async () => {
|
||||
const env = validateEnv(process.env);
|
||||
const PORT = Number(env.VITE_PORT) || 4200;
|
||||
const PORT = Number(process.env.VITE_PORT) || 4200;
|
||||
|
||||
//create the logger
|
||||
const log = createLogger({ module: "system", subModule: "main start" });
|
||||
@@ -159,7 +163,14 @@ const main = async () => {
|
||||
}),
|
||||
);
|
||||
|
||||
// docs and api stuff
|
||||
// docs and routes
|
||||
const openapiSpec: any = swaggerJsdoc(swaggerOptions);
|
||||
app.use(
|
||||
basePath + "/api/docs",
|
||||
swaggerUi.serve,
|
||||
swaggerUi.setup(openapiSpec),
|
||||
);
|
||||
|
||||
app.use(basePath + "/d", express.static(join(__dirname, "../lstDocs/build")));
|
||||
app.use(
|
||||
basePath + "/app",
|
||||
@@ -192,6 +203,7 @@ const main = async () => {
|
||||
|
||||
// start up the v1listener
|
||||
v1Listener();
|
||||
addListeners();
|
||||
userMigrate();
|
||||
}, 5 * 1000);
|
||||
|
||||
|
||||
@@ -8,10 +8,63 @@
|
||||
* add_date
|
||||
*/
|
||||
|
||||
type IncomingForecastData = {
|
||||
CustomerArticleNumber: number;
|
||||
};
|
||||
import { db } from "../../../../pkg/db/db.js";
|
||||
import {
|
||||
type ForecastData,
|
||||
forecastData,
|
||||
forecastDataSchema,
|
||||
} from "../../../../pkg/db/schema/forecastEDIData.js";
|
||||
import { prodQuery } from "../../../../pkg/prodSql/prodQuery.js";
|
||||
import { activeArticle } from "../../../../pkg/prodSql/querys/datamart/article.js";
|
||||
import { tryCatch } from "../../../../pkg/utils/tryCatch.js";
|
||||
|
||||
export const forecastData = async (data: IncomingForecastData) => {
|
||||
console.log(data);
|
||||
export const forecastEdiData = async (data: ForecastData[]) => {
|
||||
//console.log(data);
|
||||
const { data: article, error } = await tryCatch(
|
||||
prodQuery(activeArticle, "forecast data active articles"),
|
||||
);
|
||||
|
||||
if (error) {
|
||||
return {
|
||||
success: false,
|
||||
message: "Failed to get active articles",
|
||||
error: error,
|
||||
};
|
||||
}
|
||||
|
||||
const forecaseEDIDATA = [];
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const activeAV = article?.data.filter(
|
||||
(c: any) =>
|
||||
c?.CustomerArticleNumber === data[i].customerArticleNo?.toString(),
|
||||
);
|
||||
const newData = data[i];
|
||||
//console.log(activeAV[0].IdArtikelvarianten);
|
||||
|
||||
forecaseEDIDATA.push({
|
||||
...newData,
|
||||
article: activeAV[0].IdArtikelvarianten,
|
||||
requirementDate: new Date(newData.requirementDate),
|
||||
});
|
||||
}
|
||||
|
||||
console.log(forecaseEDIDATA[0]);
|
||||
const { data: f, error: ef } = await tryCatch(
|
||||
db.insert(forecastData).values(forecaseEDIDATA),
|
||||
);
|
||||
|
||||
if (ef) {
|
||||
console.log(ef);
|
||||
return {
|
||||
success: false,
|
||||
message: "There was an error posting the new data",
|
||||
error: ef,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: "All forecast Data was posted",
|
||||
data: [],
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import type { Express, Request, Response } from "express";
|
||||
import dm from "./routes/demandMgt/dmRoutes.js";
|
||||
import labeling from "./routes/labeling/labelingRoutes.js";
|
||||
import schedule from "./routes/scheduler/scheduleRoutes.js";
|
||||
|
||||
export const setupLogisticsRoutes = (app: Express, basePath: string) => {
|
||||
app.use(basePath + "/api/logistics/schedule", schedule);
|
||||
app.use(basePath + "/api/logistics/labeling", labeling);
|
||||
app.use(basePath + "/api/logistics/dm", dm);
|
||||
|
||||
// app.use(
|
||||
// basePath + "/api/admin/users",
|
||||
|
||||
@@ -4,6 +4,6 @@ import forecastData from "./forecastEDIData.js";
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.use("/", requireAuth(), forecastData);
|
||||
router.use("/", forecastData);
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Request, Response } from "express";
|
||||
import { Router } from "express";
|
||||
import z from "zod";
|
||||
import { preprintLabels } from "../../controller/labeling/preprint.js";
|
||||
import { forecastEdiData } from "../../controller/demandManagement/forecastEDIData.js";
|
||||
|
||||
export const Preprint = z.object({
|
||||
scannerId: z.number(),
|
||||
@@ -15,13 +15,10 @@ export const Preprint = z.object({
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.post("/preprint", async (req: Request, res: Response) => {
|
||||
const parsed = Preprint.safeParse(req.body);
|
||||
const print = await preprintLabels(req.body, req.user?.username || "");
|
||||
router.post("/forecastData", async (req: Request, res: Response) => {
|
||||
await forecastEdiData(req.body);
|
||||
|
||||
res
|
||||
.status(200)
|
||||
.json({ success: print.success, message: print.message, data: print.data });
|
||||
res.status(200).json({ success: true, message: "Forecast Data", data: [] });
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -40,7 +40,7 @@ export const baseModules = async () => {
|
||||
}
|
||||
|
||||
if (data) {
|
||||
log.info({ newModulesAdded: data }, "New settings added");
|
||||
//log.info({ newModulesAdded: data }, "New settings added");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -26,5 +26,12 @@
|
||||
"description": "What is the port the v1app is on",
|
||||
"moduleName": "system",
|
||||
"roles": ["systemAdmin"]
|
||||
},
|
||||
{
|
||||
"name": "dycoPrint",
|
||||
"value": "0",
|
||||
"description": "Are we using dyco to print the labels or rfid?",
|
||||
"moduleName": "ocp",
|
||||
"roles": ["systemAdmin", "admin", "manager"]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -11,7 +11,30 @@ import { checkBuildUpdate } from "../utlis/checkForBuild.js";
|
||||
|
||||
const router = Router();
|
||||
|
||||
// GET /health
|
||||
/**
|
||||
* @openapi
|
||||
* /health:
|
||||
* get:
|
||||
* summary: Health check for the API server
|
||||
* description: Returns basic system stats including memory usage, uptime, and build info.
|
||||
* responses:
|
||||
* 200:
|
||||
* description: OK
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* status:
|
||||
* type: string
|
||||
* example: ok
|
||||
* uptime:
|
||||
* type: number
|
||||
* build:
|
||||
* type: string
|
||||
* memoryUsage:
|
||||
* type: string
|
||||
*/
|
||||
router.get("/", async (req, res) => {
|
||||
const { data, error } = await tryCatch(
|
||||
db.select().from(serverStats).where(eq(serverStats.id, "serverStats")),
|
||||
|
||||
51
app/src/internal/system/utlis/addListeners.ts
Normal file
51
app/src/internal/system/utlis/addListeners.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { Client } from "pg";
|
||||
import { createLogger } from "../../../pkg/logger/logger.js";
|
||||
|
||||
export const addListeners = async () => {
|
||||
const log = createLogger({ module: "utils", subModule: "listeners" });
|
||||
const client = new Client({
|
||||
connectionString: process.env.DATABASE_URL_V1,
|
||||
});
|
||||
|
||||
await client.connect();
|
||||
|
||||
try {
|
||||
log.info({}, "Running the new log listener");
|
||||
await client.query(`
|
||||
CREATE OR REPLACE FUNCTION notify_new_log()
|
||||
RETURNS trigger AS $$
|
||||
BEGIN
|
||||
PERFORM pg_notify('logs_channel', row_to_json(NEW)::text);
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER logs_notify_trigger
|
||||
AFTER INSERT ON logs
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION notify_new_log();
|
||||
`);
|
||||
} catch (e) {
|
||||
log.info({}, "log listener exist");
|
||||
}
|
||||
|
||||
try {
|
||||
log.info({}, "Running the new label listener");
|
||||
await client.query(`
|
||||
CREATE OR REPLACE FUNCTION notify_new_label()
|
||||
RETURNS trigger AS $$
|
||||
BEGIN
|
||||
PERFORM pg_notify('label_channel', row_to_json(NEW)::text);
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER label_notify_trigger
|
||||
AFTER INSERT ON prodlabels
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION notify_new_label();
|
||||
`);
|
||||
} catch (e) {
|
||||
log.info({}, "label listener exists");
|
||||
}
|
||||
};
|
||||
11
app/src/pkg/apiDocs/swaggerOptions.ts
Normal file
11
app/src/pkg/apiDocs/swaggerOptions.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export const swaggerOptions = {
|
||||
definition: {
|
||||
openapi: "3.0.0",
|
||||
info: {
|
||||
title: "Logistics Support Tool",
|
||||
version: "1.0.0",
|
||||
},
|
||||
},
|
||||
// globs where swagger-jsdoc should look for annotations:
|
||||
apis: ["../../src/**/*.ts"],
|
||||
};
|
||||
@@ -13,12 +13,11 @@ import { z } from "zod";
|
||||
|
||||
export const forecastData = pgTable("forecast_Data", {
|
||||
id: uuid("id").defaultRandom().primaryKey(),
|
||||
customerArticleNumber: text("customer_article_number"),
|
||||
customerArticleNo: text("customer_article_no"),
|
||||
dateRequested: timestamp("date_requested").defaultNow(),
|
||||
quantity: real("quantity"),
|
||||
requestDate: timestamp("request_date").notNull(),
|
||||
requirementDate: timestamp("requirement_date").notNull(),
|
||||
article: integer("article"),
|
||||
customerID: integer("customer_id").notNull(),
|
||||
createdAt: timestamp("created_at").defaultNow(),
|
||||
});
|
||||
|
||||
|
||||
195
app/src/pkg/prodSql/querys/datamart/article.ts
Normal file
195
app/src/pkg/prodSql/querys/datamart/article.ts
Normal file
@@ -0,0 +1,195 @@
|
||||
export const activeArticle = `
|
||||
use AlplaPROD_test1
|
||||
|
||||
SELECT V_Artikel.IdArtikelvarianten,
|
||||
V_Artikel.Bezeichnung,
|
||||
V_Artikel.ArtikelvariantenTypBez,
|
||||
V_Artikel.PreisEinheitBez,
|
||||
case when sales.price is null then 0 else sales.price end as salesPrice,
|
||||
TypeOfMaterial=CASE
|
||||
WHEN
|
||||
V_Artikel.ArtikelvariantenTypBez LIKE'%Additive'
|
||||
Then 'AD'
|
||||
when V_Artikel.ArtikelvariantenTypBez Like '%Masterbatch'
|
||||
THEN 'MB'
|
||||
WHEN V_Artikel.ArtikelvariantenTypBez ='Pallet' or
|
||||
V_Artikel.ArtikelvariantenTypBez ='Top' or
|
||||
V_Artikel.ArtikelvariantenTypBez ='Bags' or
|
||||
V_Artikel.ArtikelvariantenTypBez ='Bag' or
|
||||
V_Artikel.ArtikelvariantenTypBez ='Stretch Wrap' or
|
||||
V_Artikel.ArtikelvariantenTypBez ='Stretch Film' or
|
||||
V_Artikel.ArtikelvariantenTypBez ='Banding Materials' or
|
||||
V_Artikel.ArtikelvariantenTypBez ='Carton' or
|
||||
V_Artikel.ArtikelvariantenTypBez ='Re-Shipper Box' or
|
||||
V_Artikel.ArtikelvariantenTypBez ='Label' or
|
||||
V_Artikel.ArtikelvariantenTypBez ='Pallet Label' or
|
||||
V_Artikel.ArtikelvariantenTypBez ='Carton Label' or
|
||||
V_Artikel.ArtikelvariantenTypBez ='Liner' or
|
||||
V_Artikel.ArtikelvariantenTypBez ='Dose Cup' or
|
||||
V_Artikel.ArtikelvariantenTypBez ='Metal Cage' or
|
||||
V_Artikel.ArtikelvariantenTypBez ='Spout' or
|
||||
V_Artikel.ArtikelvariantenTypBez = 'Slip Sheet' or
|
||||
V_Artikel.ArtikelvariantenTypBez = 'Palet' or
|
||||
V_Artikel.ArtikelvariantenTypBez = 'LID' or
|
||||
V_Artikel.ArtikelvariantenTypBez= 'Metal' or
|
||||
V_Artikel.ArtikelvariantenTypBez= 'Corner post' or
|
||||
V_Artikel.ArtikelvariantenTypBez= 'Bottle Label' or
|
||||
V_Artikel.ArtikelvariantenTypBez = 'Paper label' or
|
||||
V_Artikel.ArtikelvariantenTypBez = 'Banding' or
|
||||
V_Artikel.ArtikelvariantenTypBez = 'Glue' or
|
||||
V_Artikel.ArtikelvariantenTypBez = 'Top Frame' or
|
||||
V_Artikel.ArtikelvariantenTypBez = 'IML Label' or
|
||||
V_Artikel.ArtikelvariantenTypBez = 'Purch EBM Bottle' or
|
||||
V_Artikel.ArtikelvariantenTypBez = 'Purchased Spout' or
|
||||
V_Artikel.ArtikelvariantenTypBez = 'Gaylord' or
|
||||
V_Artikel.ArtikelvariantenTypBez = 'Misc. Packaging' or
|
||||
V_Artikel.ArtikelvariantenTypBez = 'Sleeve' or
|
||||
V_Artikel.ArtikelvariantenTypBez = 'Plastic Bag' or
|
||||
V_Artikel.ArtikelvariantenTypBez = 'Purch Spout' or
|
||||
V_Artikel.ArtikelvariantenTypBez = 'Seal' or
|
||||
V_Artikel.ArtikelvariantenTypBez = 'Tape' or
|
||||
V_Artikel.ArtikelvariantenTypBez = 'Box' or
|
||||
V_Artikel.ArtikelvariantenTypBez = 'Label IML' or
|
||||
V_Artikel.ArtikelvariantenTypBez = 'Pallet Runner'
|
||||
THEN 'PKG'
|
||||
WHEN V_Artikel.ArtikelvariantenTypBez='HD-PE' or
|
||||
V_Artikel.ArtikelvariantenTypBez='HD-PE PCR' or
|
||||
V_Artikel.ArtikelvariantenTypBez='HD-PP' or
|
||||
V_Artikel.ArtikelvariantenTypBez= 'PP' or
|
||||
V_Artikel.ArtikelvariantenTypBez LIKE '%PCR' or
|
||||
V_Artikel.ArtikelvariantenTypBez= 'LDPE' or
|
||||
V_Artikel.ArtikelvariantenTypBez= 'PP' or
|
||||
V_Artikel.ArtikelvariantenTypBez= 'HDPE' or
|
||||
V_Artikel.ArtikelvariantenTypBez= 'PET' or
|
||||
V_Artikel.ArtikelvariantenTypBez= 'PET-P'
|
||||
THEN 'MM'
|
||||
WHEN
|
||||
V_Artikel.ArtikelvariantenTypBez='HDPE-Waste' or
|
||||
V_Artikel.ArtikelvariantenTypBez='$Waste Container' or
|
||||
V_Artikel.ArtikelvariantenTypBez='Mixed-Waste' or
|
||||
V_Artikel.ArtikelvariantenTypBez LIKE'%-Waste%'
|
||||
THEN 'Waste'
|
||||
WHEN
|
||||
V_Artikel.ArtikelvariantenTypBez = 'Bottle' or
|
||||
V_Artikel.ArtikelvariantenTypBez = 'SBM Bottle' or
|
||||
V_Artikel.ArtikelvariantenTypBez = 'EBM Bottle' or
|
||||
V_Artikel.ArtikelvariantenTypBez = 'ISBM Bottle' or
|
||||
V_Artikel.ArtikelvariantenTypBez = 'Decorated Bottle'
|
||||
THEN 'Bottle'
|
||||
WHEN V_Artikel.ArtikelvariantenTypBez = 'Preform'
|
||||
Then 'Preform'
|
||||
When
|
||||
V_Artikel.ArtikelvariantenTypBez = 'Purchased Preform' or
|
||||
V_Artikel.ArtikelvariantenTypBez = 'Purchased Caps' or
|
||||
V_Artikel.ArtikelvariantenTypBez = 'Purchased_preform'
|
||||
THEN 'Purchased_preform'
|
||||
When
|
||||
V_Artikel.ArtikelvariantenTypBez = 'Closures' or
|
||||
V_Artikel.ArtikelvariantenTypBez = 'Cap'
|
||||
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
|
||||
V_Artikel.ProdBereichBez = 'SBM' or
|
||||
V_Artikel.ProdBereichBez = 'IM-Caps' or
|
||||
V_Artikel.ProdBereichBez = 'IM-PET' or
|
||||
V_Artikel.ProdBereichBez = 'PRINT OFFICE' or
|
||||
V_Artikel.ProdBereichBez = 'EBM' or
|
||||
V_Artikel.ProdBereichBez = 'ISBM' or
|
||||
V_Artikel.ProdBereichBez = 'IM-Finishing'
|
||||
Then 'FG'
|
||||
Else 'not Defined Profit Center'
|
||||
end,
|
||||
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,
|
||||
Sypronummer as salesAgreement,
|
||||
V_Artikel.ProdArtikelBez as ProductFamily
|
||||
--,REPLACE(pur.UOM,'UOM:','')
|
||||
,Case when LEFT(
|
||||
LTRIM(REPLACE(pur.UOM,'UOM:','')),
|
||||
CHARINDEX(' ', LTRIM(REPLACE(REPLACE(pur.UOM,'UOM:',''), CHAR(13)+CHAR(10), ' ')) + ' ') - 1
|
||||
) 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
|
||||
--,*
|
||||
FROM dbo.V_Artikel (nolock)
|
||||
|
||||
join
|
||||
dbo.V_Artikelvarianten (nolock) on dbo.V_Artikel.IdArtikelvarianten =
|
||||
dbo.V_Artikelvarianten.IdArtikelvarianten
|
||||
|
||||
join
|
||||
dbo.V_FibuKonten_BASIS (nolock) on dbo.V_Artikelvarianten.IdFibuKonto =
|
||||
dbo.V_FibuKonten_BASIS.IdFibuKonto
|
||||
|
||||
|
||||
-- adding in the sales price
|
||||
left join
|
||||
(select * from
|
||||
(select
|
||||
ROW_NUMBER() OVER (PARTITION BY IdArtikelvarianten ORDER BY GueltigabDatum DESC) AS RN,
|
||||
IdArtikelvarianten as av
|
||||
,GueltigabDatum as validDate
|
||||
,VKPreis as price
|
||||
,[KdArtNr]
|
||||
,[KdArtBez]
|
||||
--,*
|
||||
from dbo.T_HistoryVK (nolock)
|
||||
where
|
||||
--GueltigabDatum > getDate() - 120
|
||||
--and
|
||||
Aktiv = 1
|
||||
and StandardKunde = 1 -- default address
|
||||
) a
|
||||
where RN = 1) as sales
|
||||
on dbo.V_Artikel.IdArtikelvarianten = sales.av
|
||||
|
||||
/* adding the purchase price info */
|
||||
left join
|
||||
(select * from
|
||||
(select
|
||||
ROW_NUMBER() OVER (PARTITION BY IdArtikelvarianten ORDER BY GueltigabDatum DESC) AS RN,
|
||||
IdArtikelvarianten as av
|
||||
,GueltigabDatum as validDate
|
||||
,EKPreis as price
|
||||
,LiefArtNr as supplierNr
|
||||
,CASE
|
||||
WHEN Bemerkung IS NOT NULL AND Bemerkung LIKE '%UOM:%'
|
||||
THEN
|
||||
-- incase there is something funny going on in the remark well jsut check for new lines and what not
|
||||
LEFT(
|
||||
REPLACE(REPLACE(Bemerkung, CHAR(13)+CHAR(10), ' '), CHAR(10), ' '),
|
||||
CASE
|
||||
WHEN CHARINDEX(' ', REPLACE(REPLACE(Bemerkung, CHAR(13)+CHAR(10), ' '), CHAR(10), ' ')) > 0
|
||||
THEN CHARINDEX(' ', REPLACE(REPLACE(Bemerkung, CHAR(13)+CHAR(10), ' '), CHAR(10), ' ')) - 1
|
||||
ELSE LEN(Bemerkung)
|
||||
END
|
||||
)
|
||||
ELSE 'UOM:1'
|
||||
END AS UOM
|
||||
,Bemerkung
|
||||
--,*
|
||||
from dbo.T_HistoryEK (nolock)
|
||||
where
|
||||
StandardLieferant = 1 -- default address
|
||||
) a
|
||||
where RN = 1) as pur
|
||||
on dbo.V_Artikel.IdArtikelvarianten = pur.av
|
||||
|
||||
where V_Artikel.aktiv = 1 --and dbo.V_Artikel.IdArtikelvarianten = 1445
|
||||
|
||||
order by V_Artikel.IdArtikelvarianten /*, TypeOfMaterial */
|
||||
`;
|
||||
@@ -37,6 +37,7 @@ type ServerData = {
|
||||
pendingUpdateFile: string;
|
||||
lastUpdate: Date;
|
||||
memoryUsage: string;
|
||||
greatPlainsPlantCode: string;
|
||||
};
|
||||
|
||||
const updateServerItem = async (
|
||||
@@ -66,6 +67,10 @@ function RouteComponent() {
|
||||
);
|
||||
const [sorting, setSorting] = useState<SortingState>([]);
|
||||
const columnHelper = createColumnHelper<ServerData>();
|
||||
const [pagination, setPagination] = useState({
|
||||
pageIndex: 0, //initial page index
|
||||
pageSize: 20, //default page size
|
||||
});
|
||||
|
||||
const statsMap = React.useMemo(() => {
|
||||
const map = new Map<string, any>();
|
||||
@@ -93,7 +98,20 @@ function RouteComponent() {
|
||||
|
||||
const columns = [
|
||||
columnHelper.accessor("name", {
|
||||
cell: (i) => i.getValue(),
|
||||
cell: ({ row, getValue }) => {
|
||||
let url = "";
|
||||
if (row.original.plantToken.includes("test")) {
|
||||
url = `https://${row.original.serverDNS}.alpla.net/lst/app`;
|
||||
} else {
|
||||
url = `https://${row.original.plantToken}prod.alpla.net/lst/app`;
|
||||
}
|
||||
|
||||
return (
|
||||
<a href={url} target="_blank">
|
||||
{getValue()}
|
||||
</a>
|
||||
);
|
||||
},
|
||||
header: ({ column }) => {
|
||||
return (
|
||||
<Button
|
||||
@@ -204,6 +222,41 @@ function RouteComponent() {
|
||||
},
|
||||
}),
|
||||
|
||||
columnHelper.accessor("greatPlainsPlantCode", {
|
||||
header: () => {
|
||||
return <span className="flex flex-row gap-2">GP Code</span>;
|
||||
},
|
||||
cell: ({ row, getValue }) => {
|
||||
const initialValue = String(getValue() ?? "");
|
||||
const [localValue, setLocalValue] = React.useState(initialValue);
|
||||
const token = row.original.plantToken;
|
||||
const field = "greatPlainsPlantCode";
|
||||
|
||||
useEffect(() => setLocalValue(initialValue), [initialValue]);
|
||||
|
||||
const handleSubmit = (newValue: string) => {
|
||||
if (newValue !== initialValue) {
|
||||
setLocalValue(newValue); // keep new value locally immediately
|
||||
updateServer.mutate({ token, field, value: newValue });
|
||||
}
|
||||
};
|
||||
return (
|
||||
<Input
|
||||
value={localValue}
|
||||
onChange={(e) => setLocalValue(e.currentTarget.value)}
|
||||
onBlur={(e) => handleSubmit(e.currentTarget.value.trim())}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter") {
|
||||
e.preventDefault();
|
||||
handleSubmit(e.currentTarget.value.trim());
|
||||
e.currentTarget.blur(); // exit edit mode
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
}),
|
||||
|
||||
columnHelper.accessor("uptime", {
|
||||
header: () => {
|
||||
return <span className="flex flex-row gap-2">UpTime</span>;
|
||||
@@ -215,8 +268,12 @@ function RouteComponent() {
|
||||
// use Skeleton from shadcn/ui (or any placeholder)
|
||||
return <Skeleton className="h-4 w-16" />;
|
||||
}
|
||||
console.log(statsMap);
|
||||
return <span>{statsRow ? `${statsRow.uptime.toFixed(2)}` : "--"}</span>;
|
||||
//console.log(statsMap);
|
||||
return (
|
||||
<span>
|
||||
{statsRow ? `${statsRow.uptime.toFixed(2)}` : "Server Offline?"}
|
||||
</span>
|
||||
);
|
||||
},
|
||||
}),
|
||||
columnHelper.accessor("lastUpdate", {
|
||||
@@ -230,8 +287,10 @@ function RouteComponent() {
|
||||
// use Skeleton from shadcn/ui (or any placeholder)
|
||||
return <Skeleton className="h-4 w-16" />;
|
||||
}
|
||||
console.log(statsMap);
|
||||
return <span>{statsRow ? `${statsRow.lastUpdate}` : "--"}</span>;
|
||||
//console.log(statsMap);
|
||||
return (
|
||||
<span>{statsRow ? `${statsRow.lastUpdate}` : "Server Offline?"}</span>
|
||||
);
|
||||
},
|
||||
}),
|
||||
columnHelper.accessor("build", {
|
||||
@@ -245,8 +304,10 @@ function RouteComponent() {
|
||||
// use Skeleton from shadcn/ui (or any placeholder)
|
||||
return <Skeleton className="h-4 w-16" />;
|
||||
}
|
||||
console.log(statsMap);
|
||||
return <span>{statsRow ? `${statsRow.build}` : "--"}</span>;
|
||||
//console.log(statsMap);
|
||||
return (
|
||||
<span>{statsRow ? `${statsRow.build}` : "Server Offline?"}</span>
|
||||
);
|
||||
},
|
||||
}),
|
||||
columnHelper.accessor("pendingUpdateFile", {
|
||||
@@ -260,8 +321,14 @@ function RouteComponent() {
|
||||
// use Skeleton from shadcn/ui (or any placeholder)
|
||||
return <Skeleton className="h-4 w-16" />;
|
||||
}
|
||||
console.log(statsMap);
|
||||
return <span>{statsRow ? `${statsRow.pendingUpdateFile}` : "--"}</span>;
|
||||
//console.log(statsMap);
|
||||
return (
|
||||
<span>
|
||||
{statsRow
|
||||
? `${statsRow.pendingUpdateFile === null ? "nothing pending" : statsRow.pendingUpdateFile}`
|
||||
: "Server Offline?"}
|
||||
</span>
|
||||
);
|
||||
},
|
||||
}),
|
||||
columnHelper.accessor("memoryUsage", {
|
||||
@@ -276,7 +343,11 @@ function RouteComponent() {
|
||||
return <Skeleton className="h-4 w-16" />;
|
||||
}
|
||||
//console.log(statsMap);
|
||||
return <span>{statsRow ? `${statsRow.memoryUsage}` : "--"}</span>;
|
||||
return (
|
||||
<span>
|
||||
{statsRow ? `${statsRow.memoryUsage}` : "Server Offline?"}
|
||||
</span>
|
||||
);
|
||||
},
|
||||
}),
|
||||
];
|
||||
@@ -288,10 +359,12 @@ function RouteComponent() {
|
||||
getPaginationRowModel: getPaginationRowModel(),
|
||||
onSortingChange: setSorting,
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
onPaginationChange: setPagination,
|
||||
//renderSubComponent: ({ row }: { row: any }) => <ExpandedRow row={row} />,
|
||||
//getRowCanExpand: () => true,
|
||||
state: {
|
||||
sorting,
|
||||
pagination,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import { useAuth, userAccess } from "@/lib/authClient";
|
||||
import { useSettingStore } from "../../-lib/store/useSettings";
|
||||
//import { useSettingStore } from "../../-lib/store/useSettings";
|
||||
import type { LotType } from "../../-types/lots";
|
||||
import { getlots } from "../../-utils/querys/ocp/lots";
|
||||
import { LstCard } from "../extendedUi/LstCard";
|
||||
@@ -67,9 +67,9 @@ export default function Lots() {
|
||||
const { data, isError, isLoading } = useQuery(getlots());
|
||||
|
||||
const { session } = useAuth();
|
||||
const { settings } = useSettingStore();
|
||||
//const { settings } = useSettingStore();
|
||||
|
||||
const server = settings.filter((n) => n.name === "dbServer")[0]?.value || "";
|
||||
//const server = settings.filter((n) => n.name === "dbServer")[0]?.value || "";
|
||||
const lotdata = data ? data : [];
|
||||
|
||||
const accessRoles = userAccess("ocp", [
|
||||
@@ -229,7 +229,8 @@ export default function Lots() {
|
||||
</TableCell>
|
||||
{session?.user && accessRoles && (
|
||||
<>
|
||||
{server === "usday1vms006" || server === "localhost" ? (
|
||||
{location.hostname.includes("usday1") ||
|
||||
location.hostname.includes("localhost") ? (
|
||||
<>
|
||||
<TableCell className="flex justify-center">
|
||||
<ManualPrintForm />
|
||||
|
||||
@@ -37,11 +37,10 @@ const printReason = [
|
||||
];
|
||||
|
||||
export default function ManualPrintForm() {
|
||||
const token = localStorage.getItem("auth_token");
|
||||
const { settings } = useSettingStore();
|
||||
const [open, setOpen] = useState(false);
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
const server = settings.filter((n) => n.name === "server")[0]?.value;
|
||||
|
||||
// const serverPort = settings.filter((n) => n.name === "serverPort")[0]?.value;
|
||||
// const serverUrl = `http://${server}:${serverPort}`;
|
||||
|
||||
@@ -61,9 +60,7 @@ export default function ManualPrintForm() {
|
||||
const logdataUrl = `/lst/old/api/ocp/manuallabellog`;
|
||||
setIsSubmitting(true);
|
||||
axios
|
||||
.post(logdataUrl, logData, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
})
|
||||
.post(logdataUrl, logData, {})
|
||||
.then((d) => {
|
||||
console.log(d);
|
||||
if (d.data.success) {
|
||||
@@ -135,7 +132,7 @@ export default function ManualPrintForm() {
|
||||
If you clicked this in error just click close
|
||||
</p>
|
||||
<hr className="mt-2 mb-2" />
|
||||
{server == "usday1vms006" ? (
|
||||
{location.hostname.includes("usday1") ? (
|
||||
<Controller
|
||||
control={control}
|
||||
name="printReason"
|
||||
@@ -206,7 +203,7 @@ export default function ManualPrintForm() {
|
||||
/>
|
||||
</div>
|
||||
<hr />
|
||||
{dyco[0].value === "0" && (
|
||||
{dyco[0]?.value === "0" && (
|
||||
<div>
|
||||
<p>Enter the missing tag number.</p>
|
||||
<hr />
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
} from "@/components/ui/resizable";
|
||||
import { useSettingStore } from "../../-lib/store/useSettings";
|
||||
import WrapperManualTrigger from "../ocme/WrapperCard";
|
||||
//import WrapperManualTrigger from "../ocme/WrapperCard";
|
||||
import LabelLog from "./LabelLog";
|
||||
import LabelRatio from "./LabelRatio";
|
||||
import Lots from "./Lots";
|
||||
@@ -15,8 +16,6 @@ export default function OCPPage() {
|
||||
const { settings } = useSettingStore();
|
||||
|
||||
if (settings.length === 0) return;
|
||||
let token = settings.filter((n) => n.name === "plantToken");
|
||||
|
||||
return (
|
||||
<div className="ml-5 w-11/12 h-9/10">
|
||||
<ResizablePanelGroup
|
||||
@@ -62,19 +61,31 @@ export default function OCPPage() {
|
||||
<ResizableHandle />
|
||||
<ResizablePanel className="min-h-[200px] min-w-[200px] max-w-[450px]">
|
||||
<ResizablePanelGroup direction="vertical" autoSaveId="ocpPage_vert">
|
||||
{token[0].value === "usday1vms006" ||
|
||||
(location.pathname === "localhost" && (
|
||||
<ResizablePanel
|
||||
style={{
|
||||
overflow: "auto",
|
||||
scrollbarWidth: "none",
|
||||
}}
|
||||
defaultSize={50}
|
||||
className="min-h-[200px]"
|
||||
>
|
||||
<WrapperManualTrigger />
|
||||
</ResizablePanel>
|
||||
))}
|
||||
{location.hostname.includes("usday1") && (
|
||||
<ResizablePanel
|
||||
style={{
|
||||
overflow: "auto",
|
||||
scrollbarWidth: "none",
|
||||
}}
|
||||
defaultSize={50}
|
||||
className="min-h-[200px]"
|
||||
>
|
||||
<WrapperManualTrigger />
|
||||
</ResizablePanel>
|
||||
)}
|
||||
|
||||
{location.hostname.includes("localhost") && (
|
||||
<ResizablePanel
|
||||
style={{
|
||||
overflow: "auto",
|
||||
scrollbarWidth: "none",
|
||||
}}
|
||||
defaultSize={50}
|
||||
className="min-h-[200px]"
|
||||
>
|
||||
<WrapperManualTrigger />
|
||||
</ResizablePanel>
|
||||
)}
|
||||
|
||||
<ResizableHandle />
|
||||
<ResizablePanel>
|
||||
|
||||
@@ -1,286 +1,291 @@
|
||||
import axios from "axios";
|
||||
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 { excelDateStuff } from "../../../../utils/excelDateStuff.js";
|
||||
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";
|
||||
|
||||
let customerID = 4;
|
||||
export const lorealForecast = async (data: any, user: any) => {
|
||||
/**
|
||||
* Post a standard forecast based on the standard template.
|
||||
*/
|
||||
/**
|
||||
* Post a standard forecast based on the standard template.
|
||||
*/
|
||||
|
||||
const { data: s, error: e } = await tryCatch(db.select().from(settings));
|
||||
const { data: s, error: e } = await tryCatch(db.select().from(settings));
|
||||
|
||||
if (e) {
|
||||
return {
|
||||
sucess: false,
|
||||
message: `Error getting settings`,
|
||||
data: e,
|
||||
};
|
||||
}
|
||||
if (e) {
|
||||
return {
|
||||
sucess: false,
|
||||
message: `Error getting settings`,
|
||||
data: e,
|
||||
};
|
||||
}
|
||||
|
||||
const plantToken = s.filter((s) => s.name === "plantToken");
|
||||
const plantToken = s.filter((s) => s.name === "plantToken");
|
||||
|
||||
const arrayBuffer = await data.arrayBuffer();
|
||||
const buffer = Buffer.from(arrayBuffer);
|
||||
const arrayBuffer = await data.arrayBuffer();
|
||||
const buffer = Buffer.from(arrayBuffer);
|
||||
|
||||
const workbook = XLSX.read(buffer, { type: "buffer" });
|
||||
const workbook = XLSX.read(buffer, { type: "buffer" });
|
||||
|
||||
const sheet: any = workbook.Sheets["Alpla HDPE"];
|
||||
const range = XLSX.utils.decode_range(sheet["!ref"]);
|
||||
const sheet: any = workbook.Sheets["Alpla HDPE"];
|
||||
const range = XLSX.utils.decode_range(sheet["!ref"]);
|
||||
|
||||
const psheet: any = workbook.Sheets["Alpla PET"];
|
||||
const prange = XLSX.utils.decode_range(psheet["!ref"]);
|
||||
const psheet: any = workbook.Sheets["Alpla PET"];
|
||||
const prange = XLSX.utils.decode_range(psheet["!ref"]);
|
||||
|
||||
const headers = [];
|
||||
for (let C = range.s.c; C <= range.e.c; ++C) {
|
||||
const cellAddress = XLSX.utils.encode_cell({ r: 1, c: C }); // row 0 = Excel row 1
|
||||
const cell = sheet[cellAddress];
|
||||
headers.push(cell ? cell.v : undefined);
|
||||
}
|
||||
const headers = [];
|
||||
for (let C = range.s.c; C <= range.e.c; ++C) {
|
||||
const cellAddress = XLSX.utils.encode_cell({ r: 1, c: C }); // row 0 = Excel row 1
|
||||
const cell = sheet[cellAddress];
|
||||
headers.push(cell ? cell.v : undefined);
|
||||
}
|
||||
|
||||
const pheaders = [];
|
||||
for (let C = prange.s.c; C <= prange.e.c; ++C) {
|
||||
const cellAddress = XLSX.utils.encode_cell({ r: 1, c: C }); // row 0 = Excel row 1
|
||||
const cell = psheet[cellAddress];
|
||||
pheaders.push(cell ? cell.v : undefined);
|
||||
}
|
||||
const pheaders = [];
|
||||
for (let C = prange.s.c; C <= prange.e.c; ++C) {
|
||||
const cellAddress = XLSX.utils.encode_cell({ r: 1, c: C }); // row 0 = Excel row 1
|
||||
const cell = psheet[cellAddress];
|
||||
pheaders.push(cell ? cell.v : undefined);
|
||||
}
|
||||
|
||||
const ebmForeCastData: any = XLSX.utils.sheet_to_json(sheet, {
|
||||
defval: "",
|
||||
header: headers,
|
||||
range: 3,
|
||||
});
|
||||
const ebmForeCastData: any = XLSX.utils.sheet_to_json(sheet, {
|
||||
defval: "",
|
||||
header: headers,
|
||||
range: 3,
|
||||
});
|
||||
|
||||
const petForeCastData: any = XLSX.utils.sheet_to_json(psheet, {
|
||||
defval: "",
|
||||
header: pheaders,
|
||||
range: 3,
|
||||
});
|
||||
const petForeCastData: any = XLSX.utils.sheet_to_json(psheet, {
|
||||
defval: "",
|
||||
header: pheaders,
|
||||
range: 3,
|
||||
});
|
||||
|
||||
const ebmForecastData: any = [];
|
||||
const missingSku: any = [];
|
||||
const ebmForecastData: any = [];
|
||||
const missingSku: any = [];
|
||||
|
||||
const { data: a, error: ae } = await tryCatch(
|
||||
query(activeArticle, "Loreal calling active av")
|
||||
);
|
||||
const { data: a, error: ae } = await tryCatch(
|
||||
query(activeArticle, "Loreal calling active av"),
|
||||
);
|
||||
|
||||
if (ae) {
|
||||
return {
|
||||
success: false,
|
||||
message: "Error getting active av",
|
||||
data: [],
|
||||
};
|
||||
}
|
||||
if (ae) {
|
||||
return {
|
||||
success: false,
|
||||
message: "Error getting active av",
|
||||
data: [],
|
||||
};
|
||||
}
|
||||
|
||||
const article: any = a?.data;
|
||||
const article: any = a?.data;
|
||||
|
||||
// process the ebm forcast
|
||||
for (let i = 0; i < ebmForeCastData.length; i++) {
|
||||
// bottle code
|
||||
const sku = ebmForeCastData[i]["HDPE Bottle Code"];
|
||||
// process the ebm forcast
|
||||
for (let i = 0; i < ebmForeCastData.length; i++) {
|
||||
// bottle code
|
||||
const sku = ebmForeCastData[i]["HDPE Bottle Code"];
|
||||
|
||||
// ignore the blanks
|
||||
if (sku === "") continue;
|
||||
// ignore the blanks
|
||||
if (sku === "") continue;
|
||||
|
||||
// ignore zero qty
|
||||
// if (ebmForeCastData[i][`Day ${i}`]) continue;
|
||||
// ignore zero qty
|
||||
// if (ebmForeCastData[i][`Day ${i}`]) continue;
|
||||
|
||||
for (let f = 0; f <= 90; f++) {
|
||||
const day = `Day ${f + 1}`;
|
||||
// if (ebmForeCastData[i][day] === 0) continue;
|
||||
for (let f = 0; f <= 90; f++) {
|
||||
const day = `Day ${f + 1}`;
|
||||
// if (ebmForeCastData[i][day] === 0) continue;
|
||||
|
||||
const forcast = {
|
||||
customerArticleNo: sku,
|
||||
requirementDate: addDays(new Date(Date.now()), f), //excelDateStuff(parseInt(date)),
|
||||
quantity: ebmForeCastData[i][day] ?? 0,
|
||||
};
|
||||
const forcast = {
|
||||
customerArticleNo: sku,
|
||||
requirementDate: addDays(new Date(Date.now()), f), //excelDateStuff(parseInt(date)),
|
||||
quantity: ebmForeCastData[i][day] ?? 0,
|
||||
};
|
||||
|
||||
if (forcast.quantity === 0) continue;
|
||||
if (forcast.quantity === 0) continue;
|
||||
|
||||
// checking to make sure there is a real av to add to.
|
||||
const activeAV = article.filter(
|
||||
(c: any) =>
|
||||
c?.CustomerArticleNumber ===
|
||||
forcast.customerArticleNo.toString()
|
||||
);
|
||||
// checking to make sure there is a real av to add to.
|
||||
const activeAV = article.filter(
|
||||
(c: any) =>
|
||||
c?.CustomerArticleNumber === forcast.customerArticleNo.toString(),
|
||||
);
|
||||
|
||||
if (activeAV.length === 0) {
|
||||
if (typeof forcast.customerArticleNo === "number") {
|
||||
missingSku.push(forcast);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (activeAV.length === 0) {
|
||||
if (typeof forcast.customerArticleNo === "number") {
|
||||
missingSku.push(forcast);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
ebmForecastData.push(forcast);
|
||||
}
|
||||
ebmForecastData.push(forcast);
|
||||
}
|
||||
|
||||
//console.log(ebmForeCastData.length);
|
||||
}
|
||||
//console.log(ebmForeCastData.length);
|
||||
}
|
||||
|
||||
// petForeCastData.forEach((item: any, index: any) => {
|
||||
// //console.log(`Processing item ${index + 1} of ${forecastData.length}`);
|
||||
// petForeCastData.forEach((item: any, index: any) => {
|
||||
// //console.log(`Processing item ${index + 1} of ${forecastData.length}`);
|
||||
|
||||
// // Extract the customer code
|
||||
// const customerCode = item["SOUTH PET BOTTLES"];
|
||||
// // Extract the customer code
|
||||
// const customerCode = item["SOUTH PET BOTTLES"];
|
||||
|
||||
// // Process each date in the current object
|
||||
// for (const [date, qty] of Object.entries(item)) {
|
||||
// // Skip metadata fields
|
||||
// if (petMetadataFields.includes(date)) continue;
|
||||
// // Process each date in the current object
|
||||
// for (const [date, qty] of Object.entries(item)) {
|
||||
// // Skip metadata fields
|
||||
// if (petMetadataFields.includes(date)) continue;
|
||||
|
||||
// if (qty === 0) continue;
|
||||
// if (qty === 0) continue;
|
||||
|
||||
// // Create your transformed record
|
||||
// const record = {
|
||||
// customerArticleNo: customerCode,
|
||||
// requirementDate: excelDateStuff(parseInt(date)),
|
||||
// quantity: qty,
|
||||
// };
|
||||
// // Create your transformed record
|
||||
// const record = {
|
||||
// customerArticleNo: customerCode,
|
||||
// requirementDate: excelDateStuff(parseInt(date)),
|
||||
// quantity: qty,
|
||||
// };
|
||||
|
||||
// // Do something with this record
|
||||
// petForecastData.push(record);
|
||||
// }
|
||||
// });
|
||||
// // Do something with this record
|
||||
// petForecastData.push(record);
|
||||
// }
|
||||
// });
|
||||
|
||||
// pet forecast
|
||||
for (let i = 0; i < petForeCastData.length; i++) {
|
||||
// bottle code
|
||||
const sku = petForeCastData[i]["South PET Bottle Code"];
|
||||
// pet forecast
|
||||
for (let i = 0; i < petForeCastData.length; i++) {
|
||||
// bottle code
|
||||
const sku = petForeCastData[i]["South PET Bottle Code"];
|
||||
|
||||
// ignore the blanks
|
||||
if (sku === "") continue;
|
||||
// ignore the blanks
|
||||
if (sku === "") continue;
|
||||
|
||||
// ignore zero qty
|
||||
// if (ebmForeCastData[i][`Day ${i}`]) continue;
|
||||
// ignore zero qty
|
||||
// if (ebmForeCastData[i][`Day ${i}`]) continue;
|
||||
|
||||
for (let f = 0; f <= 90; f++) {
|
||||
const day = `Day ${f + 1}`;
|
||||
// if (ebmForeCastData[i][day] === 0) continue;
|
||||
for (let f = 0; f <= 90; f++) {
|
||||
const day = `Day ${f + 1}`;
|
||||
// if (ebmForeCastData[i][day] === 0) continue;
|
||||
|
||||
const forcast = {
|
||||
customerArticleNo: sku,
|
||||
requirementDate: addDays(new Date(Date.now()), f), //excelDateStuff(parseInt(date)),
|
||||
quantity: petForeCastData[i][day] ?? 0,
|
||||
};
|
||||
const forcast = {
|
||||
customerArticleNo: sku,
|
||||
requirementDate: addDays(new Date(Date.now()), f), //excelDateStuff(parseInt(date)),
|
||||
quantity: petForeCastData[i][day] ?? 0,
|
||||
};
|
||||
|
||||
if (forcast.quantity === 0 || forcast.quantity === "") continue;
|
||||
if (forcast.quantity === 0 || forcast.quantity === "") continue;
|
||||
|
||||
if (forcast.customerArticleNo < 99999) {
|
||||
//console.log(`Sku a normal av ${forcast.customerArticleNo}`);
|
||||
continue;
|
||||
}
|
||||
if (forcast.customerArticleNo < 99999) {
|
||||
//console.log(`Sku a normal av ${forcast.customerArticleNo}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
// checking to make sure there is a real av to add to.
|
||||
const activeAV = article.filter(
|
||||
(c: any) =>
|
||||
c?.CustomerArticleNumber ===
|
||||
forcast.customerArticleNo.toString()
|
||||
);
|
||||
// checking to make sure there is a real av to add to.
|
||||
const activeAV = article.filter(
|
||||
(c: any) =>
|
||||
c?.CustomerArticleNumber === forcast.customerArticleNo.toString(),
|
||||
);
|
||||
|
||||
if (activeAV.length === 0) {
|
||||
if (typeof forcast.customerArticleNo === "number") {
|
||||
missingSku.push(forcast);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (activeAV.length === 0) {
|
||||
if (typeof forcast.customerArticleNo === "number") {
|
||||
missingSku.push(forcast);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
ebmForecastData.push(forcast);
|
||||
}
|
||||
}
|
||||
ebmForecastData.push(forcast);
|
||||
}
|
||||
}
|
||||
|
||||
//console.log(comForecast);
|
||||
//console.log(comForecast);
|
||||
|
||||
// email the for the missing ones
|
||||
const missedGrouped = Object.values(
|
||||
missingSku.reduce((acc: any, item: any) => {
|
||||
const key = item.customerArticleNo;
|
||||
// email the for the missing ones
|
||||
const missedGrouped = Object.values(
|
||||
missingSku.reduce((acc: any, item: any) => {
|
||||
const key = item.customerArticleNo;
|
||||
|
||||
if (!acc[key]) {
|
||||
// first time we see this customer
|
||||
acc[key] = item;
|
||||
} else {
|
||||
// compare dates and keep the earliest
|
||||
if (
|
||||
new Date(item.requirementDate) <
|
||||
new Date(acc[key].requirementDate)
|
||||
) {
|
||||
acc[key] = item;
|
||||
}
|
||||
}
|
||||
if (!acc[key]) {
|
||||
// first time we see this customer
|
||||
acc[key] = item;
|
||||
} else {
|
||||
// compare dates and keep the earliest
|
||||
if (
|
||||
new Date(item.requirementDate) < new Date(acc[key].requirementDate)
|
||||
) {
|
||||
acc[key] = item;
|
||||
}
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {})
|
||||
);
|
||||
return acc;
|
||||
}, {}),
|
||||
);
|
||||
|
||||
const emailSetup = {
|
||||
email: "Blake.matthes@alpla.com; Stuart.Gladney@alpla.com; Harold.Mccalister@alpla.com; Jenn.Osbourn@alpla.com",
|
||||
subject:
|
||||
missedGrouped.length > 0
|
||||
? `Alert! There are ${missedGrouped.length}, missing skus.`
|
||||
: `Alert! There is a missing SKU.`,
|
||||
template: "missingLorealSkus",
|
||||
context: {
|
||||
items: missedGrouped,
|
||||
},
|
||||
};
|
||||
const emailSetup = {
|
||||
email:
|
||||
"Blake.matthes@alpla.com; Stuart.Gladney@alpla.com; Harold.Mccalister@alpla.com; Jenn.Osbourn@alpla.com",
|
||||
subject:
|
||||
missedGrouped.length > 0
|
||||
? `Alert! There are ${missedGrouped.length}, missing skus.`
|
||||
: `Alert! There is a missing SKU.`,
|
||||
template: "missingLorealSkus",
|
||||
context: {
|
||||
items: missedGrouped,
|
||||
},
|
||||
};
|
||||
|
||||
const { data: sentEmail, error: sendEmailError } = await tryCatch(
|
||||
sendEmail(emailSetup)
|
||||
);
|
||||
if (sendEmailError) {
|
||||
createLog(
|
||||
"error",
|
||||
"blocking",
|
||||
"notify",
|
||||
"Failed to send email, will try again on next interval"
|
||||
);
|
||||
return {
|
||||
success: false,
|
||||
message: "Failed to send email, will try again on next interval",
|
||||
};
|
||||
}
|
||||
const { data: sentEmail, error: sendEmailError } = await tryCatch(
|
||||
sendEmail(emailSetup),
|
||||
);
|
||||
if (sendEmailError) {
|
||||
createLog(
|
||||
"error",
|
||||
"blocking",
|
||||
"notify",
|
||||
"Failed to send email, will try again on next interval",
|
||||
);
|
||||
return {
|
||||
success: false,
|
||||
message: "Failed to send email, will try again on next interval",
|
||||
};
|
||||
}
|
||||
|
||||
// if the customerarticle number is not matching just ignore it
|
||||
const predefinedObject = {
|
||||
receivingPlantId: plantToken[0].value,
|
||||
documentName: `ForecastFromLST-${new Date(Date.now()).toLocaleString(
|
||||
"en-US"
|
||||
)}`,
|
||||
sender: user.username || "lst-system",
|
||||
customerId: customerID,
|
||||
positions: [],
|
||||
};
|
||||
// if the customerarticle number is not matching just ignore it
|
||||
const predefinedObject = {
|
||||
receivingPlantId: plantToken[0].value,
|
||||
documentName: `ForecastFromLST-${new Date(Date.now()).toLocaleString(
|
||||
"en-US",
|
||||
)}`,
|
||||
sender: user.username || "lst-system",
|
||||
customerId: customerID,
|
||||
positions: [],
|
||||
};
|
||||
|
||||
let updatedPredefinedObject = {
|
||||
...predefinedObject,
|
||||
positions: [
|
||||
...predefinedObject.positions,
|
||||
...ebmForecastData,
|
||||
let updatedPredefinedObject = {
|
||||
...predefinedObject,
|
||||
positions: [
|
||||
...predefinedObject.positions,
|
||||
...ebmForecastData,
|
||||
|
||||
// ...ebmForecastData.filter(
|
||||
// (q: any) =>
|
||||
// q.customerArticleNo != "" && q.customerArticleNo != "Total"
|
||||
// ),
|
||||
// ...petForecastData.filter(
|
||||
// (q: any) =>
|
||||
// q.customerArticleNo != "" && q.customerArticleNo != "Total"
|
||||
// ),
|
||||
],
|
||||
};
|
||||
// console.log(updatedPredefinedObject);
|
||||
const posting: any = await postForecast(updatedPredefinedObject, user);
|
||||
// ...ebmForecastData.filter(
|
||||
// (q: any) =>
|
||||
// q.customerArticleNo != "" && q.customerArticleNo != "Total"
|
||||
// ),
|
||||
// ...petForecastData.filter(
|
||||
// (q: any) =>
|
||||
// q.customerArticleNo != "" && q.customerArticleNo != "Total"
|
||||
// ),
|
||||
],
|
||||
};
|
||||
// console.log(updatedPredefinedObject);
|
||||
|
||||
return {
|
||||
success: posting.success,
|
||||
message: posting.message,
|
||||
data: posting.data === "" ? ebmForecastData : posting.data,
|
||||
};
|
||||
// posting the data to the new backend so we can store the data.
|
||||
axios.post(
|
||||
`http://localhost:${process.env.NODE_ENV?.trim() != "production" ? "4200/lst" : "4000"}/api/logistics/dm/forecastData`,
|
||||
ebmForecastData,
|
||||
);
|
||||
const posting: any = await postForecast(updatedPredefinedObject, user);
|
||||
|
||||
return {
|
||||
success: posting.success,
|
||||
message: posting.message,
|
||||
data: posting.data === "" ? ebmForecastData : posting.data,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -30,20 +30,20 @@ app.UseForwardedHeaders(new ForwardedHeadersOptions
|
||||
});
|
||||
|
||||
// Simple file logger
|
||||
void LogToFile(string message)
|
||||
{
|
||||
try
|
||||
{
|
||||
string logDir = Path.Combine(AppContext.BaseDirectory, "logs");
|
||||
Directory.CreateDirectory(logDir);
|
||||
string logFilePath = Path.Combine(logDir, "proxy_log.txt");
|
||||
File.AppendAllText(logFilePath, $"{DateTime.UtcNow:u}: {message}{Environment.NewLine}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Logging error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
// void LogToFile(string message)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// string logDir = Path.Combine(AppContext.BaseDirectory, "logs");
|
||||
// Directory.CreateDirectory(logDir);
|
||||
// string logFilePath = Path.Combine(logDir, "proxy_log.txt");
|
||||
// File.AppendAllText(logFilePath, $"{DateTime.UtcNow:u}: {message}{Environment.NewLine}");
|
||||
// }
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// Console.WriteLine($"Logging error: {ex.Message}");
|
||||
// }
|
||||
// }
|
||||
|
||||
app.Use(async (context, next) =>
|
||||
{
|
||||
|
||||
2
migrations/0026_heavy_robin_chapel.sql
Normal file
2
migrations/0026_heavy_robin_chapel.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE "forecast_Data" RENAME COLUMN "customer_article_number" TO "customer_article_no";--> statement-breakpoint
|
||||
ALTER TABLE "forecast_Data" DROP COLUMN "customer_id";
|
||||
1
migrations/0027_special_harpoon.sql
Normal file
1
migrations/0027_special_harpoon.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE "forecast_Data" RENAME COLUMN "request_date" TO "requirement_date";
|
||||
1733
migrations/meta/0026_snapshot.json
Normal file
1733
migrations/meta/0026_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1733
migrations/meta/0027_snapshot.json
Normal file
1733
migrations/meta/0027_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -183,6 +183,20 @@
|
||||
"when": 1761830426770,
|
||||
"tag": "0025_foamy_mattie_franklin",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 26,
|
||||
"version": "7",
|
||||
"when": 1761938410811,
|
||||
"tag": "0026_heavy_robin_chapel",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 27,
|
||||
"version": "7",
|
||||
"when": 1761938877395,
|
||||
"tag": "0027_special_harpoon",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
285
package-lock.json
generated
285
package-lock.json
generated
@@ -33,6 +33,8 @@
|
||||
"pino-pretty": "^13.1.2",
|
||||
"postgres": "^3.4.7",
|
||||
"socket.io": "^4.8.1",
|
||||
"swagger-jsdoc": "^6.2.8",
|
||||
"swagger-ui-express": "^5.0.1",
|
||||
"zod": "^4.1.12"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -44,6 +46,8 @@
|
||||
"@types/nodemailer": "^7.0.2",
|
||||
"@types/nodemailer-express-handlebars": "^4.0.5",
|
||||
"@types/pg": "^8.15.5",
|
||||
"@types/swagger-jsdoc": "^6.0.4",
|
||||
"@types/swagger-ui-express": "^4.1.8",
|
||||
"concurrently": "^9.2.1",
|
||||
"cz-conventional-changelog": "^3.3.0",
|
||||
"standard-version": "^9.5.0",
|
||||
@@ -52,6 +56,50 @@
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@apidevtools/json-schema-ref-parser": {
|
||||
"version": "9.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz",
|
||||
"integrity": "sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jsdevtools/ono": "^7.1.3",
|
||||
"@types/json-schema": "^7.0.6",
|
||||
"call-me-maybe": "^1.0.1",
|
||||
"js-yaml": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@apidevtools/openapi-schemas": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz",
|
||||
"integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@apidevtools/swagger-methods": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz",
|
||||
"integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@apidevtools/swagger-parser": {
|
||||
"version": "10.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz",
|
||||
"integrity": "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@apidevtools/json-schema-ref-parser": "^9.0.6",
|
||||
"@apidevtools/openapi-schemas": "^2.0.4",
|
||||
"@apidevtools/swagger-methods": "^3.0.2",
|
||||
"@jsdevtools/ono": "^7.1.3",
|
||||
"call-me-maybe": "^1.0.1",
|
||||
"z-schema": "^5.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"openapi-types": ">=7"
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-crypto/sha256-browser": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz",
|
||||
@@ -2446,6 +2494,12 @@
|
||||
"integrity": "sha512-3zwefSMwHpu8iVUW8YYz227sIv6UFqO31p1Bf1ZH/Vom7CmNyUsXjDBlnNzcuhmOL1XfxZ3nvND42kR23XlbcQ==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@jsdevtools/ono": {
|
||||
"version": "7.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz",
|
||||
"integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@levischuck/tiny-cbor": {
|
||||
"version": "0.2.11",
|
||||
"resolved": "https://registry.npmjs.org/@levischuck/tiny-cbor/-/tiny-cbor-0.2.11.tgz",
|
||||
@@ -2556,6 +2610,13 @@
|
||||
"integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@scarf/scarf": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz",
|
||||
"integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@simplewebauthn/browser": {
|
||||
"version": "13.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@simplewebauthn/browser/-/browser-13.1.2.tgz",
|
||||
@@ -3344,6 +3405,12 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
"version": "7.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/mime": {
|
||||
"version": "1.3.5",
|
||||
"dev": true,
|
||||
@@ -3476,6 +3543,24 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/swagger-jsdoc": {
|
||||
"version": "6.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/swagger-jsdoc/-/swagger-jsdoc-6.0.4.tgz",
|
||||
"integrity": "sha512-W+Xw5epcOZrF/AooUM/PccNMSAFOKWZA5dasNyMujTwsBkU74njSJBpvCCJhHAJ95XRMzQrrW844Btu0uoetwQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/swagger-ui-express": {
|
||||
"version": "4.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/swagger-ui-express/-/swagger-ui-express-4.1.8.tgz",
|
||||
"integrity": "sha512-AhZV8/EIreHFmBV5wAs0gzJUNq9JbbSXgJLQubCC0jtIo6prnI9MIRRxnU4MZX9RB9yXxF1V4R7jtLl/Wcj31g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/express": "*",
|
||||
"@types/serve-static": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@typespec/ts-http-runtime": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@typespec/ts-http-runtime/-/ts-http-runtime-0.3.0.tgz",
|
||||
@@ -3628,9 +3713,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",
|
||||
"optional": true
|
||||
"license": "Python-2.0"
|
||||
},
|
||||
"node_modules/array-ify": {
|
||||
"version": "1.0.0",
|
||||
@@ -3701,7 +3784,6 @@
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/base64-js": {
|
||||
@@ -3905,7 +3987,6 @@
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.12",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
@@ -4013,6 +4094,12 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/call-me-maybe": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz",
|
||||
"integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/callsites": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
|
||||
@@ -4282,7 +4369,6 @@
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/concat-stream": {
|
||||
@@ -5124,6 +5210,18 @@
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/doctrine": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
|
||||
"integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"esutils": "^2.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dot-prop": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz",
|
||||
@@ -5685,6 +5783,15 @@
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/esutils": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
|
||||
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/etag": {
|
||||
"version": "1.8.1",
|
||||
"license": "MIT",
|
||||
@@ -5764,6 +5871,7 @@
|
||||
"node_modules/express": {
|
||||
"version": "5.1.0",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"accepts": "^2.0.0",
|
||||
"body-parser": "^2.2.0",
|
||||
@@ -6159,7 +6267,6 @@
|
||||
},
|
||||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
@@ -6807,7 +6914,6 @@
|
||||
},
|
||||
"node_modules/inflight": {
|
||||
"version": "1.0.6",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"once": "^1.3.0",
|
||||
@@ -7228,9 +7334,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",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1"
|
||||
},
|
||||
@@ -7440,6 +7544,13 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.get": {
|
||||
"version": "4.4.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
|
||||
"integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==",
|
||||
"deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead.",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.includes": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
|
||||
@@ -7452,6 +7563,13 @@
|
||||
"integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.isequal": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
||||
"integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
|
||||
"deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.isinteger": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
|
||||
@@ -7502,9 +7620,7 @@
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz",
|
||||
"integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.once": {
|
||||
"version": "4.1.1",
|
||||
@@ -7933,7 +8049,6 @@
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
@@ -8285,6 +8400,13 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/openapi-types": {
|
||||
"version": "12.1.3",
|
||||
"resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz",
|
||||
"integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/ora": {
|
||||
"version": "5.4.1",
|
||||
"resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz",
|
||||
@@ -8505,7 +8627,6 @@
|
||||
},
|
||||
"node_modules/path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
@@ -10057,6 +10178,92 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/swagger-jsdoc": {
|
||||
"version": "6.2.8",
|
||||
"resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz",
|
||||
"integrity": "sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"commander": "6.2.0",
|
||||
"doctrine": "3.0.0",
|
||||
"glob": "7.1.6",
|
||||
"lodash.mergewith": "^4.6.2",
|
||||
"swagger-parser": "^10.0.3",
|
||||
"yaml": "2.0.0-1"
|
||||
},
|
||||
"bin": {
|
||||
"swagger-jsdoc": "bin/swagger-jsdoc.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/swagger-jsdoc/node_modules/commander": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz",
|
||||
"integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/swagger-jsdoc/node_modules/glob": {
|
||||
"version": "7.1.6",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
|
||||
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
|
||||
"deprecated": "Glob versions prior to v9 are no longer supported",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.4",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/swagger-parser": {
|
||||
"version": "10.0.3",
|
||||
"resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.3.tgz",
|
||||
"integrity": "sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@apidevtools/swagger-parser": "10.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/swagger-ui-dist": {
|
||||
"version": "5.30.1",
|
||||
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.30.1.tgz",
|
||||
"integrity": "sha512-4mNAUM31sr52K3JcK9qiGbfsFKNh/dm3PkEe+F9FAM31YY/NoRYUgsR/L6d7LLFn6PgZXtBG2ygp8+7UnpUIPg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@scarf/scarf": "=1.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/swagger-ui-express": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.1.tgz",
|
||||
"integrity": "sha512-SrNU3RiBGTLLmFU8GIJdOdanJTl4TOmT27tt3bWWHppqYmAZ6IDuEuBvMU6nZq0zLEe6b/1rACXCgLZqO6ZfrA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"swagger-ui-dist": ">=5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= v0.10.32"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"express": ">=4.0.0 || >=5.0.0-beta"
|
||||
}
|
||||
},
|
||||
"node_modules/tar-fs": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz",
|
||||
@@ -10495,6 +10702,15 @@
|
||||
"spdx-expression-parse": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/validator": {
|
||||
"version": "13.15.20",
|
||||
"resolved": "https://registry.npmjs.org/validator/-/validator-13.15.20.tgz",
|
||||
"integrity": "sha512-KxPOq3V2LmfQPP4eqf3Mq/zrT0Dqp2Vmx2Bn285LwVahLc+CsxOM0crBHczm8ijlcjZ0Q5Xd6LW3z3odTPnlrw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/vary": {
|
||||
"version": "1.1.2",
|
||||
"license": "MIT",
|
||||
@@ -10712,6 +10928,15 @@
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/yaml": {
|
||||
"version": "2.0.0-1",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.0.0-1.tgz",
|
||||
"integrity": "sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/yargs": {
|
||||
"version": "16.2.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
|
||||
@@ -10762,6 +10987,36 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/z-schema": {
|
||||
"version": "5.0.5",
|
||||
"resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz",
|
||||
"integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lodash.get": "^4.4.2",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"validator": "^13.7.0"
|
||||
},
|
||||
"bin": {
|
||||
"z-schema": "bin/z-schema"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"commander": "^9.4.1"
|
||||
}
|
||||
},
|
||||
"node_modules/z-schema/node_modules/commander": {
|
||||
"version": "9.5.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
|
||||
"integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": "^12.20.0 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/zod": {
|
||||
"version": "4.1.12",
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz",
|
||||
|
||||
@@ -67,6 +67,8 @@
|
||||
"pino-pretty": "^13.1.2",
|
||||
"postgres": "^3.4.7",
|
||||
"socket.io": "^4.8.1",
|
||||
"swagger-jsdoc": "^6.2.8",
|
||||
"swagger-ui-express": "^5.0.1",
|
||||
"zod": "^4.1.12"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -78,6 +80,8 @@
|
||||
"@types/nodemailer": "^7.0.2",
|
||||
"@types/nodemailer-express-handlebars": "^4.0.5",
|
||||
"@types/pg": "^8.15.5",
|
||||
"@types/swagger-jsdoc": "^6.0.4",
|
||||
"@types/swagger-ui-express": "^4.1.8",
|
||||
"concurrently": "^9.2.1",
|
||||
"cz-conventional-changelog": "^3.3.0",
|
||||
"standard-version": "^9.5.0",
|
||||
|
||||
Reference in New Issue
Block a user