Compare commits
5 Commits
2ebf695526
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 4ff10dfcb2 | |||
| 9a0bb18c5b | |||
| 1838c6f1e9 | |||
| 3a24d62957 | |||
| 6a14bab30c |
94
README.md
94
README.md
@@ -7,7 +7,7 @@
|
|||||||
Quick summary of current rewrite/migration goal.
|
Quick summary of current rewrite/migration goal.
|
||||||
|
|
||||||
- **Phase:** Backend rewrite
|
- **Phase:** Backend rewrite
|
||||||
- **Last updated:** 2026-05-27
|
- **Last updated:** 2026-06-17
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -39,21 +39,91 @@ _Status legend:_
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Setup / Installation
|
# Install
|
||||||
|
|
||||||
How to run the current version of the app.
|
## Files needed to be downloaded before install.
|
||||||
|
|
||||||
|
### To run the server
|
||||||
|
|
||||||
|
- [PostgresSQL](https://www.postgresql.org/download/windows/) - current version using is 17
|
||||||
|
- [NodeJS](https://nodejs.org)
|
||||||
|
- [NSSM](https://nssm.cc/)
|
||||||
|
|
||||||
|
### To manage the server
|
||||||
|
|
||||||
|
- [VSCODE](https://code.visualstudio.com/)
|
||||||
|
|
||||||
|
## Creating directories needed
|
||||||
|
|
||||||
|
- Create a new folder where we will host the server files.
|
||||||
|
- Copy the nssm.exe into this folder
|
||||||
|
- Copy the get the build from the releases and extract.
|
||||||
|
- This will house all the compiles and minified files needed to start the server up, this includes the frontend.
|
||||||
|
- Save the nssm.exe into this folder as well, this will be used to control the service.
|
||||||
|
|
||||||
|
## Do the initial install
|
||||||
|
|
||||||
|
### DB instal setup
|
||||||
|
|
||||||
|
1. Install postgres
|
||||||
|
2. Open pgAdmin
|
||||||
|
3. create a new Database named lst_db_v3. this can also be to your liking
|
||||||
|
|
||||||
|
### Initial server setup
|
||||||
|
|
||||||
|
1. Open VSCode and navigate to the folder where you extracted the files.
|
||||||
|
2. Click trusted when it pops up.
|
||||||
|
3. Open a terminal window inside vscode.
|
||||||
|
4. Run the install script this will install all dependence's needed as well as do all the database migrations
|
||||||
|
|
||||||
|
|
||||||
|
### Create the .env file
|
||||||
|
|
||||||
|
In the root of the folder create a new .env file by renaming .env-example to .env
|
||||||
|
|
||||||
|
change all the parameters to your desired server
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://git.tuffraid.net/cowch/lst_v3.git
|
npm run install --omit=dev
|
||||||
cd lst_v3
|
|
||||||
npm install
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Rename the .env-example to .env
|
Next we want to do an initial db
|
||||||
|
|
||||||
Update all the fields
|
```bash
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run dev:db:migrate
|
npm run dev:db:migrate
|
||||||
npm run dev
|
```
|
||||||
```
|
|
||||||
|
### Run the start command to get all the basic settings and modules installed
|
||||||
|
|
||||||
|
1. Run the below
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm start
|
||||||
|
```
|
||||||
|
|
||||||
|
### Creating first user.
|
||||||
|
|
||||||
|
Open http://[SERVER]:[PORT]/api/docs or postman and create a user.
|
||||||
|
- Please do not try to manually enter a new user this is due to how the password is hashed, as well as setting systemAdmin for the first user.
|
||||||
|
- Change the server and port to what you changed in the DB.
|
||||||
|
|
||||||
|
### Running as a serivice.
|
||||||
|
|
||||||
|
You want to CD into the scripts folder.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd .\scripts\
|
||||||
|
```
|
||||||
|
|
||||||
|
Next use the example command below to get the service up and running.
|
||||||
|
|
||||||
|
- Options legend
|
||||||
|
- serviceName = not recommended to change to reduce issues with the update process
|
||||||
|
- option = use install for the install, but you can use this script later to stop, start, restart the service.
|
||||||
|
- appPath = where did you extract the server files
|
||||||
|
- description = no need to change this unless you want it to be something else
|
||||||
|
- command = do not change this unless you know what your doing and really need to change this.
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
.\services.ps1 -serviceName "LSTV3_app" -option "install" -appPath "D:\LS_V3T" -description "Logistics Support Tool V3" -command "run start"
|
||||||
|
```
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ import os from "node:os";
|
|||||||
import { apiReference } from "@scalar/express-api-reference";
|
import { apiReference } from "@scalar/express-api-reference";
|
||||||
// const port = 3000;
|
// const port = 3000;
|
||||||
import type { OpenAPIV3_1 } from "openapi-types";
|
import type { OpenAPIV3_1 } from "openapi-types";
|
||||||
import { cronerActiveJobs } from "../scaler/cronerActiveJobs.spec.js";
|
|
||||||
import { cronerStatusChange } from "../scaler/cronerStatusChange.spec.js";
|
|
||||||
import { prodLoginSpec } from "../scaler/login.spec.js";
|
import { prodLoginSpec } from "../scaler/login.spec.js";
|
||||||
import { openDockApt } from "../scaler/opendockGetRelease.spec.js";
|
import { openDockApt } from "../scaler/opendockGetRelease.spec.js";
|
||||||
import { prodRestartSpec } from "../scaler/prodSqlRestart.spec.js";
|
import { prodRestartSpec } from "../scaler/prodSqlRestart.spec.js";
|
||||||
@@ -125,8 +123,6 @@ export const setupApiDocsRoutes = (baseUrl: string, app: Express) => {
|
|||||||
...prodLoginSpec,
|
...prodLoginSpec,
|
||||||
...prodRegisterSpec,
|
...prodRegisterSpec,
|
||||||
//...mergedDatamart,
|
//...mergedDatamart,
|
||||||
...cronerActiveJobs,
|
|
||||||
...cronerStatusChange,
|
|
||||||
...openDockApt,
|
...openDockApt,
|
||||||
|
|
||||||
// Add more specs here as you build features
|
// Add more specs here as you build features
|
||||||
|
|||||||
@@ -275,10 +275,10 @@ export const runDatamartQuery = async (data: Data) => {
|
|||||||
.replace("[startDate]", `${data.options.startDate}`)
|
.replace("[startDate]", `${data.options.startDate}`)
|
||||||
.replace("[endDate]", `${data.options.endDate}`)
|
.replace("[endDate]", `${data.options.endDate}`)
|
||||||
.replace(
|
.replace(
|
||||||
"and p.IdArtikelvarianten in ([articles])",
|
"and pl.ArticleHumanReadableId IN ([articles]) ",
|
||||||
data.options.articles
|
data.options.articles
|
||||||
? `and p.IdArtikelvarianten in (${data.options.articles})`
|
? `and pl.ArticleHumanReadableId IN (${data.options.articles})`
|
||||||
: "--and p.IdArtikelvarianten in ([articles])",
|
: "--and pl.ArticleHumanReadableId IN ([articles])",
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
57
backend/logistics/logistics.dm.repost.route.ts
Normal file
57
backend/logistics/logistics.dm.repost.route.ts
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import { Router } from "express";
|
||||||
|
import { requireAuth } from "../middleware/auth.middleware.js";
|
||||||
|
import { apiReturn } from "../utils/returnHelper.utils.js";
|
||||||
|
import { postData } from "./logistics.dm.postData.js";
|
||||||
|
|
||||||
|
const r = Router();
|
||||||
|
|
||||||
|
r.post("/", requireAuth, async (req, res) => {
|
||||||
|
let posting: any;
|
||||||
|
|
||||||
|
|
||||||
|
if (req.body.type !== "forecast" || req.body.type !== "orders") {
|
||||||
|
return apiReturn(res, {
|
||||||
|
success: false,
|
||||||
|
level: "error",
|
||||||
|
module: "dm",
|
||||||
|
subModule: "repost",
|
||||||
|
message: "You must pass over a proper type.",
|
||||||
|
data: [],
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.body.type === "forecast") {
|
||||||
|
posting = await postData(
|
||||||
|
{
|
||||||
|
type: "forecast",
|
||||||
|
endpoint: "/public/v1.0/DemandManagement/DELFOR",
|
||||||
|
data: req.body.data as any,
|
||||||
|
},
|
||||||
|
req.user,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.body.type === "orders") {
|
||||||
|
posting = await postData(
|
||||||
|
{
|
||||||
|
type: "orders",
|
||||||
|
endpoint: "/public/v1.0/DemandManagement/ORDERS",
|
||||||
|
data: req.body.data as any,
|
||||||
|
},
|
||||||
|
req.user,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return apiReturn(res, {
|
||||||
|
success: posting.success,
|
||||||
|
level: posting.success ? "info" : "error",
|
||||||
|
module: "dm",
|
||||||
|
subModule: "repost",
|
||||||
|
message: posting.message,
|
||||||
|
data: [],
|
||||||
|
status: 200,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
export default r;
|
||||||
@@ -1,74 +1,73 @@
|
|||||||
use [test1_AlplaPROD2.0_Read]
|
use [test1_AlplaPROD2.0_Read]
|
||||||
|
|
||||||
DECLARE @StartDate DATE = '[startDate]' -- 2025-1-1
|
DECLARE @StartDate DATE = '[startDate]'
|
||||||
DECLARE @EndDate DATE = '[endDate]' -- 2025-1-31
|
DECLARE @EndDate DATE = '[endDate]'
|
||||||
SELECT
|
|
||||||
r.[ArticleHumanReadableId]
|
;WITH bol_20 AS ( -- 2.0 BOL, one per release (newest doc wins)
|
||||||
,[ReleaseNumber]
|
SELECT pos.ReleaseId,
|
||||||
,h.CustomerOrderNumber
|
dd.JournalNumber,
|
||||||
,x.CustomerLineItemNumber
|
ROW_NUMBER() OVER (PARTITION BY pos.ReleaseId
|
||||||
,[CustomerReleaseNumber]
|
ORDER BY dd.ShippingDate DESC) AS rn
|
||||||
,[ReleaseState]
|
FROM [outboundDelivery].[DeliveryDocumentPosition] (nolock) pos
|
||||||
,[DeliveryState]
|
JOIN [outboundDelivery].[DeliveryDocument] (nolock) dd
|
||||||
,ea.JournalNummer as BOL_Number
|
ON dd.Id = pos.DeliveryDocumentId
|
||||||
,[ReleaseConfirmationState]
|
-- WHERE dd.DocumentType = <BOL value> -- see note below
|
||||||
,[PlanningState]
|
)
|
||||||
|
SELECT
|
||||||
|
r.[ArticleHumanReadableId]
|
||||||
|
,[ReleaseNumber]
|
||||||
|
,h.CustomerOrderNumber
|
||||||
|
,x.CustomerLineItemNumber
|
||||||
|
,[CustomerReleaseNumber]
|
||||||
|
,[ReleaseState]
|
||||||
|
,[DeliveryState]
|
||||||
|
,COALESCE(ea.JournalNummer, bol_20.JournalNumber) AS BOL_Number -- 1.0 or 2.0
|
||||||
|
,[ReleaseConfirmationState]
|
||||||
|
,[PlanningState]
|
||||||
,format(r.[OrderDate], 'yyyy-MM-dd HH:mm') as OrderDate
|
,format(r.[OrderDate], 'yyyy-MM-dd HH:mm') as OrderDate
|
||||||
--,r.[OrderDate]
|
--,r.[OrderDate]
|
||||||
,FORMAT(r.[DeliveryDate], 'yyyy-MM-dd HH:mm') as DeliveryDate
|
,FORMAT(r.[DeliveryDate], 'yyyy-MM-dd HH:mm') as DeliveryDate
|
||||||
--,r.[DeliveryDate]
|
--,r.[DeliveryDate]
|
||||||
,FORMAT(r.[LoadingDate], 'yyyy-MM-dd HH:mm') as LoadingDate
|
,FORMAT(r.[LoadingDate], 'yyyy-MM-dd HH:mm') as LoadingDate
|
||||||
--,r.[LoadingDate]
|
--,r.[LoadingDate]
|
||||||
,[Quantity]
|
,[Quantity]
|
||||||
,[DeliveredQuantity]
|
,[DeliveredQuantity]
|
||||||
,r.[AdditionalInformation1]
|
,r.[AdditionalInformation1]
|
||||||
,r.[AdditionalInformation2]
|
,r.[AdditionalInformation2]
|
||||||
,[TradeUnits]
|
,[TradeUnits]
|
||||||
,[LoadingUnits]
|
,[LoadingUnits]
|
||||||
,[Trucks]
|
,[Trucks]
|
||||||
,[LoadingToleranceType]
|
,[LoadingToleranceType]
|
||||||
,[SalesPrice]
|
,[SalesPrice]
|
||||||
,[Currency]
|
,[Currency]
|
||||||
,[QuantityUnit]
|
,[QuantityUnit]
|
||||||
,[SalesPriceRemark]
|
,[SalesPriceRemark]
|
||||||
,r.[Remark]
|
,r.[Remark]
|
||||||
,[Irradiated]
|
,[Irradiated]
|
||||||
,r.[CreatedByEdi]
|
,r.[CreatedByEdi]
|
||||||
,[DeliveryAddressHumanReadableId]
|
,[DeliveryAddressHumanReadableId]
|
||||||
,DeliveryAddressDescription
|
,DeliveryAddressDescription
|
||||||
,[CustomerArtNo]
|
,[CustomerArtNo]
|
||||||
,[TotalPrice]
|
,[TotalPrice]
|
||||||
,r.[ArticleAlias]
|
,r.[ArticleAlias]
|
||||||
|
FROM [order].[Release] (nolock) AS r
|
||||||
|
LEFT JOIN [order].LineItem AS x ON r.LineItemId = x.id
|
||||||
|
LEFT JOIN [order].Header AS h ON x.HeaderId = h.id
|
||||||
|
|
||||||
FROM [order].[Release] (nolock) as r
|
-- 1.0 BOL (legacy) — unchanged
|
||||||
|
LEFT JOIN AlplaPROD_test1.dbo.V_LadePlanungenLadeAuftragAbruf (nolock) AS zz
|
||||||
|
ON zz.AbrufIdAuftragsAbruf = r.ReleaseNumber
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT * FROM (
|
||||||
|
SELECT ROW_NUMBER() OVER (PARTITION BY IdJournal ORDER BY add_date DESC) AS RowNum, *
|
||||||
|
FROM [AlplaPROD_test1].[dbo].[T_Lieferungen] (nolock)
|
||||||
|
) t WHERE RowNum = 1
|
||||||
|
) AS ea ON zz.IdLieferschein = ea.IdJournal
|
||||||
|
|
||||||
left join
|
-- 2.0 BOL (new)
|
||||||
[order].LineItem as x on
|
LEFT JOIN bol_20 ON bol_20.ReleaseId = r.Id AND bol_20.rn = 1
|
||||||
|
|
||||||
r.LineItemId = x.id
|
WHERE r.DeliveryDate BETWEEN @StartDate AND @EndDate
|
||||||
|
|
||||||
left join
|
|
||||||
[order].Header as h on
|
|
||||||
x.HeaderId = h.id
|
|
||||||
|
|
||||||
--bol stuff
|
|
||||||
left join
|
|
||||||
AlplaPROD_test1.dbo.V_LadePlanungenLadeAuftragAbruf (nolock) as zz
|
|
||||||
on zz.AbrufIdAuftragsAbruf = r.ReleaseNumber
|
|
||||||
|
|
||||||
left join
|
|
||||||
(select * from (SELECT
|
|
||||||
ROW_NUMBER() OVER (PARTITION BY IdJournal ORDER BY add_date DESC) AS RowNum
|
|
||||||
,*
|
|
||||||
FROM [AlplaPROD_test1].[dbo].[T_Lieferungen] (nolock)) x
|
|
||||||
|
|
||||||
where RowNum = 1) as ea on
|
|
||||||
zz.IdLieferschein = ea.IdJournal
|
|
||||||
|
|
||||||
where
|
|
||||||
--r.ReleaseNumber = 1452
|
|
||||||
|
|
||||||
r.DeliveryDate between @StartDate AND @EndDate
|
|
||||||
and DeliveredQuantity > 0
|
and DeliveredQuantity > 0
|
||||||
--and r.ArticleHumanReadableId in ([articles])
|
--and r.ArticleHumanReadableId in ([articles])
|
||||||
--and Journalnummer = 169386
|
--and Journalnummer = 169386
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
use AlplaPROD_test1
|
|
||||||
/**
|
|
||||||
|
|
||||||
move this over to the delivery date range query once we have the shift data mapped over correctly.
|
|
||||||
|
|
||||||
update the psi stuff on this as well.
|
|
||||||
**/
|
|
||||||
DECLARE @StartDate DATE = '[startDate]' -- 2025-1-1
|
|
||||||
DECLARE @EndDate DATE = '[endDate]' -- 2025-1-31
|
|
||||||
SELECT
|
|
||||||
r.[ArticleHumanReadableId]
|
|
||||||
,[ReleaseNumber]
|
|
||||||
,h.CustomerOrderNumber
|
|
||||||
,x.CustomerLineItemNumber
|
|
||||||
,[CustomerReleaseNumber]
|
|
||||||
,[ReleaseState]
|
|
||||||
,[DeliveryState]
|
|
||||||
,ea.JournalNummer as BOL_Number
|
|
||||||
,[ReleaseConfirmationState]
|
|
||||||
,[PlanningState]
|
|
||||||
--,format(r.[OrderDate], 'yyyy-MM-dd HH:mm') as OrderDate
|
|
||||||
,r.[OrderDate]
|
|
||||||
--,FORMAT(r.[DeliveryDate], 'yyyy-MM-dd HH:mm') as DeliveryDate
|
|
||||||
,r.[DeliveryDate]
|
|
||||||
--,FORMAT(r.[LoadingDate], 'yyyy-MM-dd HH:mm') as LoadingDate
|
|
||||||
,r.[LoadingDate]
|
|
||||||
,[Quantity]
|
|
||||||
,[DeliveredQuantity]
|
|
||||||
,r.[AdditionalInformation1]
|
|
||||||
,r.[AdditionalInformation2]
|
|
||||||
,[TradeUnits]
|
|
||||||
,[LoadingUnits]
|
|
||||||
,[Trucks]
|
|
||||||
,[LoadingToleranceType]
|
|
||||||
,[SalesPrice]
|
|
||||||
,[Currency]
|
|
||||||
,[QuantityUnit]
|
|
||||||
,[SalesPriceRemark]
|
|
||||||
,r.[Remark]
|
|
||||||
,[Irradiated]
|
|
||||||
,r.[CreatedByEdi]
|
|
||||||
,[DeliveryAddressHumanReadableId]
|
|
||||||
,DeliveryAddressDescription
|
|
||||||
,[CustomerArtNo]
|
|
||||||
,[TotalPrice]
|
|
||||||
,r.[ArticleAlias]
|
|
||||||
|
|
||||||
FROM [order].[Release] (nolock) as r
|
|
||||||
|
|
||||||
left join
|
|
||||||
[order].LineItem as x on
|
|
||||||
|
|
||||||
r.LineItemId = x.id
|
|
||||||
|
|
||||||
left join
|
|
||||||
[order].Header as h on
|
|
||||||
x.HeaderId = h.id
|
|
||||||
|
|
||||||
--bol stuff
|
|
||||||
left join
|
|
||||||
AlplaPROD_test1.dbo.V_LadePlanungenLadeAuftragAbruf (nolock) as zz
|
|
||||||
on zz.AbrufIdAuftragsAbruf = r.ReleaseNumber
|
|
||||||
|
|
||||||
left join
|
|
||||||
(select * from (SELECT
|
|
||||||
ROW_NUMBER() OVER (PARTITION BY IdJournal ORDER BY add_date DESC) AS RowNum
|
|
||||||
,*
|
|
||||||
FROM [AlplaPROD_test1].[dbo].[T_Lieferungen] (nolock)) x
|
|
||||||
|
|
||||||
where RowNum = 1) as ea on
|
|
||||||
zz.IdLieferschein = ea.IdJournal
|
|
||||||
|
|
||||||
where
|
|
||||||
r.ArticleHumanReadableId in ([articles])
|
|
||||||
--r.ReleaseNumber = 1452
|
|
||||||
|
|
||||||
and r.DeliveryDate between @StartDate AND @EndDate
|
|
||||||
--and DeliveredQuantity > 0
|
|
||||||
--and Journalnummer = 169386
|
|
||||||
@@ -1,32 +1,72 @@
|
|||||||
use AlplaPROD_test1
|
use [test1_AlplaPROD2.0_Read]
|
||||||
declare @start_date nvarchar(30) = '[startDate]' --'2025-01-01'
|
|
||||||
declare @end_date nvarchar(30) = '[endDate]' --'2025-08-09'
|
|
||||||
/*
|
|
||||||
articles will need to be passed over as well as the date structure we want to see
|
|
||||||
*/
|
|
||||||
|
|
||||||
select x.IdArtikelvarianten As Article,
|
DECLARE @start_date date = '[startDate]'; --'2025-01-01'
|
||||||
ProduktionAlias as Description,
|
DECLARE @end_date date = '[endDate]'; --'2025-08-09'
|
||||||
standort as MachineId,
|
DECLARE @tz sysname = 'Eastern Standard Time'; -- usday1; use 'Central Standard Time' for usksc1
|
||||||
MaschinenBezeichnung as MachineName,
|
DECLARE @shiftSeconds int = 7*3600; -- 07:00 production-day anchor
|
||||||
--MaschZyklus as PlanningCycleTime,
|
--TODO: add in the proper time zone based on the env, get correcr shift time as well
|
||||||
x.IdProdPlanung as LotNumber,
|
;WITH src AS (
|
||||||
FORMAT(ProdTag, 'MM/dd/yyyy') as ProductionDay,
|
SELECT
|
||||||
x.planMenge as TotalPlanned,
|
pl.RunningNumber, pl.ArticleHumanReadableId, pl.ArticleAlias, pl.ArticleDescription,
|
||||||
ProduktionMenge as QTYPerDay,
|
pl.MachineLocation, pl.MachineDescription, pl.ProductionLotState, pl.ProductionInterrupt,
|
||||||
round(ProduktionMengeVPK, 2) PalDay,
|
pl.PlanQuantityPieces, pl.PlanQuantityLoadingUnit,
|
||||||
Status as finished
|
CAST(pl.ProdStart AT TIME ZONE @tz AS datetime2(0)) AS StartLocal,
|
||||||
--MaschStdAuslastung as nee
|
CAST(pl.PlanEnd AT TIME ZONE @tz AS datetime2(0)) AS EndLocal
|
||||||
|
FROM productionScheduling.ProductionLot AS pl
|
||||||
from dbo.V_ProdLosProduktionJeProdTag_PLANNING (nolock) as x
|
WHERE pl.PlanEnd > pl.ProdStart
|
||||||
|
and pl.publishState = 1
|
||||||
left join
|
and pl.ArticleHumanReadableId IN ([articles]) -- <-- article filter (was IdArtikelvarianten)
|
||||||
dbo.V_ProdPlanung (nolock) as p on
|
--AND pl.RunningNumber = 28094 -- <-- lot filter (was IdProdPlanung); comment out for all
|
||||||
x.IdProdPlanung = p.IdProdPlanung
|
),
|
||||||
|
calc AS (
|
||||||
where ProdTag between @start_date and @end_date
|
SELECT *,
|
||||||
and p.IdArtikelvarianten in ([articles])
|
DATEADD(SECOND, @shiftSeconds,
|
||||||
--and V_ProdLosProduktionJeProdTag_PLANNING.IdKunde = 10
|
CAST(CASE WHEN DATEDIFF(SECOND, CAST(StartLocal AS date), StartLocal) >= @shiftSeconds
|
||||||
--and IdProdPlanung = 18442
|
THEN CAST(StartLocal AS date)
|
||||||
|
ELSE DATEADD(DAY,-1, CAST(StartLocal AS date)) END AS datetime2(0))) AS FirstBoundary
|
||||||
order by ProdTag desc
|
FROM src
|
||||||
|
),
|
||||||
|
days AS ( -- one row per production day the lot touches
|
||||||
|
SELECT RunningNumber, ArticleHumanReadableId, ArticleAlias, ArticleDescription, MachineLocation,
|
||||||
|
MachineDescription, ProductionLotState, PlanQuantityPieces, PlanQuantityLoadingUnit,
|
||||||
|
StartLocal, EndLocal, FirstBoundary AS DayStart
|
||||||
|
FROM calc
|
||||||
|
UNION ALL
|
||||||
|
SELECT RunningNumber, ArticleHumanReadableId, ArticleAlias, ArticleDescription, MachineLocation,
|
||||||
|
MachineDescription, ProductionLotState, PlanQuantityPieces, PlanQuantityLoadingUnit,
|
||||||
|
StartLocal, EndLocal, DATEADD(DAY,1,DayStart)
|
||||||
|
FROM days
|
||||||
|
WHERE DATEADD(DAY,1,DayStart) < EndLocal
|
||||||
|
),
|
||||||
|
seg AS ( -- working seconds inside each production day
|
||||||
|
SELECT *,
|
||||||
|
DATEDIFF(SECOND,
|
||||||
|
CASE WHEN StartLocal > DayStart THEN StartLocal ELSE DayStart END,
|
||||||
|
CASE WHEN EndLocal < DATEADD(DAY,1,DayStart) THEN EndLocal ELSE DATEADD(DAY,1,DayStart) END
|
||||||
|
) AS SegSec
|
||||||
|
FROM days
|
||||||
|
),
|
||||||
|
cum AS ( -- cumulative seconds for telescoping round
|
||||||
|
SELECT *,
|
||||||
|
SUM(SegSec) OVER (PARTITION BY RunningNumber ORDER BY DayStart ROWS UNBOUNDED PRECEDING) AS CumEnd,
|
||||||
|
SUM(SegSec) OVER (PARTITION BY RunningNumber ORDER BY DayStart ROWS UNBOUNDED PRECEDING) - SegSec AS CumStart,
|
||||||
|
SUM(SegSec) OVER (PARTITION BY RunningNumber) AS DenomSec
|
||||||
|
FROM seg
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
ArticleHumanReadableId AS Article,
|
||||||
|
ArticleAlias AS Description,
|
||||||
|
MachineLocation AS MachineId,
|
||||||
|
MachineDescription AS MachineName,
|
||||||
|
RunningNumber AS LotNumber,
|
||||||
|
FORMAT(DayStart, 'MM/dd/yyyy') AS ProductionDay,
|
||||||
|
PlanQuantityPieces AS TotalPlanned,
|
||||||
|
ROUND(PlanQuantityPieces * 1.0 * CumEnd / DenomSec, 0)
|
||||||
|
- ROUND(PlanQuantityPieces * 1.0 * CumStart / DenomSec, 0) AS QTYPerDay,
|
||||||
|
ROUND(PlanQuantityLoadingUnit * CumEnd / DenomSec, 2)
|
||||||
|
- ROUND(PlanQuantityLoadingUnit * CumStart / DenomSec, 2) AS PalDay,
|
||||||
|
ProductionLotState AS finished
|
||||||
|
FROM cum
|
||||||
|
WHERE CAST(DayStart AS date) BETWEEN @start_date AND @end_date -- filter AFTER cumulative calc
|
||||||
|
ORDER BY RunningNumber, DayStart DESC
|
||||||
|
OPTION (MAXRECURSION 366);
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
import type { OpenAPIV3_1 } from "openapi-types";
|
|
||||||
|
|
||||||
export const cronerActiveJobs: OpenAPIV3_1.PathsObject = {
|
|
||||||
"/api/utils/croner": {
|
|
||||||
get: {
|
|
||||||
summary: "Cron jobs",
|
|
||||||
description: "Returns all jobs on the server.",
|
|
||||||
tags: ["Utils"],
|
|
||||||
responses: {
|
|
||||||
"200": {
|
|
||||||
description: "Jobs returned",
|
|
||||||
content: {
|
|
||||||
"application/json": {
|
|
||||||
schema: {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
status: {
|
|
||||||
type: "boolean",
|
|
||||||
format: "boolean",
|
|
||||||
example: true,
|
|
||||||
},
|
|
||||||
uptime: {
|
|
||||||
type: "number",
|
|
||||||
format: "3454.34",
|
|
||||||
example: 3454.34,
|
|
||||||
},
|
|
||||||
memoryUsage: {
|
|
||||||
type: "string",
|
|
||||||
format: "Heap: 11.62 MB / RSS: 86.31 MB",
|
|
||||||
},
|
|
||||||
sqlServerStats: {
|
|
||||||
type: "number",
|
|
||||||
format: "442127",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
import type { OpenAPIV3_1 } from "openapi-types";
|
|
||||||
|
|
||||||
export const cronerStatusChange: OpenAPIV3_1.PathsObject = {
|
|
||||||
"/api/utils/croner/{status}": {
|
|
||||||
patch: {
|
|
||||||
summary: "Pauses or Resume the Job",
|
|
||||||
description:
|
|
||||||
"When sending start or stop with job name it will resume or stop the job",
|
|
||||||
tags: ["Utils"],
|
|
||||||
|
|
||||||
parameters: [
|
|
||||||
{
|
|
||||||
name: "status",
|
|
||||||
in: "path",
|
|
||||||
required: true,
|
|
||||||
description: "Status change",
|
|
||||||
schema: {
|
|
||||||
type: "string",
|
|
||||||
},
|
|
||||||
example: "start",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "limit",
|
|
||||||
in: "query",
|
|
||||||
required: false, // 👈 optional
|
|
||||||
description: "Maximum number of records to return",
|
|
||||||
schema: {
|
|
||||||
type: "integer",
|
|
||||||
minimum: 1,
|
|
||||||
maximum: 100,
|
|
||||||
},
|
|
||||||
example: 10,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
requestBody: {
|
|
||||||
required: true,
|
|
||||||
content: {
|
|
||||||
"application/json": {
|
|
||||||
schema: {
|
|
||||||
type: "object",
|
|
||||||
required: ["name"],
|
|
||||||
properties: {
|
|
||||||
name: {
|
|
||||||
type: "string",
|
|
||||||
example: "start",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
responses: {
|
|
||||||
"200": {
|
|
||||||
description: "Successful response",
|
|
||||||
content: {
|
|
||||||
"application/json": {
|
|
||||||
schema: {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
success: { type: "boolean", example: true },
|
|
||||||
data: {
|
|
||||||
type: "object",
|
|
||||||
example: {
|
|
||||||
name: "exampleName",
|
|
||||||
value: "some value",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"400": {
|
|
||||||
description: "Bad request",
|
|
||||||
content: {
|
|
||||||
"application/json": {
|
|
||||||
schema: {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
success: { type: "boolean", example: false },
|
|
||||||
message: {
|
|
||||||
type: "string",
|
|
||||||
example: "Invalid name parameter",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -1,10 +1,14 @@
|
|||||||
import { useQuery, useSuspenseQuery } from "@tanstack/react-query";
|
import { useQuery, useSuspenseQuery } from "@tanstack/react-query";
|
||||||
|
import { Link } from "@tanstack/react-router";
|
||||||
|
import { LaptopMinimal } from "lucide-react";
|
||||||
import {
|
import {
|
||||||
Sidebar,
|
Sidebar,
|
||||||
SidebarContent,
|
SidebarContent,
|
||||||
SidebarHeader,
|
SidebarFooter,
|
||||||
SidebarMenu,
|
SidebarMenu,
|
||||||
|
SidebarMenuButton,
|
||||||
SidebarMenuItem,
|
SidebarMenuItem,
|
||||||
|
useSidebar,
|
||||||
} from "@/components/ui/sidebar";
|
} from "@/components/ui/sidebar";
|
||||||
import { useSession } from "@/lib/auth-client";
|
import { useSession } from "@/lib/auth-client";
|
||||||
import { getSettings } from "../../lib/queries/getSettings";
|
import { getSettings } from "../../lib/queries/getSettings";
|
||||||
@@ -23,6 +27,7 @@ export function AppSidebar() {
|
|||||||
openDock: ["read"],
|
openDock: ["read"],
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
const { setOpen } = useSidebar();
|
||||||
|
|
||||||
// const { data: canReadWarehouse = false } = useQuery(
|
// const { data: canReadWarehouse = false } = useQuery(
|
||||||
// permissionQuery({
|
// permissionQuery({
|
||||||
@@ -36,7 +41,7 @@ export function AppSidebar() {
|
|||||||
collapsible="offcanvas"
|
collapsible="offcanvas"
|
||||||
className="top-(--header-height) h-[calc(100svh-var(--header-height))]!"
|
className="top-(--header-height) h-[calc(100svh-var(--header-height))]!"
|
||||||
>
|
>
|
||||||
<SidebarHeader>
|
<SidebarContent>
|
||||||
<SidebarMenu>
|
<SidebarMenu>
|
||||||
<SidebarMenuItem>
|
<SidebarMenuItem>
|
||||||
<SidebarContent>
|
<SidebarContent>
|
||||||
@@ -64,7 +69,24 @@ export function AppSidebar() {
|
|||||||
</SidebarContent>
|
</SidebarContent>
|
||||||
</SidebarMenuItem>
|
</SidebarMenuItem>
|
||||||
</SidebarMenu>
|
</SidebarMenu>
|
||||||
</SidebarHeader>
|
</SidebarContent>
|
||||||
|
{session &&
|
||||||
|
(session.user.role === "admin" ||
|
||||||
|
session.user.role === "systemAdmin" ||
|
||||||
|
session.user.role === "manager") && (
|
||||||
|
<SidebarFooter>
|
||||||
|
<SidebarMenu>
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<SidebarMenuButton asChild>
|
||||||
|
<Link to={"/apidocs"} onClick={() => setOpen(false)}>
|
||||||
|
<LaptopMinimal />
|
||||||
|
<span>Api docs</span>
|
||||||
|
</Link>
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
</SidebarMenu>
|
||||||
|
</SidebarFooter>
|
||||||
|
)}
|
||||||
</Sidebar>
|
</Sidebar>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,9 +11,11 @@
|
|||||||
import { Route as rootRouteImport } from './routes/__root'
|
import { Route as rootRouteImport } from './routes/__root'
|
||||||
import { Route as ForbiddenRouteImport } from './routes/forbidden'
|
import { Route as ForbiddenRouteImport } from './routes/forbidden'
|
||||||
import { Route as AppDownRouteImport } from './routes/app-down'
|
import { Route as AppDownRouteImport } from './routes/app-down'
|
||||||
|
import { Route as ApidocsRouteImport } from './routes/apidocs'
|
||||||
import { Route as AboutRouteImport } from './routes/about'
|
import { Route as AboutRouteImport } from './routes/about'
|
||||||
import { Route as IndexRouteImport } from './routes/index'
|
import { Route as IndexRouteImport } from './routes/index'
|
||||||
import { Route as DocsIndexRouteImport } from './routes/docs/index'
|
import { Route as DocsIndexRouteImport } from './routes/docs/index'
|
||||||
|
import { Route as DocsDatamartRouteImport } from './routes/docs/datamart'
|
||||||
import { Route as DocsSplatRouteImport } from './routes/docs/$'
|
import { Route as DocsSplatRouteImport } from './routes/docs/$'
|
||||||
import { Route as AdminUsersRouteImport } from './routes/admin/users'
|
import { Route as AdminUsersRouteImport } from './routes/admin/users'
|
||||||
import { Route as AdminSettingsRouteImport } from './routes/admin/settings'
|
import { Route as AdminSettingsRouteImport } from './routes/admin/settings'
|
||||||
@@ -41,6 +43,11 @@ const AppDownRoute = AppDownRouteImport.update({
|
|||||||
path: '/app-down',
|
path: '/app-down',
|
||||||
getParentRoute: () => rootRouteImport,
|
getParentRoute: () => rootRouteImport,
|
||||||
} as any)
|
} as any)
|
||||||
|
const ApidocsRoute = ApidocsRouteImport.update({
|
||||||
|
id: '/apidocs',
|
||||||
|
path: '/apidocs',
|
||||||
|
getParentRoute: () => rootRouteImport,
|
||||||
|
} as any)
|
||||||
const AboutRoute = AboutRouteImport.update({
|
const AboutRoute = AboutRouteImport.update({
|
||||||
id: '/about',
|
id: '/about',
|
||||||
path: '/about',
|
path: '/about',
|
||||||
@@ -56,6 +63,11 @@ const DocsIndexRoute = DocsIndexRouteImport.update({
|
|||||||
path: '/docs/',
|
path: '/docs/',
|
||||||
getParentRoute: () => rootRouteImport,
|
getParentRoute: () => rootRouteImport,
|
||||||
} as any)
|
} as any)
|
||||||
|
const DocsDatamartRoute = DocsDatamartRouteImport.update({
|
||||||
|
id: '/docs/datamart',
|
||||||
|
path: '/docs/datamart',
|
||||||
|
getParentRoute: () => rootRouteImport,
|
||||||
|
} as any)
|
||||||
const DocsSplatRoute = DocsSplatRouteImport.update({
|
const DocsSplatRoute = DocsSplatRouteImport.update({
|
||||||
id: '/docs/$',
|
id: '/docs/$',
|
||||||
path: '/docs/$',
|
path: '/docs/$',
|
||||||
@@ -145,6 +157,7 @@ const WarehouseDockdoorscanningScansDockScansRoute =
|
|||||||
export interface FileRoutesByFullPath {
|
export interface FileRoutesByFullPath {
|
||||||
'/': typeof IndexRoute
|
'/': typeof IndexRoute
|
||||||
'/about': typeof AboutRoute
|
'/about': typeof AboutRoute
|
||||||
|
'/apidocs': typeof ApidocsRoute
|
||||||
'/app-down': typeof AppDownRoute
|
'/app-down': typeof AppDownRoute
|
||||||
'/forbidden': typeof ForbiddenRoute
|
'/forbidden': typeof ForbiddenRoute
|
||||||
'/login': typeof authLoginRoute
|
'/login': typeof authLoginRoute
|
||||||
@@ -155,6 +168,7 @@ export interface FileRoutesByFullPath {
|
|||||||
'/admin/settings': typeof AdminSettingsRoute
|
'/admin/settings': typeof AdminSettingsRoute
|
||||||
'/admin/users': typeof AdminUsersRoute
|
'/admin/users': typeof AdminUsersRoute
|
||||||
'/docs/$': typeof DocsSplatRoute
|
'/docs/$': typeof DocsSplatRoute
|
||||||
|
'/docs/datamart': typeof DocsDatamartRoute
|
||||||
'/docs/': typeof DocsIndexRoute
|
'/docs/': typeof DocsIndexRoute
|
||||||
'/user/profile': typeof authUserProfileRoute
|
'/user/profile': typeof authUserProfileRoute
|
||||||
'/user/resetpassword': typeof authUserResetpasswordRoute
|
'/user/resetpassword': typeof authUserResetpasswordRoute
|
||||||
@@ -168,6 +182,7 @@ export interface FileRoutesByFullPath {
|
|||||||
export interface FileRoutesByTo {
|
export interface FileRoutesByTo {
|
||||||
'/': typeof IndexRoute
|
'/': typeof IndexRoute
|
||||||
'/about': typeof AboutRoute
|
'/about': typeof AboutRoute
|
||||||
|
'/apidocs': typeof ApidocsRoute
|
||||||
'/app-down': typeof AppDownRoute
|
'/app-down': typeof AppDownRoute
|
||||||
'/forbidden': typeof ForbiddenRoute
|
'/forbidden': typeof ForbiddenRoute
|
||||||
'/login': typeof authLoginRoute
|
'/login': typeof authLoginRoute
|
||||||
@@ -178,6 +193,7 @@ export interface FileRoutesByTo {
|
|||||||
'/admin/settings': typeof AdminSettingsRoute
|
'/admin/settings': typeof AdminSettingsRoute
|
||||||
'/admin/users': typeof AdminUsersRoute
|
'/admin/users': typeof AdminUsersRoute
|
||||||
'/docs/$': typeof DocsSplatRoute
|
'/docs/$': typeof DocsSplatRoute
|
||||||
|
'/docs/datamart': typeof DocsDatamartRoute
|
||||||
'/docs': typeof DocsIndexRoute
|
'/docs': typeof DocsIndexRoute
|
||||||
'/user/profile': typeof authUserProfileRoute
|
'/user/profile': typeof authUserProfileRoute
|
||||||
'/user/resetpassword': typeof authUserResetpasswordRoute
|
'/user/resetpassword': typeof authUserResetpasswordRoute
|
||||||
@@ -192,6 +208,7 @@ export interface FileRoutesById {
|
|||||||
__root__: typeof rootRouteImport
|
__root__: typeof rootRouteImport
|
||||||
'/': typeof IndexRoute
|
'/': typeof IndexRoute
|
||||||
'/about': typeof AboutRoute
|
'/about': typeof AboutRoute
|
||||||
|
'/apidocs': typeof ApidocsRoute
|
||||||
'/app-down': typeof AppDownRoute
|
'/app-down': typeof AppDownRoute
|
||||||
'/forbidden': typeof ForbiddenRoute
|
'/forbidden': typeof ForbiddenRoute
|
||||||
'/(auth)/login': typeof authLoginRoute
|
'/(auth)/login': typeof authLoginRoute
|
||||||
@@ -202,6 +219,7 @@ export interface FileRoutesById {
|
|||||||
'/admin/settings': typeof AdminSettingsRoute
|
'/admin/settings': typeof AdminSettingsRoute
|
||||||
'/admin/users': typeof AdminUsersRoute
|
'/admin/users': typeof AdminUsersRoute
|
||||||
'/docs/$': typeof DocsSplatRoute
|
'/docs/$': typeof DocsSplatRoute
|
||||||
|
'/docs/datamart': typeof DocsDatamartRoute
|
||||||
'/docs/': typeof DocsIndexRoute
|
'/docs/': typeof DocsIndexRoute
|
||||||
'/(auth)/user/profile': typeof authUserProfileRoute
|
'/(auth)/user/profile': typeof authUserProfileRoute
|
||||||
'/(auth)/user/resetpassword': typeof authUserResetpasswordRoute
|
'/(auth)/user/resetpassword': typeof authUserResetpasswordRoute
|
||||||
@@ -217,6 +235,7 @@ export interface FileRouteTypes {
|
|||||||
fullPaths:
|
fullPaths:
|
||||||
| '/'
|
| '/'
|
||||||
| '/about'
|
| '/about'
|
||||||
|
| '/apidocs'
|
||||||
| '/app-down'
|
| '/app-down'
|
||||||
| '/forbidden'
|
| '/forbidden'
|
||||||
| '/login'
|
| '/login'
|
||||||
@@ -227,6 +246,7 @@ export interface FileRouteTypes {
|
|||||||
| '/admin/settings'
|
| '/admin/settings'
|
||||||
| '/admin/users'
|
| '/admin/users'
|
||||||
| '/docs/$'
|
| '/docs/$'
|
||||||
|
| '/docs/datamart'
|
||||||
| '/docs/'
|
| '/docs/'
|
||||||
| '/user/profile'
|
| '/user/profile'
|
||||||
| '/user/resetpassword'
|
| '/user/resetpassword'
|
||||||
@@ -240,6 +260,7 @@ export interface FileRouteTypes {
|
|||||||
to:
|
to:
|
||||||
| '/'
|
| '/'
|
||||||
| '/about'
|
| '/about'
|
||||||
|
| '/apidocs'
|
||||||
| '/app-down'
|
| '/app-down'
|
||||||
| '/forbidden'
|
| '/forbidden'
|
||||||
| '/login'
|
| '/login'
|
||||||
@@ -250,6 +271,7 @@ export interface FileRouteTypes {
|
|||||||
| '/admin/settings'
|
| '/admin/settings'
|
||||||
| '/admin/users'
|
| '/admin/users'
|
||||||
| '/docs/$'
|
| '/docs/$'
|
||||||
|
| '/docs/datamart'
|
||||||
| '/docs'
|
| '/docs'
|
||||||
| '/user/profile'
|
| '/user/profile'
|
||||||
| '/user/resetpassword'
|
| '/user/resetpassword'
|
||||||
@@ -263,6 +285,7 @@ export interface FileRouteTypes {
|
|||||||
| '__root__'
|
| '__root__'
|
||||||
| '/'
|
| '/'
|
||||||
| '/about'
|
| '/about'
|
||||||
|
| '/apidocs'
|
||||||
| '/app-down'
|
| '/app-down'
|
||||||
| '/forbidden'
|
| '/forbidden'
|
||||||
| '/(auth)/login'
|
| '/(auth)/login'
|
||||||
@@ -273,6 +296,7 @@ export interface FileRouteTypes {
|
|||||||
| '/admin/settings'
|
| '/admin/settings'
|
||||||
| '/admin/users'
|
| '/admin/users'
|
||||||
| '/docs/$'
|
| '/docs/$'
|
||||||
|
| '/docs/datamart'
|
||||||
| '/docs/'
|
| '/docs/'
|
||||||
| '/(auth)/user/profile'
|
| '/(auth)/user/profile'
|
||||||
| '/(auth)/user/resetpassword'
|
| '/(auth)/user/resetpassword'
|
||||||
@@ -287,6 +311,7 @@ export interface FileRouteTypes {
|
|||||||
export interface RootRouteChildren {
|
export interface RootRouteChildren {
|
||||||
IndexRoute: typeof IndexRoute
|
IndexRoute: typeof IndexRoute
|
||||||
AboutRoute: typeof AboutRoute
|
AboutRoute: typeof AboutRoute
|
||||||
|
ApidocsRoute: typeof ApidocsRoute
|
||||||
AppDownRoute: typeof AppDownRoute
|
AppDownRoute: typeof AppDownRoute
|
||||||
ForbiddenRoute: typeof ForbiddenRoute
|
ForbiddenRoute: typeof ForbiddenRoute
|
||||||
authLoginRoute: typeof authLoginRoute
|
authLoginRoute: typeof authLoginRoute
|
||||||
@@ -297,6 +322,7 @@ export interface RootRouteChildren {
|
|||||||
AdminSettingsRoute: typeof AdminSettingsRoute
|
AdminSettingsRoute: typeof AdminSettingsRoute
|
||||||
AdminUsersRoute: typeof AdminUsersRoute
|
AdminUsersRoute: typeof AdminUsersRoute
|
||||||
DocsSplatRoute: typeof DocsSplatRoute
|
DocsSplatRoute: typeof DocsSplatRoute
|
||||||
|
DocsDatamartRoute: typeof DocsDatamartRoute
|
||||||
DocsIndexRoute: typeof DocsIndexRoute
|
DocsIndexRoute: typeof DocsIndexRoute
|
||||||
authUserProfileRoute: typeof authUserProfileRoute
|
authUserProfileRoute: typeof authUserProfileRoute
|
||||||
authUserResetpasswordRoute: typeof authUserResetpasswordRoute
|
authUserResetpasswordRoute: typeof authUserResetpasswordRoute
|
||||||
@@ -324,6 +350,13 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof AppDownRouteImport
|
preLoaderRoute: typeof AppDownRouteImport
|
||||||
parentRoute: typeof rootRouteImport
|
parentRoute: typeof rootRouteImport
|
||||||
}
|
}
|
||||||
|
'/apidocs': {
|
||||||
|
id: '/apidocs'
|
||||||
|
path: '/apidocs'
|
||||||
|
fullPath: '/apidocs'
|
||||||
|
preLoaderRoute: typeof ApidocsRouteImport
|
||||||
|
parentRoute: typeof rootRouteImport
|
||||||
|
}
|
||||||
'/about': {
|
'/about': {
|
||||||
id: '/about'
|
id: '/about'
|
||||||
path: '/about'
|
path: '/about'
|
||||||
@@ -345,6 +378,13 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof DocsIndexRouteImport
|
preLoaderRoute: typeof DocsIndexRouteImport
|
||||||
parentRoute: typeof rootRouteImport
|
parentRoute: typeof rootRouteImport
|
||||||
}
|
}
|
||||||
|
'/docs/datamart': {
|
||||||
|
id: '/docs/datamart'
|
||||||
|
path: '/docs/datamart'
|
||||||
|
fullPath: '/docs/datamart'
|
||||||
|
preLoaderRoute: typeof DocsDatamartRouteImport
|
||||||
|
parentRoute: typeof rootRouteImport
|
||||||
|
}
|
||||||
'/docs/$': {
|
'/docs/$': {
|
||||||
id: '/docs/$'
|
id: '/docs/$'
|
||||||
path: '/docs/$'
|
path: '/docs/$'
|
||||||
@@ -463,6 +503,7 @@ declare module '@tanstack/react-router' {
|
|||||||
const rootRouteChildren: RootRouteChildren = {
|
const rootRouteChildren: RootRouteChildren = {
|
||||||
IndexRoute: IndexRoute,
|
IndexRoute: IndexRoute,
|
||||||
AboutRoute: AboutRoute,
|
AboutRoute: AboutRoute,
|
||||||
|
ApidocsRoute: ApidocsRoute,
|
||||||
AppDownRoute: AppDownRoute,
|
AppDownRoute: AppDownRoute,
|
||||||
ForbiddenRoute: ForbiddenRoute,
|
ForbiddenRoute: ForbiddenRoute,
|
||||||
authLoginRoute: authLoginRoute,
|
authLoginRoute: authLoginRoute,
|
||||||
@@ -473,6 +514,7 @@ const rootRouteChildren: RootRouteChildren = {
|
|||||||
AdminSettingsRoute: AdminSettingsRoute,
|
AdminSettingsRoute: AdminSettingsRoute,
|
||||||
AdminUsersRoute: AdminUsersRoute,
|
AdminUsersRoute: AdminUsersRoute,
|
||||||
DocsSplatRoute: DocsSplatRoute,
|
DocsSplatRoute: DocsSplatRoute,
|
||||||
|
DocsDatamartRoute: DocsDatamartRoute,
|
||||||
DocsIndexRoute: DocsIndexRoute,
|
DocsIndexRoute: DocsIndexRoute,
|
||||||
authUserProfileRoute: authUserProfileRoute,
|
authUserProfileRoute: authUserProfileRoute,
|
||||||
authUserResetpasswordRoute: authUserResetpasswordRoute,
|
authUserResetpasswordRoute: authUserResetpasswordRoute,
|
||||||
|
|||||||
@@ -19,8 +19,10 @@ const RootLayout = () => {
|
|||||||
<div className="relative min-h-[calc(100svh-var(--header-height))]">
|
<div className="relative min-h-[calc(100svh-var(--header-height))]">
|
||||||
<AppSidebar />
|
<AppSidebar />
|
||||||
|
|
||||||
<main className="w-full p-4">
|
<main className="w-full">
|
||||||
<div className="mx-auto w-full max-w-7xl">
|
<div className="mx-auto w-full flex justify-center">
|
||||||
|
{" "}
|
||||||
|
{/* className="mx-auto w-full max-w-7xl" use this for dashboards and stuff*/}
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
@@ -31,7 +33,7 @@ const RootLayout = () => {
|
|||||||
</SidebarProvider>
|
</SidebarProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
{session && session.user.role === "systemAdmin" && (
|
{session && session.user.role === "systemAdmin" && (
|
||||||
<TanStackRouterDevtools />
|
<TanStackRouterDevtools position="bottom-right" />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ function RouteComponent() {
|
|||||||
};
|
};
|
||||||
//console.log(logs);
|
//console.log(logs);
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1 max-w-7xl">
|
||||||
<div className="flex gap-1 justify-end">
|
<div className="flex gap-1 justify-end">
|
||||||
<Button onClick={triggerBuild}>Trigger Build</Button>
|
<Button onClick={triggerBuild}>Trigger Build</Button>
|
||||||
<Button onClick={() => clearRoom()}>Clear Logs</Button>
|
<Button onClick={() => clearRoom()}>Clear Logs</Button>
|
||||||
|
|||||||
15
frontend/src/routes/apidocs.tsx
Normal file
15
frontend/src/routes/apidocs.tsx
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { createFileRoute } from "@tanstack/react-router";
|
||||||
|
|
||||||
|
export const Route = createFileRoute("/apidocs")({
|
||||||
|
component: RouteComponent,
|
||||||
|
});
|
||||||
|
|
||||||
|
function RouteComponent() {
|
||||||
|
return (
|
||||||
|
<iframe
|
||||||
|
src="/lst/api/docs"
|
||||||
|
className="h-[calc(100vh-64px)] w-full border-0"
|
||||||
|
title="LST API Docs"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,18 +1,18 @@
|
|||||||
import { useSuspenseQuery } from "@tanstack/react-query";
|
import { useSuspenseQuery } from "@tanstack/react-query";
|
||||||
import { createFileRoute, redirect } from "@tanstack/react-router";
|
import { createFileRoute, redirect } from "@tanstack/react-router";
|
||||||
import { createColumnHelper } from "@tanstack/react-table";
|
import { createColumnHelper } from "@tanstack/react-table";
|
||||||
|
import { Trash } from "lucide-react";
|
||||||
import { Suspense, useState } from "react";
|
import { Suspense, useState } from "react";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
import { Button } from "../../../components/ui/button";
|
||||||
|
import { Spinner } from "../../../components/ui/spinner";
|
||||||
|
import { api } from "../../../lib/apiHelper";
|
||||||
import { authClient } from "../../../lib/auth-client";
|
import { authClient } from "../../../lib/auth-client";
|
||||||
import { getArticleLinks } from "../../../lib/queries/getArticleLinks";
|
import { getArticleLinks } from "../../../lib/queries/getArticleLinks";
|
||||||
import LstTable from "../../../lib/tableStuff/LstTable";
|
import LstTable from "../../../lib/tableStuff/LstTable";
|
||||||
import SearchableHeader from "../../../lib/tableStuff/SearchableHeader";
|
import SearchableHeader from "../../../lib/tableStuff/SearchableHeader";
|
||||||
import SkellyTable from "../../../lib/tableStuff/SkellyTable";
|
import SkellyTable from "../../../lib/tableStuff/SkellyTable";
|
||||||
import NewArticleLink from "./-components/NewArticleLink";
|
import NewArticleLink from "./-components/NewArticleLink";
|
||||||
import { api } from "../../../lib/apiHelper";
|
|
||||||
import { toast } from "sonner";
|
|
||||||
import { Button } from "../../../components/ui/button";
|
|
||||||
import { Spinner } from "../../../components/ui/spinner";
|
|
||||||
import { Trash } from "lucide-react";
|
|
||||||
|
|
||||||
export const Route = createFileRoute("/transportation/opendock/")({
|
export const Route = createFileRoute("/transportation/opendock/")({
|
||||||
beforeLoad: async ({ location }) => {
|
beforeLoad: async ({ location }) => {
|
||||||
@@ -97,77 +97,77 @@ const ArticleLinkTable = () => {
|
|||||||
cell: (i) => i.getValue(),
|
cell: (i) => i.getValue(),
|
||||||
}),
|
}),
|
||||||
columnHelper.accessor("deleteUser", {
|
columnHelper.accessor("deleteUser", {
|
||||||
header: ({ column }) => (
|
header: ({ column }) => (
|
||||||
<SearchableHeader
|
<SearchableHeader
|
||||||
column={column}
|
column={column}
|
||||||
title="Delete Link"
|
title="Delete Link"
|
||||||
searchable={false}
|
searchable={false}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
filterFn: "includesString",
|
filterFn: "includesString",
|
||||||
cell: (i) => {
|
cell: (i) => {
|
||||||
// biome-ignore lint: just removing the lint for now to get this going will maybe fix later
|
// biome-ignore lint: just removing the lint for now to get this going will maybe fix later
|
||||||
const [activeToggle, setActiveToggle] = useState(false);
|
const [activeToggle, setActiveToggle] = useState(false);
|
||||||
|
|
||||||
const onTrigger = async () => {
|
const onTrigger = async () => {
|
||||||
setActiveToggle(true);
|
setActiveToggle(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await api.delete(
|
const res = await api.delete(
|
||||||
`/opendock/articleCheck/${i.row.original.id}`,
|
`/opendock/articleCheck/${i.row.original.id}`,
|
||||||
|
|
||||||
{
|
{
|
||||||
withCredentials: true,
|
withCredentials: true,
|
||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
validateStatus: () => true,
|
validateStatus: () => true,
|
||||||
},
|
},
|
||||||
);
|
|
||||||
|
|
||||||
if (res.data.success) {
|
|
||||||
toast.success(`AV: ${i.row.original.av} was deleted.`);
|
|
||||||
refetch();
|
|
||||||
setActiveToggle(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!res.data.success) {
|
|
||||||
toast.error(
|
|
||||||
`AV: ${i.row.original.av} encountered an error when trying to delete: ${res.data.message}`,
|
|
||||||
);
|
|
||||||
refetch();
|
|
||||||
setActiveToggle(false);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
setActiveToggle(false);
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<div className="flex items-center space-x-2">
|
|
||||||
<Button
|
|
||||||
variant="destructive"
|
|
||||||
disabled={activeToggle}
|
|
||||||
onClick={onTrigger}
|
|
||||||
>
|
|
||||||
{activeToggle ? (
|
|
||||||
<span>
|
|
||||||
<Spinner />
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
<span>
|
|
||||||
<Trash />
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
},
|
|
||||||
}),
|
if (res.data.success) {
|
||||||
|
toast.success(`AV: ${i.row.original.av} was deleted.`);
|
||||||
|
refetch();
|
||||||
|
setActiveToggle(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!res.data.success) {
|
||||||
|
toast.error(
|
||||||
|
`AV: ${i.row.original.av} encountered an error when trying to delete: ${res.data.message}`,
|
||||||
|
);
|
||||||
|
refetch();
|
||||||
|
setActiveToggle(false);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
setActiveToggle(false);
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<Button
|
||||||
|
variant="destructive"
|
||||||
|
disabled={activeToggle}
|
||||||
|
onClick={onTrigger}
|
||||||
|
>
|
||||||
|
{activeToggle ? (
|
||||||
|
<span>
|
||||||
|
<Spinner />
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<span>
|
||||||
|
<Trash />
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className="">
|
||||||
<div>
|
<div>
|
||||||
<div className="flex justify-end m-2">
|
<div className="flex justify-end m-2">
|
||||||
<Suspense
|
<Suspense
|
||||||
|
|||||||
90
package-lock.json
generated
90
package-lock.json
generated
@@ -10,7 +10,7 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@dotenvx/dotenvx": "^1.57.0",
|
"@dotenvx/dotenvx": "^1.57.0",
|
||||||
"@scalar/express-api-reference": "^0.9.4",
|
"@scalar/express-api-reference": "^0.9.20",
|
||||||
"@socket.io/admin-ui": "^0.5.1",
|
"@socket.io/admin-ui": "^0.5.1",
|
||||||
"archiver": "^7.0.1",
|
"archiver": "^7.0.1",
|
||||||
"axios": "^1.13.6",
|
"axios": "^1.13.6",
|
||||||
@@ -44,7 +44,8 @@
|
|||||||
"socket.io": "^4.8.3",
|
"socket.io": "^4.8.3",
|
||||||
"socket.io-client": "^4.8.3",
|
"socket.io-client": "^4.8.3",
|
||||||
"xlsx": "^0.18.5",
|
"xlsx": "^0.18.5",
|
||||||
"zod": "^4.3.6"
|
"zod": "^4.3.6",
|
||||||
|
"zod-openapi": "^6.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "2.4.8",
|
"@biomejs/biome": "2.4.8",
|
||||||
@@ -2424,46 +2425,61 @@
|
|||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@scalar/core": {
|
"node_modules/@scalar/client-side-rendering": {
|
||||||
"version": "0.4.4",
|
"version": "0.1.13",
|
||||||
"resolved": "https://registry.npmjs.org/@scalar/core/-/core-0.4.4.tgz",
|
"resolved": "https://registry.npmjs.org/@scalar/client-side-rendering/-/client-side-rendering-0.1.13.tgz",
|
||||||
"integrity": "sha512-eXIG0opyQn45FzpTp0dAWFP1Vjcx+helgUAsa0uN36tyUR7DSmz2kRwHqqedzvPWryeRCKPz7/vwzKpETZp5lg==",
|
"integrity": "sha512-p8V4HgEWjaCpqsnhclg1pTfjE9JA0AWRr0ocBQHexoHo+pqnSs1d83Mv9rjH7R0FZJrlCSandZZeY3DMX2gYXQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@scalar/types": "0.7.4"
|
"@scalar/schemas": "0.3.3",
|
||||||
|
"@scalar/types": "0.12.3",
|
||||||
|
"@scalar/validation": "0.6.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=22"
|
"node": ">=22"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@scalar/express-api-reference": {
|
"node_modules/@scalar/express-api-reference": {
|
||||||
"version": "0.9.4",
|
"version": "0.9.20",
|
||||||
"resolved": "https://registry.npmjs.org/@scalar/express-api-reference/-/express-api-reference-0.9.4.tgz",
|
"resolved": "https://registry.npmjs.org/@scalar/express-api-reference/-/express-api-reference-0.9.20.tgz",
|
||||||
"integrity": "sha512-KXG+VaMArCGcWhzDV2rfkHd+UF1HYevIFbO6cqFpd+az7QHvVT99BU8Yh60T1dmtCp504s0Pl/vcTyJ91fK1Ug==",
|
"integrity": "sha512-J0P6qpYoL0kXvs/A/vuAwCqQFCYnErbXSB5/3lEGTbARuK0oGyMvl55dQyW5Ucq3CX1npuRejlTX6bxEprSvJA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@scalar/core": "0.4.4"
|
"@scalar/client-side-rendering": "0.1.13"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=22"
|
"node": ">=22"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@scalar/helpers": {
|
"node_modules/@scalar/helpers": {
|
||||||
"version": "0.4.2",
|
"version": "0.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/@scalar/helpers/-/helpers-0.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/@scalar/helpers/-/helpers-0.8.1.tgz",
|
||||||
"integrity": "sha512-IrgrGVSahCfYDNWITazz4Q1BOndp5eEzlimRkfxiYn++KqeWyLfALyym1omqcdKGYtiSx1KIbKaUJL9vkjaN7w==",
|
"integrity": "sha512-yuiuBCadP5bjAnIv23QvifVN/NaMi9xBF6b8Wdk4QOzwzLPJmp699MAdf33J0A5i2qKcvnu32iz/VkEJmQRe5g==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=22"
|
"node": ">=22"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@scalar/types": {
|
"node_modules/@scalar/schemas": {
|
||||||
"version": "0.7.4",
|
"version": "0.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/@scalar/types/-/types-0.7.4.tgz",
|
"resolved": "https://registry.npmjs.org/@scalar/schemas/-/schemas-0.3.3.tgz",
|
||||||
"integrity": "sha512-1o9uf42lZ9YD0XP/HMWrwXN0unx6vFTTgtduA1F28Yloea9Pfv9N2R/t0wO91iSIzw4+NubEFolunbdb2QcgHA==",
|
"integrity": "sha512-qDcgFu6ta5Z90L9D2P6DFKzYesU+FW5+m55SGmdI4iRMRCwj5umHpec2Y2W/SJcCF6bbUZawMxuOH2Ja6rUNpQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@scalar/helpers": "0.4.2",
|
"@scalar/helpers": "0.8.1",
|
||||||
|
"@scalar/validation": "0.6.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=22"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@scalar/types": {
|
||||||
|
"version": "0.12.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@scalar/types/-/types-0.12.3.tgz",
|
||||||
|
"integrity": "sha512-7zaXafbgTFmsJ/9AwYeExUWzXoZNyKOL0SEVAUWRaOndcjxpFCtwzuPrc1elMEWdHopWbY1Qe5pWKbE2aqG2HA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@scalar/helpers": "0.8.1",
|
||||||
"nanoid": "^5.1.6",
|
"nanoid": "^5.1.6",
|
||||||
"type-fest": "^5.3.1",
|
"type-fest": "^5.3.1",
|
||||||
"zod": "^4.3.5"
|
"zod": "^4.3.5"
|
||||||
@@ -2472,6 +2488,15 @@
|
|||||||
"node": ">=22"
|
"node": ">=22"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@scalar/validation": {
|
||||||
|
"version": "0.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@scalar/validation/-/validation-0.6.0.tgz",
|
||||||
|
"integrity": "sha512-tpmmG+/xRE2Kn9RpflU3AIyZv08v10+E1ZrJCx7z6+/91zHVxy0M73kC1LT4/8PbYNt85ywyC8+n+D99JdMcGA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@serialport/binding-mock": {
|
"node_modules/@serialport/binding-mock": {
|
||||||
"version": "10.2.2",
|
"version": "10.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-10.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-10.2.2.tgz",
|
||||||
@@ -10566,9 +10591,9 @@
|
|||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/nanoid": {
|
"node_modules/nanoid": {
|
||||||
"version": "5.1.7",
|
"version": "5.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.7.tgz",
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.11.tgz",
|
||||||
"integrity": "sha512-ua3NDgISf6jdwezAheMOk4mbE1LXjm1DfMUDMuJf4AqxLFK3ccGpgWizwa5YV7Yz9EpXwEaWoRXSb/BnV0t5dQ==",
|
"integrity": "sha512-v+KEsUv2ps74PaSKv0gHTxTCgMXOIfBEbaqa6w6ISIGC7ZsvHN4N9oJ8d4cmf0n5oTzQz2SLmThbQWhjd/8eKg==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "github",
|
"type": "github",
|
||||||
@@ -13252,9 +13277,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/type-fest": {
|
"node_modules/type-fest": {
|
||||||
"version": "5.5.0",
|
"version": "5.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.7.0.tgz",
|
||||||
"integrity": "sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g==",
|
"integrity": "sha512-1URUxUqfHFM1c+zfSPsa3gnkO7Aq21qyH75SIduNYz4SzY964rn1X2vCMQaHSHhktiw+0kPa2iyb6PUpXqB6Vg==",
|
||||||
"license": "(MIT OR CC0-1.0)",
|
"license": "(MIT OR CC0-1.0)",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tagged-tag": "^1.0.0"
|
"tagged-tag": "^1.0.0"
|
||||||
@@ -13937,6 +13962,21 @@
|
|||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/colinhacks"
|
"url": "https://github.com/sponsors/colinhacks"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"node_modules/zod-openapi": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/zod-openapi/-/zod-openapi-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-mS4eRJ4DGCPrg6elRbJqc/3nLe4EPVi8KiHRKZ7dcTR5m5orPy8EfoWmceAyGZAq71MAWuyrTTOag7W5N61ZPQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=22.14.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/samchungy/zod-openapi?sponsor=1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"zod": "^4.0.0"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@dotenvx/dotenvx": "^1.57.0",
|
"@dotenvx/dotenvx": "^1.57.0",
|
||||||
"@scalar/express-api-reference": "^0.9.4",
|
"@scalar/express-api-reference": "^0.9.20",
|
||||||
"@socket.io/admin-ui": "^0.5.1",
|
"@socket.io/admin-ui": "^0.5.1",
|
||||||
"archiver": "^7.0.1",
|
"archiver": "^7.0.1",
|
||||||
"axios": "^1.13.6",
|
"axios": "^1.13.6",
|
||||||
@@ -102,7 +102,8 @@
|
|||||||
"socket.io": "^4.8.3",
|
"socket.io": "^4.8.3",
|
||||||
"socket.io-client": "^4.8.3",
|
"socket.io-client": "^4.8.3",
|
||||||
"xlsx": "^0.18.5",
|
"xlsx": "^0.18.5",
|
||||||
"zod": "^4.3.6"
|
"zod": "^4.3.6",
|
||||||
|
"zod-openapi": "^6.0.0"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"commitizen": {
|
"commitizen": {
|
||||||
|
|||||||
Reference in New Issue
Block a user