Compare commits
84 Commits
468f933168
...
migration
| Author | SHA1 | Date | |
|---|---|---|---|
| 8943407f27 | |||
| 0bbe411db0 | |||
| 99b3ad633c | |||
| c892348d19 | |||
| 360549aaf4 | |||
| bdc1e72fc1 | |||
| 4cae96b1ee | |||
| 1cde8ab2e6 | |||
| 03e8378213 | |||
| 275c93dc79 | |||
| fbb8c21d5c | |||
| dce93d3de2 | |||
| faf4e9f9ab | |||
| a9783a7d35 | |||
| e9ca6dbbb2 | |||
| e996f99400 | |||
| 3b939ff2d3 | |||
| a7ff88025e | |||
| 00899a5b77 | |||
| 99ecf52218 | |||
| a6920d7cd8 | |||
| 788efdf4b3 | |||
| a2a17beeeb | |||
| 6c793c66a4 | |||
| 6918a5a7d4 | |||
| ddd9b0e372 | |||
| 41d921756b | |||
| d86ca7d3bf | |||
| 932a72ba88 | |||
| b9c6d0ba57 | |||
| 592e4c8cd7 | |||
| b772666905 | |||
| a6edcb71bf | |||
| 76d929abea | |||
| da17defe82 | |||
| 669f5ca33f | |||
| b649dca4c9 | |||
| 04b8d041f9 | |||
| 71bc7c29bc | |||
| 79f1f8f91b | |||
| b677bc1498 | |||
| a53915ad8c | |||
| b3ce767b32 | |||
| 6caa5984e7 | |||
| 415d2e4a1d | |||
| 271cdbdbfa | |||
| 796a8dccd2 | |||
| e03e92c18d | |||
| dd2e5d04ae | |||
| 708b57b926 | |||
| 0444da8bbc | |||
| 6d49fae16d | |||
| be8a44f2dc | |||
| a3994a1f69 | |||
| 00eaf62d4c | |||
| 6851777faf | |||
| f9e97fc224 | |||
| 4e3c5e4191 | |||
| 172fd1d5c2 | |||
| 1094de2ebd | |||
| 7462b3d90b | |||
| 2045c13ef2 | |||
| 5fa9e83d5b | |||
| f48c944bd0 | |||
| dddd1d422e | |||
| 8133443ec9 | |||
| 28c7d30c1a | |||
| 57966ac9de | |||
| 6910550de7 | |||
| 1f8b8a7248 | |||
| cfed981928 | |||
| 0efe74d4b1 | |||
| c35db2e209 | |||
| e1cdeb740b | |||
| 3c9e75dc3c | |||
| 64b5b0d248 | |||
| 668eae9719 | |||
| 7cc3778506 | |||
| af47c1582e | |||
| 081572c421 | |||
| c6f6ef6262 | |||
| 34849e15d1 | |||
| 9bd66942f5 | |||
| 795da35141 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -157,3 +157,4 @@ backend-0.1.3.zip
|
|||||||
BulkForecastTemplate
|
BulkForecastTemplate
|
||||||
BulkOrdersTemplate
|
BulkOrdersTemplate
|
||||||
check.json
|
check.json
|
||||||
|
server/services/ocp/controller/materials/materialcheck.bak
|
||||||
|
|||||||
8
.includes
Normal file
8
.includes
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
database
|
||||||
|
dist
|
||||||
|
frontend/dist
|
||||||
|
CHANGELOG.md
|
||||||
|
drizzle.config.ts
|
||||||
|
package.json
|
||||||
|
package-lock.json
|
||||||
|
README.md
|
||||||
68
CHANGELOG.md
68
CHANGELOG.md
@@ -1,5 +1,73 @@
|
|||||||
# All CHanges to LST can be found below.
|
# All CHanges to LST can be found below.
|
||||||
|
|
||||||
|
## [2.27.0](https://git.tuffraid.net/cowch/lstV2/compare/v2.26.0...v2.27.0) (2025-09-10)
|
||||||
|
|
||||||
|
|
||||||
|
### 🌟 Enhancements
|
||||||
|
|
||||||
|
* **eom:** lastSales, lastPurch added to be pulled with new template ([7cc3778](https://git.tuffraid.net/cowch/lstV2/commits/7cc3778506fc92392ca8431aee0edb203861e10d))
|
||||||
|
|
||||||
|
|
||||||
|
### 🛠️ Code Refactor
|
||||||
|
|
||||||
|
* **cosume:** changes to allow non logged in users to use this function ([271cdbd](https://git.tuffraid.net/cowch/lstV2/commits/271cdbdbfa2478ecf56e9b01a4474508acacda2e))
|
||||||
|
* **mm query:** changes to the query to see pkg and materials properly and not duplicates ([57966ac](https://git.tuffraid.net/cowch/lstV2/commits/57966ac9de72543014451b7ccd75539296ccaa51))
|
||||||
|
* **rfid:** changes to show all tags vs only 3 if there are more ([b677bc1](https://git.tuffraid.net/cowch/lstV2/commits/b677bc14981faff30c91f6ffe4602319dd3c6016))
|
||||||
|
* **silo card:** changes to allow viewers to see and able to attach and detach ([796a8dc](https://git.tuffraid.net/cowch/lstV2/commits/796a8dccd2807890abdff7c8dacf8b2246eb265e))
|
||||||
|
* **sql:** articles added in UOM ([cfed981](https://git.tuffraid.net/cowch/lstV2/commits/cfed981928a56389e09ef428c43ceabc1caec28e))
|
||||||
|
|
||||||
|
|
||||||
|
### 🐛 Bug fixes
|
||||||
|
|
||||||
|
* **article check:** corrected the query to not have a specfic plant in it ([79f1f8f](https://git.tuffraid.net/cowch/lstV2/commits/79f1f8f91ba33533de7f4a7cc91503cfd8dd4ce5))
|
||||||
|
* **bookin:** corrected the bookin in error response ([1f8b8a7](https://git.tuffraid.net/cowch/lstV2/commits/1f8b8a7248c11c7e264c8c5ae7c042c5a0878c46))
|
||||||
|
* **bookin:** corrections to only show the message on error vs the json ([b3ce767](https://git.tuffraid.net/cowch/lstV2/commits/b3ce767b323c990c0ccf35ad6c2c67136a27272e))
|
||||||
|
* **db:** changes to the user so it deletes correctly ([932a72b](https://git.tuffraid.net/cowch/lstV2/commits/932a72ba884673471f0056e721cc3f2c8e34b4f3))
|
||||||
|
* **eomservice:** changes to stop a crash incase the sql returned nothing due to start up ([6caa598](https://git.tuffraid.net/cowch/lstV2/commits/6caa5984e7a3e7b48b119c176835663ffec71151))
|
||||||
|
* **frontend:** typos ([c6f6ef6](https://git.tuffraid.net/cowch/lstV2/commits/c6f6ef626295f452cdf26f6776b74cfb3b1a10f5))
|
||||||
|
* **label query:** fixes to only pull in active layouts ([99ecf52](https://git.tuffraid.net/cowch/lstV2/commits/99ecf52218556e048ba9262e74f9b3d020dea31d))
|
||||||
|
* **main material check:** corrections to properly ignore pkg during color checks ([6910550](https://git.tuffraid.net/cowch/lstV2/commits/6910550de769dce04b1045f96ab19cf7b8d1ef8c))
|
||||||
|
* **material check:** split manual material out of the mm to properly catch it ([a53915a](https://git.tuffraid.net/cowch/lstV2/commits/a53915ad8cbec5bd8d6ba4643c460ad0162249e2))
|
||||||
|
* **materials:** more fixes to try and please all plants to use this version and not call me ([00899a5](https://git.tuffraid.net/cowch/lstV2/commits/00899a5b778eab792b350a0b47589de1524d91c8))
|
||||||
|
* **register:** changes to not give everyone system admin ([415d2e4](https://git.tuffraid.net/cowch/lstV2/commits/415d2e4a1d851cc46ac64ffc814a280a02293bbc))
|
||||||
|
|
||||||
|
## [2.26.0](https://git.tuffraid.net/cowch/lstV2/compare/v2.25.0...v2.26.0) (2025-08-28)
|
||||||
|
|
||||||
|
|
||||||
|
### 🛠️ Code Refactor
|
||||||
|
|
||||||
|
* **labeling:** moved bookin fails inside bookin as it could be off ([df42319](https://git.tuffraid.net/cowch/lstV2/commits/df423192bfc5e2389872147e92b7d22e648a2927))
|
||||||
|
* **labeling:** removed the wrong import ([788d636](https://git.tuffraid.net/cowch/lstV2/commits/788d6367a380a81722a76bd6adbe18831d88eeb5))
|
||||||
|
* **materials:** changes for permissions on material consume ([3148aa7](https://git.tuffraid.net/cowch/lstV2/commits/3148aa79d73823499824cc0601fcabec97bb4f9d))
|
||||||
|
* **materials:** changes to allow exact and eom transfers ([0a6ddea](https://git.tuffraid.net/cowch/lstV2/commits/0a6ddea8c0d2773aba00266df7e2839879d10cb1))
|
||||||
|
* **notifcations:** changed hour to min in ti intergrations ([73d38ba](https://git.tuffraid.net/cowch/lstV2/commits/73d38ba3fe7ab4d5ca3a4a1e1c99fdd7bf5e92dc))
|
||||||
|
* **tms intergration:** corrected how we added gl coding ([37f82a9](https://git.tuffraid.net/cowch/lstV2/commits/37f82a9710cf20e6d0d056893c9da43c70b9e619))
|
||||||
|
|
||||||
|
|
||||||
|
### 🌟 Enhancements
|
||||||
|
|
||||||
|
* **materials:** added in a bigger window on eom transfer lots ([53ed2c4](https://git.tuffraid.net/cowch/lstV2/commits/53ed2c4e6a0d3fafafbcb655b5d06cff6324363d))
|
||||||
|
* **ocp:** zechetti 1 added in ([27586e9](https://git.tuffraid.net/cowch/lstV2/commits/27586e923a106f2b8dd804e9c8292edd5d009cf0))
|
||||||
|
* **rfid:** new check to remove tags that have been at a line longer than 6 hours ([0ba338d](https://git.tuffraid.net/cowch/lstV2/commits/0ba338d48037f7def74196ca3f41de5807e2cb31))
|
||||||
|
* **tms:** a clean up function was added to remove releases added as blockers older than 45d ([662a951](https://git.tuffraid.net/cowch/lstV2/commits/662a951b9871d5dfc21f01a76ba23be77b475757))
|
||||||
|
|
||||||
|
|
||||||
|
### 📝 Testing Code
|
||||||
|
|
||||||
|
* **forklifts:** forklift starting process ([8c296c5](https://git.tuffraid.net/cowch/lstV2/commits/8c296c5b783f42f85c30a955d6e9d540c50dcfbe))
|
||||||
|
|
||||||
|
|
||||||
|
### 🐛 Bug fixes
|
||||||
|
|
||||||
|
* **bookin:** corrected the error received from the book in fail ([369d160](https://git.tuffraid.net/cowch/lstV2/commits/369d16018c8be9fdb936afbc3749b3f9fcea58c8))
|
||||||
|
* **dm:** corrected the remark section so its properly sent over ([68901a8](https://git.tuffraid.net/cowch/lstV2/commits/68901a857ae5161f024da9cdefc0a981a4907205))
|
||||||
|
* **eom stats:** corrections to the eom inv stuff to be proper tiems ([468f933](https://git.tuffraid.net/cowch/lstV2/commits/468f933168cc40be0c1b159c31948a2c97600390))
|
||||||
|
* **fake edi:** removed console log ([24a97af](https://git.tuffraid.net/cowch/lstV2/commits/24a97afe064d5c44872e24e6e3299ed5f2977a78))
|
||||||
|
* **material check:** alt mm causing issues and utilizing an 80% to just be ok ([f4f3de4](https://git.tuffraid.net/cowch/lstV2/commits/f4f3de49cae277ffa158116d1802495b27fa8e75))
|
||||||
|
* **ocp:** zechetti type correction to include the printer name ([4486fe2](https://git.tuffraid.net/cowch/lstV2/commits/4486fe24362b4811d7cff0467c7f2f85e0c9e3c4))
|
||||||
|
* **produser:** changes to include DM ([8d6ead3](https://git.tuffraid.net/cowch/lstV2/commits/8d6ead3aa11aed95ffa3537fbe72cfa9bbceb380))
|
||||||
|
* **transferlots:** missed adding this ([846ac47](https://git.tuffraid.net/cowch/lstV2/commits/846ac479b1bf211a7891ae362525ea14580ff0cc))
|
||||||
|
|
||||||
## [2.25.0](https://git.tuffraid.net/cowch/lstV2/compare/v2.24.1...v2.25.0) (2025-08-21)
|
## [2.25.0](https://git.tuffraid.net/cowch/lstV2/compare/v2.24.1...v2.25.0) (2025-08-21)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
# THIS VERSION IS NO LONGER BEING UPDATED PLEASE GO TO THE NEW REPO LINK BELOW
|
||||||
|
|
||||||
|
[NEW LST REPO](https://git.tuffraid.net/cowch/lst)
|
||||||
|
|
||||||
# lstV2
|
# lstV2
|
||||||
|
|
||||||
Logistics Support Tool V2
|
Logistics Support Tool V2
|
||||||
|
|||||||
3
database/migrations/0072_round_black_knight.sql
Normal file
3
database/migrations/0072_round_black_knight.sql
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
ALTER TABLE "userRoles" DROP CONSTRAINT "userRoles_user_id_users_user_id_fk";
|
||||||
|
--> statement-breakpoint
|
||||||
|
ALTER TABLE "userRoles" ADD CONSTRAINT "userRoles_user_id_users_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("user_id") ON DELETE cascade ON UPDATE no action;
|
||||||
2252
database/migrations/meta/0072_snapshot.json
Normal file
2252
database/migrations/meta/0072_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -505,6 +505,13 @@
|
|||||||
"when": 1754768521841,
|
"when": 1754768521841,
|
||||||
"tag": "0071_fantastic_old_lace",
|
"tag": "0071_fantastic_old_lace",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 72,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1757167736042,
|
||||||
|
"tag": "0072_round_black_knight",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -27,7 +27,7 @@ export const userRoles = pgTable(
|
|||||||
{
|
{
|
||||||
user_id: uuid("user_id")
|
user_id: uuid("user_id")
|
||||||
.notNull()
|
.notNull()
|
||||||
.references(() => users.user_id),
|
.references(() => users.user_id, { onDelete: "cascade" }),
|
||||||
role_id: uuid("role_id")
|
role_id: uuid("role_id")
|
||||||
.notNull()
|
.notNull()
|
||||||
.references(() => roles.role_id),
|
.references(() => roles.role_id),
|
||||||
|
|||||||
@@ -6,7 +6,10 @@ import Barcode from "react-barcode";
|
|||||||
import { BarcodePDFExport } from "./BarcodeExport";
|
import { BarcodePDFExport } from "./BarcodeExport";
|
||||||
import { BulkBarcodePDFExport } from "./BulkExport";
|
import { BulkBarcodePDFExport } from "./BulkExport";
|
||||||
|
|
||||||
const commoncmd = [{ name: "Relocate", commandId: 33 }];
|
const commoncmd = [
|
||||||
|
{ name: "Relocate", commandId: 33 },
|
||||||
|
//-{ name: "Stock in", commandId: 22 },
|
||||||
|
];
|
||||||
export default function CommonCommands() {
|
export default function CommonCommands() {
|
||||||
const [checked, setChecked] = useState([]);
|
const [checked, setChecked] = useState([]);
|
||||||
|
|
||||||
|
|||||||
@@ -1,26 +1,30 @@
|
|||||||
import {LstCard} from "@/components/extendedUI/LstCard";
|
import { LstCard } from "@/components/extendedUI/LstCard";
|
||||||
import {Button} from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import {CardHeader} from "@/components/ui/card";
|
import { CardHeader } from "@/components/ui/card";
|
||||||
import {Input} from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import {Label} from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import {useSessionStore} from "@/lib/store/sessionStore";
|
|
||||||
import axios from "axios";
|
|
||||||
import {useState} from "react";
|
|
||||||
|
|
||||||
import {useForm} from "react-hook-form";
|
import axios from "axios";
|
||||||
import {toast} from "sonner";
|
import { useState } from "react";
|
||||||
|
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
|
||||||
export default function ConsumeMaterial() {
|
export default function ConsumeMaterial() {
|
||||||
const {register: register1, handleSubmit: handleSubmit1, reset} = useForm();
|
const {
|
||||||
|
register: register1,
|
||||||
|
handleSubmit: handleSubmit1,
|
||||||
|
reset,
|
||||||
|
} = useForm();
|
||||||
const [submitting, setSubmitting] = useState(false);
|
const [submitting, setSubmitting] = useState(false);
|
||||||
const {token} = useSessionStore();
|
|
||||||
|
|
||||||
const handleConsume = async (data: any) => {
|
const handleConsume = async (data: any) => {
|
||||||
setSubmitting(true);
|
setSubmitting(true);
|
||||||
try {
|
try {
|
||||||
const result = await axios.post(`/api/logistics/consume`, data, {
|
// const result = await axios.post(`/api/logistics/consume`, data, {
|
||||||
headers: {Authorization: `Bearer ${token}`},
|
// headers: {Authorization: `Bearer ${token}`},
|
||||||
});
|
// });
|
||||||
|
const result = await axios.post(`/api/logistics/consume`, data);
|
||||||
if (result.data.success) {
|
if (result.data.success) {
|
||||||
toast.success(result.data.message);
|
toast.success(result.data.message);
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
@@ -33,12 +37,14 @@ export default function ConsumeMaterial() {
|
|||||||
toast.error(result.data.message);
|
toast.error(result.data.message);
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
//console.log(error);
|
console.log(error);
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
if (error.status === 401) {
|
if (error.status === 401) {
|
||||||
toast.error("Unauthorized to do this task.");
|
toast.error("Unauthorized to do this task.");
|
||||||
} else {
|
} else {
|
||||||
toast.error("Unexpected error if this continues please constact an admin.");
|
toast.error(
|
||||||
|
"Unexpected error if this continues please constact an admin."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -53,7 +59,9 @@ export default function ConsumeMaterial() {
|
|||||||
<LstCard>
|
<LstCard>
|
||||||
<form onSubmit={handleSubmit1(handleConsume)}>
|
<form onSubmit={handleSubmit1(handleConsume)}>
|
||||||
<div className="m-2">
|
<div className="m-2">
|
||||||
<Label htmlFor="runningNr">Enter unit running number</Label>
|
<Label htmlFor="runningNr">
|
||||||
|
Enter unit running number
|
||||||
|
</Label>
|
||||||
<Input
|
<Input
|
||||||
className="mt-2"
|
className="mt-2"
|
||||||
//defaultValue="634"
|
//defaultValue="634"
|
||||||
@@ -62,7 +70,9 @@ export default function ConsumeMaterial() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="m-2">
|
<div className="m-2">
|
||||||
<Label htmlFor="lotNum">Enter lot number</Label>
|
<Label htmlFor="lotNum">
|
||||||
|
Enter lot number
|
||||||
|
</Label>
|
||||||
<Input
|
<Input
|
||||||
className="mt-2"
|
className="mt-2"
|
||||||
//defaultValue="634"
|
//defaultValue="634"
|
||||||
@@ -71,7 +81,12 @@ export default function ConsumeMaterial() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Button className="m-2" color="primary" type="submit" disabled={submitting}>
|
<Button
|
||||||
|
className="m-2"
|
||||||
|
color="primary"
|
||||||
|
type="submit"
|
||||||
|
disabled={submitting}
|
||||||
|
>
|
||||||
Consume materal
|
Consume materal
|
||||||
</Button>
|
</Button>
|
||||||
</form>
|
</form>
|
||||||
@@ -81,12 +96,19 @@ export default function ConsumeMaterial() {
|
|||||||
<LstCard>
|
<LstCard>
|
||||||
<div className="w-96 p-1">
|
<div className="w-96 p-1">
|
||||||
<ol>
|
<ol>
|
||||||
<li>1. Enter the running number of the material you would like to consume</li>
|
<li>
|
||||||
<li>2. Enter the lot number you will be consuming to</li>
|
1. Enter the running number of the
|
||||||
|
material you would like to consume
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
2. Enter the lot number you will be
|
||||||
|
consuming to
|
||||||
|
</li>
|
||||||
<li>3. Press consume material</li>
|
<li>3. Press consume material</li>
|
||||||
</ol>
|
</ol>
|
||||||
<p className="text-pretty w-96">
|
<p className="text-pretty w-96">
|
||||||
*This process is only for barcoded material, if it is set to auto consume you will
|
*This process is only for barcoded material,
|
||||||
|
if it is set to auto consume you will
|
||||||
encounter and error.
|
encounter and error.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -14,16 +14,19 @@ import {
|
|||||||
TooltipContent,
|
TooltipContent,
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
|
import { useSettingStore } from "@/lib/store/useSettings";
|
||||||
|
|
||||||
export default function TransferToNextLot() {
|
export default function TransferToNextLot() {
|
||||||
const [gaylordFilled, setGaylordFilled] = useState([0]);
|
const [gaylordFilled, setGaylordFilled] = useState([0]);
|
||||||
const [actualAmount, setActualAmount] = useState(0);
|
const [actualAmount, setActualAmount] = useState(0);
|
||||||
const [tab, setTab] = useState("esitmate");
|
const [tab, setTab] = useState("esitmate");
|
||||||
const [typeSwitch, setTypeSwitch] = useState(false);
|
const [typeSwitch, setTypeSwitch] = useState(false);
|
||||||
|
const { settings } = useSettingStore();
|
||||||
|
|
||||||
|
const server = settings.filter((n: any) => n.name === "dbServer");
|
||||||
const form = useAppForm({
|
const form = useAppForm({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
runnungNumber: "",
|
runningNumber: "",
|
||||||
lotNumber: "",
|
lotNumber: "",
|
||||||
originalAmount: "",
|
originalAmount: "",
|
||||||
amount: "",
|
amount: "",
|
||||||
@@ -33,7 +36,7 @@ export default function TransferToNextLot() {
|
|||||||
//toast.success("603468: qty: 361, was transfered to lot:24897");
|
//toast.success("603468: qty: 361, was transfered to lot:24897");
|
||||||
try {
|
try {
|
||||||
const res = await axios.post("/api/ocp/materiallottransfer", {
|
const res = await axios.post("/api/ocp/materiallottransfer", {
|
||||||
runnungNumber: Number(value.runnungNumber),
|
runningNumber: Number(value.runningNumber),
|
||||||
lotNumber: Number(value.lotNumber),
|
lotNumber: Number(value.lotNumber),
|
||||||
originalAmount: Number(value.originalAmount),
|
originalAmount: Number(value.originalAmount),
|
||||||
level: Number(
|
level: Number(
|
||||||
@@ -111,7 +114,7 @@ export default function TransferToNextLot() {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<p className="text-center">
|
<p className="text-center">
|
||||||
Almost full
|
Almost full - 95%
|
||||||
</p>
|
</p>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
@@ -129,7 +132,7 @@ export default function TransferToNextLot() {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<p className="text-center">
|
<p className="text-center">
|
||||||
About 75% full
|
About full - 75%
|
||||||
</p>
|
</p>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
@@ -145,7 +148,7 @@ export default function TransferToNextLot() {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<p className="text-center">
|
<p className="text-center">
|
||||||
Half full
|
Half full - 50%
|
||||||
</p>
|
</p>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
@@ -163,7 +166,7 @@ export default function TransferToNextLot() {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<p className="text-center">
|
<p className="text-center">
|
||||||
Almost empty
|
Almost empty - 25%
|
||||||
</p>
|
</p>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -215,10 +218,10 @@ export default function TransferToNextLot() {
|
|||||||
>
|
>
|
||||||
<div className="mt-3 p-2">
|
<div className="mt-3 p-2">
|
||||||
<form.AppField
|
<form.AppField
|
||||||
name="runnungNumber"
|
name="runningNumber"
|
||||||
children={(field) => (
|
children={(field) => (
|
||||||
<field.InputField
|
<field.InputField
|
||||||
label="Runnung Number"
|
label="Running Number"
|
||||||
inputType="number"
|
inputType="number"
|
||||||
required={true}
|
required={true}
|
||||||
/>
|
/>
|
||||||
@@ -398,6 +401,19 @@ export default function TransferToNextLot() {
|
|||||||
process, this process will just get
|
process, this process will just get
|
||||||
the gaylord to the next lot.
|
the gaylord to the next lot.
|
||||||
</p>
|
</p>
|
||||||
|
<br />
|
||||||
|
{settings.length > 0 && (
|
||||||
|
<p>
|
||||||
|
For more in depth instructions
|
||||||
|
please{" "}
|
||||||
|
<a
|
||||||
|
href={`https://${server[0].value}.alpla.net/lst/d/docs/ocp/ocp#tranfer-partial-estimated-quantity-to-the-next-lot`}
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
<em>CLICK HERE</em>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<div>
|
||||||
@@ -437,6 +453,19 @@ export default function TransferToNextLot() {
|
|||||||
process, this process will just get
|
process, this process will just get
|
||||||
the gaylord to the next lot.
|
the gaylord to the next lot.
|
||||||
</p>
|
</p>
|
||||||
|
<br />
|
||||||
|
{settings.length > 0 && (
|
||||||
|
<p>
|
||||||
|
For more in depth instructions
|
||||||
|
please{" "}
|
||||||
|
<a
|
||||||
|
href={`https://${server[0].value}.alpla.net/lst/d/docs/ocp/ocp#tranfer-partial-estimated-quantity-to-the-next-lot`}
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
<em>CLICK HERE</em>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</LstCard>
|
</LstCard>
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ export function DetachSilo(props: any) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
|
console.log(res.data.data);
|
||||||
toast.success(res.data.message);
|
toast.success(res.data.message);
|
||||||
|
|
||||||
refetch();
|
refetch();
|
||||||
|
|||||||
@@ -21,13 +21,28 @@ import { toast } from "sonner";
|
|||||||
import ChartData from "./ChartData";
|
import ChartData from "./ChartData";
|
||||||
import { AttachSilo } from "./AttachSilo";
|
import { AttachSilo } from "./AttachSilo";
|
||||||
import { DetachSilo } from "./DetachSilo";
|
import { DetachSilo } from "./DetachSilo";
|
||||||
|
import { useSessionStore } from "@/lib/store/sessionStore";
|
||||||
|
import { useModuleStore } from "@/lib/store/useModuleStore";
|
||||||
|
import { useGetUserRoles } from "@/lib/store/useGetRoles";
|
||||||
|
|
||||||
export default function SiloCard(data: any) {
|
export default function SiloCard(data: any) {
|
||||||
const token = localStorage.getItem("auth_token");
|
const token = localStorage.getItem("auth_token");
|
||||||
const [submitting, setSubmitting] = useState(false);
|
const [submitting, setSubmitting] = useState(false);
|
||||||
const { refetch } = useQuery(getStockSilo());
|
const { refetch } = useQuery(getStockSilo());
|
||||||
|
const { user } = useSessionStore();
|
||||||
|
const { userRoles } = useGetUserRoles();
|
||||||
|
const { modules } = useModuleStore();
|
||||||
const silo = data.silo;
|
const silo = data.silo;
|
||||||
|
|
||||||
|
// roles that can do the silo adjustments
|
||||||
|
const roles = ["systemAdmin", "technician", "admin", "manager"];
|
||||||
|
|
||||||
|
const module = modules.filter((n) => n.name === "logistics");
|
||||||
|
|
||||||
|
const accessRoles = userRoles.filter(
|
||||||
|
(n) => n.module_id === module[0]?.module_id
|
||||||
|
) as any;
|
||||||
|
|
||||||
const form = useForm({
|
const form = useForm({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
newLevel: "",
|
newLevel: "",
|
||||||
@@ -46,7 +61,7 @@ export default function SiloCard(data: any) {
|
|||||||
dataToSubmit,
|
dataToSubmit,
|
||||||
{ headers: { Authorization: `Bearer ${token}` } }
|
{ headers: { Authorization: `Bearer ${token}` } }
|
||||||
);
|
);
|
||||||
console.log(res.data);
|
//console.log(res.data);
|
||||||
|
|
||||||
if (res.data.success) {
|
if (res.data.success) {
|
||||||
toast.success(res.data.message);
|
toast.success(res.data.message);
|
||||||
@@ -70,6 +85,8 @@ export default function SiloCard(data: any) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(accessRoles);
|
||||||
return (
|
return (
|
||||||
<LstCard>
|
<LstCard>
|
||||||
<div className="flex flex-row">
|
<div className="flex flex-row">
|
||||||
@@ -109,82 +126,98 @@ export default function SiloCard(data: any) {
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<form
|
<>
|
||||||
onSubmit={(e) => {
|
{user &&
|
||||||
e.preventDefault();
|
roles.includes(accessRoles[0]?.role) && (
|
||||||
e.stopPropagation();
|
<form
|
||||||
}}
|
onSubmit={(e) => {
|
||||||
>
|
e.preventDefault();
|
||||||
<form.Field
|
e.stopPropagation();
|
||||||
name="newLevel"
|
}}
|
||||||
validators={{
|
>
|
||||||
// We can choose between form-wide and field-specific validators
|
<form.Field
|
||||||
onChange: ({ value }) =>
|
name="newLevel"
|
||||||
value.length > 1
|
validators={{
|
||||||
? undefined
|
// We can choose between form-wide and field-specific validators
|
||||||
: "You must enter a value greate than 1",
|
onChange: ({ value }) =>
|
||||||
}}
|
value.length > 1
|
||||||
children={(field) => {
|
? undefined
|
||||||
return (
|
: "You must enter a value greate than 1",
|
||||||
<div className="m-2 min-w-48 max-w-96 p-2">
|
}}
|
||||||
<div className="flex flex-row">
|
children={(field) => {
|
||||||
<Label htmlFor="newLevel">
|
return (
|
||||||
New level
|
<div className="m-2 min-w-48 max-w-96 p-2">
|
||||||
</Label>
|
<div className="flex flex-row">
|
||||||
<div>
|
<Label htmlFor="newLevel">
|
||||||
<Disclaimer />
|
New level
|
||||||
</div>
|
</Label>
|
||||||
</div>
|
<div>
|
||||||
<div className="flex flex-row">
|
<Disclaimer />
|
||||||
<Input
|
</div>
|
||||||
name={field.name}
|
</div>
|
||||||
value={
|
<div className="flex flex-row">
|
||||||
field.state.value
|
<Input
|
||||||
}
|
name={
|
||||||
onBlur={
|
field.name
|
||||||
field.handleBlur
|
}
|
||||||
}
|
value={
|
||||||
type="decimal"
|
field
|
||||||
onChange={(e) =>
|
.state
|
||||||
field.handleChange(
|
.value
|
||||||
e.target.value
|
}
|
||||||
)
|
onBlur={
|
||||||
}
|
field.handleBlur
|
||||||
/>
|
}
|
||||||
<Button
|
type="decimal"
|
||||||
className="ml-1"
|
onChange={(
|
||||||
variant="outline"
|
e
|
||||||
type="submit"
|
) =>
|
||||||
onClick={
|
field.handleChange(
|
||||||
form.handleSubmit
|
e
|
||||||
}
|
.target
|
||||||
disabled={submitting}
|
.value
|
||||||
>
|
)
|
||||||
{submitting ? (
|
}
|
||||||
<span className="w-24">
|
/>
|
||||||
Submitting...
|
<Button
|
||||||
</span>
|
className="ml-1"
|
||||||
) : (
|
variant="outline"
|
||||||
<span className="w-24">
|
type="submit"
|
||||||
Submit
|
onClick={
|
||||||
</span>
|
form.handleSubmit
|
||||||
)}
|
}
|
||||||
</Button>
|
disabled={
|
||||||
</div>
|
submitting
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{submitting ? (
|
||||||
|
<span className="w-24">
|
||||||
|
Submitting...
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<span className="w-24">
|
||||||
|
Submit
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
{field.state.meta.errors
|
{field.state.meta
|
||||||
.length ? (
|
.errors
|
||||||
<em>
|
.length ? (
|
||||||
{field.state.meta.errors.join(
|
<em>
|
||||||
","
|
{field.state.meta.errors.join(
|
||||||
)}
|
","
|
||||||
</em>
|
)}
|
||||||
) : null}
|
</em>
|
||||||
</div>
|
) : null}
|
||||||
);
|
</div>
|
||||||
}}
|
);
|
||||||
/>
|
}}
|
||||||
</form>
|
/>
|
||||||
|
</form>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</LstCard>
|
</LstCard>
|
||||||
|
|||||||
@@ -243,7 +243,8 @@ export default function ManualPrintForm() {
|
|||||||
<Textarea
|
<Textarea
|
||||||
//label="Comments"
|
//label="Comments"
|
||||||
placeholder="add more info as needed."
|
placeholder="add more info as needed."
|
||||||
{...register("additionalComments")}
|
{...(register("additionalComments"),
|
||||||
|
{ required: true, minLength: 10 })}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,10 @@ function RouteComponent() {
|
|||||||
<TransferToNextLot />
|
<TransferToNextLot />
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<TransferToNextLot />
|
<>
|
||||||
|
<ConsumeMaterial />
|
||||||
|
<TransferToNextLot />
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import { useLogout } from "@/hooks/useLogout";
|
|||||||
import ExportInventoryData from "@/components/logistics/warehouse/ExportInventoryData";
|
import ExportInventoryData from "@/components/logistics/warehouse/ExportInventoryData";
|
||||||
import { AddCards } from "@/components/dashboard/AddCards";
|
import { AddCards } from "@/components/dashboard/AddCards";
|
||||||
import DMButtons from "@/components/logistics/dm/DMButtons";
|
import DMButtons from "@/components/logistics/dm/DMButtons";
|
||||||
|
import { useSettingStore } from "@/lib/store/useSettings";
|
||||||
//import { AddCards } from "@/components/dashboard/AddCards";
|
//import { AddCards } from "@/components/dashboard/AddCards";
|
||||||
|
|
||||||
// same as the layout
|
// same as the layout
|
||||||
@@ -38,6 +39,9 @@ export const Route = createRootRoute({
|
|||||||
const { user } = useSessionStore();
|
const { user } = useSessionStore();
|
||||||
const logout = useLogout();
|
const logout = useLogout();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
const { settings } = useSettingStore();
|
||||||
|
|
||||||
|
const server = settings.filter((n: any) => n.name === "dbServer");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="overflow-hidden">
|
<div className="overflow-hidden">
|
||||||
@@ -61,6 +65,17 @@ export const Route = createRootRoute({
|
|||||||
<div className="m-1">
|
<div className="m-1">
|
||||||
<ModeToggle />
|
<ModeToggle />
|
||||||
</div>
|
</div>
|
||||||
|
<div className="mr-1 ml-1">
|
||||||
|
{settings.length > 0 && (
|
||||||
|
<a
|
||||||
|
href={`https://${server[0].value}.alpla.net/lst/d`}
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
LST - Docs
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
{session ? (
|
{session ? (
|
||||||
<div className="m-1">
|
<div className="m-1">
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
|
|||||||
@@ -33,13 +33,12 @@ function RouteComponent() {
|
|||||||
<span className="font-bold">
|
<span className="font-bold">
|
||||||
Authentication Notice:
|
Authentication Notice:
|
||||||
</span>
|
</span>
|
||||||
To interact with the Alpla prod through this
|
<span>
|
||||||
application, you must use your{" "}
|
The username, email, and password are
|
||||||
<span className="font-semibold">
|
only for LST you <em>DO NOT</em>Need to
|
||||||
Windows login credentials
|
use Windows username if you do not wish
|
||||||
|
to.
|
||||||
</span>
|
</span>
|
||||||
. These credentials are used solely for
|
|
||||||
authentication purposes.
|
|
||||||
</li>
|
</li>
|
||||||
{/* <li>
|
{/* <li>
|
||||||
<span className="font-bold">
|
<span className="font-bold">
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "lstv2",
|
"name": "lstv2",
|
||||||
"version": "2.25.0",
|
"version": "2.27.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "lstv2",
|
"name": "lstv2",
|
||||||
"version": "2.25.0",
|
"version": "2.27.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@dotenvx/dotenvx": "^1.45.1",
|
"@dotenvx/dotenvx": "^1.45.1",
|
||||||
"@hono/node-server": "^1.14.4",
|
"@hono/node-server": "^1.14.4",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "lstv2",
|
"name": "lstv2",
|
||||||
"version": "2.25.0",
|
"version": "2.27.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "concurrently -n \"server,frontend\" -c \"#007755,#2f6da3\" \"npm run dev:server\" \"cd frontend && npm run dev\"",
|
"dev": "concurrently -n \"server,frontend\" -c \"#007755,#2f6da3\" \"npm run dev:server\" \"cd frontend && npm run dev\"",
|
||||||
@@ -21,8 +21,8 @@
|
|||||||
"db:dev": "npm run build && npm run db:generate && npm run db:migrate",
|
"db:dev": "npm run build && npm run db:generate && npm run db:migrate",
|
||||||
"deploy": "standard-version --conventional-commits && npm run build",
|
"deploy": "standard-version --conventional-commits && npm run build",
|
||||||
"zipServer": "dotenvx run -f .env -- tsx server/scripts/zipUpBuild.ts \"C:\\Users\\matthes01\\Documents\\lstv2\"",
|
"zipServer": "dotenvx run -f .env -- tsx server/scripts/zipUpBuild.ts \"C:\\Users\\matthes01\\Documents\\lstv2\"",
|
||||||
"v1Build": "cd C:\\Users\\matthes01\\Documents\\logisticsSupportTool && npm run oldBuilder",
|
"newBuild": "npm run build:server && npm run build:frontend && npm run zipServer && npm run copyToNew",
|
||||||
"scriptBuild": "powershell -ExecutionPolicy Bypass -File server/scripts/build.ps1 -dir \"C:\\Users\\matthes01\\Documents\\lstv2\"",
|
"copyToNew": "powershell -ExecutionPolicy Bypass -File server/scripts/copyToLst.ps1 -dir \"C:\\Users\\matthes01\\Documents\\lstv2\"",
|
||||||
"removeOld": "rimraf dist && rimraf frontend/dist",
|
"removeOld": "rimraf dist && rimraf frontend/dist",
|
||||||
"prodBuild": "npm run v1Build && npm run build && npm run zipServer && npm run dev",
|
"prodBuild": "npm run v1Build && npm run build && npm run zipServer && npm run dev",
|
||||||
"commit": "cz",
|
"commit": "cz",
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"admConfig": {
|
"admConfig": {
|
||||||
"build": 575,
|
"build": 661,
|
||||||
"oldBuild": "backend-0.1.3.zip"
|
"oldBuild": "backend-0.1.3.zip"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
61
server/scripts/copyToLst.ps1
Normal file
61
server/scripts/copyToLst.ps1
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
param(
|
||||||
|
[string]$IncludesFile = ".includes",
|
||||||
|
[string]$Destination = "C:\Users\matthes01\Documents\lst\lstV2",
|
||||||
|
[string]$BaseDir = "C:\Users\matthes01\Documents\lst"
|
||||||
|
)
|
||||||
|
|
||||||
|
# .\copy-includes.ps1 will run with defaults
|
||||||
|
# .\copy-includes.ps1 -IncludesFile ".\mylist.txt" -Destination "D:\build\lstV2" will override defaults
|
||||||
|
|
||||||
|
if (-Not (Test-Path $IncludesFile)) {
|
||||||
|
Write-Error "Includes file not found: $IncludesFile"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ensure destination exists
|
||||||
|
if (!(Test-Path -Path $Destination)) {
|
||||||
|
New-Item -ItemType Directory -Path $Destination | Out-Null
|
||||||
|
Write-Host "Folder created: $Destination"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Empty the destination folder
|
||||||
|
Get-ChildItem -Path $Destination -Recurse -Force | Remove-Item -Recurse -Force
|
||||||
|
|
||||||
|
# If BaseDir wasn’t explicitly passed in, use IncludesFile directory
|
||||||
|
if (-not $PSBoundParameters.ContainsKey('BaseDir')) {
|
||||||
|
$BaseDir = Split-Path -Parent (Resolve-Path $IncludesFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Read includes list (ignore blank lines & comments)
|
||||||
|
$items = Get-Content $IncludesFile |
|
||||||
|
ForEach-Object { $_.Trim() } |
|
||||||
|
Where-Object { $_ -and -not $_.StartsWith("#") }
|
||||||
|
|
||||||
|
foreach ($item in $items) {
|
||||||
|
if ([System.IO.Path]::IsPathRooted($item)) {
|
||||||
|
# Absolute path (rare case)
|
||||||
|
$sourcePath = $item
|
||||||
|
$relative = Split-Path $item -Leaf # just take folder/file name
|
||||||
|
} else {
|
||||||
|
# Relative to BaseDir
|
||||||
|
$sourcePath = Join-Path $BaseDir $item
|
||||||
|
$relative = $item # keep full relative path e.g. "frontend\dist"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-Not (Test-Path $sourcePath)) {
|
||||||
|
Write-Warning "Skipping missing path: $sourcePath"
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
# Destination path should preserve the relative structure
|
||||||
|
$targetPath = Join-Path $Destination $relative
|
||||||
|
|
||||||
|
# Ensure the parent folder exists
|
||||||
|
$targetDir = Split-Path $targetPath -Parent
|
||||||
|
if (-not (Test-Path $targetDir)) {
|
||||||
|
New-Item -ItemType Directory -Path $targetDir -Force | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Copying $sourcePath -> $targetPath" -ForegroundColor Cyan
|
||||||
|
Copy-Item -Path $sourcePath -Destination $targetPath -Recurse -Force
|
||||||
|
}
|
||||||
@@ -37,7 +37,7 @@ export const registerUser = async (
|
|||||||
.values({ username, email, password })
|
.values({ username, email, password })
|
||||||
.returning({ user: users.username, email: users.email });
|
.returning({ user: users.username, email: users.email });
|
||||||
|
|
||||||
if (usercount.length <= 1) {
|
if (usercount.length === 0) {
|
||||||
createLog(
|
createLog(
|
||||||
"info",
|
"info",
|
||||||
"auth",
|
"auth",
|
||||||
|
|||||||
63
server/services/dataMart/controller/psiGetInventory.ts
Normal file
63
server/services/dataMart/controller/psiGetInventory.ts
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import { and, between, inArray, sql } from "drizzle-orm";
|
||||||
|
import { db } from "../../../../database/dbclient.js";
|
||||||
|
import { invHistoricalData } from "../../../../database/schema/historicalINV.js";
|
||||||
|
import { tryCatch } from "../../../globalUtils/tryCatch.js";
|
||||||
|
import { createLog } from "../../logger/logger.js";
|
||||||
|
|
||||||
|
// type ArticleData = {
|
||||||
|
// id: string
|
||||||
|
// }
|
||||||
|
export const psiGetInventory = async (
|
||||||
|
avs: string,
|
||||||
|
startDate: string,
|
||||||
|
endDate: string
|
||||||
|
) => {
|
||||||
|
let articles: any = [];
|
||||||
|
|
||||||
|
if (!avs) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: `Missing av's please send at least one over`,
|
||||||
|
data: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const ids = avs.split(",").map((id) => id.trim());
|
||||||
|
|
||||||
|
const { data, error } = (await tryCatch(
|
||||||
|
db
|
||||||
|
.select()
|
||||||
|
.from(invHistoricalData)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
inArray(invHistoricalData.article, ids),
|
||||||
|
between(invHistoricalData.histDate, startDate, endDate)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
//.limit(100)
|
||||||
|
)) as any;
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
createLog(
|
||||||
|
"error",
|
||||||
|
"datamart",
|
||||||
|
"datamart",
|
||||||
|
`There was an error getting the planning info: ${JSON.stringify(
|
||||||
|
error
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
messsage: `There was an error getting the planning info`,
|
||||||
|
data: error,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
articles = data;
|
||||||
|
console.log(articles.length);
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: "PSI planning Data",
|
||||||
|
data: articles,
|
||||||
|
};
|
||||||
|
};
|
||||||
63
server/services/dataMart/controller/psiGetPlanningData.ts
Normal file
63
server/services/dataMart/controller/psiGetPlanningData.ts
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import { tryCatch } from "../../../globalUtils/tryCatch.js";
|
||||||
|
import { createLog } from "../../logger/logger.js";
|
||||||
|
import { query } from "../../sqlServer/prodSqlServer.js";
|
||||||
|
import { planningNumbersByAVDate } from "../../sqlServer/querys/psiReport/planningNumbersByAv.js";
|
||||||
|
|
||||||
|
// type ArticleData = {
|
||||||
|
// id: string
|
||||||
|
// }
|
||||||
|
export const psiGetPlanningData = async (
|
||||||
|
avs: string,
|
||||||
|
startDate: string,
|
||||||
|
endDate: string
|
||||||
|
) => {
|
||||||
|
let articles: any = [];
|
||||||
|
|
||||||
|
if (!avs) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: `Missing av's please send at least one over`,
|
||||||
|
data: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data, error } = (await tryCatch(
|
||||||
|
query(
|
||||||
|
planningNumbersByAVDate
|
||||||
|
.replace("[articles]", avs)
|
||||||
|
.replace("[startDate]", startDate)
|
||||||
|
.replace("[endDate]", endDate),
|
||||||
|
"PSI planning info"
|
||||||
|
)
|
||||||
|
)) as any;
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
createLog(
|
||||||
|
"error",
|
||||||
|
"datamart",
|
||||||
|
"datamart",
|
||||||
|
`There was an error getting the planning info: ${JSON.stringify(
|
||||||
|
error
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
messsage: `There was an error getting the planning info`,
|
||||||
|
data: error,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
articles = data.data;
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: "PSI planning Data",
|
||||||
|
data: articles.map((n: any) => {
|
||||||
|
if (n.PalDay) {
|
||||||
|
return { ...n, PalDay: n.PalDay.toFixed(2) };
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
};
|
||||||
63
server/services/dataMart/controller/psiGetProductionData.ts
Normal file
63
server/services/dataMart/controller/psiGetProductionData.ts
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import { tryCatch } from "../../../globalUtils/tryCatch.js";
|
||||||
|
import { createLog } from "../../logger/logger.js";
|
||||||
|
import { query } from "../../sqlServer/prodSqlServer.js";
|
||||||
|
import { productionNumbers } from "../../sqlServer/querys/psiReport/prodcuctionNumbers.js";
|
||||||
|
|
||||||
|
// type ArticleData = {
|
||||||
|
// id: string
|
||||||
|
// }
|
||||||
|
export const psiGetProductionData = async (
|
||||||
|
avs: string,
|
||||||
|
startDate: string,
|
||||||
|
endDate: string
|
||||||
|
) => {
|
||||||
|
let articles: any = [];
|
||||||
|
|
||||||
|
if (!avs) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: `Missing av's please send at least one over`,
|
||||||
|
data: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data, error } = (await tryCatch(
|
||||||
|
query(
|
||||||
|
productionNumbers
|
||||||
|
.replace("[articles]", avs)
|
||||||
|
.replace("[startDate]", startDate)
|
||||||
|
.replace("[endDate]", endDate),
|
||||||
|
"PSI production info"
|
||||||
|
)
|
||||||
|
)) as any;
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
createLog(
|
||||||
|
"error",
|
||||||
|
"datamart",
|
||||||
|
"datamart",
|
||||||
|
`There was an error getting the planning info: ${JSON.stringify(
|
||||||
|
error
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
messsage: `There was an error getting the planning info`,
|
||||||
|
data: error,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
articles = data.data;
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: "PSI planning Data",
|
||||||
|
data: articles.map((n: any) => {
|
||||||
|
if (n.PalDay) {
|
||||||
|
return { ...n, PalDay: n.PalDay.toFixed(2) };
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -10,6 +10,9 @@ import addressCorrections from "./route/getCityStateData.js";
|
|||||||
import fifoIndex from "./route/getFifoIndex.js";
|
import fifoIndex from "./route/getFifoIndex.js";
|
||||||
import financeAudit from "./route/getFinanceAudit.js";
|
import financeAudit from "./route/getFinanceAudit.js";
|
||||||
import psiArticleData from "./route/getPsiArticleData.js";
|
import psiArticleData from "./route/getPsiArticleData.js";
|
||||||
|
import psiPlanningData from "./route/getPsiPlanningData.js";
|
||||||
|
import psiProductionData from "./route/getPsiProductionData.js";
|
||||||
|
import psiInventory from "./route/getPsiinventory.js";
|
||||||
|
|
||||||
const app = new OpenAPIHono();
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
@@ -25,6 +28,9 @@ const routes = [
|
|||||||
fifoIndex,
|
fifoIndex,
|
||||||
financeAudit,
|
financeAudit,
|
||||||
psiArticleData,
|
psiArticleData,
|
||||||
|
psiPlanningData,
|
||||||
|
psiProductionData,
|
||||||
|
psiInventory,
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
const appRoutes = routes.forEach((route) => {
|
const appRoutes = routes.forEach((route) => {
|
||||||
|
|||||||
64
server/services/dataMart/route/getPsiPlanningData.ts
Normal file
64
server/services/dataMart/route/getPsiPlanningData.ts
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||||
|
import { responses } from "../../../globalUtils/routeDefs/responses.js";
|
||||||
|
import { tryCatch } from "../../../globalUtils/tryCatch.js";
|
||||||
|
import { apiHit } from "../../../globalUtils/apiHits.js";
|
||||||
|
import { psiGetPlanningData } from "../controller/psiGetPlanningData.js";
|
||||||
|
|
||||||
|
const app = new OpenAPIHono({ strict: false });
|
||||||
|
const Body = z.object({
|
||||||
|
includeRunnningNumbers: z.string().openapi({ example: "x" }),
|
||||||
|
});
|
||||||
|
app.openapi(
|
||||||
|
createRoute({
|
||||||
|
tags: ["dataMart"],
|
||||||
|
summary: "Returns the psiarticleData.",
|
||||||
|
method: "get",
|
||||||
|
path: "/psiplanningdata",
|
||||||
|
request: {
|
||||||
|
body: {
|
||||||
|
content: {
|
||||||
|
"application/json": { schema: Body },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
responses: responses(),
|
||||||
|
}),
|
||||||
|
async (c) => {
|
||||||
|
const q: any = c.req.queries();
|
||||||
|
|
||||||
|
// make sure we have a vaid user being accessed thats really logged in
|
||||||
|
apiHit(c, { endpoint: "/psiplanningdata" });
|
||||||
|
//console.log(articles["avs"][0]);
|
||||||
|
const { data, error } = await tryCatch(
|
||||||
|
psiGetPlanningData(
|
||||||
|
q["avs"] ? q["avs"][0] : null,
|
||||||
|
q["startDate"] ? q["startDate"][0] : null,
|
||||||
|
q["endDate"] ? q["endDate"][0] : null
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.log(error);
|
||||||
|
return c.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message: "There was an error getting the planning.",
|
||||||
|
data: error,
|
||||||
|
},
|
||||||
|
400
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//console.log(data);
|
||||||
|
|
||||||
|
return c.json(
|
||||||
|
{
|
||||||
|
success: data.success,
|
||||||
|
message: data.message,
|
||||||
|
data: data.data,
|
||||||
|
},
|
||||||
|
data.success ? 200 : 400
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
export default app;
|
||||||
64
server/services/dataMart/route/getPsiProductionData.ts
Normal file
64
server/services/dataMart/route/getPsiProductionData.ts
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||||
|
import { responses } from "../../../globalUtils/routeDefs/responses.js";
|
||||||
|
import { tryCatch } from "../../../globalUtils/tryCatch.js";
|
||||||
|
import { apiHit } from "../../../globalUtils/apiHits.js";
|
||||||
|
import { psiGetProductionData } from "../controller/psiGetProductionData.js";
|
||||||
|
|
||||||
|
const app = new OpenAPIHono({ strict: false });
|
||||||
|
const Body = z.object({
|
||||||
|
includeRunnningNumbers: z.string().openapi({ example: "x" }),
|
||||||
|
});
|
||||||
|
app.openapi(
|
||||||
|
createRoute({
|
||||||
|
tags: ["dataMart"],
|
||||||
|
summary: "Returns the psiproductiondata.",
|
||||||
|
method: "get",
|
||||||
|
path: "/psiproductiondata",
|
||||||
|
request: {
|
||||||
|
body: {
|
||||||
|
content: {
|
||||||
|
"application/json": { schema: Body },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
responses: responses(),
|
||||||
|
}),
|
||||||
|
async (c) => {
|
||||||
|
const q: any = c.req.queries();
|
||||||
|
|
||||||
|
// make sure we have a vaid user being accessed thats really logged in
|
||||||
|
apiHit(c, { endpoint: "/psiproductiondata" });
|
||||||
|
//console.log(articles["avs"][0]);
|
||||||
|
const { data, error } = await tryCatch(
|
||||||
|
psiGetProductionData(
|
||||||
|
q["avs"] ? q["avs"][0] : null,
|
||||||
|
q["startDate"] ? q["startDate"][0] : null,
|
||||||
|
q["endDate"] ? q["endDate"][0] : null
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.log(error);
|
||||||
|
return c.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message: "There was an error getting the production.",
|
||||||
|
data: error,
|
||||||
|
},
|
||||||
|
400
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//console.log(data);
|
||||||
|
|
||||||
|
return c.json(
|
||||||
|
{
|
||||||
|
success: data.success,
|
||||||
|
message: data.message,
|
||||||
|
data: data.data,
|
||||||
|
},
|
||||||
|
data.success ? 200 : 400
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
export default app;
|
||||||
64
server/services/dataMart/route/getPsiinventory.ts
Normal file
64
server/services/dataMart/route/getPsiinventory.ts
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||||
|
import { responses } from "../../../globalUtils/routeDefs/responses.js";
|
||||||
|
import { tryCatch } from "../../../globalUtils/tryCatch.js";
|
||||||
|
import { apiHit } from "../../../globalUtils/apiHits.js";
|
||||||
|
import { psiGetInventory } from "../controller/psiGetInventory.js";
|
||||||
|
|
||||||
|
const app = new OpenAPIHono({ strict: false });
|
||||||
|
const Body = z.object({
|
||||||
|
includeRunnningNumbers: z.string().openapi({ example: "x" }),
|
||||||
|
});
|
||||||
|
app.openapi(
|
||||||
|
createRoute({
|
||||||
|
tags: ["dataMart"],
|
||||||
|
summary: "Returns the getPsiinventory.",
|
||||||
|
method: "get",
|
||||||
|
path: "/getpsiinventory",
|
||||||
|
request: {
|
||||||
|
body: {
|
||||||
|
content: {
|
||||||
|
"application/json": { schema: Body },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
responses: responses(),
|
||||||
|
}),
|
||||||
|
async (c) => {
|
||||||
|
const q: any = c.req.queries();
|
||||||
|
|
||||||
|
// make sure we have a vaid user being accessed thats really logged in
|
||||||
|
apiHit(c, { endpoint: "/getpsiinventory" });
|
||||||
|
//console.log(articles["avs"][0]);
|
||||||
|
const { data, error } = await tryCatch(
|
||||||
|
psiGetInventory(
|
||||||
|
q["avs"] ? q["avs"][0] : null,
|
||||||
|
q["startDate"] ? q["startDate"][0] : null,
|
||||||
|
q["endDate"] ? q["endDate"][0] : null
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.log(error);
|
||||||
|
return c.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message: "There was an error getting the production.",
|
||||||
|
data: error,
|
||||||
|
},
|
||||||
|
400
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//console.log(data);
|
||||||
|
|
||||||
|
return c.json(
|
||||||
|
{
|
||||||
|
success: data.success,
|
||||||
|
message: data.message,
|
||||||
|
data: data.data,
|
||||||
|
},
|
||||||
|
data.success ? 200 : 400
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
export default app;
|
||||||
32
server/services/eom/controller/getHistoricalInvByDate.ts
Normal file
32
server/services/eom/controller/getHistoricalInvByDate.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import { eq } from "drizzle-orm";
|
||||||
|
import { db } from "../../../../database/dbclient.js";
|
||||||
|
import { invHistoricalData } from "../../../../database/schema/historicalINV.js";
|
||||||
|
import { tryCatch } from "../../../globalUtils/tryCatch.js";
|
||||||
|
import { format } from "date-fns";
|
||||||
|
|
||||||
|
export const historicalInvByDate = async (date: string) => {
|
||||||
|
const histDate = new Date(date);
|
||||||
|
|
||||||
|
const { data, error } = (await tryCatch(
|
||||||
|
db
|
||||||
|
.select()
|
||||||
|
.from(invHistoricalData)
|
||||||
|
.where(
|
||||||
|
eq(invHistoricalData.histDate, format(histDate, "yyyy-MM-dd"))
|
||||||
|
)
|
||||||
|
)) as any;
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "There was an error with getting the inventory",
|
||||||
|
data: error,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: `Historical inventory for ${date}`,
|
||||||
|
data: data,
|
||||||
|
};
|
||||||
|
};
|
||||||
24
server/services/eom/controller/getLastPurchasesPrice.ts
Normal file
24
server/services/eom/controller/getLastPurchasesPrice.ts
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import { tryCatch } from "../../../globalUtils/tryCatch.js";
|
||||||
|
import { format } from "date-fns";
|
||||||
|
import { query } from "../../sqlServer/prodSqlServer.js";
|
||||||
|
import { lastPurchasePrice } from "../../sqlServer/querys/eom/lstPurchasePrice.js";
|
||||||
|
|
||||||
|
export const lastPurchase = async () => {
|
||||||
|
const { data, error } = (await tryCatch(
|
||||||
|
query(lastPurchasePrice, "Last purchase price")
|
||||||
|
)) as any;
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "Error getting the last purchase price",
|
||||||
|
data: error,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: `Last purchase price for all av in the last 5 years`,
|
||||||
|
data: data.data,
|
||||||
|
};
|
||||||
|
};
|
||||||
23
server/services/eom/controller/getLastestSalesPrice.ts
Normal file
23
server/services/eom/controller/getLastestSalesPrice.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { tryCatch } from "../../../globalUtils/tryCatch.js";
|
||||||
|
import { query } from "../../sqlServer/prodSqlServer.js";
|
||||||
|
import { lastSalesPriceCheck } from "../../sqlServer/querys/eom/lastSalesprice.js";
|
||||||
|
|
||||||
|
export const lastSales = async (date: string) => {
|
||||||
|
const { data, error } = (await tryCatch(
|
||||||
|
query(lastSalesPriceCheck.replace("[date]", date), "Last sales price")
|
||||||
|
)) as any;
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "Error getting the last sales price",
|
||||||
|
data: error,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: `Last sales price for all av in the last 5 years`,
|
||||||
|
data: data.data,
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -10,7 +10,10 @@ import { tryCatch } from "../../globalUtils/tryCatch.js";
|
|||||||
import { query } from "../sqlServer/prodSqlServer.js";
|
import { query } from "../sqlServer/prodSqlServer.js";
|
||||||
import { shiftChange } from "../sqlServer/querys/misc/shiftChange.js";
|
import { shiftChange } from "../sqlServer/querys/misc/shiftChange.js";
|
||||||
import { createLog } from "../logger/logger.js";
|
import { createLog } from "../logger/logger.js";
|
||||||
const routes = [stats, history] as const;
|
import lastPurch from "./route/getLastPurchPrice.js";
|
||||||
|
import lastSales from "./route/getLastSalesPrice.js";
|
||||||
|
|
||||||
|
const routes = [stats, history, lastPurch, lastSales] as const;
|
||||||
|
|
||||||
const appRoutes = routes.forEach((route) => {
|
const appRoutes = routes.forEach((route) => {
|
||||||
app.route("/eom", route);
|
app.route("/eom", route);
|
||||||
@@ -34,9 +37,9 @@ setTimeout(async () => {
|
|||||||
const shiftTimeSplit = shift?.data[0]?.shiftChange.split(":");
|
const shiftTimeSplit = shift?.data[0]?.shiftChange.split(":");
|
||||||
|
|
||||||
const cronSetup = `${
|
const cronSetup = `${
|
||||||
shiftTimeSplit.length > 0 ? `${parseInt(shiftTimeSplit[1])}` : "0"
|
shiftTimeSplit?.length > 0 ? `${parseInt(shiftTimeSplit[1])}` : "0"
|
||||||
} ${
|
} ${
|
||||||
shiftTimeSplit.length > 0 ? `${parseInt(shiftTimeSplit[0])}` : "7"
|
shiftTimeSplit?.length > 0 ? `${parseInt(shiftTimeSplit[0])}` : "7"
|
||||||
} * * *`;
|
} * * *`;
|
||||||
|
|
||||||
//console.log(cronSetup);
|
//console.log(cronSetup);
|
||||||
|
|||||||
41
server/services/eom/route/getLastPurchPrice.ts
Normal file
41
server/services/eom/route/getLastPurchPrice.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||||
|
import { apiHit } from "../../../globalUtils/apiHits.js";
|
||||||
|
import { responses } from "../../../globalUtils/routeDefs/responses.js";
|
||||||
|
|
||||||
|
import { lastPurchase } from "../controller/getLastPurchasesPrice.js";
|
||||||
|
|
||||||
|
const app = new OpenAPIHono({ strict: false });
|
||||||
|
|
||||||
|
app.openapi(
|
||||||
|
createRoute({
|
||||||
|
tags: ["eom"],
|
||||||
|
summary: "Returns last sales price.",
|
||||||
|
method: "get",
|
||||||
|
path: "/lastpurchprice",
|
||||||
|
responses: responses(),
|
||||||
|
}),
|
||||||
|
async (c) => {
|
||||||
|
//const body = await c.req.json();
|
||||||
|
// make sure we have a vaid user being accessed thats really logged in
|
||||||
|
|
||||||
|
apiHit(c, { endpoint: "/lastpurchprice" });
|
||||||
|
try {
|
||||||
|
const res = await lastPurchase();
|
||||||
|
|
||||||
|
return c.json(
|
||||||
|
{ success: res.success, message: res.message, data: res.data },
|
||||||
|
200
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
return c.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message: "There was an error posting the eom stat.",
|
||||||
|
data: error,
|
||||||
|
},
|
||||||
|
400
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
export default app;
|
||||||
43
server/services/eom/route/getLastSalesPrice.ts
Normal file
43
server/services/eom/route/getLastSalesPrice.ts
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||||
|
import { apiHit } from "../../../globalUtils/apiHits.js";
|
||||||
|
import { responses } from "../../../globalUtils/routeDefs/responses.js";
|
||||||
|
|
||||||
|
import { lastPurchase } from "../controller/getLastPurchasesPrice.js";
|
||||||
|
import { lastSales } from "../controller/getLastestSalesPrice.js";
|
||||||
|
|
||||||
|
const app = new OpenAPIHono({ strict: false });
|
||||||
|
|
||||||
|
app.openapi(
|
||||||
|
createRoute({
|
||||||
|
tags: ["eom"],
|
||||||
|
summary: "Returns last sales price.",
|
||||||
|
method: "get",
|
||||||
|
path: "/lastsalesprice",
|
||||||
|
responses: responses(),
|
||||||
|
}),
|
||||||
|
async (c) => {
|
||||||
|
//const body = await c.req.json();
|
||||||
|
const month: string = c.req.query("month") ?? "";
|
||||||
|
// make sure we have a vaid user being accessed thats really logged in
|
||||||
|
|
||||||
|
apiHit(c, { endpoint: "/lastsalesprice" });
|
||||||
|
try {
|
||||||
|
const res = await lastSales(month);
|
||||||
|
|
||||||
|
return c.json(
|
||||||
|
{ success: res.success, message: res.message, data: res.data },
|
||||||
|
200
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
return c.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message: "There was an error posting the eom stat.",
|
||||||
|
data: error,
|
||||||
|
},
|
||||||
|
400
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
export default app;
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||||
import { apiHit } from "../../../globalUtils/apiHits.js";
|
import { apiHit } from "../../../globalUtils/apiHits.js";
|
||||||
import { responses } from "../../../globalUtils/routeDefs/responses.js";
|
import { responses } from "../../../globalUtils/routeDefs/responses.js";
|
||||||
|
import { historicalInvByDate } from "../controller/getHistoricalInvByDate.js";
|
||||||
|
|
||||||
const app = new OpenAPIHono({ strict: false });
|
const app = new OpenAPIHono({ strict: false });
|
||||||
const EomStat = z.object({
|
const EomStat = z.object({
|
||||||
@@ -12,20 +13,24 @@ const EomStat = z.object({
|
|||||||
app.openapi(
|
app.openapi(
|
||||||
createRoute({
|
createRoute({
|
||||||
tags: ["eom"],
|
tags: ["eom"],
|
||||||
summary: "Gets the correct eom history.",
|
summary: "Gets History Data by date.",
|
||||||
method: "post",
|
method: "get",
|
||||||
path: "/histinv",
|
path: "/histinv",
|
||||||
request: {
|
|
||||||
params: EomStat,
|
|
||||||
},
|
|
||||||
responses: responses(),
|
responses: responses(),
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) => {
|
||||||
//const body = await c.req.json();
|
//const body = await c.req.json();
|
||||||
// make sure we have a vaid user being accessed thats really logged in
|
// make sure we have a vaid user being accessed thats really logged in
|
||||||
|
const month: string = c.req.query("month") ?? "";
|
||||||
|
|
||||||
apiHit(c, { endpoint: "/histinv" });
|
apiHit(c, { endpoint: "/histinv" });
|
||||||
try {
|
try {
|
||||||
return c.json({ success: true, message: "", data: [] }, 200);
|
const res = await historicalInvByDate(month);
|
||||||
|
|
||||||
|
return c.json(
|
||||||
|
{ success: res.success, message: res.message, data: res.data },
|
||||||
|
200
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return c.json(
|
return c.json(
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { totalInvNoRn } from "../../sqlServer/querys/dataMart/totalINV.js";
|
|||||||
import { format } from "date-fns-tz";
|
import { format } from "date-fns-tz";
|
||||||
import { serverSettings } from "../../server/controller/settings/getSettings.js";
|
import { serverSettings } from "../../server/controller/settings/getSettings.js";
|
||||||
import { deleteHistory } from "./removeHistorical.js";
|
import { deleteHistory } from "./removeHistorical.js";
|
||||||
|
import { activeArticle } from "../../sqlServer/querys/dataMart/article.js";
|
||||||
|
|
||||||
export const historicalInvIMmport = async () => {
|
export const historicalInvIMmport = async () => {
|
||||||
const plantToken = serverSettings.filter((n) => n.name === "plantToken");
|
const plantToken = serverSettings.filter((n) => n.name === "plantToken");
|
||||||
@@ -52,6 +53,12 @@ export const historicalInvIMmport = async () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { data: articles, error: avError } = (await tryCatch(
|
||||||
|
query(activeArticle, "Get active articles")
|
||||||
|
)) as any;
|
||||||
|
|
||||||
|
const av = articles.data.length > 0 ? articles.data : ([] as any);
|
||||||
|
|
||||||
const importInv = inv.data ? inv.data : [];
|
const importInv = inv.data ? inv.data : [];
|
||||||
const eomImportData = importInv.map((i: any) => {
|
const eomImportData = importInv.map((i: any) => {
|
||||||
return {
|
return {
|
||||||
@@ -59,7 +66,13 @@ export const historicalInvIMmport = async () => {
|
|||||||
plantToken: plantToken[0].value,
|
plantToken: plantToken[0].value,
|
||||||
article: i.av,
|
article: i.av,
|
||||||
articleDescription: i.Alias,
|
articleDescription: i.Alias,
|
||||||
materialType: "",
|
materialType:
|
||||||
|
av.filter((a: any) => a.IdArtikelvarianten === i.av)
|
||||||
|
.length > 0
|
||||||
|
? av.filter(
|
||||||
|
(a: any) => a.IdArtikelvarianten === i.av
|
||||||
|
)[0]?.TypeOfMaterial
|
||||||
|
: "Item not defined",
|
||||||
total_QTY: i.Total_PalletQTY,
|
total_QTY: i.Total_PalletQTY,
|
||||||
avaliable_QTY: i.Avaliable_PalletQTY,
|
avaliable_QTY: i.Avaliable_PalletQTY,
|
||||||
coa_QTY: i.COA_QTY,
|
coa_QTY: i.COA_QTY,
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export const deleteHistory = async () => {
|
|||||||
.where(
|
.where(
|
||||||
lte(
|
lte(
|
||||||
invHistoricalData.histDate,
|
invHistoricalData.histDate,
|
||||||
sql`(NOW() - INTERVAL '45 day')::date`
|
sql`(NOW() - INTERVAL '365 day')::date`
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import { postForecast } from "../postForecast.js";
|
|||||||
import { query } from "../../../../../sqlServer/prodSqlServer.js";
|
import { query } from "../../../../../sqlServer/prodSqlServer.js";
|
||||||
import { activeArticle } from "../../../../../sqlServer/querys/dataMart/article.js";
|
import { activeArticle } from "../../../../../sqlServer/querys/dataMart/article.js";
|
||||||
import { addDays } from "date-fns";
|
import { addDays } from "date-fns";
|
||||||
|
import { sendEmail } from "../../../../../notifications/controller/sendMail.js";
|
||||||
|
import { createLog } from "../../../../../logger/logger.js";
|
||||||
|
|
||||||
let customerID = 4;
|
let customerID = 4;
|
||||||
export const lorealForecast = async (data: any, user: any) => {
|
export const lorealForecast = async (data: any, user: any) => {
|
||||||
@@ -111,6 +113,9 @@ export const lorealForecast = async (data: any, user: any) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (activeAV.length === 0) {
|
if (activeAV.length === 0) {
|
||||||
|
if (typeof forcast.customerArticleNo === "number") {
|
||||||
|
missingSku.push(forcast);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,6 +186,9 @@ export const lorealForecast = async (data: any, user: any) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (activeAV.length === 0) {
|
if (activeAV.length === 0) {
|
||||||
|
if (typeof forcast.customerArticleNo === "number") {
|
||||||
|
missingSku.push(forcast);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,6 +198,56 @@ export const lorealForecast = async (data: any, user: any) => {
|
|||||||
|
|
||||||
//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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}, {})
|
||||||
|
);
|
||||||
|
|
||||||
|
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",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// if the customerarticle number is not matching just ignore it
|
// if the customerarticle number is not matching just ignore it
|
||||||
const predefinedObject = {
|
const predefinedObject = {
|
||||||
receivingPlantId: plantToken[0].value,
|
receivingPlantId: plantToken[0].value,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ type Data = {
|
|||||||
runningNr: string;
|
runningNr: string;
|
||||||
lotNum: number;
|
lotNum: number;
|
||||||
};
|
};
|
||||||
export const consumeMaterial = async (data: Data, prod: any) => {
|
export const consumeMaterial = async (data: Data) => {
|
||||||
const { runningNr, lotNum } = data;
|
const { runningNr, lotNum } = data;
|
||||||
// replace the rn
|
// replace the rn
|
||||||
|
|
||||||
@@ -28,12 +28,7 @@ export const consumeMaterial = async (data: Data, prod: any) => {
|
|||||||
barcode = r?.data;
|
barcode = r?.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
createLog(
|
createLog("error", "", "logistics", `Error getting barcode: ${error}`);
|
||||||
"error",
|
|
||||||
prod.user.username,
|
|
||||||
"logistics",
|
|
||||||
`Error getting barcode: ${error}`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (barcode.length === 0) {
|
if (barcode.length === 0) {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ app.openapi(
|
|||||||
summary: "Consumes material based on its running number",
|
summary: "Consumes material based on its running number",
|
||||||
method: "post",
|
method: "post",
|
||||||
path: "/consume",
|
path: "/consume",
|
||||||
middleware: authMiddleware,
|
//middleware: authMiddleware,
|
||||||
description:
|
description:
|
||||||
"Provided a running number and lot number you can consume material.",
|
"Provided a running number and lot number you can consume material.",
|
||||||
responses: {
|
responses: {
|
||||||
@@ -51,33 +51,29 @@ app.openapi(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
apiHit(c, { endpoint: "/consume", lastBody: data });
|
apiHit(c, { endpoint: "/consume", lastBody: data });
|
||||||
const authHeader = c.req.header("Authorization");
|
//const authHeader = c.req.header("Authorization");
|
||||||
const token = authHeader?.split("Bearer ")[1] || "";
|
//const token = authHeader?.split("Bearer ")[1] || "";
|
||||||
|
|
||||||
|
//const payload = await verify(token, process.env.JWT_SECRET!);
|
||||||
try {
|
try {
|
||||||
const payload = await verify(token, process.env.JWT_SECRET!);
|
//return apiReturn(c, true, access?.message, access?.data, 200);
|
||||||
try {
|
|
||||||
//return apiReturn(c, true, access?.message, access?.data, 200);
|
|
||||||
|
|
||||||
const consume = await consumeMaterial(data, payload);
|
const consume = await consumeMaterial(data);
|
||||||
return c.json(
|
return c.json(
|
||||||
{ success: consume?.success, message: consume?.message },
|
{ success: consume?.success, message: consume?.message },
|
||||||
200
|
200
|
||||||
);
|
);
|
||||||
} catch (error) {
|
|
||||||
//console.log(error);
|
|
||||||
//return apiReturn(c, false, "Error in setting the user access", error, 400);
|
|
||||||
return c.json(
|
|
||||||
{
|
|
||||||
success: false,
|
|
||||||
message: "Missing data please try again",
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
400
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return c.json({ success: false, message: "Unauthorized" }, 401);
|
//console.log(error);
|
||||||
|
//return apiReturn(c, false, "Error in setting the user access", error, 400);
|
||||||
|
return c.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message: "Missing data please try again",
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
400
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ app.openapi(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log(silo);
|
||||||
return c.json({
|
return c.json({
|
||||||
success: silo.success,
|
success: silo.success,
|
||||||
message: silo.message,
|
message: silo.message,
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
{{!-- <link rel="stylesheet" href="styles/styles.css" /> --}}
|
||||||
|
{{> styles}}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>All,</p>
|
||||||
|
<p>The below SKU's do not currently have an av and will be ignored in the forcast import.</p>
|
||||||
|
<p>The date and qty are the first time needed showing from teh vmi report</p>
|
||||||
|
<table >
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Customer Article Number</th>
|
||||||
|
<th>First Date Needed</th>
|
||||||
|
<th>Quantity</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
{{#each items}}
|
||||||
|
<tr>
|
||||||
|
<td>{{customerArticleNo}}</td>
|
||||||
|
<td>{{requirementDate}}</td>
|
||||||
|
<td>{{quantity}}</td>
|
||||||
|
</tr>
|
||||||
|
{{/each}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<p>Thank you,</p>
|
||||||
|
<p>LST Team</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -285,9 +285,17 @@ export const labelingProcess = async ({
|
|||||||
// "ocp",
|
// "ocp",
|
||||||
// `Error Booking in label: ${book.errors[0].message}`
|
// `Error Booking in label: ${book.errors[0].message}`
|
||||||
// );
|
// );
|
||||||
|
createLog(
|
||||||
|
"error",
|
||||||
|
"labeling",
|
||||||
|
"ocp",
|
||||||
|
`There was an error booking in the label: ${JSON.stringify(
|
||||||
|
book.data
|
||||||
|
)}`
|
||||||
|
);
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
message: `Error Booking in label: ${book.errors[0]?.message}`,
|
message: `Error Booking in label`,
|
||||||
data: book,
|
data: book,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,13 +60,47 @@ export const isMainMatStaged = async (lot: any) => {
|
|||||||
// isStaged = true;
|
// isStaged = true;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
type CheckConditionArgs = {
|
||||||
|
results: any[];
|
||||||
|
filterFn: (n: any) => boolean;
|
||||||
|
failCondition: (n: any) => boolean;
|
||||||
|
failMessage: string;
|
||||||
|
successMessage: string;
|
||||||
|
lot: { lot: string | number };
|
||||||
|
};
|
||||||
|
|
||||||
|
const checkCondition = ({
|
||||||
|
results,
|
||||||
|
filterFn,
|
||||||
|
failCondition,
|
||||||
|
failMessage,
|
||||||
|
successMessage,
|
||||||
|
lot,
|
||||||
|
}: CheckConditionArgs): { message: string; success: boolean } => {
|
||||||
|
const subset = results.filter(filterFn);
|
||||||
|
|
||||||
|
if (subset.some(failCondition)) {
|
||||||
|
const failing = subset.filter(failCondition);
|
||||||
|
return {
|
||||||
|
message: `lot: ${lot.lot}, is missing: ${failing
|
||||||
|
.map(
|
||||||
|
(o: any) =>
|
||||||
|
`${o.MaterialHumanReadableId} - ${o.MaterialDescription}`
|
||||||
|
)
|
||||||
|
.join(",\n ")} ${failMessage}`,
|
||||||
|
success: false,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return { message: successMessage, success: true };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
createLog("info", "mainMaterial", "ocp", `Maint material query ran.`);
|
createLog("info", "mainMaterial", "ocp", `Maint material query ran.`);
|
||||||
|
|
||||||
const mainMateiral = res.filter((n: any) => n.IsMainMaterial);
|
const mainMaterial = res.find((n: any) => n.IsMainMaterial);
|
||||||
|
if (mainMaterial?.noMMShortage === "noMM") {
|
||||||
if (mainMateiral[0]?.noMaterialShortage === "no") {
|
return {
|
||||||
isStaged = {
|
message: `Main material: ${mainMaterial.MaterialHumanReadableId} - ${mainMaterial.MaterialDescription}: is not staged for ${lot.lot}`,
|
||||||
message: `Main material: ${mainMateiral[0].MaterialHumanReadableId} - ${mainMateiral[0].MaterialDescription}: is not staged for ${lot.lot} `,
|
|
||||||
success: false,
|
success: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -75,48 +109,39 @@ export const isMainMatStaged = async (lot: any) => {
|
|||||||
// for manual consume color if active to check colors
|
// for manual consume color if active to check colors
|
||||||
const checkColorSetting = set.filter((n) => n.name === "checkColor");
|
const checkColorSetting = set.filter((n) => n.name === "checkColor");
|
||||||
|
|
||||||
|
// 2. Auto color
|
||||||
if (checkColorSetting[0].value === "1") {
|
if (checkColorSetting[0].value === "1") {
|
||||||
const autoConsumeColor = res.filter(
|
// auto check
|
||||||
(n: any) => !n.IsMainMaterial && !n.isManual
|
// 2. Auto color
|
||||||
);
|
const autoColor = checkCondition({
|
||||||
if (
|
results: res,
|
||||||
autoConsumeColor.some(
|
lot,
|
||||||
(n: any) => n.autoConsumeCheck === "autoConsumeNOK"
|
filterFn: (n) =>
|
||||||
)
|
n.isManual &&
|
||||||
) {
|
!("noPKGAutoShortage" in n) &&
|
||||||
const onlyNOK = autoConsumeColor.filter(
|
!("noPKGManualShortage" in n), // pool = non-main, auto
|
||||||
(n: any) => n.autoConsumeCheck === "autoConsumeNOK"
|
failCondition: (n) => n.autoConsumeCheck === "autoConsumeNOK", // column = autoConsumeCheck
|
||||||
);
|
failMessage: "for autoconsume",
|
||||||
isStaged = {
|
successMessage: "auto color is good",
|
||||||
message: `lot: ${lot.lot}, is missing: ${onlyNOK
|
});
|
||||||
.map(
|
if (!autoColor.success) return autoColor;
|
||||||
(o: any) =>
|
console.log(autoColor);
|
||||||
`${o.MaterialHumanReadableId} - ${o.MaterialDescription}`
|
|
||||||
)
|
|
||||||
.join(",\n ")} for autoconsume`,
|
|
||||||
success: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// // for manual consume color
|
// 3. Manual color
|
||||||
const manualConsumeColor = res.filter(
|
const manualColor = checkCondition({
|
||||||
(n: any) => !n.IsMainMaterial && n.isManual
|
results: res,
|
||||||
);
|
lot,
|
||||||
if (
|
filterFn: (n) =>
|
||||||
manualConsumeColor.some(
|
!n.IsMainMaterial &&
|
||||||
(n: any) => n.noMaterialShortage === "yes"
|
n.isManual &&
|
||||||
)
|
!("noPKGAutoShortage" in n) &&
|
||||||
) {
|
!("noPKGManualShortage" in n), // pool = non-main, manual
|
||||||
isStaged = {
|
failCondition: (n) => n.noManualShortage === "noOK", // column = noManualShortage
|
||||||
message: `lot: ${lot.lot}, is missing: ${manualConsumeColor
|
failMessage: "for manual material",
|
||||||
.map(
|
successMessage: "manual color is good",
|
||||||
(o: any) =>
|
});
|
||||||
`${o.MaterialHumanReadableId} - ${o.MaterialDescription}`
|
if (!manualColor.success) return manualColor;
|
||||||
)
|
console.log(manualColor);
|
||||||
.join(",\n ")} for manual Material`,
|
|
||||||
success: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
createLog(
|
createLog(
|
||||||
"info",
|
"info",
|
||||||
@@ -129,11 +154,58 @@ export const isMainMatStaged = async (lot: any) => {
|
|||||||
// // if we want to check the packaging
|
// // if we want to check the packaging
|
||||||
const checkPKGSetting = set.filter((n) => n.name === "checkPKG");
|
const checkPKGSetting = set.filter((n) => n.name === "checkPKG");
|
||||||
if (checkPKGSetting[0].value === "1") {
|
if (checkPKGSetting[0].value === "1") {
|
||||||
const packagingCheck = res.filter(
|
const pkgAuto = checkCondition({
|
||||||
(n: any) => !n.IsMainMaterial && n.isManual
|
results: res,
|
||||||
|
lot,
|
||||||
|
filterFn: (n) =>
|
||||||
|
!n.IsMainMaterial &&
|
||||||
|
!n.isManual &&
|
||||||
|
"noPKGAutoShortage" in n,
|
||||||
|
failCondition: (n) => n.noPKGAutoShortage === "noAutoPkg",
|
||||||
|
failMessage: "for pkg",
|
||||||
|
successMessage: "auto PKG is good",
|
||||||
|
});
|
||||||
|
if (!pkgAuto.success) return pkgAuto;
|
||||||
|
console.log(pkgAuto);
|
||||||
|
|
||||||
|
// 5. Packaging manual
|
||||||
|
const pkgManual = checkCondition({
|
||||||
|
results: res,
|
||||||
|
lot,
|
||||||
|
filterFn: (n) =>
|
||||||
|
!n.IsMainMaterial &&
|
||||||
|
n.isManual &&
|
||||||
|
"noPKGManualShortage" in n,
|
||||||
|
failCondition: (n) => n.noPKGManualShortage === "noManPkg",
|
||||||
|
failMessage: "for pkg",
|
||||||
|
successMessage: "manual PKG is good",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!pkgManual.success) return pkgManual;
|
||||||
|
console.log(pkgManual);
|
||||||
|
} else {
|
||||||
|
createLog(
|
||||||
|
"info",
|
||||||
|
"mainMaterial",
|
||||||
|
"ocp",
|
||||||
|
"PKG check is not active."
|
||||||
);
|
);
|
||||||
if (packagingCheck.some((n: any) => n.noPKGShortage === "noPkg")) {
|
}
|
||||||
isStaged = {
|
|
||||||
|
// manual pkg
|
||||||
|
if (checkPKGSetting[0].value === "1") {
|
||||||
|
const packagingCheck = res.filter(
|
||||||
|
(n: any) =>
|
||||||
|
!n.IsMainMaterial &&
|
||||||
|
n.isManual &&
|
||||||
|
"noPKGManualShortage" in n
|
||||||
|
);
|
||||||
|
if (
|
||||||
|
packagingCheck.some(
|
||||||
|
(n: any) => n.noPKGManualShortage === "noManPkg"
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return (isStaged = {
|
||||||
message: `lot: ${lot.lot}, is missing: ${packagingCheck
|
message: `lot: ${lot.lot}, is missing: ${packagingCheck
|
||||||
.map(
|
.map(
|
||||||
(o: any) =>
|
(o: any) =>
|
||||||
@@ -141,7 +213,7 @@ export const isMainMatStaged = async (lot: any) => {
|
|||||||
)
|
)
|
||||||
.join(",\n ")} for pkg`,
|
.join(",\n ")} for pkg`,
|
||||||
success: false,
|
success: false,
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
createLog(
|
createLog(
|
||||||
|
|||||||
@@ -33,13 +33,13 @@ export const delieryInhouse = async (data: any) => {
|
|||||||
"error",
|
"error",
|
||||||
"labeling",
|
"labeling",
|
||||||
"ocp",
|
"ocp",
|
||||||
`${data.printer.name}, Error:${res.data.Message}`
|
`${data.printer?.name}, Error:${res.data.Message}`
|
||||||
);
|
);
|
||||||
//printerUpdate(data.printer, 7, "Error while deliverying inhouse.");
|
//printerUpdate(data.printer, 7, "Error while deliverying inhouse.");
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
message: `${data.printer.name} had an error while trying to deliver.`,
|
message: `${data.printer?.name} had an error while trying to deliver.`,
|
||||||
data: res.data,
|
data: res.data,
|
||||||
};
|
};
|
||||||
} // label was just delivered
|
} // label was just delivered
|
||||||
|
|||||||
@@ -43,9 +43,9 @@ export const wrapperStuff = async (tagData: any) => {
|
|||||||
"rfid",
|
"rfid",
|
||||||
`There are ${tagData.length} tags and this ${
|
`There are ${tagData.length} tags and this ${
|
||||||
tagData[0].reader
|
tagData[0].reader
|
||||||
} only allows 1 tag to create a label: tag ${tagData[0].tag}, ${
|
} only allows 1 tag to create a label: tag ${tagData
|
||||||
tagData[1].tag
|
.map((o: any) => `${o.tag}`)
|
||||||
}, ${tagData.length === 3 && tagData[2].tag}`
|
.join(",\n ")}`
|
||||||
);
|
);
|
||||||
const tag = { ...tagData[0], runningNr: 0 };
|
const tag = { ...tagData[0], runningNr: 0 };
|
||||||
//tagStuff([tag]);
|
//tagStuff([tag]);
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
export const activeArticle = `
|
export const activeArticle = `
|
||||||
|
use AlplaPROD_test1
|
||||||
|
|
||||||
SELECT V_Artikel.IdArtikelvarianten,
|
SELECT V_Artikel.IdArtikelvarianten,
|
||||||
V_Artikel.Bezeichnung,
|
V_Artikel.Bezeichnung,
|
||||||
V_Artikel.ArtikelvariantenTypBez,
|
V_Artikel.ArtikelvariantenTypBez,
|
||||||
@@ -43,7 +45,12 @@ V_Artikel.ArtikelvariantenTypBez = 'Gaylord' or
|
|||||||
V_Artikel.ArtikelvariantenTypBez = 'Misc. Packaging' or
|
V_Artikel.ArtikelvariantenTypBez = 'Misc. Packaging' or
|
||||||
V_Artikel.ArtikelvariantenTypBez = 'Sleeve' or
|
V_Artikel.ArtikelvariantenTypBez = 'Sleeve' or
|
||||||
V_Artikel.ArtikelvariantenTypBez = 'Plastic Bag' or
|
V_Artikel.ArtikelvariantenTypBez = 'Plastic Bag' or
|
||||||
V_Artikel.ArtikelvariantenTypBez = 'Purch Spout'
|
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'
|
THEN 'PKG'
|
||||||
WHEN V_Artikel.ArtikelvariantenTypBez='HD-PE' or
|
WHEN V_Artikel.ArtikelvariantenTypBez='HD-PE' or
|
||||||
V_Artikel.ArtikelvariantenTypBez='HD-PE PCR' or
|
V_Artikel.ArtikelvariantenTypBez='HD-PE PCR' or
|
||||||
@@ -77,7 +84,8 @@ V_Artikel.ArtikelvariantenTypBez = 'Purchased Caps' or
|
|||||||
V_Artikel.ArtikelvariantenTypBez = 'Purchased_preform'
|
V_Artikel.ArtikelvariantenTypBez = 'Purchased_preform'
|
||||||
THEN 'Purchased_preform'
|
THEN 'Purchased_preform'
|
||||||
When
|
When
|
||||||
V_Artikel.ArtikelvariantenTypBez = 'Closures'
|
V_Artikel.ArtikelvariantenTypBez = 'Closures' or
|
||||||
|
V_Artikel.ArtikelvariantenTypBez = 'Cap'
|
||||||
THEN 'Caps'
|
THEN 'Caps'
|
||||||
When
|
When
|
||||||
V_Artikel.ArtikelvariantenTypBez = 'Dummy'
|
V_Artikel.ArtikelvariantenTypBez = 'Dummy'
|
||||||
@@ -95,7 +103,8 @@ V_Artikel.ProdBereichBez = 'IM-Caps' or
|
|||||||
V_Artikel.ProdBereichBez = 'IM-PET' or
|
V_Artikel.ProdBereichBez = 'IM-PET' or
|
||||||
V_Artikel.ProdBereichBez = 'PRINT OFFICE' or
|
V_Artikel.ProdBereichBez = 'PRINT OFFICE' or
|
||||||
V_Artikel.ProdBereichBez = 'EBM' or
|
V_Artikel.ProdBereichBez = 'EBM' or
|
||||||
V_Artikel.ProdBereichBez = 'ISBM'
|
V_Artikel.ProdBereichBez = 'ISBM' or
|
||||||
|
V_Artikel.ProdBereichBez = 'IM-Finishing'
|
||||||
Then 'FG'
|
Then 'FG'
|
||||||
Else 'not Defined Profit Center'
|
Else 'not Defined Profit Center'
|
||||||
end,
|
end,
|
||||||
@@ -107,16 +116,17 @@ sales.[KdArtBez] as CustomerArticleDescription,
|
|||||||
round(V_Artikel.Zyklus, 2) as CycleTime,
|
round(V_Artikel.Zyklus, 2) as CycleTime,
|
||||||
Sypronummer as salesAgreement,
|
Sypronummer as salesAgreement,
|
||||||
V_Artikel.ProdArtikelBez as ProductFamily
|
V_Artikel.ProdArtikelBez as ProductFamily
|
||||||
|
,REPLACE(pur.UOM,'UOM:','') as UOM
|
||||||
--,*
|
--,*
|
||||||
FROM AlplaPROD_test1.dbo.V_Artikel (nolock)
|
FROM dbo.V_Artikel (nolock)
|
||||||
|
|
||||||
join
|
join
|
||||||
AlplaPROD_test1.dbo.V_Artikelvarianten on AlplaPROD_test1.dbo.V_Artikel.IdArtikelvarianten =
|
dbo.V_Artikelvarianten (nolock) on dbo.V_Artikel.IdArtikelvarianten =
|
||||||
AlplaPROD_test1.dbo.V_Artikelvarianten.IdArtikelvarianten
|
dbo.V_Artikelvarianten.IdArtikelvarianten
|
||||||
|
|
||||||
join
|
join
|
||||||
AlplaPROD_test1.dbo.V_FibuKonten_BASIS on AlplaPROD_test1.dbo.V_Artikelvarianten.IdFibuKonto =
|
dbo.V_FibuKonten_BASIS (nolock) on dbo.V_Artikelvarianten.IdFibuKonto =
|
||||||
AlplaPROD_test1.dbo.V_FibuKonten_BASIS.IdFibuKonto
|
dbo.V_FibuKonten_BASIS.IdFibuKonto
|
||||||
|
|
||||||
|
|
||||||
-- adding in the sales price
|
-- adding in the sales price
|
||||||
@@ -130,7 +140,7 @@ left join
|
|||||||
,[KdArtNr]
|
,[KdArtNr]
|
||||||
,[KdArtBez]
|
,[KdArtBez]
|
||||||
--,*
|
--,*
|
||||||
from AlplaPROD_test1.dbo.T_HistoryVK (nolock)
|
from dbo.T_HistoryVK (nolock)
|
||||||
where
|
where
|
||||||
--GueltigabDatum > getDate() - 120
|
--GueltigabDatum > getDate() - 120
|
||||||
--and
|
--and
|
||||||
@@ -138,7 +148,26 @@ left join
|
|||||||
and StandardKunde = 1 -- default address
|
and StandardKunde = 1 -- default address
|
||||||
) a
|
) a
|
||||||
where RN = 1) as sales
|
where RN = 1) as sales
|
||||||
on AlplaPROD_test1.dbo.V_Artikel.IdArtikelvarianten = sales.av
|
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 LEFT(Bemerkung, CHARINDEX(' ', Bemerkung)) 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
|
where V_Artikel.aktiv = 1
|
||||||
|
|
||||||
|
|||||||
17
server/services/sqlServer/querys/eom/lastSalesprice.ts
Normal file
17
server/services/sqlServer/querys/eom/lastSalesprice.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
export const lastSalesPriceCheck = `
|
||||||
|
use AlplaPROD_test1
|
||||||
|
|
||||||
|
select * from
|
||||||
|
(select IdArtikelvarianten as av,
|
||||||
|
VKPreis as salesPrice,
|
||||||
|
MPB, FWMPAlpla,
|
||||||
|
FWMPB,
|
||||||
|
ROW_NUMBER() over(partition by IdArtikelVarianten order by gueltigabdatum desc) rn,
|
||||||
|
convert(date, gueltigabdatum, 120) as validDate
|
||||||
|
from dbo.T_HistoryVK (nolock)
|
||||||
|
where convert(date, gueltigabdatum, 120) <= '[date]' and StandardKunde = 1) a
|
||||||
|
where rn =1
|
||||||
|
order by av asc,
|
||||||
|
validDate desc
|
||||||
|
|
||||||
|
`;
|
||||||
17
server/services/sqlServer/querys/eom/lstPurchasePrice.ts
Normal file
17
server/services/sqlServer/querys/eom/lstPurchasePrice.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
export const lastPurchasePrice = `
|
||||||
|
use AlplaPROD_test1
|
||||||
|
|
||||||
|
SELECT plant=(SELECT Wert FROM dbo.T_SystemParameter (nolock) WHERE (Bezeichnung = 'Werkskuerzel')),
|
||||||
|
plantName=(SELECT Wert FROM dbo.T_SystemParameter AS T_SystemParameter (nolock) WHERE (Bezeichnung = 'Mandant-intern')),*
|
||||||
|
from
|
||||||
|
(Select IdBestellung as 'Purchase order number',
|
||||||
|
IdArtikelVarianten AS AV,
|
||||||
|
BestellMenge,
|
||||||
|
BestellMengeVPK,
|
||||||
|
PreisProEinheit,
|
||||||
|
convert(varchar,Lieferdatum,23) as deliveryDate,
|
||||||
|
ROW_NUMBER() over(partition by IdArtikelVarianten order by Lieferdatum desc) rn
|
||||||
|
from dbo.V_Bestellpositionen_PURCHASE (nolock)
|
||||||
|
where PositionsStatus = '7' or PositionsStatus = '6' or PositionsStatus = '5' and convert(varchar,Lieferdatum,23) > DATEADD(year, -5, GetDate()) )a
|
||||||
|
where rn = 1
|
||||||
|
`;
|
||||||
@@ -23,69 +23,78 @@
|
|||||||
|
|
||||||
export const mmQuery = `
|
export const mmQuery = `
|
||||||
use [test1_AlplaPROD2.0_Read]
|
use [test1_AlplaPROD2.0_Read]
|
||||||
|
declare @lot as NVARCHAR(max) = [lotNumber]
|
||||||
/*
|
/*
|
||||||
checks all needed material including pkg
|
checks all needed material including pkg
|
||||||
|
|
||||||
we only want to monitor the manual materials and the mm materail to make sure they are good.
|
we only want to monitor the manual materials and the mm materail to make sure they are good.
|
||||||
|
|
||||||
for auto consume materails this will be compared with another query.
|
for auto consume materails this will be compared with another query.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
SELECT lot.ProductionLotHumanReadableId
|
/*
|
||||||
,MaterialHumanReadableId
|
Material demands for this lot
|
||||||
|
*/
|
||||||
|
select
|
||||||
|
MaterialHumanReadableId
|
||||||
,MaterialDescription
|
,MaterialDescription
|
||||||
--IsMainMaterial,
|
-- check box is staged so we could book in even if we used preprint.
|
||||||
,case when SourcingState in (1, 2) then 1
|
,case when SourcingState in (1, 2) then 1
|
||||||
when x.ProvidedAmount > 0 then 1
|
when x.ProvidedAmount > 0 then 1
|
||||||
when x.EffectiveConsumption > 0 then 1
|
when x.EffectiveConsumption > 0 then 1
|
||||||
else 0 end as Staged
|
else 0 end as Staged
|
||||||
,x.ProvidedAmount as Provided
|
|
||||||
,x.EffectiveConsumption as consumption
|
|
||||||
,x.TotalDemand as totalDemand ,
|
|
||||||
case when cp.Pieces = 1 then (lot.TotalProducedLoadingUnits+1) * p.LoadingUnitPieces else
|
|
||||||
(a.Weight *((case when cp.Percentage is null then 80.25 else cp.Percentage end) / 100) * ((lot.TotalProducedLoadingUnits+1) * p.LoadingUnitPieces)) / 1000 end totalNeeded
|
|
||||||
,l.qty as invForAutoConsume
|
|
||||||
/* remaining needed to complete the lot */
|
|
||||||
--,x.TotalDemand - x.EffectiveConsumption as remainingNeeded
|
|
||||||
/* do we have enough staged or scanned to the lot? */
|
|
||||||
,case when (case when x.ProvidedAmount <> 0
|
|
||||||
then x.ProvidedAmount else x.EffectiveConsumption end) >
|
|
||||||
(case when cp.Pieces = 1 then (lot.TotalProducedLoadingUnits+1) * p.LoadingUnitPieces else
|
|
||||||
(a.Weight *((case when cp.Percentage is null then 80.25 else cp.Percentage end) / 100) * ((lot.TotalProducedLoadingUnits+1) * p.LoadingUnitPieces)) / 1000 end)
|
|
||||||
then 'good'
|
|
||||||
else 'no' end as noMaterialShortage
|
|
||||||
-- pkg check
|
|
||||||
,case when pkg.QuantityPosition is null then null else
|
|
||||||
(case when l.qty > (lot.TotalProducedLoadingUnits+1) * pkg.QuantityPosition then 'pkgGood' else 'noPkg' end) end as noPKGShortage
|
|
||||||
|
|
||||||
,case when cp.Percentage is null then
|
|
||||||
case when l.qty > ((lot.TotalProducedLoadingUnits +1) * pkg.QuantityPosition) then 'autoConsumeOk' else 'autoConsumeNOK' end else
|
|
||||||
(case when l.qty > (a.Weight *((case when cp.Percentage is null then 80.25 else cp.Percentage end) / 100) * ((lot.TotalProducedLoadingUnits+1) * p.LoadingUnitPieces)) / 1000 and IsManualProcess = 0
|
|
||||||
then 'autoConsumeOk' else 'autoConsumeNOK' end) end as autoConsumeCheck
|
|
||||||
,x.IsManualProcess as isManual
|
,x.IsManualProcess as isManual
|
||||||
,IsMainMaterial
|
,IsMainMaterial
|
||||||
|
-- lot stuff
|
||||||
,lot.TotalPlannedLoadingUnits
|
,lot.TotalPlannedLoadingUnits
|
||||||
,lot.TotalProducedLoadingUnits
|
,lot.TotalProducedLoadingUnits
|
||||||
,lot.TotalPlannedLoadingUnits - lot.TotalProducedLoadingUnits as remainingPallets
|
,lot.TotalPlannedLoadingUnits - lot.TotalProducedLoadingUnits as remainingPallets
|
||||||
,case when cp.Percentage is null then 80.25 else cp.Percentage end as Percentage -- this is to over come the alternate mm put in planning
|
,x.ProvidedAmount as Provided -- this is what has been provided most of the time this is due to a silo attachment
|
||||||
,case when cp.Pieces is not null then cp.Pieces else pkg.QuantityPosition end as peices
|
,x.EffectiveConsumption as consumption -- this is how much was consummed via cmd 112
|
||||||
FROM [issueMaterial].[MaterialDemand] x (nolock)
|
,x.TotalDemand as totalDemand -- the total demand needed to finish the lot out
|
||||||
|
|
||||||
|
,case when cp.Pieces >= 0.001 then (lot.TotalProducedLoadingUnits+1) * cp.Pieces else
|
||||||
|
(a.Weight *((case when cp.Percentage is null then 80 else cp.Percentage end) / 100) * ((lot.TotalProducedLoadingUnits+1) * p.LoadingUnitPieces)) / 1000 end totalNeeded
|
||||||
|
|
||||||
|
,case when IsMainMaterial = 1 then
|
||||||
|
case when (case when x.ProvidedAmount <> 0
|
||||||
|
then x.ProvidedAmount else x.EffectiveConsumption end) >
|
||||||
|
(case when cp.Pieces >= 0.001 then (lot.TotalProducedQuantity+1) * cp.Pieces else
|
||||||
|
(a.Weight *((case when cp.Percentage is null then 80 else cp.Percentage end) / 100) * ((lot.TotalProducedLoadingUnits+1) * p.LoadingUnitPieces)) / 1000 end)
|
||||||
|
then 'mmGood'
|
||||||
|
else 'noMM' end else null end as noMMShortage
|
||||||
|
|
||||||
|
-- pkg check auto
|
||||||
|
,case when pkg.QuantityPosition is null then null else
|
||||||
|
(case when l.qty > ((lot.TotalProducedLoadingUnits+1) * pkg.QuantityPosition) and IsManualProcess = 0 then 'pkgAutoGood' else 'noAutoPkg' end) end as noPKGAutoShortage
|
||||||
|
-- plg check manual
|
||||||
|
,case when pkg.QuantityPosition is null then null else
|
||||||
|
(case when x.EffectiveConsumption > ((lot.TotalProducedLoadingUnits+1) * pkg.QuantityPosition) and IsManualProcess = 1 then 'pkgManGood' else 'noManPkg' end) end as noPKGManualShortage
|
||||||
|
-- manualMateiral
|
||||||
|
,case when IsMainMaterial = 0 and IsManualProcess = 1 then
|
||||||
|
case when (case when x.ProvidedAmount <> 0
|
||||||
|
then x.ProvidedAmount else x.EffectiveConsumption end) >
|
||||||
|
(case when cp.Pieces >= 0.001 then (lot.TotalProducedQuantity+1) * cp.Pieces else
|
||||||
|
(a.Weight *((case when cp.Percentage is null then 80 else cp.Percentage end) / 100) * ((lot.TotalProducedLoadingUnits+1) * p.LoadingUnitPieces)) / 1000 end)
|
||||||
|
then 'manualGood'
|
||||||
|
else 'noOK' end else null end as noManualShortage
|
||||||
|
-- autoconsume
|
||||||
|
,case when cp.Percentage is null then
|
||||||
|
case when l.qty > ((lot.TotalProducedLoadingUnits +1) * pkg.QuantityPosition) then 'autoConsumeOk' else 'autoConsumeNOK' end else
|
||||||
|
(case when l.qty > (a.Weight *(cp.Percentage / 100) * ((lot.TotalProducedLoadingUnits+1) * p.LoadingUnitPieces)) / 1000 and IsManualProcess = 0
|
||||||
|
then 'autoConsumeOk' else 'autoConsumeNOK' end) end as autoConsumeCheck
|
||||||
|
-- stock amounts
|
||||||
|
,l.qty as invForAutoConsume
|
||||||
|
|
||||||
|
,case when cp.Percentage is null then 0 else cp.Percentage end as Percentage
|
||||||
|
,pkg.QuantityPosition
|
||||||
|
,(lot.TotalProducedQuantity+1) * cp.Pieces
|
||||||
|
from [issueMaterial].[MaterialDemand] x (nolock)
|
||||||
|
|
||||||
|
/* production lot info */
|
||||||
left join
|
left join
|
||||||
[productionControlling].[ProducedLot] as lot on
|
[productionControlling].[ProducedLot] as lot on
|
||||||
lot.Id = x.ProductionLotId
|
lot.Id = x.ProductionLotId
|
||||||
|
|
||||||
/* av data */
|
|
||||||
left join
|
|
||||||
[masterData].[Article] as a on
|
|
||||||
a.id = lot.ArticleId
|
|
||||||
|
|
||||||
/* compound*/
|
|
||||||
left join
|
|
||||||
[masterData].[CompoundPosition] as cp on
|
|
||||||
cp.CompoundId = a.CompoundId
|
|
||||||
and cp.ArticleId = x.MaterialId
|
|
||||||
|
|
||||||
/* packagaing */
|
/* packagaing */
|
||||||
left join
|
left join
|
||||||
[masterData].[PackagingInstructionPosition] as pkg on
|
[masterData].[PackagingInstructionPosition] as pkg on
|
||||||
@@ -97,6 +106,17 @@ left join
|
|||||||
[masterData].[PackagingInstruction] as p on
|
[masterData].[PackagingInstruction] as p on
|
||||||
p.id = lot.PackagingId
|
p.id = lot.PackagingId
|
||||||
|
|
||||||
|
/* av data */
|
||||||
|
left join
|
||||||
|
[masterData].[Article] as a on
|
||||||
|
a.id = lot.ArticleId
|
||||||
|
|
||||||
|
/* compound*/
|
||||||
|
left join
|
||||||
|
[masterData].[CompoundPosition] as cp on
|
||||||
|
cp.CompoundId = a.CompoundId
|
||||||
|
and cp.ArticleId = x.MaterialId
|
||||||
|
|
||||||
/* current stock info for auto consumption*/
|
/* current stock info for auto consumption*/
|
||||||
left join
|
left join
|
||||||
(select
|
(select
|
||||||
@@ -113,5 +133,8 @@ where autoverbrauch = 1 and aktiv = 1
|
|||||||
group by IdArtikelVarianten,ArtikelVariantenBez
|
group by IdArtikelVarianten,ArtikelVariantenBez
|
||||||
) as l on
|
) as l on
|
||||||
l.IdArtikelVarianten = MaterialHumanReadableId
|
l.IdArtikelVarianten = MaterialHumanReadableId
|
||||||
where lot.ProductionLotHumanReadableId = [lotNumber]
|
|
||||||
|
where lot.ProductionLotHumanReadableId = @lot and MaterialDescription not like '%nopal%'
|
||||||
|
and MaterialDescription NOT LIKE '%bb%'
|
||||||
|
and MaterialDescription NOT LIKE '%mcg%'
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -1,33 +1,34 @@
|
|||||||
export const planningNumbersByAVDate = `
|
export const planningNumbersByAVDate = `
|
||||||
use AlplaPROD_test1
|
use AlplaPROD_test1
|
||||||
declare @start_date nvarchar(30) = [startDate] --'2025-01-01'
|
declare @start_date nvarchar(30) = '[startDate]' --'2025-01-01'
|
||||||
declare @end_date nvarchar(30) = [endDate] --'2025-08-09'
|
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
|
articles will need to be passed over as well as the date structure we want to see
|
||||||
*/
|
*/
|
||||||
|
|
||||||
-- planned lots in planning
|
select x.IdArtikelvarianten As Article,
|
||||||
|
|
||||||
select V_ProdLosProduktionJeProdTag_PLANNING.IdArtikelvarianten As Article,
|
|
||||||
ProduktionAlias as Description,
|
ProduktionAlias as Description,
|
||||||
standort as MachineId,
|
standort as MachineId,
|
||||||
MaschinenBezeichnung as MachineName,
|
MaschinenBezeichnung as MachineName,
|
||||||
--MaschZyklus as PlanningCycleTime,
|
--MaschZyklus as PlanningCycleTime,
|
||||||
V_ProdLosProduktionJeProdTag_PLANNING.IdProdPlanung as LotNumber,
|
x.IdProdPlanung as LotNumber,
|
||||||
FORMAT(ProdTag, 'MM/dd/yyyy') as ProductionDay,
|
FORMAT(ProdTag, 'MM/dd/yyyy') as ProductionDay,
|
||||||
V_ProdLosProduktionJeProdTag_PLANNING.planMenge as TotalPlanned,
|
x.planMenge as TotalPlanned,
|
||||||
ProduktionMenge as QTYPerDay,
|
ProduktionMenge as QTYPerDay,
|
||||||
round(ProduktionMengeVPK, 2) PalDay,
|
round(ProduktionMengeVPK, 2) PalDay,
|
||||||
Status as finished
|
Status as finished
|
||||||
--MaschStdAuslastung as nee
|
--MaschStdAuslastung as nee
|
||||||
|
|
||||||
from dbo.V_ProdLosProduktionJeProdTag_PLANNING (nolock)
|
from dbo.V_ProdLosProduktionJeProdTag_PLANNING (nolock) as x
|
||||||
|
|
||||||
left join
|
left join
|
||||||
dbo.V_ProdPlanung (nolock) on
|
dbo.V_ProdPlanung (nolock) as p on
|
||||||
V_ProdLosProduktionJeProdTag_PLANNING .IdProdPlanung = V_ProdPlanung.IdProdPlanung
|
x.IdProdPlanung = p.IdProdPlanung
|
||||||
|
|
||||||
where V_ProdLosProduktionJeProdTag_PLANNING.IdArtikelvarianten in ([articles]) and ProdTag between @start_date and @end_date --and IdProdPlanung = 18442
|
where ProdTag between @start_date and @end_date
|
||||||
|
and p.IdArtikelvarianten in ([articles])
|
||||||
|
--and V_ProdLosProduktionJeProdTag_PLANNING.IdKunde = 10
|
||||||
|
--and IdProdPlanung = 18442
|
||||||
|
|
||||||
order by ProdTag
|
order by ProdTag desc
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
export const productionNumbers = `
|
export const productionNumbers = `
|
||||||
use [test1_AlplaPROD2.0_Reporting]
|
use [test1_AlplaPROD2.0_Reporting]
|
||||||
|
|
||||||
declare @startDate nvarchar(30) = [startDate] --'2024-12-30'
|
declare @startDate nvarchar(30) = '[startDate]' --'2024-12-30'
|
||||||
declare @endDate nvarchar(30) = [endDate] --'2025-08-09'
|
declare @endDate nvarchar(30) = '[endDate]' --'2025-08-09'
|
||||||
|
|
||||||
select MachineLocation,
|
select MachineLocation,
|
||||||
ArticleHumanReadableId as article,
|
ArticleHumanReadableId as article,
|
||||||
|
|||||||
34
server/services/sqlServer/querys/psiReport/psiinventory.ts
Normal file
34
server/services/sqlServer/querys/psiReport/psiinventory.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
export const planningNumbersByAVDate = `
|
||||||
|
use AlplaPROD_test1
|
||||||
|
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,
|
||||||
|
ProduktionAlias as Description,
|
||||||
|
standort as MachineId,
|
||||||
|
MaschinenBezeichnung as MachineName,
|
||||||
|
--MaschZyklus as PlanningCycleTime,
|
||||||
|
x.IdProdPlanung as LotNumber,
|
||||||
|
FORMAT(ProdTag, 'MM/dd/yyyy') as ProductionDay,
|
||||||
|
x.planMenge as TotalPlanned,
|
||||||
|
ProduktionMenge as QTYPerDay,
|
||||||
|
round(ProduktionMengeVPK, 2) PalDay,
|
||||||
|
Status as finished
|
||||||
|
--MaschStdAuslastung as nee
|
||||||
|
|
||||||
|
from dbo.V_ProdLosProduktionJeProdTag_PLANNING (nolock) as x
|
||||||
|
|
||||||
|
left join
|
||||||
|
dbo.V_ProdPlanung (nolock) as p on
|
||||||
|
x.IdProdPlanung = p.IdProdPlanung
|
||||||
|
|
||||||
|
where ProdTag between @start_date and @end_date
|
||||||
|
and p.IdArtikelvarianten in ([articles])
|
||||||
|
--and V_ProdLosProduktionJeProdTag_PLANNING.IdKunde = 10
|
||||||
|
--and IdProdPlanung = 18442
|
||||||
|
|
||||||
|
order by ProdTag desc
|
||||||
|
`;
|
||||||
@@ -21,7 +21,7 @@ select ext.Barcode
|
|||||||
,RunningNumber as runnungNumber
|
,RunningNumber as runnungNumber
|
||||||
,SsccEanRunningNumber as externalRunningNumber
|
,SsccEanRunningNumber as externalRunningNumber
|
||||||
,ArticleHumanReadableId
|
,ArticleHumanReadableId
|
||||||
,case when LabelManagementHumanReadableId is null then (select HumanReadableId from [test1_AlplaPROD2.0_Read].[masterData].[LabelManagement] (nolock) where LabelMarkerId = 7) else LabelManagementHumanReadableId end as labelLayout
|
,case when LabelManagementHumanReadableId is null then (select HumanReadableId from [test1_AlplaPROD2.0_Read].[masterData].[LabelManagement] (nolock) where LabelMarkerId = 7 and Active = 1) else LabelManagementHumanReadableId end as labelLayout
|
||||||
,case when EinlagerungsMengeSum IS NULL then 'notOnStock' else 'onStock' end as stockStatus
|
,case when EinlagerungsMengeSum IS NULL then 'notOnStock' else 'onStock' end as stockStatus
|
||||||
from [test1_AlplaPROD2.0_Read].[labelling].[ExternalLabel] (nolock) as ext
|
from [test1_AlplaPROD2.0_Read].[labelling].[ExternalLabel] (nolock) as ext
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user