Compare commits

...

299 Commits

Author SHA1 Message Date
88b6d0a235 Merge pull request 'migration' (#51) from migration into main
Reviewed-on: #51
2025-09-19 22:18:40 -05:00
8943407f27 feat(finaly): the final push before moving all to the new lst 2025-09-19 22:16:47 -05:00
0bbe411db0 feat(docs): added in link to the main docs and to the material xfer 2025-09-19 07:56:43 -05:00
99b3ad633c fix(materials): changes for consuming peices vs units 2025-09-18 11:00:54 -05:00
c892348d19 refactor(manual print): added a min length of 10 characters 2025-09-18 11:00:18 -05:00
360549aaf4 fix(consume material): changes made to remove the rest of the auth needs 2025-09-18 10:59:55 -05:00
bdc1e72fc1 refactor(frontend): comment required now when doing manual labels 2025-09-17 20:02:14 -05:00
4cae96b1ee refactor(detach): just a log to monitor better 2025-09-11 06:42:31 -05:00
1cde8ab2e6 fix(mm query): more changes to the material query to please more plants 2025-09-11 06:42:02 -05:00
03e8378213 fix(inhouse): changes to no longer error 2025-09-11 06:39:36 -05:00
275c93dc79 refactor(detach silo): changes to now show the error in the console in the browser 2025-09-11 06:39:07 -05:00
fbb8c21d5c feat(loreal forecast): added in an email to be sent when we are missing skus 2025-09-11 06:38:36 -05:00
dce93d3de2 ci(release): bump build number to 652 2025-09-11 06:32:08 -05:00
faf4e9f9ab ci(release): bump build number to 651 2025-09-11 06:30:48 -05:00
a9783a7d35 ci(release): bump build number to 650 2025-09-10 11:15:07 -05:00
e9ca6dbbb2 ci(release): bump build number to 649 2025-09-10 11:13:59 -05:00
e996f99400 ci(release): bump build number to 648 2025-09-10 06:59:19 -05:00
3b939ff2d3 ci(release): bump build number to 647 2025-09-09 21:21:08 -05:00
a7ff88025e chore(release): 2.27.0 2025-09-09 21:20:39 -05:00
00899a5b77 fix(materials): more fixes to try and please all plants to use this version and not call me 2025-09-09 21:20:23 -05:00
99ecf52218 fix(label query): fixes to only pull in active layouts 2025-09-09 21:19:39 -05:00
a6920d7cd8 ci(release): bump build number to 645 2025-09-09 17:52:15 -05:00
788efdf4b3 ci(release): bump build number to 644 2025-09-09 17:40:05 -05:00
a2a17beeeb ci(release): bump build number to 643 2025-09-09 17:28:29 -05:00
6c793c66a4 ci(release): bump build number to 642 2025-09-09 15:57:41 -05:00
6918a5a7d4 ci(release): bump build number to 641 2025-09-09 09:12:18 -05:00
ddd9b0e372 ci(release): bump build number to 640 2025-09-09 07:48:24 -05:00
41d921756b ci(release): bump build number to 638 2025-09-08 19:16:44 -05:00
d86ca7d3bf ci(release): bump build number to 636 2025-09-08 13:30:05 -05:00
932a72ba88 fix(db): changes to the user so it deletes correctly 2025-09-07 15:38:27 -05:00
b9c6d0ba57 ci(release): bump build number to 622 2025-09-06 16:33:56 -05:00
592e4c8cd7 ci(release): bump build number to 621 2025-09-06 16:02:36 -05:00
b772666905 ci(release): bump build number to 620 2025-09-06 14:56:05 -05:00
a6edcb71bf ci(release): bump build number to 619 2025-09-06 14:51:26 -05:00
76d929abea ci(release): bump build number to 618 2025-09-06 14:43:44 -05:00
da17defe82 ci(release): bump build number to 617 2025-09-06 14:37:44 -05:00
669f5ca33f ci(release): bump build number to 616 2025-09-06 14:31:51 -05:00
b649dca4c9 ci(release): bump build number to 615 2025-09-06 14:28:44 -05:00
04b8d041f9 ci(release): bump build number to 611 2025-09-06 09:24:09 -05:00
71bc7c29bc ci(release): bump build number to 610 2025-09-06 09:22:13 -05:00
79f1f8f91b fix(article check): corrected the query to not have a specfic plant in it 2025-09-06 09:04:00 -05:00
b677bc1498 refactor(rfid): changes to show all tags vs only 3 if there are more 2025-09-06 09:03:35 -05:00
a53915ad8c fix(material check): split manual material out of the mm to properly catch it 2025-09-06 09:03:11 -05:00
b3ce767b32 fix(bookin): corrections to only show the message on error vs the json 2025-09-06 09:02:42 -05:00
6caa5984e7 fix(eomservice): changes to stop a crash incase the sql returned nothing due to start up 2025-09-06 09:02:09 -05:00
415d2e4a1d fix(register): changes to not give everyone system admin 2025-09-06 09:01:42 -05:00
271cdbdbfa refactor(cosume): changes to allow non logged in users to use this function 2025-09-06 09:01:12 -05:00
796a8dccd2 refactor(silo card): changes to allow viewers to see and able to attach and detach 2025-09-06 09:00:46 -05:00
e03e92c18d ci(build): changes to build then copy to new version being rewritten 2025-09-06 09:00:11 -05:00
dd2e5d04ae ci(release): bump build number to 609 2025-09-06 08:54:39 -05:00
708b57b926 ci(release): bump build number to 608 2025-09-06 08:50:28 -05:00
0444da8bbc ci(release): bump build number to 607 2025-09-06 08:34:18 -05:00
6d49fae16d ci(release): bump build number to 602 2025-09-05 09:55:52 -05:00
be8a44f2dc ci(release): bump build number to 601 2025-09-05 09:52:25 -05:00
a3994a1f69 ci(release): bump build number to 600 2025-09-05 09:45:02 -05:00
00eaf62d4c ci(release): bump build number to 600 2025-09-05 09:44:58 -05:00
6851777faf ci(release): bump build number to 599 2025-09-05 09:43:27 -05:00
f9e97fc224 ci(release): bump build number to 598 2025-09-05 09:43:25 -05:00
4e3c5e4191 ci(release): bump build number to 595 2025-09-05 08:28:25 -05:00
172fd1d5c2 ci(release): bump build number to 594 2025-09-05 08:28:22 -05:00
1094de2ebd ci(release): bump build number to 593 2025-09-05 08:23:59 -05:00
7462b3d90b ci(release): bump build number to 592 2025-09-05 08:23:56 -05:00
2045c13ef2 ci(release): bump build number to 591 2025-09-05 08:22:41 -05:00
5fa9e83d5b ci(release): bump build number to 590 2025-09-05 08:22:39 -05:00
f48c944bd0 ci(release): bump build number to 589 2025-09-05 07:50:36 -05:00
dddd1d422e ci(release): bump build number to 588 2025-09-04 13:12:21 -05:00
8133443ec9 ci(release): bump build number to 587 2025-09-03 10:56:13 -05:00
28c7d30c1a ci(release): bump build number to 586 2025-09-03 10:54:37 -05:00
57966ac9de refactor(mm query): changes to the query to see pkg and materials properly and not duplicates 2025-09-01 11:08:47 -05:00
6910550de7 fix(main material check): corrections to properly ignore pkg during color checks 2025-09-01 11:08:16 -05:00
1f8b8a7248 fix(bookin): corrected the bookin in error response
this could still print a label if the system detects the material properly but some other issue with
alplaprod happened
2025-09-01 11:05:36 -05:00
cfed981928 refactor(sql): articles added in UOM 2025-09-01 11:02:32 -05:00
0efe74d4b1 ci(release): bump build number to 585 2025-09-01 07:31:05 -05:00
c35db2e209 ci(release): bump build number to 584 2025-08-29 19:01:12 -05:00
e1cdeb740b ci(release): bump build number to 583 2025-08-29 18:57:25 -05:00
3c9e75dc3c ci(release): bump build number to 582 2025-08-29 18:32:34 -05:00
64b5b0d248 ci(release): bump build number to 581 2025-08-29 11:37:47 -05:00
668eae9719 ci(release): bump build number to 580 2025-08-29 11:31:22 -05:00
7cc3778506 feat(eom): lastSales, lastPurch added to be pulled with new template 2025-08-29 11:26:26 -05:00
af47c1582e ci(release): bump build number to 579 2025-08-29 08:59:50 -05:00
081572c421 ci(release): bump build number to 578 2025-08-28 11:09:44 -05:00
c6f6ef6262 fix(frontend): typos 2025-08-28 10:56:49 -05:00
34849e15d1 ci(release): bump build number to 577 2025-08-28 10:19:10 -05:00
9bd66942f5 chore(release): 2.26.0 2025-08-28 10:18:13 -05:00
795da35141 ci(release): bump build number to 576 2025-08-28 10:17:15 -05:00
468f933168 fix(eom stats): corrections to the eom inv stuff to be proper tiems 2025-08-28 10:15:41 -05:00
8c296c5b78 test(forklifts): forklift starting process 2025-08-28 10:15:13 -05:00
53ed2c4e6a feat(materials): added in a bigger window on eom transfer lots 2025-08-28 10:14:41 -05:00
0a6ddea8c0 refactor(materials): changes to allow exact and eom transfers 2025-08-27 17:17:32 -05:00
df423192bf refactor(labeling): moved bookin fails inside bookin as it could be off 2025-08-27 17:17:03 -05:00
2f908398bc ci(release): bump build number to 575 2025-08-27 16:08:58 -05:00
bf8203bbee ci(release): bump build number to 574 2025-08-27 15:50:49 -05:00
e92eccf785 ci(release): bump build number to 573 2025-08-27 14:43:04 -05:00
f4f3de49ca fix(material check): alt mm causing issues and utilizing an 80% to just be ok 2025-08-25 18:34:09 -05:00
788d6367a3 refactor(labeling): removed the wrong import 2025-08-25 15:47:18 -05:00
24a97afe06 fix(fake edi): removed console log 2025-08-25 14:40:21 -05:00
37f82a9710 refactor(tms intergration): corrected how we added gl coding 2025-08-25 14:39:54 -05:00
369d16018c fix(bookin): corrected the error received from the book in fail 2025-08-25 14:38:00 -05:00
68901a857a fix(dm): corrected the remark section so its properly sent over 2025-08-25 14:09:13 -05:00
171763184c ci(release): bump build number to 572 2025-08-25 13:58:47 -05:00
b7de2a8dbe ci(release): bump build number to 571 2025-08-25 13:15:06 -05:00
e78083f496 ci(release): bump build number to 570 2025-08-25 12:18:17 -05:00
3f3b64bf2b ci(release): bump build number to 569 2025-08-25 12:15:27 -05:00
123bb127e8 ci(release): bump build number to 568 2025-08-21 07:33:43 -05:00
8d6ead3aa1 fix(produser): changes to include DM 2025-08-21 05:55:41 -05:00
3148aa79d7 refactor(materials): changes for permissions on material consume 2025-08-21 05:55:20 -05:00
4486fe2436 fix(ocp): zechetti type correction to include the printer name 2025-08-21 05:54:48 -05:00
0ba338d480 feat(rfid): new check to remove tags that have been at a line longer than 6 hours 2025-08-21 05:18:49 -05:00
846ac479b1 fix(transferlots): missed adding this 2025-08-21 05:14:03 -05:00
73d38ba3fe refactor(notifcations): changed hour to min in ti intergrations 2025-08-21 05:13:34 -05:00
27586e923a feat(ocp): zechetti 1 added in 2025-08-21 05:13:06 -05:00
662a951b98 feat(tms): a clean up function was added to remove releases added as blockers older than 45d 2025-08-21 05:10:25 -05:00
0c54cecbd4 ci(release): bump build number to 567 2025-08-20 20:51:22 -05:00
bcf5378966 ci(release): bump build number to 566 2025-08-20 20:04:51 -05:00
c5668e6cf1 chore(release): 2.25.0 2025-08-20 20:04:05 -05:00
213814b868 ci(release): bump build number to 565 2025-08-20 19:02:42 -05:00
7d5b0c46c1 ci(release): bump build number to 564 2025-08-19 17:37:40 -05:00
595e22e8e9 ci(release): bump build number to 563 2025-08-19 17:04:13 -05:00
a6f18554b8 ci(release): bump build number to 562 2025-08-19 17:00:13 -05:00
88f61c8eaa feat(ocp): materials contorls and transfer to next lot logic 2025-08-19 16:00:49 -05:00
a183279268 ci(release): bump build number to 561 2025-08-17 18:10:25 -05:00
5156c8bf7b ci(release): bump build number to 560 2025-08-14 09:32:25 -05:00
4669ff95dc ci(release): bump build number to 559 2025-08-13 22:52:44 -05:00
ed93992165 ci(release): bump build number to 558 2025-08-13 16:32:23 -05:00
f16e2bf53b ci(release): bump build number to 557 2025-08-13 15:50:35 -05:00
a84998438c ci(release): bump build number to 556 2025-08-13 11:33:45 -05:00
83469105f0 ci(release): bump build number to 555 2025-08-12 17:53:08 -05:00
835ae58f04 ci(release): bump build number to 554 2025-08-12 16:26:39 -05:00
1498a19121 ci(release): bump build number to 553 2025-08-12 14:28:42 -05:00
ca96849991 ci(release): bump build number to 552 2025-08-12 13:55:49 -05:00
27b37f9849 ci(release): bump build number to 551 2025-08-12 11:24:50 -05:00
7f81a2e09a ci(release): bump build number to 550 2025-08-11 12:24:30 -05:00
e14abd3644 ci(release): bump build number to 549 2025-08-11 08:22:44 -05:00
2ff7b9baf9 refactor(migrations): not needed but we have it and needed to correct the settings 2025-08-10 18:15:07 -05:00
8145dc800d refactor(siloadjustment): refactored to get the settings from the state vs direct from db 2025-08-10 18:14:38 -05:00
6ccf500e5e feat(prodrole): added in planner role 2025-08-10 18:14:08 -05:00
103171c924 refactor(notifications): refactored the cron job system so we can utilize outside the service 2025-08-10 18:13:32 -05:00
2eb6fa7794 fix(gotransport): error handling so we dont get spammed with errors 2025-08-10 18:12:52 -05:00
397f1da595 fix(inv query): error in improper placed , in the query 2025-08-10 18:12:29 -05:00
8d63f7f6b0 feat(psi): psi querys added and av grab right now 2025-08-10 18:11:57 -05:00
52345bc94c feat(eom): added in hostorical data and deletion for data over 45 days 2025-08-10 18:11:16 -05:00
a8a1c1d7fb ci(release): bump build number to 548 2025-08-09 15:05:59 -05:00
83ff2641f3 ci(release): bump build number to 547 2025-08-09 15:02:21 -05:00
7c48f608bc ci(release): bump build number to 546 2025-08-09 14:58:02 -05:00
1802b9ba4e ci(release): bump build number to 545 2025-08-09 14:41:23 -05:00
67a12ccc5c ci(release): bump build number to 544 2025-08-09 14:28:17 -05:00
15e2a65cbb ci(release): bump build number to 543 2025-08-07 21:18:09 -05:00
9e5577e6bb feat(dm): changes to have a default time if nothing is passed in the excel 2025-08-06 15:25:45 -05:00
c52e2a8671 ci(release): bump build number to 542 2025-08-06 15:19:54 -05:00
8f76d6998c ci(release): bump build number to 541 2025-08-06 15:08:13 -05:00
e209686d3c ci(release): bump build number to 540 2025-08-05 14:50:05 -05:00
803c963f96 fix(https fixes): made it so the settings can be grabbed via https 2025-08-05 14:45:04 -05:00
078f35626b ci(release): bump build number to 539 2025-08-05 14:16:26 -05:00
2288884829 fix(inv cards): correction to properly display the names 2025-08-04 18:12:32 -05:00
69fc7418c9 ci(release): bump build number to 538 2025-08-04 14:41:53 -05:00
a0179a41ba refactor(migration progress): moved to start looking at the go backedn 2025-08-04 12:48:49 -05:00
a36552fd9b fix(dm page): correction to the insturcitons 2025-08-04 12:48:04 -05:00
c7bb12822b fix(dyco): correction to disable the camera if ocme is off 2025-08-04 12:44:03 -05:00
98a5ca7bb8 ci(release): bump build number to 537 2025-08-04 09:48:20 -05:00
74ac2864c9 ci(release): bump build number to 536 2025-08-04 07:56:50 -05:00
1f93eca561 ci(release): bump build number to 535 2025-08-04 06:54:23 -05:00
1f44750346 ci(release): bump build number to 534 2025-07-31 11:58:56 -05:00
0d17fef1a1 fix(mainmaterial check): if the machine dose not require mm to be staged properly ignore 2025-07-31 11:54:40 -05:00
f574645b44 ci(release): bump build number to 533 2025-07-30 19:37:13 -05:00
998e84f564 feat(migration start): this starts the migration of all settings to look at the go backend vs this 2025-07-30 14:34:15 -05:00
3e51ebc18b ci(release): bump build number to 532 2025-07-29 21:11:53 -05:00
8129dbb787 ci(release): bump build number to 531 2025-07-29 20:51:27 -05:00
b5561635dd ci(release): bump build number to 530 2025-07-25 07:33:48 -05:00
ff340161d6 chore(release): 2.24.1 2025-07-25 07:33:03 -05:00
39d0768d50 fix(mm check): correction to know if a machine is required to have mm or not 2025-07-25 07:32:09 -05:00
d40ed30f55 fix(create labels): better logging to know where the error came from 2025-07-25 07:31:43 -05:00
8594d72d2c ci(release): bump build number to 529 2025-07-23 10:11:37 -05:00
3e680a5a50 fix(submodules): correction to accessing when changes made to roles 2025-07-23 10:10:18 -05:00
e1113c49b3 ci(release): bump build number to 528 2025-07-21 15:33:00 -05:00
e964bb70ae ci(release): bump build number to 527 2025-07-21 14:07:39 -05:00
f01b6941ba ci(release): bump build number to 526 2025-07-21 13:53:57 -05:00
e78f3ffdb5 ci(release): bump build number to 525 2025-07-20 08:51:38 -05:00
713df0b615 ci(release): bump build number to 524 2025-07-19 11:06:03 -05:00
f2615fbcea ci(release): bump build number to 523 2025-07-19 11:04:19 -05:00
4f7d6fe4af ci(release): bump build number to 522 2025-07-19 09:41:06 -05:00
96a3fd451b ci(release): bump build number to 521 2025-07-19 09:36:44 -05:00
d1befadd1c ci(release): bump build number to 520 2025-07-19 08:19:56 -05:00
fa99eb41dd ci(release): bump build number to 519 2025-07-19 08:14:19 -05:00
11cc3662cf ci(release): bump build number to 518 2025-07-18 17:15:13 -05:00
d9a2f90056 ci(release): bump build number to 517 2025-07-18 16:44:07 -05:00
23ee0468ad ci(release): bump build number to 516 2025-07-18 16:27:26 -05:00
83ba84cf6f ci(release): bump build number to 515 2025-07-18 16:14:44 -05:00
96d2a25081 ci(release): bump build number to 514 2025-07-18 16:04:01 -05:00
d54f85cf3d ci(release): bump build number to 513 2025-07-18 15:58:43 -05:00
371870cbe5 ci(release): bump build number to 512 2025-07-18 15:47:18 -05:00
dd31763fdd ci(release): bump build number to 511 2025-07-18 15:14:29 -05:00
c9a64e2e7c ci(release): bump build number to 510 2025-07-18 15:11:12 -05:00
733603fffa ci(release): bump build number to 509 2025-07-18 14:50:19 -05:00
bc92f8be0e ci(release): bump build number to 508 2025-07-18 14:47:55 -05:00
9ced82b154 ci(release): bump build number to 507 2025-07-18 14:40:30 -05:00
d9bc68d6ac ci(release): bump build number to 506 2025-07-18 14:13:08 -05:00
248e4cfeef ci(release): bump build number to 505 2025-07-18 13:59:18 -05:00
9707990211 ci(release): bump build number to 504 2025-07-18 13:53:03 -05:00
60672ba751 ci(release): bump build number to 503 2025-07-18 13:26:51 -05:00
3b8190b080 ci(release): bump build number to 502 2025-07-18 12:44:53 -05:00
c1577ff432 ci(release): bump build number to 501 2025-07-18 11:10:43 -05:00
40b382ca62 ci(release): bump build number to 500 2025-07-18 11:00:53 -05:00
1ec3de0f02 ci(release): bump build number to 499 2025-07-18 10:45:37 -05:00
f5c035081c ci(release): bump build number to 498 2025-07-18 10:43:27 -05:00
885e0ce348 ci(release): bump build number to 497 2025-07-18 09:02:37 -05:00
7a59da77f2 ci(release): bump build number to 496 2025-07-18 09:01:15 -05:00
82fb85ba0d ci(release): bump build number to 495 2025-07-18 08:30:11 -05:00
0d263f6941 ci(release): bump build number to 494 2025-07-18 08:16:07 -05:00
1762c70859 ci(release): bump build number to 493 2025-07-18 08:12:21 -05:00
c196b1d612 ci(release): bump build number to 492 2025-07-18 08:09:41 -05:00
8926bfde00 ci(release): bump build number to 491 2025-07-18 08:07:54 -05:00
256405b5a5 ci(release): bump build number to 490 2025-07-18 08:04:32 -05:00
eecf35fc9c ci(release): bump build number to 489 2025-07-18 07:57:26 -05:00
700b18160c ci(release): bump build number to 488 2025-07-18 07:50:57 -05:00
2dd6947bd6 ci(release): bump build number to 487 2025-07-18 07:41:41 -05:00
fe8ab62e94 ci(release): bump build number to 486 2025-07-18 07:17:04 -05:00
a0d476042b ci(release): bump build number to 485 2025-07-18 07:04:55 -05:00
8e99a2e5e5 ci(release): bump build number to 484 2025-07-18 06:53:22 -05:00
4b9f96f3b0 ci(release): bump build number to 483 2025-07-18 06:51:03 -05:00
390107a1fb ci(release): bump build number to 482 2025-07-18 06:44:53 -05:00
e3a4ef7a80 refactor(zip builds): removed the c# wrapper as it wont be used on this build anymore 2025-07-18 06:40:50 -05:00
c224e30b8d revert(mainmaterial): reverted changes to check for machine needing mm 2025-07-18 06:40:15 -05:00
16b710dc91 ci(release): bump build number to 481 2025-07-17 11:55:46 -05:00
a9e788f438 ci(release): bump build number to 480 2025-07-17 10:39:33 -05:00
3aa4191b0f ci(release): bump build number to 479 2025-07-17 10:36:08 -05:00
260d513ee3 ci(release): bump build number to 478 2025-07-17 07:21:51 -05:00
e9f729d5e2 ci(release): bump build number to 477 2025-07-17 07:10:51 -05:00
e43ac65d04 ci(release): bump build number to 476 2025-07-16 09:52:45 -05:00
5199a9ce69 ci(release): bump build number to 475 2025-07-16 09:45:29 -05:00
5ce78222b9 ci(release): bump build number to 474 2025-07-16 09:34:51 -05:00
904de61e5a ci(release): bump build number to 473 2025-07-16 09:31:28 -05:00
c1ed482073 ci(release): bump build number to 472 2025-07-16 09:26:49 -05:00
f57426cf13 refactor(serverdata): moved stp1 to d drive 2025-07-15 15:38:48 -05:00
7079b151da ci(release): bump build number to 471 2025-07-15 08:42:09 -05:00
b87cd8dd7c chore(release): 2.24.0 2025-07-15 08:41:27 -05:00
531b343d17 fix(dm): missing api key call, and better logging on the post orders section 2025-07-15 08:40:38 -05:00
e2b549714c ci(release): bump build number to 470 2025-07-15 08:33:18 -05:00
e6f3a9b4d0 fix(label ratio): missed a manual spot that was not considered 2025-07-15 08:20:03 -05:00
33295dc3c3 fix(rfid): corrections to the manual tag to no fail on manual when a tag already exists but failed 2025-07-15 08:19:36 -05:00
49fd9d65c9 refactor(dyco): pickup changed to let spam again so we dont miss anything 2025-07-15 08:18:50 -05:00
0510f13885 ci(release): bump build number to 469 2025-07-15 08:12:40 -05:00
588f264854 refactor(printers): addedin daily check for printers used to only be on a restart 2025-07-15 06:27:33 -05:00
8afa4176ef ci(release): bump build number to 468 2025-07-14 15:13:38 -05:00
611183fc19 ci(release): bump build number to 467 2025-07-14 14:48:16 -05:00
c31856ac3e ci(release): bump build number to 466 2025-07-14 12:38:59 -05:00
61f0b7f06b feat(labeling): ratios reset for labeling implemeneted 2025-07-14 12:37:38 -05:00
a7f8e39bac refactor(rfid): ratio resets implemeneted 2025-07-14 12:36:36 -05:00
4923b3c698 ci(release): bump build number to 465 2025-07-14 12:22:12 -05:00
28f34a6a31 ci(release): bump build number to 464 2025-07-14 12:14:34 -05:00
b81675e445 ci(release): bump build number to 463 2025-07-14 10:23:22 -05:00
c6d80dbc8a fix(rfid reader): ratio to be fixed 2 digits so it dose not span across the entire page 2025-07-14 10:19:34 -05:00
bc54b365ea refactor(consume material): changes to use api vs prod user 2025-07-14 10:18:59 -05:00
41308788fd feat(labelratio): new feature to monitor label ratio from auto and manual
this was designed more for dayton but could be used for all plants
2025-07-14 10:18:23 -05:00
d6232cb358 ci(release): bump build number to 462 2025-07-14 10:13:08 -05:00
d89a336fb1 ci(release): bump build number to 461 2025-07-14 09:40:41 -05:00
e84ae42c83 ci(release): bump build number to 460 2025-07-14 09:35:44 -05:00
6ec8f0863b ci(release): bump build number to 459 2025-07-14 09:19:38 -05:00
4f231b343c ci(release): bump build number to 458 2025-07-12 22:16:18 -05:00
454039e60c ci(release): bump build number to 457 2025-07-12 22:09:50 -05:00
c7c148fede ci(release): bump build number to 456 2025-07-11 06:56:14 -05:00
e30adc6612 ci(release): bump build number to 455 2025-07-11 06:49:29 -05:00
f7b4de8130 feat(rfid): front end view of the readers and there status 2025-07-10 21:29:01 -05:00
6584b37cb0 ci(release): bump build number to 454 2025-07-10 20:52:29 -05:00
6a082d9737 feat(rfid): more rfid topics while monitoring the system run 2025-07-10 20:09:35 -05:00
58711becf2 refactor(mm check): added in a check that if we dont need mm we return mm checked 2025-07-10 20:08:45 -05:00
f757085fc2 refactor(ocp page): changes to the layout so it can better be moved for the tiles 2025-07-10 20:07:59 -05:00
8f5e1cb094 refactor(wrapper card): changes to include the rfid and remove the manual trigger as no one used it 2025-07-10 20:07:35 -05:00
7497ee454c feat(rfid): added in manual trigger for rfid reader at the wrapper 2025-07-10 20:07:10 -05:00
c0ede8714c feat(readers): added in good and bad reads to monitor eff 2025-07-10 20:06:31 -05:00
1a6a05112b fix(db): lastRead column was named incorrectly 2025-07-10 20:06:05 -05:00
97c6631eab ci(release): bump build number to 453 2025-07-10 20:04:31 -05:00
1ae506939c ci(release): bump build number to 452 2025-07-10 19:56:21 -05:00
f0294942a7 ci(release): bump build number to 451 2025-07-10 14:42:37 -05:00
e323607b39 ci(release): bump build number to 450 2025-07-10 14:32:25 -05:00
df0851414e ci(release): bump build number to 449 2025-07-10 14:13:05 -05:00
a9b860a34d ci(release): bump build number to 448 2025-07-10 14:06:37 -05:00
ead35b4360 ci(release): bump build number to 447 2025-07-10 13:52:06 -05:00
d6b1a75afa ci(release): bump build number to 446 2025-07-10 12:25:17 -05:00
1b661a6685 ci(release): bump build number to 445 2025-07-10 12:16:58 -05:00
f597142ee3 ci(release): bump build number to 444 2025-07-10 08:04:44 -05:00
18780d872c ci(release): bump build number to 443 2025-07-10 07:25:23 -05:00
ba02ee42c5 ci(release): bump build number to 442 2025-07-10 07:14:56 -05:00
f573f4f721 ci(release): bump build number to 441 2025-07-10 07:13:51 -05:00
1d6bf7215b ci(release): bump build number to 440 2025-07-09 20:15:37 -05:00
e616574fa6 ci(release): bump build number to 439 2025-07-09 18:24:44 -05:00
08109f500f ci(release): bump build number to 438 2025-07-08 17:36:31 -05:00
ab8102afbf feat(prodroles): new cto role added 2025-07-08 17:35:20 -05:00
e13b5a4283 fix(logs): time crap 2025-07-08 17:28:11 -05:00
7a4dea9d87 fix(rfid): lots of changes to the wrapper area 2025-07-08 17:27:08 -05:00
a19ac539e7 refactor(rfid): reduced teh rssi peak -50 > -40 2025-07-08 17:25:38 -05:00
1c910d80ea fix(rfid): existing tags were trying to be inserted and instead of updating failed corrected 2025-07-08 17:25:09 -05:00
56e0f3eb47 fix(rfid): typos in station 3 logging 2025-07-08 17:24:21 -05:00
e50e9af839 refactor(dyco): change the plc check time from 5 > 8 2025-07-08 17:23:48 -05:00
e34f273acb ci(release): bump build number to 437 2025-07-08 15:11:48 -05:00
2c5f8a3a8c ci(release): bump build number to 436 2025-07-08 15:06:13 -05:00
9e4729690a ci(release): bump build number to 435 2025-07-08 15:03:24 -05:00
26ab6ecd8d ci(release): bump build number to 434 2025-07-07 15:05:44 -05:00
05fa774d68 fix(detach silo): when pressing cancel the detach funciton would not work 2025-06-26 13:45:14 -05:00
b1acd97232 ci(release): bump build number to 433 2025-06-26 13:35:06 -05:00
165 changed files with 16774 additions and 705 deletions

2
.gitignore vendored
View File

@@ -156,3 +156,5 @@ dist
backend-0.1.3.zip
BulkForecastTemplate
BulkOrdersTemplate
check.json
server/services/ocp/controller/materials/materialcheck.bak

8
.includes Normal file
View File

@@ -0,0 +1,8 @@
database
dist
frontend/dist
CHANGELOG.md
drizzle.config.ts
package.json
package-lock.json
README.md

View File

@@ -1,5 +1,185 @@
# 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)
### 🐛 Bug fixes
* **dm page:** correction to the insturcitons ([a36552f](https://git.tuffraid.net/cowch/lstV2/commits/a36552fd9b9c77f8ecee8b36f45e613383841f95))
* **dyco:** correction to disable the camera if ocme is off ([c7bb128](https://git.tuffraid.net/cowch/lstV2/commits/c7bb12822b13c0c1c929d2c8a9ab150cd0feeff2))
* **gotransport:** error handling so we dont get spammed with errors ([2eb6fa7](https://git.tuffraid.net/cowch/lstV2/commits/2eb6fa77946d5f8572ffc5baa47da602482bce2b))
* **https fixes:** made it so the settings can be grabbed via https ([803c963](https://git.tuffraid.net/cowch/lstV2/commits/803c963f964f26095b2aa6a7d0a60e03615d4c17))
* **inv cards:** correction to properly display the names ([2288884](https://git.tuffraid.net/cowch/lstV2/commits/22888848291aa3df4ebbdd224656731fbb305fa7))
* **inv query:** error in improper placed , in the query ([397f1da](https://git.tuffraid.net/cowch/lstV2/commits/397f1da595fd8a1e1c2a630a3650eb8715604c82))
* **mainmaterial check:** if the machine dose not require mm to be staged properly ignore ([0d17fef](https://git.tuffraid.net/cowch/lstV2/commits/0d17fef1a1c75dd0f27988fd2e3527b508b915cb))
### 🛠️ Code Refactor
* **migration progress:** moved to start looking at the go backedn ([a0179a4](https://git.tuffraid.net/cowch/lstV2/commits/a0179a41bac93d2a7320802e9d70aa966ed79ae4))
* **migrations:** not needed but we have it and needed to correct the settings ([2ff7b9b](https://git.tuffraid.net/cowch/lstV2/commits/2ff7b9baf9ca288f8a33bec3ab1a2ba331ace6b9))
* **notifications:** refactored the cron job system so we can utilize outside the service ([103171c](https://git.tuffraid.net/cowch/lstV2/commits/103171c924a9de78b0a7600abb455fdd6f4bfea1))
* **siloadjustment:** refactored to get the settings from the state vs direct from db ([8145dc8](https://git.tuffraid.net/cowch/lstV2/commits/8145dc800dced31860a926c80eca72cb39433b29))
### 🌟 Enhancements
* **dm:** changes to have a default time if nothing is passed in the excel ([9e5577e](https://git.tuffraid.net/cowch/lstV2/commits/9e5577e6bb4ff3b6c4004288e177fbab322a4b44))
* **eom:** added in hostorical data and deletion for data over 45 days ([52345bc](https://git.tuffraid.net/cowch/lstV2/commits/52345bc94c9e8abc82150fb371a9ba0d0757f16a))
* **migration start:** this starts the migration of all settings to look at the go backend vs this ([998e84f](https://git.tuffraid.net/cowch/lstV2/commits/998e84f5648148c9a94df7177a3d311e16bf4614))
* **ocp:** materials contorls and transfer to next lot logic ([88f61c8](https://git.tuffraid.net/cowch/lstV2/commits/88f61c8eaa32a581094b04b5e18c654040dbeb92))
* **prodrole:** added in planner role ([6ccf500](https://git.tuffraid.net/cowch/lstV2/commits/6ccf500e5eb82125f7bcd3d764282a4b8a750be9))
* **psi:** psi querys added and av grab right now ([8d63f7f](https://git.tuffraid.net/cowch/lstV2/commits/8d63f7f6b0981d604b628ff2f710b8eb41d32837))
### [2.24.1](https://git.tuffraid.net/cowch/lstV2/compare/v2.24.0...v2.24.1) (2025-07-25)
### 🛠️ Code Refactor
* **serverdata:** moved stp1 to d drive ([f57426c](https://git.tuffraid.net/cowch/lstV2/commits/f57426cf13b11b357a1436317f592286084e0fb1))
* **zip builds:** removed the c# wrapper as it wont be used on this build anymore ([e3a4ef7](https://git.tuffraid.net/cowch/lstV2/commits/e3a4ef7a804390cf1e381766baf7baf60b873a57))
### 🐛 Bug fixes
* **create labels:** better logging to know where the error came from ([d40ed30](https://git.tuffraid.net/cowch/lstV2/commits/d40ed30f55b1fb1a3c7a4ecde6dc40c535f3c0ed))
* **mm check:** correction to know if a machine is required to have mm or not ([39d0768](https://git.tuffraid.net/cowch/lstV2/commits/39d0768d503c415b5d1ca845db2a292613f4fbed))
* **submodules:** correction to accessing when changes made to roles ([3e680a5](https://git.tuffraid.net/cowch/lstV2/commits/3e680a5a503761a4a358b4a62e07c4aa545a6f10))
## [2.24.0](https://git.tuffraid.net/cowch/lstV2/compare/v2.23.0...v2.24.0) (2025-07-15)
### 📝 Chore
* **updated packages:** all pacakges were just updated ([4a02bbc](https://git.tuffraid.net/cowch/lstV2/commits/4a02bbc3686f6ed150f1f22146c924aacf1f6b1b))
### 📝 Testing Code
* **material returns:** added type check ([d6d19f8](https://git.tuffraid.net/cowch/lstV2/commits/d6d19f8e5b81d34652c9b7421cb934a81ef03136))
### 🌟 Enhancements
* **default accounts:** added in a default account run this will create a bunch of system admins ([b9ff0a4](https://git.tuffraid.net/cowch/lstV2/commits/b9ff0a4138843e191351f2bcec75e8305a78d6f2))
* **labeling:** ratios reset for labeling implemeneted ([61f0b7f](https://git.tuffraid.net/cowch/lstV2/commits/61f0b7f06b8f0a811387dc3f17fcacb00804d146))
* **labelratio:** new feature to monitor label ratio from auto and manual ([4130878](https://git.tuffraid.net/cowch/lstV2/commits/41308788fdc5e918450db0721199bd4ac7da17e7))
* **logistics:** get sscc based on runnning number ([7df512a](https://git.tuffraid.net/cowch/lstV2/commits/7df512acaa3a2b3cc30131d61563580c124d4f05))
* **notifcations:** pallets booked as waste brought back in via cycle count ([095d724](https://git.tuffraid.net/cowch/lstV2/commits/095d724e65f211253ccdb075a2afb3c5ad267932))
* **notify:** shortage bookings based on time and article type ([c5bd5a7](https://git.tuffraid.net/cowch/lstV2/commits/c5bd5a7c0a074ac1b94fa5435992f2b9a8e65132))
* **prodroles:** added in quality manager ([4abecd0](https://git.tuffraid.net/cowch/lstV2/commits/4abecd045556c98b42cd6ac132958a32a3279a54))
* **prodroles:** new cto role added ([ab8102a](https://git.tuffraid.net/cowch/lstV2/commits/ab8102afbfc62ba41de38c021ab7c0a78e972a90))
* **readers:** added in good and bad reads to monitor eff ([c0ede87](https://git.tuffraid.net/cowch/lstV2/commits/c0ede8714cd99e9b92b4169b9eaf90de3e1d46ab))
* **rfid:** added in manual trigger for rfid reader at the wrapper ([7497ee4](https://git.tuffraid.net/cowch/lstV2/commits/7497ee454c792fabe2c5bd0427f63e725b4a781e))
* **rfid:** front end view of the readers and there status ([f7b4de8](https://git.tuffraid.net/cowch/lstV2/commits/f7b4de813051f1bd28fea98c6473a156024b1a1c))
* **rfid:** more rfid topics while monitoring the system run ([6a082d9](https://git.tuffraid.net/cowch/lstV2/commits/6a082d97375be872ecec33c2045d37c8368d790a))
* **silo attached detach:** added in silo attach detach setup in the silo card ([2ac4813](https://git.tuffraid.net/cowch/lstV2/commits/2ac48138cba961fc09853ab16b4bb2f1dc2972f0))
### 🛠️ Code Refactor
* **consume material:** changes to use api vs prod user ([bc54b36](https://git.tuffraid.net/cowch/lstV2/commits/bc54b365ea9472170a1d22364ac3d9b635175386))
* **datamart:** changes to customer inventory to include specific whse ([3073df3](https://git.tuffraid.net/cowch/lstV2/commits/3073df342ff2ede979d2e7f4b2bb16dacb99c093))
* **dbscheme:** refactoring from opening and saving ([c155e89](https://git.tuffraid.net/cowch/lstV2/commits/c155e89bc7e62a4beb09b4978445075c088d0133))
* **dyco:** change the plc check time from 5 > 8 ([e50e9af](https://git.tuffraid.net/cowch/lstV2/commits/e50e9af839caf9aca8bf71419433bee41702a656))
* **dyco:** pickup changed to let spam again so we dont miss anything ([49fd9d6](https://git.tuffraid.net/cowch/lstV2/commits/49fd9d65c9cf23c1524ec2d4c16628cb742a6077))
* **finance query:** changes to include article type ([26ceb95](https://git.tuffraid.net/cowch/lstV2/commits/26ceb95daefa1615dbc4e41f68763283c1ae91a3))
* **lim:** shipping hours change ([7ed9db1](https://git.tuffraid.net/cowch/lstV2/commits/7ed9db1bdb2c5a1fee867d1501fc909f47e8ddaf))
* **mm check:** added in a check that if we dont need mm we return mm checked ([58711be](https://git.tuffraid.net/cowch/lstV2/commits/58711becf2eec518ebca9a0239c2b97f23b38372))
* **ocp page:** changes to the layout so it can better be moved for the tiles ([f757085](https://git.tuffraid.net/cowch/lstV2/commits/f757085fc2936c929fbfce19e9784ab14654193d))
* **printers:** addedin daily check for printers used to only be on a restart ([588f264](https://git.tuffraid.net/cowch/lstV2/commits/588f264854a5898f633114032398608985e4371c))
* **rfid:** ratio resets implemeneted ([a7f8e39](https://git.tuffraid.net/cowch/lstV2/commits/a7f8e39bac684b94a68ed484987b9c6c1693e3ec))
* **rfid:** reduced teh rssi peak -50 > -40 ([a19ac53](https://git.tuffraid.net/cowch/lstV2/commits/a19ac539e7e65741858730e2089517756962c558))
* **server data:** changes to bet and stp1 ([bd5bad3](https://git.tuffraid.net/cowch/lstV2/commits/bd5bad3cba587f53c8c6e31555c6433620c7a474))
* **serverdb:** format changes ([77d9e5d](https://git.tuffraid.net/cowch/lstV2/commits/77d9e5d095a1f31fcbdd094b2dd39b89ddabce87))
* **wrapper card:** changes to include the rfid and remove the manual trigger as no one used it ([8f5e1cb](https://git.tuffraid.net/cowch/lstV2/commits/8f5e1cb0948354d13b7def478226e3e82b377829))
### 🐛 Bug fixes
* **dashboard:** some more rending fixes due to some strange behaivers ([f4dd572](https://git.tuffraid.net/cowch/lstV2/commits/f4dd572a8f8889c5938145ef9d74621da27ae206))
* **db:** lastRead column was named incorrectly ([1a6a051](https://git.tuffraid.net/cowch/lstV2/commits/1a6a05112b869358b3f2e87e688670ab95eb27a7))
* **detach silo:** when pressing cancel the detach funciton would not work ([05fa774](https://git.tuffraid.net/cowch/lstV2/commits/05fa774d68c5bb006dd7fb317138bbc630a1cf55))
* **dm:** missing api key call, and better logging on the post orders section ([531b343](https://git.tuffraid.net/cowch/lstV2/commits/531b343d17a0706bb18f8c7fc047422c5348fb92))
* **label ratio:** missed a manual spot that was not considered ([e6f3a9b](https://git.tuffraid.net/cowch/lstV2/commits/e6f3a9b4d07765264d788a261a7b10c731d19987))
* **logs:** time crap ([e13b5a4](https://git.tuffraid.net/cowch/lstV2/commits/e13b5a42836f337607f2fc0fd359c3f8cfdf4443))
* **ocp page:** server info error added check to make sure was there ([3cafbd9](https://git.tuffraid.net/cowch/lstV2/commits/3cafbd92d0d1fd6dbdb8d92cfa811b9eaa7c60d0))
* **renderfixes:** some strange rendering fixes that should have been caught long time ago ([3b56a5e](https://git.tuffraid.net/cowch/lstV2/commits/3b56a5e3e2d37858be4c4ce08f33abbf31f141d0))
* **rfid reader:** ratio to be fixed 2 digits so it dose not span across the entire page ([c6d80db](https://git.tuffraid.net/cowch/lstV2/commits/c6d80dbc8a0dcb5a8b219913c9dec1065208012e))
* **rfid:** corrections to the manual tag to no fail on manual when a tag already exists but failed ([33295dc](https://git.tuffraid.net/cowch/lstV2/commits/33295dc3c39569d818d4c7245390891e34080c9d))
* **rfid:** existing tags were trying to be inserted and instead of updating failed corrected ([1c910d8](https://git.tuffraid.net/cowch/lstV2/commits/1c910d80ead6b9196dd4181534c6044a007e81b5))
* **rfid:** lots of changes to the wrapper area ([7a4dea9](https://git.tuffraid.net/cowch/lstV2/commits/7a4dea9d87fa15def544d810b8da422acd142e6c))
* **rfid:** typos in station 3 logging ([56e0f3e](https://git.tuffraid.net/cowch/lstV2/commits/56e0f3eb47a1c34b9b07121bc6189e793e08eea5))
* **settings page:** error with the store not starting as fast as the page ([edc874c](https://git.tuffraid.net/cowch/lstV2/commits/edc874c302a8693b5d7a3abdb98cd95f44134e49))
## [2.23.0](https://git.tuffraid.net/cowch/lstV2/compare/v2.22.0...v2.23.0) (2025-06-17)

View File

@@ -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
Logistics Support Tool V2

View File

@@ -0,0 +1 @@
ALTER TABLE "rfidTags" RENAME COLUMN "timeStamp" TO "lastRead";

View File

@@ -0,0 +1,2 @@
ALTER TABLE "rfidReaders" ADD COLUMN "goodReads" integer DEFAULT 0;--> statement-breakpoint
ALTER TABLE "rfidReaders" ADD COLUMN "badReads" integer DEFAULT 0;

View File

@@ -0,0 +1,10 @@
CREATE TABLE "labelRatio" (
" ratio_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"name" text DEFAULT 'labels',
"autoLabel" integer DEFAULT 0,
"manualLabel" integer DEFAULT 0,
"lastReset" timestamp DEFAULT now()
);
--> statement-breakpoint
ALTER TABLE "invHistoricalData" ADD COLUMN "lot_number" text;--> statement-breakpoint
CREATE UNIQUE INDEX "labelname" ON "labelRatio" USING btree ("name");

View File

@@ -0,0 +1,2 @@
ALTER TABLE "invHistoricalData" ALTER COLUMN "upd_user" SET DEFAULT 'lst';--> statement-breakpoint
ALTER TABLE "invHistoricalData" ALTER COLUMN "upd_date" SET DEFAULT now();

View 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;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -477,6 +477,41 @@
"when": 1749744049457,
"tag": "0067_shallow_trish_tilby",
"breakpoints": true
},
{
"idx": 68,
"version": "7",
"when": 1752195741709,
"tag": "0068_last_caretaker",
"breakpoints": true
},
{
"idx": 69,
"version": "7",
"when": 1752195894698,
"tag": "0069_chemical_maximus",
"breakpoints": true
},
{
"idx": 70,
"version": "7",
"when": 1754767718941,
"tag": "0070_brief_mephisto",
"breakpoints": true
},
{
"idx": 71,
"version": "7",
"when": 1754768521841,
"tag": "0071_fantastic_old_lace",
"breakpoints": true
},
{
"idx": 72,
"version": "7",
"when": 1757167736042,
"tag": "0072_round_black_knight",
"breakpoints": true
}
]
}

View File

View File

View File

View File

@@ -12,7 +12,7 @@ export const invHistoricalData = pgTable(
"invHistoricalData",
{
inv_id: uuid("inv_id").defaultRandom().primaryKey(),
histDate: date("histDate").notNull(), // what month are we running in should just be the first of current month
histDate: date("histDate").notNull(), // this date should always be yesterday when we post it.
plantToken: text("plantToken"),
article: text("article").notNull(),
articleDescription: text("articleDescription").notNull(),
@@ -21,10 +21,11 @@ export const invHistoricalData = pgTable(
avaliable_QTY: text("avaliable_QTY"),
coa_QTY: text("coa_QTY"),
held_QTY: text("held_QTY"),
lot_Number: text("lot_number"),
consignment: text("consignment"),
location: text("location"),
upd_user: text("upd_user"),
upd_date: timestamp("upd_date"),
upd_user: text("upd_user").default("lst"),
upd_date: timestamp("upd_date").defaultNow(),
}
// (table) => [
// // uniqueIndex('emailUniqueIndex').on(sql`lower(${table.email})`),

32
database/schema/ratios.ts Normal file
View File

@@ -0,0 +1,32 @@
import {
integer,
jsonb,
pgTable,
text,
timestamp,
uniqueIndex,
uuid,
} from "drizzle-orm/pg-core";
import { createSelectSchema } from "drizzle-zod";
export const labelRatio = pgTable(
"labelRatio",
{
ratio_id: uuid(" ratio_id").defaultRandom().primaryKey(),
name: text("name").default("labels"),
autoLabel: integer("autoLabel").default(0),
manualLabel: integer("manualLabel").default(0),
lastReset: timestamp().defaultNow(),
},
(table) => [
// uniqueIndex('emailUniqueIndex').on(sql`lower(${table.email})`),
uniqueIndex("labelname").on(table.name),
]
);
// Schema for inserting a user - can be used to validate API requests
// export const insertRolesSchema = createInsertSchema(roles, {
// name: z.string().min(3, {message: "Role name must be more than 3 letters"}),
// });
// Schema for selecting a Expenses - can be used to validate API responses
export const selectRolesSchema = createSelectSchema(labelRatio);

View File

@@ -8,6 +8,7 @@ import {
uuid,
uniqueIndex,
jsonb,
integer,
} from "drizzle-orm/pg-core";
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
import { z } from "zod";
@@ -23,6 +24,8 @@ export const rfidReaders = pgTable(
lastTriggerGood: boolean("lastTiggerGood").default(true),
active: boolean("active").default(true),
lastTagScanned: text("lastTagScanned"),
goodReads: integer("goodReads").default(0),
badReads: integer("badReads").default(0),
},
(table) => [
// uniqueIndex('emailUniqueIndex').on(sql`lower(${table.email})`),

View File

@@ -16,7 +16,7 @@ export const rfidTags = pgTable(
rfidTag_id: uuid("rfidTag_id").defaultRandom().primaryKey(),
tagHex: text("tagHex"),
tag: text("tag"),
lastRead: timestamp("timeStamp").defaultNow(),
lastRead: timestamp("lastRead").defaultNow(), // cahnge this and hope we dont loose the data.
counts: jsonb("counts").default([]), // example [{area: Line3.2, count: 1}, {area: line3.1, count: 6}]
lastareaIn: text("lastareaIn").notNull(),
runningNumber: integer("runningNumber"),

View File

@@ -27,7 +27,7 @@ export const userRoles = pgTable(
{
user_id: uuid("user_id")
.notNull()
.references(() => users.user_id),
.references(() => users.user_id, { onDelete: "cascade" }),
role_id: uuid("role_id")
.notNull()
.references(() => roles.role_id),

View File

@@ -21,6 +21,7 @@
"@radix-ui/react-select": "^2.2.5",
"@radix-ui/react-separator": "^1.1.7",
"@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-switch": "^1.2.6",
"@radix-ui/react-tabs": "^1.1.12",
"@radix-ui/react-tooltip": "^1.2.7",
"@react-pdf/renderer": "^4.3.0",
@@ -2072,6 +2073,41 @@
}
}
},
"node_modules/@radix-ui/react-switch": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.2.6.tgz",
"integrity": "sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==",
"license": "MIT",
"dependencies": {
"@radix-ui/primitive": "1.1.3",
"@radix-ui/react-compose-refs": "1.1.2",
"@radix-ui/react-context": "1.1.2",
"@radix-ui/react-primitive": "2.1.3",
"@radix-ui/react-use-controllable-state": "1.2.2",
"@radix-ui/react-use-previous": "1.1.1",
"@radix-ui/react-use-size": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-switch/node_modules/@radix-ui/primitive": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz",
"integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==",
"license": "MIT"
},
"node_modules/@radix-ui/react-tabs": {
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.12.tgz",
@@ -5316,18 +5352,6 @@
"node": ">= 4"
}
},
"node_modules/immer": {
"version": "10.1.1",
"resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz",
"integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==",
"license": "MIT",
"optional": true,
"peer": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/immer"
}
},
"node_modules/import-fresh": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",

View File

@@ -25,6 +25,7 @@
"@radix-ui/react-select": "^2.2.5",
"@radix-ui/react-separator": "^1.1.7",
"@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-switch": "^1.2.6",
"@radix-ui/react-tabs": "^1.1.12",
"@radix-ui/react-tooltip": "^1.2.7",
"@react-pdf/renderer": "^4.3.0",

View File

@@ -15,6 +15,7 @@ import { ChangeSubModule } from "./SubModuleForm";
import { Skeleton } from "@/components/ui/skeleton";
import { getSubModules } from "@/utils/querys/admin/subModules";
import { useEffect } from "react";
export type Settings = {
settings_id?: string;
@@ -28,14 +29,34 @@ export default function SubModulePage() {
const { modules } = useModuleStore();
const router = useRouter();
const adminModule = modules.filter((n) => n.name === "admin");
const userLevel =
user?.roles.filter((r) => r.module_id === adminModule[0].module_id) ||
[];
// const adminModule = modules.filter((n) => n.name === "admin");
// const userLevel =
// user?.roles.filter((r) => r.module_id === adminModule[0].module_id) ||
// [];
if (!adminModule[0].roles.includes(userLevel[0]?.role)) {
router.navigate({ to: "/" });
}
// if (!adminModule[0]?.roles.includes(userLevel[0]?.role)) {
// //router.navigate({ to: "/" });
// }
useEffect(() => {
if (!user || modules.length === 0) return;
const adminModule = modules.find((n) => n.name === "admin");
if (!adminModule) {
console.log("no module loaded");
//router.navigate({ to: "/" });
return;
}
const userLevel =
user?.roles?.filter((r) => r.module_id === adminModule.module_id) ||
[];
if (!adminModule.roles?.includes(userLevel[0]?.role)) {
console.log("Something failed");
//router.navigate({ to: "/" });
}
}, [modules, user, router]);
const { data, isError, error, isLoading } = useQuery(
getSubModules(token ?? "")

View File

@@ -1,131 +1,9 @@
import {useSessionStore} from "@/lib/store/sessionStore";
import {LstCard} from "../extendedUI/LstCard";
import {Tabs, TabsContent, TabsList, TabsTrigger} from "../ui/tabs";
import {useModuleStore} from "@/lib/store/useModuleStore";
import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "../ui/table";
import {Skeleton} from "../ui/skeleton";
import {Link, useRouter} from "@tanstack/react-router";
import {Popover, PopoverContent, PopoverTrigger} from "../ui/popover";
import {Button} from "../ui/button";
import {cn} from "@/lib/utils";
import {CalendarIcon} from "lucide-react";
import {format, startOfMonth} from "date-fns";
import {Calendar} from "../ui/calendar";
import {useState} from "react";
import {toast} from "sonner";
import KFP from "./KFP";
import MaterialCheck from "./materialCheck/MaterialCheck";
export default function EomPage() {
const {modules} = useModuleStore();
const {user} = useSessionStore();
const router = useRouter();
const [date, setDate] = useState<Date>();
if (!user) {
router.navigate({to: "/"});
}
const eomMod = modules.filter((m) => m.name === "eom");
// the users current role for eom is?
const role: any = user?.roles.filter((r) => r.module_id === eomMod[0].module_id) || "";
const tabs = [
{key: "kfp", label: "Key Figures", roles: ["admin", "systemAdmin"], content: <KFP />},
{key: "fg", label: "Finished Goods", roles: ["admin", "systemAdmin"], content: <DummyContent />},
{key: "mm", label: "Main Material", roles: ["admin", "systemAdmin"], content: <DummyContent />},
{key: "mb", label: "Master Batch", roles: ["admin", "systemAdmin"], content: <DummyContent />},
{key: "ab", label: "Additive", roles: ["admin", "systemAdmin"], content: <DummyContent />},
{key: "pp", label: "Purchased Preforms", roles: ["admin", "systemAdmin"], content: <DummyContent />},
{key: "pre", label: "Preforms", roles: ["admin", "systemAdmin"], content: <DummyContent />},
{key: "pkg", label: "Packaging", roles: ["admin", "systemAdmin"], content: <DummyContent />},
{key: "ui", label: "Undefined Items", roles: ["admin"], content: <DummyContent />},
];
return (
<div className="m-2 w-screen">
<div className="mb-2 flex flex-row">
<Popover>
<PopoverTrigger asChild>
<Button
variant={"outline"}
className={cn(
"w-[280px] justify-start text-left font-normal",
!date && "text-muted-foreground"
)}
>
<CalendarIcon className="mr-2 h-4 w-4" />
{date ? format(date, "PPP") : <span>Pick a date</span>}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Calendar mode="single" selected={date} onSelect={setDate} initialFocus />
</PopoverContent>
</Popover>
<div className="ml-2">
<Button onClick={() => toast.success(`Getting data for ${startOfMonth(date!)}-${date}`)}>
<span className="text-sm">Update Data</span>
</Button>
</div>
</div>
<Tabs defaultValue="mm">
<TabsList>
{tabs.map((tab) => {
if (tab.roles.includes(role[0].role))
return <TabsTrigger value={tab.key}>{tab.label}</TabsTrigger>;
})}
</TabsList>
{tabs.map((tab) => {
if (tab.roles.includes(role[0].role))
return <TabsContent value={tab.key}>{tab.content}</TabsContent>;
})}
</Tabs>
<MaterialCheck />
</div>
);
}
function DummyContent() {
return (
<LstCard className="w-5/6">
<Table>
<TableHeader>
<TableRow>
<TableHead>Av</TableHead>
<TableHead>Description</TableHead>
<TableHead>Material Type</TableHead>
<TableHead>Waste</TableHead>
<TableHead>Loss / Gain $$</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{Array(10)
.fill(0)
.map((_, i) => (
<TableRow key={i}>
<TableCell className="font-medium m-2">
<Link to="/article/$av" params={{av: `${i}`}}>
{i}
</Link>
</TableCell>
<TableCell className="font-medium">
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
{/* <TableCell>
<Skeleton className="h-4" />
</TableCell> */}
</TableRow>
))}
</TableBody>
</Table>
</LstCard>
);
}

View File

@@ -0,0 +1,3 @@
export default function MaterialCheck() {
return <div>MaterialCheck</div>;
}

View File

@@ -0,0 +1,211 @@
import { LstCard } from "@/components/extendedUI/LstCard";
import { Button } from "@/components/ui/button";
import { Calendar } from "@/components/ui/calendar";
import { Popover, PopoverTrigger } from "@/components/ui/popover";
import { Skeleton } from "@/components/ui/skeleton";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { useSessionStore } from "@/lib/store/sessionStore";
import { useModuleStore } from "@/lib/store/useModuleStore";
import { cn } from "@/lib/utils";
import { PopoverContent } from "@radix-ui/react-popover";
import { Link, useRouter } from "@tanstack/react-router";
import { startOfMonth } from "date-fns";
import { format } from "date-fns-tz";
import { CalendarIcon } from "lucide-react";
import { useState } from "react";
import { toast } from "sonner";
import KFP from "../KFP";
export default function MaterialData() {
const { modules } = useModuleStore();
const { user } = useSessionStore();
const router = useRouter();
const [date, setDate] = useState<Date>();
if (!user) {
router.navigate({ to: "/" });
}
const eomMod = modules.filter((m) => m.name === "eom");
// the users current role for eom is?
const role: any =
user?.roles.filter((r) => r.module_id === eomMod[0].module_id) || "";
const tabs = [
{
key: "kfp",
label: "Key Figures",
roles: ["admin", "systemAdmin"],
content: <KFP />,
},
{
key: "fg",
label: "Finished Goods",
roles: ["admin", "systemAdmin"],
content: <DummyContent />,
},
{
key: "mm",
label: "Main Material",
roles: ["admin", "systemAdmin"],
content: <DummyContent />,
},
{
key: "mb",
label: "Master Batch",
roles: ["admin", "systemAdmin"],
content: <DummyContent />,
},
{
key: "ab",
label: "Additive",
roles: ["admin", "systemAdmin"],
content: <DummyContent />,
},
{
key: "pp",
label: "Purchased Preforms",
roles: ["admin", "systemAdmin"],
content: <DummyContent />,
},
{
key: "pre",
label: "Preforms",
roles: ["admin", "systemAdmin"],
content: <DummyContent />,
},
{
key: "pkg",
label: "Packaging",
roles: ["admin", "systemAdmin"],
content: <DummyContent />,
},
{
key: "ui",
label: "Undefined Items",
roles: ["admin"],
content: <DummyContent />,
},
];
return (
<div className="m-2 w-screen">
<div className="mb-2 flex flex-row">
<Popover>
<PopoverTrigger asChild>
<Button
variant={"outline"}
className={cn(
"w-[280px] justify-start text-left font-normal",
!date && "text-muted-foreground"
)}
>
<CalendarIcon className="mr-2 h-4 w-4" />
{date ? (
format(date, "PPP")
) : (
<span>Pick a date</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Calendar
mode="single"
selected={date}
onSelect={setDate}
initialFocus
/>
</PopoverContent>
</Popover>
<div className="ml-2">
<Button
onClick={() =>
toast.success(
`Getting data for ${startOfMonth(date!)}-${date}`
)
}
>
<span className="text-sm">Update Data</span>
</Button>
</div>
</div>
<Tabs defaultValue="mm">
<TabsList>
{tabs.map((tab) => {
if (tab.roles.includes(role[0].role))
return (
<TabsTrigger value={tab.key}>
{tab.label}
</TabsTrigger>
);
})}
</TabsList>
{tabs.map((tab) => {
if (tab.roles.includes(role[0].role))
return (
<TabsContent value={tab.key}>
{tab.content}
</TabsContent>
);
})}
</Tabs>
</div>
);
}
function DummyContent() {
return (
<LstCard className="w-5/6">
<Table>
<TableHeader>
<TableRow>
<TableHead>Av</TableHead>
<TableHead>Description</TableHead>
<TableHead>Material Type</TableHead>
<TableHead>Waste</TableHead>
<TableHead>Loss / Gain $$</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{Array(10)
.fill(0)
.map((_, i) => (
<TableRow key={i}>
<TableCell className="font-medium m-2">
<Link
to="/article/$av"
params={{ av: `${i}` }}
>
{i}
</Link>
</TableCell>
<TableCell className="font-medium">
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
{/* <TableCell>
<Skeleton className="h-4" />
</TableCell> */}
</TableRow>
))}
</TableBody>
</Table>
</LstCard>
);
}

View File

@@ -1,4 +1,4 @@
import {Printer} from "lucide-react";
import { Printer, Tag } from "lucide-react";
import {
SidebarGroup,
SidebarGroupContent,
@@ -7,21 +7,36 @@ import {
SidebarMenuButton,
SidebarMenuItem,
} from "../../ui/sidebar";
import {hasPageAccess} from "@/utils/userAccess";
import {User} from "@/types/users";
import { hasPageAccess } from "@/utils/userAccess";
import { User } from "@/types/users";
const items = [
{
title: "One Click Print",
url: "/ocp",
icon: Printer,
role: ["viewer"],
module: "ocp",
active: true,
},
];
export function ProductionSideBar({user, moduleID}: {user: User | null; moduleID: string}) {
export function ProductionSideBar({
user,
moduleID,
}: {
user: User | null;
moduleID: string;
}) {
const url: string = window.location.host.split(":")[0];
const items = [
{
title: "One Click Print",
url: "/ocp",
icon: Printer,
role: ["viewer"],
module: "ocp",
active: true,
},
{
title: "Rfid Readers",
url: "/rfid",
icon: Tag,
role: ["viewer"],
module: "production",
active:
url === "usday1vms006" || url === "localhost" ? true : false,
},
];
return (
<SidebarGroup>
<SidebarGroupLabel>Production</SidebarGroupLabel>
@@ -30,14 +45,15 @@ export function ProductionSideBar({user, moduleID}: {user: User | null; moduleID
{items.map((item) => (
<SidebarMenuItem key={item.title}>
<>
{hasPageAccess(user, item.role, moduleID) && item.active && (
<SidebarMenuButton asChild>
<a href={item.url}>
<item.icon />
<span>{item.title}</span>
</a>
</SidebarMenuButton>
)}
{hasPageAccess(user, item.role, moduleID) &&
item.active && (
<SidebarMenuButton asChild>
<a href={item.url}>
<item.icon />
<span>{item.title}</span>
</a>
</SidebarMenuButton>
)}
</>
</SidebarMenuItem>
))}

View File

@@ -6,7 +6,10 @@ import Barcode from "react-barcode";
import { BarcodePDFExport } from "./BarcodeExport";
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() {
const [checked, setChecked] = useState([]);

View File

@@ -26,7 +26,7 @@ export default function DmPage() {
<ul className="list-disc mr-2">
<li>
Download the standard template if you have not yet done
so, top right click standard, then template.
so, Above click Standard Order Template.
</li>
<li>
Add in the orders like you see in the example below.
@@ -37,8 +37,8 @@ export default function DmPage() {
customerReleaseNumber. Quatity and dates can change.
</li>
<li>
Once you have all the orders enters click the upload
button on the top right
Once you have all the orders entered, click Standard
Order Import
</li>
</ul>

View File

@@ -1,26 +1,30 @@
import {LstCard} from "@/components/extendedUI/LstCard";
import {Button} from "@/components/ui/button";
import {CardHeader} from "@/components/ui/card";
import {Input} from "@/components/ui/input";
import {Label} from "@/components/ui/label";
import {useSessionStore} from "@/lib/store/sessionStore";
import axios from "axios";
import {useState} from "react";
import { LstCard } from "@/components/extendedUI/LstCard";
import { Button } from "@/components/ui/button";
import { CardHeader } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {useForm} from "react-hook-form";
import {toast} from "sonner";
import axios from "axios";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
export default function ConsumeMaterial() {
const {register: register1, handleSubmit: handleSubmit1, reset} = useForm();
const {
register: register1,
handleSubmit: handleSubmit1,
reset,
} = useForm();
const [submitting, setSubmitting] = useState(false);
const {token} = useSessionStore();
const handleConsume = async (data: any) => {
setSubmitting(true);
try {
const result = await axios.post(`/api/logistics/consume`, data, {
headers: {Authorization: `Bearer ${token}`},
});
// const result = await axios.post(`/api/logistics/consume`, data, {
// headers: {Authorization: `Bearer ${token}`},
// });
const result = await axios.post(`/api/logistics/consume`, data);
if (result.data.success) {
toast.success(result.data.message);
setSubmitting(false);
@@ -33,12 +37,14 @@ export default function ConsumeMaterial() {
toast.error(result.data.message);
}
} catch (error: any) {
//console.log(error);
console.log(error);
setSubmitting(false);
if (error.status === 401) {
toast.error("Unauthorized to do this task.");
} 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>
<form onSubmit={handleSubmit1(handleConsume)}>
<div className="m-2">
<Label htmlFor="runningNr">Enter unit running number</Label>
<Label htmlFor="runningNr">
Enter unit running number
</Label>
<Input
className="mt-2"
//defaultValue="634"
@@ -62,7 +70,9 @@ export default function ConsumeMaterial() {
/>
</div>
<div className="m-2">
<Label htmlFor="lotNum">Enter lot number</Label>
<Label htmlFor="lotNum">
Enter lot number
</Label>
<Input
className="mt-2"
//defaultValue="634"
@@ -71,7 +81,12 @@ export default function ConsumeMaterial() {
/>
</div>
<Button className="m-2" color="primary" type="submit" disabled={submitting}>
<Button
className="m-2"
color="primary"
type="submit"
disabled={submitting}
>
Consume materal
</Button>
</form>
@@ -81,12 +96,19 @@ export default function ConsumeMaterial() {
<LstCard>
<div className="w-96 p-1">
<ol>
<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>
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>
</ol>
<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.
</p>
</div>

View File

@@ -0,0 +1,478 @@
import { LstCard } from "@/components/extendedUI/LstCard";
import { Button } from "@/components/ui/button";
import { CardContent, CardHeader } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Switch } from "@/components/ui/switch";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { useAppForm } from "@/utils/formStuff";
import axios from "axios";
import { useState } from "react";
import { toast } from "sonner";
import { Info } from "lucide-react";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { useSettingStore } from "@/lib/store/useSettings";
export default function TransferToNextLot() {
const [gaylordFilled, setGaylordFilled] = useState([0]);
const [actualAmount, setActualAmount] = useState(0);
const [tab, setTab] = useState("esitmate");
const [typeSwitch, setTypeSwitch] = useState(false);
const { settings } = useSettingStore();
const server = settings.filter((n: any) => n.name === "dbServer");
const form = useAppForm({
defaultValues: {
runningNumber: "",
lotNumber: "",
originalAmount: "",
amount: "",
},
onSubmit: async ({ value }) => {
//console.log(transferData);
//toast.success("603468: qty: 361, was transfered to lot:24897");
try {
const res = await axios.post("/api/ocp/materiallottransfer", {
runningNumber: Number(value.runningNumber),
lotNumber: Number(value.lotNumber),
originalAmount: Number(value.originalAmount),
level: Number(
gaylordFilled.length === 1
? 0.25
: gaylordFilled.length === 2
? 0.5
: gaylordFilled.length === 3
? 0.75
: gaylordFilled.length === 4 && 0.95
),
amount: actualAmount,
type: typeSwitch ? "eom" : "lot",
});
if (res.data.success) {
toast.success(`${res.data.message}`);
form.reset();
setGaylordFilled([0]);
setActualAmount(0);
}
//console.log(res.data);
if (!res.data.success) {
toast.error(res.data.message);
}
} catch (error) {
if (error) {
console.log(error);
//toast.error(error)
}
}
},
});
return (
<div>
<LstCard>
<CardHeader>
<p className="text-center text-lg">
Material Transfer to Next lot
</p>
</CardHeader>
<div>
<div className="flex flex-wrap m-2 gap-2">
<div className="flex gap-2">
<div>
<LstCard className="">
<Tabs
defaultValue={tab}
onValueChange={setTab}
>
<TabsList>
<TabsTrigger value="esitmate">
Estimate Amount
</TabsTrigger>
<TabsTrigger value="actual">
Actual Amount
</TabsTrigger>
</TabsList>
<TabsContent value="esitmate">
<div className="grid columns-1">
<button
className={`box-border h-16 w-96 border-3 ${
gaylordFilled.includes(
4
)
? " bg-green-500"
: ""
}`}
onClick={() =>
setGaylordFilled([
1, 2, 3, 4,
])
}
>
<p className="text-center">
Almost full - 95%
</p>
</button>
<button
className={`box-border h-16 w-96 border-3 ${
gaylordFilled.includes(
3
)
? " bg-green-500"
: ""
}`}
onClick={() =>
setGaylordFilled([
1, 2, 3,
])
}
>
<p className="text-center">
About full - 75%
</p>
</button>
<button
className={`box-border h-16 w-96 border-3 ${
gaylordFilled.includes(
2
)
? " bg-green-500"
: ""
}`}
onClick={() =>
setGaylordFilled([1, 2])
}
>
<p className="text-center">
Half full - 50%
</p>
</button>
<button
className={`box-border h-16 w-96 border-3 ${
gaylordFilled.includes(
1
)
? " bg-green-500"
: ""
}`}
onClick={() =>
setGaylordFilled(() => [
1,
])
}
>
<p className="text-center">
Almost empty - 25%
</p>
</button>
</div>
<div className="flex justify-end pr-1">
<Button
onClick={() =>
setGaylordFilled([0])
}
>
Reset Gaylord
</Button>
</div>
</TabsContent>
<TabsContent
value="actual"
className="w-96"
>
<CardHeader>
<p>
Enter the total amount of
the cage/gaylord
</p>
</CardHeader>
<CardContent>
<Input
type="number"
//placeholder="35"
onChange={(e) =>
setActualAmount(
Number(
e.target.value
)
)
}
/>
</CardContent>
</TabsContent>
</Tabs>
</LstCard>
</div>
<div>
<div className="w-96">
<LstCard>
<form
onSubmit={(e) => {
e.preventDefault();
form.handleSubmit();
}}
>
<div className="mt-3 p-2">
<form.AppField
name="runningNumber"
children={(field) => (
<field.InputField
label="Running Number"
inputType="number"
required={true}
/>
)}
/>
</div>
<div className="mt-3 p-2">
<form.AppField
name="lotNumber"
children={(field) => (
<field.InputField
label="Lot Number"
inputType="number"
required={true}
/>
)}
/>
{tab !== "actual" && (
<div className="mt-3 p-2">
<form.AppField
name="originalAmount"
children={(
field
) => (
<field.InputField
label="Orignal Quantity"
inputType="number"
required={
true
}
/>
)}
/>
</div>
)}
</div>
<div className="flex justify-between p-2">
<div className="flex items-center space-x-2">
<Switch
checked={typeSwitch}
onCheckedChange={
setTypeSwitch
}
/>
<span>
{typeSwitch ? (
<div className="flex items-center space-x-2">
<span>
"EOM
Transfer"
</span>
<Tooltip>
<TooltipTrigger>
<Info className="h-[16px] w-[16px]" />
</TooltipTrigger>
<TooltipContent>
<p>
Click
the
toggle
if
you
will
be
transfering
at
EOM,
NOTE:
This
will
trigger
the
delayed
transfer.
</p>
</TooltipContent>
</Tooltip>
</div>
) : (
<div className="flex items-center space-x-2">
<span>
"Lot
Transfer"
</span>
<Tooltip>
<TooltipTrigger>
<Info className="h-[16px] w-[16px]" />
</TooltipTrigger>
<TooltipContent>
<p>
Click
the
toggle
if
you
will
be
transfering
at
EOM,
NOTE:
This
will
trigger
the
delayed
transfer.
</p>
</TooltipContent>
</Tooltip>
</div>
)}
</span>
</div>
<form.AppForm>
<form.SubmitButton>
Transfer To Lot
</form.SubmitButton>
</form.AppForm>
</div>
</form>
</LstCard>
</div>
</div>
</div>
<div>
<LstCard className="p-2">
<CardHeader>
<p className="text-center text-lg">
Moving material to the next lot.
</p>
</CardHeader>
{tab !== "actual" ? (
<div>
<ol>
<li>
1. Grab the gaylord running
number from the gaylord at the
line/next to the tschritter
</li>
<li>
2. Grab the next lot number you
are going to be running (or the
one that state no Main material
prepared)
</li>
<li>
3. Enter the total gaylord
weight (this is how much the
gaylord weighed when it came in
from the supplier.)
</li>
<li>
4. *Click the level of the
gaylord (this is just an
estimate to move to the next
lot.)
</li>
<li>
5. type in running number on the
gaylord.
</li>
<li>
6. Type in the new lot number.
</li>
<li>7. Press "Transfer To Lot"</li>
</ol>
<br></br>
<p>
* to reduce the time needed to get
the lot going we will use an
estimate of how full the gaylord is.
</p>
<p>
NOTE: This is not the return
process, this process will just get
the gaylord to the next lot.
</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>
<ol>
<li>
1. Grab the gaylord running
number from the gaylord at the
line/next to the tschritter
</li>
<li>
2. Grab the next lot number you
are going to be running (or the
one that state no Main material
prepared)
</li>
<li>
3. Take the gaylord to the scale
and weight it
</li>
<li>
4. Enter the weight of the
gaylord minus the tar weight.
</li>
<li>
5. type in running number on the
gaylord.
</li>
<li>
6. Type in the new lot number.
</li>
<li>7. Press "Transfer To Lot"</li>
</ol>
<br></br>
<p>
NOTE: This is not the return
process, this process will just get
the gaylord to the next lot.
</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>
)}
</LstCard>
</div>
</div>
</div>
</LstCard>
</div>
);
}

View File

@@ -0,0 +1,31 @@
import { Button } from "@/components/ui/button";
import axios from "axios";
import { toast } from "sonner";
export default function ManualTrigger() {
const rfidReaderTrigger = async () => {
try {
const res = await axios.post("/api/rfid/manualtrigger/wrapper1");
if (res.data.success) {
toast.success(res.data.message);
return;
}
if (!res.data.success) {
toast.error(res.data.message);
}
} catch (error) {
console.log(error);
//stoast.success(error.data.message);
}
};
return (
<div>
<Button onClick={rfidReaderTrigger}>Wrapper 1 RFID</Button>
</div>
);
}

View File

@@ -40,7 +40,6 @@ export function AttachSilo(props: any) {
machineId: "",
},
onSubmit: async ({ value }) => {
console.log(value);
try {
const res = await axios.post(
"/api/logistics/attachsilo",

View File

@@ -48,6 +48,7 @@ export function DetachSilo(props: any) {
);
if (res.status === 200) {
console.log(res.data.data);
toast.success(res.data.message);
refetch();
@@ -132,7 +133,12 @@ export function DetachSilo(props: any) {
</div>
<DialogFooter>
<DialogClose asChild>
<Button variant="outline">Cancel</Button>
<Button
variant="outline"
onClick={() => setOpen(!open)}
>
Cancel
</Button>
</DialogClose>
<form.AppForm>
<form.SubmitButton>Detach</form.SubmitButton>

View File

@@ -21,13 +21,28 @@ import { toast } from "sonner";
import ChartData from "./ChartData";
import { AttachSilo } from "./AttachSilo";
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) {
const token = localStorage.getItem("auth_token");
const [submitting, setSubmitting] = useState(false);
const { refetch } = useQuery(getStockSilo());
const { user } = useSessionStore();
const { userRoles } = useGetUserRoles();
const { modules } = useModuleStore();
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({
defaultValues: {
newLevel: "",
@@ -46,7 +61,7 @@ export default function SiloCard(data: any) {
dataToSubmit,
{ headers: { Authorization: `Bearer ${token}` } }
);
console.log(res.data);
//console.log(res.data);
if (res.data.success) {
toast.success(res.data.message);
@@ -70,6 +85,8 @@ export default function SiloCard(data: any) {
}
},
});
console.log(accessRoles);
return (
<LstCard>
<div className="flex flex-row">
@@ -109,82 +126,98 @@ export default function SiloCard(data: any) {
</ul>
</div>
) : (
<form
onSubmit={(e) => {
e.preventDefault();
e.stopPropagation();
}}
>
<form.Field
name="newLevel"
validators={{
// We can choose between form-wide and field-specific validators
onChange: ({ value }) =>
value.length > 1
? undefined
: "You must enter a value greate than 1",
}}
children={(field) => {
return (
<div className="m-2 min-w-48 max-w-96 p-2">
<div className="flex flex-row">
<Label htmlFor="newLevel">
New level
</Label>
<div>
<Disclaimer />
</div>
</div>
<div className="flex flex-row">
<Input
name={field.name}
value={
field.state.value
}
onBlur={
field.handleBlur
}
type="decimal"
onChange={(e) =>
field.handleChange(
e.target.value
)
}
/>
<Button
className="ml-1"
variant="outline"
type="submit"
onClick={
form.handleSubmit
}
disabled={submitting}
>
{submitting ? (
<span className="w-24">
Submitting...
</span>
) : (
<span className="w-24">
Submit
</span>
)}
</Button>
</div>
<>
{user &&
roles.includes(accessRoles[0]?.role) && (
<form
onSubmit={(e) => {
e.preventDefault();
e.stopPropagation();
}}
>
<form.Field
name="newLevel"
validators={{
// We can choose between form-wide and field-specific validators
onChange: ({ value }) =>
value.length > 1
? undefined
: "You must enter a value greate than 1",
}}
children={(field) => {
return (
<div className="m-2 min-w-48 max-w-96 p-2">
<div className="flex flex-row">
<Label htmlFor="newLevel">
New level
</Label>
<div>
<Disclaimer />
</div>
</div>
<div className="flex flex-row">
<Input
name={
field.name
}
value={
field
.state
.value
}
onBlur={
field.handleBlur
}
type="decimal"
onChange={(
e
) =>
field.handleChange(
e
.target
.value
)
}
/>
<Button
className="ml-1"
variant="outline"
type="submit"
onClick={
form.handleSubmit
}
disabled={
submitting
}
>
{submitting ? (
<span className="w-24">
Submitting...
</span>
) : (
<span className="w-24">
Submit
</span>
)}
</Button>
</div>
{field.state.meta.errors
.length ? (
<em>
{field.state.meta.errors.join(
","
)}
</em>
) : null}
</div>
);
}}
/>
</form>
{field.state.meta
.errors
.length ? (
<em>
{field.state.meta.errors.join(
","
)}
</em>
) : null}
</div>
);
}}
/>
</form>
)}
</>
)}
</div>
</LstCard>

View File

@@ -16,8 +16,7 @@ import { getOcmeInfo } from "@/utils/querys/production/getOcmeInfo";
import { useQuery } from "@tanstack/react-query";
import { format } from "date-fns";
import { Trash } from "lucide-react";
import ManuallyEnterRn from "./ManuallyEnterRn";
import { Separator } from "../ui/separator";
import ManualTrigger from "../logistics/rfid/ManualTrigger";
const currentPallets = [
{ key: "line", label: "Line" },
@@ -160,11 +159,12 @@ export default function WrapperManualTrigger() {
<div>
<hr />
<p className="text-center mb-3">Manual Trigger</p>
{/* <p className="text-center mb-3">Manual Trigger</p>
<ManuallyEnterRn />
<Separator className="m-1" />
<div className="flex flex-row justify-between">
<Separator className="m-1" /> */}
<div className="flex flex-row justify-between m-2">
<Button onClick={cameraTrigger}>Camera</Button>
<ManualTrigger />
</div>
</div>
</LstCard>

View File

@@ -0,0 +1,27 @@
import { getlabelRatio } from "@/utils/querys/production/labelRatio";
import { labelRatioColumns } from "@/utils/tableData/production/labelRatio/labelRatioColumns";
import { LabelRatioTable } from "@/utils/tableData/production/labelRatio/labelRatioData";
import { useQuery } from "@tanstack/react-query";
export default function LabelRatio() {
const { data, isError, isLoading } = useQuery(getlabelRatio());
const ratioData = data ? data : [];
if (isError) {
return <div>Error</div>;
}
if (isLoading) {
return <div>Loading</div>;
}
return (
<div className="m-2">
<LabelRatioTable
columns={labelRatioColumns}
data={ratioData}
//style={style}
/>
</div>
);
}

View File

@@ -243,7 +243,8 @@ export default function ManualPrintForm() {
<Textarea
//label="Comments"
placeholder="add more info as needed."
{...register("additionalComments")}
{...(register("additionalComments"),
{ required: true, minLength: 10 })}
/>
</div>

View File

@@ -11,6 +11,7 @@ import {
ResizablePanel,
ResizablePanelGroup,
} from "@/components/ui/resizable-panels";
import LabelRatio from "./LabelRatio";
export default function OCPPage() {
const { settings } = useSettingStore();
@@ -64,18 +65,32 @@ export default function OCPPage() {
</ResizablePanelGroup>
</ResizablePanel>
<ResizableHandle />
<ResizablePanel defaultSize={25}>
<ResizablePanel className="min-h-[200px] min-w-[200px] max-w-[450px]">
<ResizablePanelGroup
direction="vertical"
autoSaveId="ocpPage"
autoSaveId="ocpPage_vert"
>
{server[0].value === "usday1vms006" && (
<ResizablePanel className="max-h-[300px]">
<ResizablePanel
style={{
overflow: "auto",
scrollbarWidth: "none",
}}
defaultSize={50}
className="min-h-[200px]"
>
<WrapperManualTrigger />
</ResizablePanel>
)}
{server[0]?.value === "localhost" && (
<ResizablePanel className="max-h-[300px]">
<ResizablePanel
className="min-h-[200px]"
style={{
overflow: "auto",
scrollbarWidth: "none",
}}
defaultSize={50}
>
<WrapperManualTrigger />
</ResizablePanel>
)}
@@ -83,6 +98,7 @@ export default function OCPPage() {
<ResizableHandle />
<ResizablePanel>
<PrinterStatus />
<LabelRatio />
</ResizablePanel>
</ResizablePanelGroup>
</ResizablePanel>

View File

@@ -0,0 +1,28 @@
import { getReaders } from "@/utils/querys/rfid/getReaders";
import { readerColumns } from "@/utils/tableData/rfid/readers/readerColumns";
import { ReaderTable } from "@/utils/tableData/rfid/readers/readerData";
import { useQuery } from "@tanstack/react-query";
export default function RfidPage() {
const { data, isError, isLoading } = useQuery(getReaders());
if (isError) {
return <div>Error</div>;
}
if (isLoading) {
return <div>Loading</div>;
}
return (
<div className="m-2">
<ReaderTable
columns={readerColumns}
data={data.data.sort((a: any, b: any) =>
a.reader.localeCompare(b.reader)
)}
//style={style}
/>
</div>
);
}

View File

@@ -0,0 +1,29 @@
import * as React from "react"
import * as SwitchPrimitive from "@radix-ui/react-switch"
import { cn } from "@/lib/utils"
function Switch({
className,
...props
}: React.ComponentProps<typeof SwitchPrimitive.Root>) {
return (
<SwitchPrimitive.Root
data-slot="switch"
className={cn(
"peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring focus-visible:ring-ring/50 dark:data-[state=unchecked]:bg-input/80 inline-flex h-[1.15rem] w-8 shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
className
)}
{...props}
>
<SwitchPrimitive.Thumb
data-slot="switch-thumb"
className={cn(
"bg-background dark:data-[state=unchecked]:bg-foreground dark:data-[state=checked]:bg-primary-foreground pointer-events-none block size-4 rounded-full ring-0 transition-transform data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0"
)}
/>
</SwitchPrimitive.Root>
)
}
export { Switch }

View File

@@ -17,6 +17,7 @@ import { Route as EomRouteImport } from './routes/_eom'
import { Route as AuthRouteImport } from './routes/_auth'
import { Route as AdminRouteImport } from './routes/_admin'
import { Route as IndexRouteImport } from './routes/index'
import { Route as RfidIndexRouteImport } from './routes/rfid/index'
import { Route as OcpIndexRouteImport } from './routes/ocp/index'
import { Route as EomEomRouteImport } from './routes/_eom/eom'
import { Route as AuthProfileRouteImport } from './routes/_auth/profile'
@@ -78,6 +79,11 @@ const IndexRoute = IndexRouteImport.update({
path: '/',
getParentRoute: () => rootRouteImport,
} as any)
const RfidIndexRoute = RfidIndexRouteImport.update({
id: '/rfid/',
path: '/rfid/',
getParentRoute: () => rootRouteImport,
} as any)
const OcpIndexRoute = OcpIndexRouteImport.update({
id: '/ocp/',
path: '/ocp/',
@@ -220,6 +226,7 @@ export interface FileRoutesByFullPath {
'/profile': typeof AuthProfileRoute
'/eom': typeof EomEomRoute
'/ocp': typeof OcpIndexRoute
'/rfid': typeof RfidIndexRoute
'/siloAdjustments/$hist': typeof logisticsSiloAdjustmentsHistRoute
'/article/$av': typeof EomArticleAvRoute
'/barcodegen': typeof logisticsBarcodegenIndexRoute
@@ -250,6 +257,7 @@ export interface FileRoutesByTo {
'/profile': typeof AuthProfileRoute
'/eom': typeof EomEomRoute
'/ocp': typeof OcpIndexRoute
'/rfid': typeof RfidIndexRoute
'/siloAdjustments/$hist': typeof logisticsSiloAdjustmentsHistRoute
'/article/$av': typeof EomArticleAvRoute
'/barcodegen': typeof logisticsBarcodegenIndexRoute
@@ -284,6 +292,7 @@ export interface FileRoutesById {
'/_auth/profile': typeof AuthProfileRoute
'/_eom/eom': typeof EomEomRoute
'/ocp/': typeof OcpIndexRoute
'/rfid/': typeof RfidIndexRoute
'/(logistics)/siloAdjustments/$hist': typeof logisticsSiloAdjustmentsHistRoute
'/_eom/article/$av': typeof EomArticleAvRoute
'/(logistics)/barcodegen/': typeof logisticsBarcodegenIndexRoute
@@ -316,6 +325,7 @@ export interface FileRouteTypes {
| '/profile'
| '/eom'
| '/ocp'
| '/rfid'
| '/siloAdjustments/$hist'
| '/article/$av'
| '/barcodegen'
@@ -346,6 +356,7 @@ export interface FileRouteTypes {
| '/profile'
| '/eom'
| '/ocp'
| '/rfid'
| '/siloAdjustments/$hist'
| '/article/$av'
| '/barcodegen'
@@ -379,6 +390,7 @@ export interface FileRouteTypes {
| '/_auth/profile'
| '/_eom/eom'
| '/ocp/'
| '/rfid/'
| '/(logistics)/siloAdjustments/$hist'
| '/_eom/article/$av'
| '/(logistics)/barcodegen/'
@@ -404,6 +416,7 @@ export interface RootRouteChildren {
RegisterRoute: typeof RegisterRoute
userPasswordChangeRoute: typeof userPasswordChangeRoute
OcpIndexRoute: typeof OcpIndexRoute
RfidIndexRoute: typeof RfidIndexRoute
logisticsSiloAdjustmentsHistRoute: typeof logisticsSiloAdjustmentsHistRoute
logisticsBarcodegenIndexRoute: typeof logisticsBarcodegenIndexRoute
logisticsDmIndexRoute: typeof logisticsDmIndexRoute
@@ -475,6 +488,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof IndexRouteImport
parentRoute: typeof rootRouteImport
}
'/rfid/': {
id: '/rfid/'
path: '/rfid'
fullPath: '/rfid'
preLoaderRoute: typeof RfidIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/ocp/': {
id: '/ocp/'
path: '/ocp'
@@ -694,6 +714,7 @@ const rootRouteChildren: RootRouteChildren = {
RegisterRoute: RegisterRoute,
userPasswordChangeRoute: userPasswordChangeRoute,
OcpIndexRoute: OcpIndexRoute,
RfidIndexRoute: RfidIndexRoute,
logisticsSiloAdjustmentsHistRoute: logisticsSiloAdjustmentsHistRoute,
logisticsBarcodegenIndexRoute: logisticsBarcodegenIndexRoute,
logisticsDmIndexRoute: logisticsDmIndexRoute,

View File

@@ -1,5 +1,6 @@
import ConsumeMaterial from "@/components/logistics/materialHelper/consumption/ConsumeMaterial";
import PreformReturn from "@/components/logistics/materialHelper/consumption/MaterialReturn";
import TransferToNextLot from "@/components/logistics/materialHelper/consumption/TransferToNextLot";
import { createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute(
@@ -21,10 +22,21 @@ export const Route = createFileRoute(
function RouteComponent() {
const url: string = window.location.host.split(":")[0];
const auth = localStorage.getItem("auth_token");
return (
<div>
<ConsumeMaterial />
{url === "localhost" && <PreformReturn />}
<div className="flex flex-wrap">
{auth ? (
<>
<ConsumeMaterial />
{url === "localhost" && <PreformReturn />}
<TransferToNextLot />
</>
) : (
<>
<ConsumeMaterial />
<TransferToNextLot />
</>
)}
</div>
);
}

View File

@@ -28,6 +28,7 @@ import { useLogout } from "@/hooks/useLogout";
import ExportInventoryData from "@/components/logistics/warehouse/ExportInventoryData";
import { AddCards } from "@/components/dashboard/AddCards";
import DMButtons from "@/components/logistics/dm/DMButtons";
import { useSettingStore } from "@/lib/store/useSettings";
//import { AddCards } from "@/components/dashboard/AddCards";
// same as the layout
@@ -38,6 +39,9 @@ export const Route = createRootRoute({
const { user } = useSessionStore();
const logout = useLogout();
const location = useLocation();
const { settings } = useSettingStore();
const server = settings.filter((n: any) => n.name === "dbServer");
return (
<div className="overflow-hidden">
@@ -61,6 +65,17 @@ export const Route = createRootRoute({
<div className="m-1">
<ModeToggle />
</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 ? (
<div className="m-1">
<DropdownMenu>

View File

@@ -33,13 +33,12 @@ function RouteComponent() {
<span className="font-bold">
Authentication Notice:
</span>
To interact with the Alpla prod through this
application, you must use your{" "}
<span className="font-semibold">
Windows login credentials
<span>
The username, email, and password are
only for LST you <em>DO NOT</em>Need to
use Windows username if you do not wish
to.
</span>
. These credentials are used solely for
authentication purposes.
</li>
{/* <li>
<span className="font-bold">

View File

@@ -0,0 +1,14 @@
import RfidPage from "@/components/rfid/RfidPage";
import { createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/rfid/")({
component: RouteComponent,
});
function RouteComponent() {
return (
<div>
<RfidPage />
</div>
);
}

View File

@@ -0,0 +1,20 @@
import { queryOptions } from "@tanstack/react-query";
import axios from "axios";
export function getlabelRatio() {
return queryOptions({
queryKey: ["labelRatio"],
queryFn: () => fetchSettings(),
//staleTime: 1000,
refetchInterval: 2 * 2000,
refetchOnWindowFocus: true,
});
}
const fetchSettings = async () => {
const { data } = await axios.get(`/api/ocp/labelratio`);
// if we are not localhost ignore the devDir setting.
//const url: string = window.location.host.split(":")[0];
return data.data ?? [];
};

View File

@@ -0,0 +1,20 @@
import { queryOptions } from "@tanstack/react-query";
import axios from "axios";
export function getReaders() {
return queryOptions({
queryKey: ["getReaders"],
queryFn: () => fetchReaders(),
//enabled:
staleTime: 1000,
refetchInterval: 60 * 1000,
refetchOnWindowFocus: true,
});
}
const fetchReaders = async () => {
const { data } = await axios.get(`/api/rfid/getreaders`);
// if we are not localhost ignore the devDir setting.
//const url: string = window.location.host.split(":")[0];
return data.data ?? [];
};

View File

@@ -66,6 +66,7 @@ export function InvTable<TData, TValue>({
});
//console.log(table.getState().sorting);
//console.log(parseInt(style.height.replace("px", "")) - 50);
console.log(info);
return (
<LstCard
className="p-3"
@@ -79,8 +80,9 @@ export function InvTable<TData, TValue>({
<div>
<div className="flex flex-row justify-between">
<p className="text-center text-pretty">
{info.type} {data.length > 0 ? "lanes" : "lane"} older
than: {info.age}, needing to be completed
{info.rowType} {data.length > 0 ? "lanes" : "lane"}{" "}
older than: {info.age}, {data.length} needing to be
completed
</p>
</div>
<ScrollArea className="h-72 rounded-md border m-2">

View File

@@ -0,0 +1,87 @@
//import { fixTime } from "@/utils/fixTime";
import { Button } from "@/components/ui/button";
import { getReaders } from "@/utils/querys/rfid/getReaders";
import { useQuery } from "@tanstack/react-query";
import { ColumnDef } from "@tanstack/react-table";
import axios from "axios";
import { useState } from "react";
import { toast } from "sonner";
// This type is used to define the shape of our data.
// You can use a Zod schema here if you want.
export type Adjustmnets = {
ratio_id: string;
name: string;
autoLabel: number;
manualLabel: string;
};
export const labelRatioColumns: ColumnDef<Adjustmnets>[] = [
// {
// accessorKey: "line",
// header: () => <div className="text-left">Line</div>,
// },
{
accessorKey: "autoLabel",
header: "Auto Labels",
},
{
accessorKey: "manualLabel",
header: "Manual Labels",
},
{
accessorKey: "goodRatio",
header: "Ratio",
cell: ({ row }) => {
const goodRatio =
(parseInt(row.getValue("autoLabel")) /
(parseInt(row.getValue("autoLabel")) +
parseInt(row.getValue("manualLabel")))) *
100;
return (
<div className="text-center font-medium">
{isNaN(goodRatio) ? 0 : goodRatio.toFixed(2)}%
</div>
);
},
},
{
accessorKey: "reset",
header: "Reset Reads",
cell: () => {
const { refetch } = useQuery(getReaders());
const [readerReset, setReaderReset] = useState(false);
const resetReads = async () => {
setReaderReset(true);
try {
const res = await axios.post("/api/ocp/resetlabelratio", {
reader: name,
});
if (res.status === 200) {
toast.success(res.data.message);
setReaderReset(false);
} else {
toast.error(res.data.message);
setReaderReset(false);
}
} catch (error: any) {
toast.error(error.data.message);
setReaderReset(false);
}
refetch();
};
return (
<div className="text-left font-medium">
<Button
className="h-4"
onClick={resetReads}
disabled={readerReset}
>
Reset
</Button>
</div>
);
},
},
];

View File

@@ -0,0 +1,124 @@
import {
ColumnDef,
flexRender,
getCoreRowModel,
useReactTable,
getPaginationRowModel,
} from "@tanstack/react-table";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { useState } from "react";
import { ScrollArea } from "@/components/ui/scroll-area";
import { LstCard } from "@/components/extendedUI/LstCard";
interface DataTableProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[];
data: TData[];
//style: any;
}
export function LabelRatioTable<TData, TValue>({
columns,
data,
//style,
}: DataTableProps<TData, TValue>) {
const [pagination, setPagination] = useState({
pageIndex: 0, //initial page index
pageSize: 5, //default page size
});
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
onPaginationChange: setPagination,
state: {
//...
pagination,
},
});
//console.log(parseInt(style.height.replace("px", "")) - 50);
return (
<LstCard>
<div>
<div className="flex flex-row justify-between">
{data.length === 0 ? (
<span className="text-center">
No labels printed since last reset.
</span>
) : (
<span>Label Ratio</span>
)}
</div>
<ScrollArea className="max-h-32 rounded-md border m-2">
<Table
// style={{
// width: `${parseInt(style.width.replace("px", "")) - 50}px`,
// height: `${parseInt(style.height.replace("px", "")) - 200}px`,
// cursor: "move",
// }}
>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column
.columnDef.header,
header.getContext()
)}
</TableHead>
);
})}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
<TableRow
key={row.id}
data-state={
row.getIsSelected() && "selected"
}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell
colSpan={columns.length}
className="h-24 text-center"
>
No labels.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</ScrollArea>
</div>
</LstCard>
);
}

View File

@@ -1,6 +1,6 @@
import { Button } from "@/components/ui/button";
import { fixTime } from "@/utils/fixTime";
import { ColumnDef } from "@tanstack/react-table";
import { format } from "date-fns-tz";
import { Trash } from "lucide-react";
// This type is used to define the shape of our data.
@@ -38,9 +38,11 @@ export const ocpColumns = (
header: "Error Date",
cell: ({ row }) => {
if (row.getValue("created_at")) {
const correctDate = fixTime(row.getValue("created_at"));
const correctDate: any = row.getValue("created_at");
const strippedDate = correctDate.replace("Z", ""); // Remove Z
const formattedDate = format(strippedDate, "MM/dd/yyyy HH:mm");
return (
<div className="text-left font-medium">{correctDate}</div>
<div className="text-left font-medium">{formattedDate}</div>
);
}
},

View File

@@ -0,0 +1,148 @@
//import { fixTime } from "@/utils/fixTime";
import { Button } from "@/components/ui/button";
import { getReaders } from "@/utils/querys/rfid/getReaders";
import { useQuery } from "@tanstack/react-query";
import { ColumnDef } from "@tanstack/react-table";
import axios from "axios";
import { format } from "date-fns-tz";
import { useState } from "react";
import { toast } from "sonner";
// This type is used to define the shape of our data.
// You can use a Zod schema here if you want.
export type Readers = {
rfidReader_id: string;
reader: string;
readerIP: string;
lastHeartBeat: string;
lastTrigger: string;
lastTriggerGood: boolean;
active: boolean;
lastTagScanned: string;
goodReads: number;
badReads: number;
totalReads: number;
goodRatio: number;
};
export const readerColumns: ColumnDef<Readers>[] = [
{
accessorKey: "reader",
header: () => <div className="text-left">Name</div>,
},
{
accessorKey: "lastHeartBeat",
header: "Last HeartBeat",
cell: ({ row }) => {
if (row.getValue("lastHeartBeat")) {
const correctDate: any = row.getValue("lastHeartBeat");
const strippedDate = correctDate.replace("Z", ""); // Remove Z
const formattedDate = format(strippedDate, "MM/dd/yyyy HH:mm");
return (
<div className="text-left font-medium">{formattedDate}</div>
);
}
},
},
{
accessorKey: "lastTrigger",
header: "Last Trigger",
cell: ({ row }) => {
if (row.getValue("lastTrigger")) {
const correctDate: any = row.getValue("lastTrigger");
const strippedDate = correctDate.replace("Z", ""); // Remove Z
const formattedDate = format(strippedDate, "MM/dd/yyyy HH:mm");
return (
<div className="text-left font-medium">{formattedDate}</div>
);
}
},
},
{
accessorKey: "lastTriggerGood",
header: "Last Trigger Status",
},
{
accessorKey: "lastTagScanned",
header: "Last Scanned Tag",
},
{
accessorKey: "goodReads",
header: "Total Good Reads",
},
{
accessorKey: "badReads",
header: "Total Bad Reads",
},
{
accessorKey: "totalReads",
header: "Total Reads",
cell: ({ row }) => {
const total =
parseInt(row.getValue("goodReads")) +
parseInt(row.getValue("badReads"));
return <div className="text-left font-medium">{total}</div>;
},
},
{
accessorKey: "goodRatio",
header: "Good Ratio",
cell: ({ row }) => {
const goodRatio =
(parseInt(row.getValue("goodReads")) /
(parseInt(row.getValue("goodReads")) +
parseInt(row.getValue("badReads")))) *
100;
return (
<div className="text-left font-medium">
{isNaN(goodRatio) ? 0 : goodRatio.toFixed(2)}%
</div>
);
},
},
{
accessorKey: "reset",
header: "Reset Reads",
cell: ({ row }) => {
const { refetch } = useQuery(getReaders());
const [readerReset, setReaderReset] = useState(false);
// const goodRatio =
// (parseInt(row.getValue("goodReads")) /
// (parseInt(row.getValue("goodReads")) +
// parseInt(row.getValue("badReads")))) *
// 100;
const name = row.getValue("reader");
const resetReads = async () => {
setReaderReset(true);
try {
const res = await axios.post("/api/rfid/resetRatio", {
reader: name,
});
if (res.status === 200) {
toast.success(res.data.message);
setReaderReset(false);
} else {
toast.error(res.data.message);
setReaderReset(false);
}
} catch (error: any) {
toast.error(error.data.message);
setReaderReset(false);
}
refetch();
};
return (
<div className="text-left font-medium">
<Button
className="h-4"
onClick={resetReads}
disabled={readerReset}
>
Reset Reads
</Button>
</div>
);
},
},
];

View File

@@ -0,0 +1,174 @@
import {
ColumnDef,
flexRender,
getCoreRowModel,
useReactTable,
getPaginationRowModel,
} from "@tanstack/react-table";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { Button } from "@/components/ui/button";
import { useState } from "react";
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectLabel,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { ScrollArea } from "@/components/ui/scroll-area";
import { LstCard } from "@/components/extendedUI/LstCard";
interface DataTableProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[];
data: TData[];
//style: any;
}
export function ReaderTable<TData, TValue>({
columns,
data,
//style,
}: DataTableProps<TData, TValue>) {
const [pagination, setPagination] = useState({
pageIndex: 0, //initial page index
pageSize: 10, //default page size
});
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
onPaginationChange: setPagination,
state: {
//...
pagination,
},
});
//console.log(parseInt(style.height.replace("px", "")) - 50);
return (
<LstCard>
<div>
<div className="flex flex-row justify-between">
{data.length === 0 ? (
<span>No readers</span>
) : (
<span>Current reader Info</span>
)}
<Select
value={pagination.pageSize.toString()}
onValueChange={(e) =>
setPagination({
...pagination,
pageSize: parseInt(e),
})
}
>
<SelectTrigger className="w-[180px]">
<SelectValue
//id={field.name}
placeholder="Select Page"
defaultValue={10}
/>
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Page Size</SelectLabel>
<SelectItem value="5">5</SelectItem>
<SelectItem value="10">10</SelectItem>
<SelectItem value="50">50</SelectItem>
<SelectItem value="100">100</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
<ScrollArea className="h-96 rounded-md border m-2">
<Table
// style={{
// width: `${parseInt(style.width.replace("px", "")) - 50}px`,
// height: `${parseInt(style.height.replace("px", "")) - 200}px`,
// cursor: "move",
// }}
>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column
.columnDef.header,
header.getContext()
)}
</TableHead>
);
})}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
<TableRow
key={row.id}
data-state={
row.getIsSelected() && "selected"
}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell
colSpan={columns.length}
className="h-24 text-center"
>
No labels.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</ScrollArea>
</div>
<div className="flex items-center justify-end space-x-2">
<Button
variant="outline"
size="sm"
onClick={() => table.previousPage()}
disabled={!table.getCanPreviousPage()}
>
Previous
</Button>
<Button
variant="outline"
size="sm"
onClick={() => table.nextPage()}
disabled={!table.getCanNextPage()}
>
Next
</Button>
</div>
</LstCard>
);
}

164
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "lstv2",
"version": "2.23.0",
"version": "2.27.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "lstv2",
"version": "2.23.0",
"version": "2.27.0",
"dependencies": {
"@dotenvx/dotenvx": "^1.45.1",
"@hono/node-server": "^1.14.4",
@@ -29,6 +29,7 @@
"fast-xml-parser": "^5.2.5",
"fs-extra": "^11.3.0",
"jsonwebtoken": "^9.0.2",
"morgan": "^1.10.1",
"mssql": "^11.0.1",
"nodemailer": "^7.0.3",
"nodemailer-express-handlebars": "^7.0.0",
@@ -1548,14 +1549,6 @@
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@petamoriken/float16": {
"version": "3.9.2",
"resolved": "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.9.2.tgz",
"integrity": "sha512-VgffxawQde93xKxT3qap3OH+meZf7VaSB5Sqd4Rqc+FP5alWbpOyan/7tRbOAvynjpG3GpdtAuGU/NdhQpmrog==",
"license": "MIT",
"optional": true,
"peer": true
},
"node_modules/@scalar/core": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/@scalar/core/-/core-0.3.3.tgz",
@@ -2118,6 +2111,24 @@
],
"license": "MIT"
},
"node_modules/basic-auth": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
"integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
"license": "MIT",
"dependencies": {
"safe-buffer": "5.1.2"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/basic-auth/node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"license": "MIT"
},
"node_modules/bcryptjs": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-3.0.2.tgz",
@@ -3379,6 +3390,15 @@
"node": ">=0.4.0"
}
},
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/detect-file": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz",
@@ -3716,6 +3736,12 @@
"node": ">=16"
}
},
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
"license": "MIT"
},
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
@@ -4227,70 +4253,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/gel": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/gel/-/gel-2.0.1.tgz",
"integrity": "sha512-gfem3IGvqKqXwEq7XseBogyaRwGsQGuE7Cw/yQsjLGdgiyqX92G1xENPCE0ltunPGcsJIa6XBOTx/PK169mOqw==",
"license": "Apache-2.0",
"optional": true,
"peer": true,
"dependencies": {
"@petamoriken/float16": "^3.8.7",
"debug": "^4.3.4",
"env-paths": "^3.0.0",
"semver": "^7.6.2",
"shell-quote": "^1.8.1",
"which": "^4.0.0"
},
"bin": {
"gel": "dist/cli.mjs"
},
"engines": {
"node": ">= 18.0.0"
}
},
"node_modules/gel/node_modules/env-paths": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz",
"integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==",
"license": "MIT",
"optional": true,
"peer": true,
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/gel/node_modules/isexe": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz",
"integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==",
"license": "ISC",
"optional": true,
"peer": true,
"engines": {
"node": ">=16"
}
},
"node_modules/gel/node_modules/which": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz",
"integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==",
"license": "ISC",
"optional": true,
"peer": true,
"dependencies": {
"isexe": "^3.1.1"
},
"bin": {
"node-which": "bin/which.js"
},
"engines": {
"node": "^16.13.0 || >=18.0.0"
}
},
"node_modules/get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
@@ -6080,6 +6042,37 @@
"node": ">=0.10.0"
}
},
"node_modules/morgan": {
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.1.tgz",
"integrity": "sha512-223dMRJtI/l25dJKWpgij2cMtywuG/WiUKXdvwfbhGKBhy1puASqXwFzmWZ7+K73vUPoR7SS2Qz2cI/g9MKw0A==",
"license": "MIT",
"dependencies": {
"basic-auth": "~2.0.1",
"debug": "2.6.9",
"depd": "~2.0.0",
"on-finished": "~2.3.0",
"on-headers": "~1.1.0"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/morgan/node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
},
"node_modules/morgan/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT"
},
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@@ -6236,6 +6229,27 @@
"node": ">=14.0.0"
}
},
"node_modules/on-finished": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
"integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==",
"license": "MIT",
"dependencies": {
"ee-first": "1.1.1"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/on-headers": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz",
"integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -7396,7 +7410,7 @@
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz",
"integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==",
"devOptional": true,
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"

View File

@@ -1,6 +1,6 @@
{
"name": "lstv2",
"version": "2.23.0",
"version": "2.27.0",
"type": "module",
"scripts": {
"dev": "concurrently -n \"server,frontend\" -c \"#007755,#2f6da3\" \"npm run dev:server\" \"cd frontend && npm run dev\"",
@@ -8,7 +8,7 @@
"dev:frontend": "cd frontend && npm run dev",
"dev:dbgen": " drizzle-kit generate --config=drizzle-dev.config.ts",
"dev:dbmigrate": " drizzle-kit migrate --config=drizzle-dev.config.ts",
"build": "npm run build:server && npm run build:frontend && npm run build:iisNet && npm run zipServer && npm run dev",
"build": "npm run build:server && npm run build:frontend && npm run zipServer",
"build:server": "rimraf dist && tsc --build && npm run copy:scripts && xcopy server\\services\\notifications\\utils\\views\\ dist\\server\\services\\notifications\\utils\\views\\ /E /I /Y",
"build:frontend": "cd frontend && npm run build",
"build:iisNet": "rimraf dotnetwrapper\\bin && xcopy frontend\\dist dotnetwrapper\\wwwroot /E /I /Y && cd dotnetwrapper && dotnet publish lst-wrapper.csproj --configuration Release --output ../prodBuild",
@@ -21,8 +21,8 @@
"db:dev": "npm run build && npm run db:generate && npm run db:migrate",
"deploy": "standard-version --conventional-commits && npm run build",
"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",
"scriptBuild": "powershell -ExecutionPolicy Bypass -File server/scripts/build.ps1 -dir \"C:\\Users\\matthes01\\Documents\\lstv2\"",
"newBuild": "npm run build:server && npm run build:frontend && npm run zipServer && npm run copyToNew",
"copyToNew": "powershell -ExecutionPolicy Bypass -File server/scripts/copyToLst.ps1 -dir \"C:\\Users\\matthes01\\Documents\\lstv2\"",
"removeOld": "rimraf dist && rimraf frontend/dist",
"prodBuild": "npm run v1Build && npm run build && npm run zipServer && npm run dev",
"commit": "cz",
@@ -36,7 +36,7 @@
}
},
"admConfig": {
"build": 432,
"build": 661,
"oldBuild": "backend-0.1.3.zip"
},
"devDependencies": {
@@ -78,6 +78,7 @@
"fast-xml-parser": "^5.2.5",
"fs-extra": "^11.3.0",
"jsonwebtoken": "^9.0.2",
"morgan": "^1.10.1",
"mssql": "^11.0.1",
"nodemailer": "^7.0.3",
"nodemailer-express-handlebars": "^7.0.0",

View File

@@ -1,16 +1,19 @@
import { eq } from "drizzle-orm";
import { db } from "../../database/dbclient.js";
import { settings } from "../../database/schema/settings.js";
import { query } from "../services/sqlServer/prodSqlServer.js";
import { plantInfo } from "../services/sqlServer/querys/dataMart/plantInfo.js";
import { createLog } from "../services/logger/logger.js";
import { getSettings } from "../services/server/controller/settings/getSettings.js";
export const createSSCC = async (runningNumber: number) => {
// get the token
const plantToken = await db
.select()
.from(settings)
.where(eq(settings.name, "plantToken"));
let serverSettings = (await getSettings()) as any;
const plantToken = serverSettings?.filter(
(n: any) => n.name === "plantToken"
);
// const plantToken = await db
// .select()
// .from(settings)
// .where(eq(settings.name, "plantToken"));
let global: any = []; // get from plant address in basis enter the entire string here.
try {

View File

@@ -1,6 +1,7 @@
import { eq } from "drizzle-orm";
import { db } from "../../database/dbclient.js";
import { settings } from "../../database/schema/settings.js";
import { getSettings } from "../services/server/controller/settings/getSettings.js";
// create the test server stuff
const testServers = [
@@ -12,19 +13,22 @@ const testServers = [
export const prodEndpointCreation = async (endpoint: string) => {
let url = "";
//get the plant token
const plantToken = await db
.select()
.from(settings)
.where(eq(settings.name, "plantToken"));
let serverSettings = await getSettings();
const plantToken = serverSettings?.filter((n) => n.name === "plantToken");
// await db
// .select()
// .from(settings)
// .where(eq(settings.name, "plantToken"));
// check if we are a test server
const testServer = testServers.some(
(server) => server.token === plantToken[0]?.value
);
const server = await db
.select()
.from(settings)
.where(eq(settings.name, "dbServer"));
const server = serverSettings?.filter((n) => n.name === "dbServer");
// await db
// .select()
// .from(settings)
// .where(eq(settings.name, "dbServer"));
if (testServer) {
//filter out what testserver we are

View File

@@ -1,23 +1,43 @@
import type { Context } from "hono";
import { createLog } from "../../services/logger/logger.js";
export type ReturnRes<T> =
| { success: true; message: string; data: T }
| { success: false; message: string; error: any };
export function returnRes<T>(
success: true,
message: string,
service: string,
user: string,
level: "info" | "error",
data: T
): { success: true; message: string; data: T };
export const returnRes = <T>(
success: boolean,
message: string,
data: T | null = null
): ReturnRes<T> => {
/**
* just a simple return to reduce the typing and make sure we are always consitant with our returns.
*
* data can be an error as well.
*/
return success
? { success, message, data: data as T }
: { success, message, error: data ?? "An unknown error occurred" };
};
export function returnRes<T>(
success: false,
message: string,
service: string,
user: string,
level: "info" | "error",
data?: T
): { success: false; message: string; error: T | string };
export function returnRes<T>(
success: boolean,
message: string,
service: string,
user: string,
level: "info" | "error",
data?: T
) {
createLog(level, user, service, message);
if (success) {
return { success: true, message, data: data as T };
} else {
return {
success: false,
message,
error: data ?? "An unknown error occurred",
};
}
}
// export const returnApi = (c:Context,success: boolean, message: string, data?: any, code: number)=>{
// /**

View File

@@ -29,6 +29,11 @@ import eom from "./services/eom/eomService.js";
import dataMart from "./services/dataMart/dataMartService.js";
import qualityRequest from "./services/quality/qualityService.js";
import produser from "./services/prodUser/prodUser.js";
import {
getSettings,
serverSettings,
} from "./services/server/controller/settings/getSettings.js";
import type { Settings } from "./types/settings.js";
// create the main prodlogin here
const username = "lst_user";
@@ -36,15 +41,16 @@ const password = "Alpla$$Prod";
export const lstAuth = btoa(`${username}:${password}`);
// checking to make sure we have the settings intialized
const { data: settingsData, error: settingError } = await tryCatch(
db.select().from(settings)
);
// const { data: settingsData, error: settingError } = await tryCatch(
// db.select().from(settings)
// );
if (settingError) {
throw Error("Error getting settings from the db. critical error.");
}
// if (settingError) {
// throw Error("Error getting settings from the db. critical error.");
// }
const serverIntialized: any = await getSettings();
const serverIntialized: any = settingsData;
export const installed =
serverIntialized.length === 0 && process.env.NODE_ENV !== "development"
? false
@@ -211,7 +217,8 @@ serve(
/**
* Only for ocme until we get them switched over to the single port setup.
*/
const setting = await db.select().from(settings);
// const setting = await db.select().from(settings);
const setting = serverSettings;
const isActive = setting.filter((n) => n.name === "ocmeService");
if (ocmeport && isActive[0]?.value === "1") {
serve(

View 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 wasnt 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
}

View File

@@ -4,6 +4,7 @@ import { db } from "../../database/dbclient.js";
import { serverData } from "../../database/schema/serverData.js";
import { eq, sql } from "drizzle-orm";
import { createLog } from "../services/logger/logger.js";
import { serverSettings } from "../services/server/controller/settings/getSettings.js";
type UpdateServerResponse = {
success: boolean;
@@ -48,6 +49,7 @@ export const updateServer = async (
};
}
console.log(serverInfo);
const scriptPath = `${process.env.DEVFOLDER}\\server\\scripts\\update.ps1 `;
const args = [
"-NoProfile",

View File

@@ -38,6 +38,7 @@ const ignoreList = [
//misc files
"jsTesting",
"dotnetwrapper",
"prodBuild",
];
const shouldIgnore = (itemPath: any) => {

View File

@@ -37,7 +37,7 @@ export const registerUser = async (
.values({ username, email, password })
.returning({ user: users.username, email: users.email });
if (usercount.length <= 1) {
if (usercount.length === 0) {
createLog(
"info",
"auth",

View File

@@ -12,13 +12,15 @@ export const getAllUsersRoles = async () => {
const { data, error } = await tryCatch(db.select().from(userRoles));
if (error) {
returnRes(
return returnRes(
false,
"auth",
"auth",
"There was an error getting users",
"error",
new Error("No user exists.")
);
}
returnRes(true, "All users.", data);
return { success: true, message: "All users", data };
return returnRes(true, "auth", "auth", "All users.", "info", data);
};

View File

@@ -32,7 +32,10 @@ export const getAllUsers = async () => {
if (error) {
returnRes(
false,
"auth",
"auth",
"There was an error getting users",
"error",
new Error("No user exists.")
);
}

View File

@@ -7,6 +7,7 @@ import { createPassword } from "../../utils/createPassword.js";
import { createLog } from "../../../logger/logger.js";
import { sendEmail } from "../../../notifications/controller/sendMail.js";
import { settings } from "../../../../../database/schema/settings.js";
import { getSettings } from "../../../server/controller/settings/getSettings.js";
export const updateUserADM = async (userData: User) => {
/**
@@ -40,8 +41,8 @@ export const updateUserADM = async (userData: User) => {
};
}
const { data: s, error: se } = await tryCatch(db.select().from(settings));
//const { data: s, error: se } = await tryCatch(db.select().from(settings));
const { data: s, error: se } = await tryCatch(getSettings());
if (se) {
return {
success: false,

View File

@@ -7,16 +7,16 @@ import { deliveryByDateRange } from "../../sqlServer/querys/dataMart/deleveryByD
import { addDays, format } from "date-fns";
export const getDeliveryByDateRange = async (data: any | null) => {
const { data: plantToken, error: plantError } = await tryCatch(
db.select().from(settings).where(eq(settings.name, "plantToken"))
);
if (plantError) {
return {
success: false,
message: "Error getting Settings",
data: plantError,
};
}
// const { data: plantToken, error: plantError } = await tryCatch(
// db.select().from(settings).where(eq(settings.name, "plantToken"))
// );
// if (plantError) {
// return {
// success: false,
// message: "Error getting Settings",
// data: plantError,
// };
// }
let deliverys: any = [];
let updatedQuery = deliveryByDateRange;

View File

@@ -4,18 +4,21 @@ import { settings } from "../../../../database/schema/settings.js";
import { tryCatch } from "../../../globalUtils/tryCatch.js";
import { query } from "../../sqlServer/prodSqlServer.js";
import { openOrders } from "../../sqlServer/querys/dataMart/openOrders.js";
import { serverSettings } from "../../server/controller/settings/getSettings.js";
export const getOpenOrders = async (data: any | null) => {
const { data: plantToken, error: plantError } = await tryCatch(
db.select().from(settings).where(eq(settings.name, "plantToken"))
);
if (plantError) {
return {
success: false,
message: "Error getting Settings",
data: plantError,
};
}
// const { data: plantToken, error: plantError } = await tryCatch(
// db.select().from(settings).where(eq(settings.name, "plantToken"))
// );
// if (plantError) {
// return {
// success: false,
// message: "Error getting Settings",
// data: plantError,
// };
// }
const plantToken = serverSettings.filter((n) => n.name === "plantToken");
let orders: any = [];
let updatedQuery = openOrders;

View File

@@ -0,0 +1,47 @@
import { tryCatch } from "../../../globalUtils/tryCatch.js";
import { createLog } from "../../logger/logger.js";
import { query } from "../../sqlServer/prodSqlServer.js";
import { articleInfo } from "../../sqlServer/querys/psiReport/articleData.js";
// type ArticleData = {
// id: string
// }
export const getGetPSIArticleData = async (avs: 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(articleInfo.replace("[articles]", avs), "PSI article info")
)) as any;
if (error) {
createLog(
"error",
"datamart",
"datamart",
`There was an error getting the article info: ${JSON.stringify(
error
)}`
);
return {
success: false,
messsage: `There was an error getting the article info`,
data: error,
};
}
articles = data.data;
return {
success: true,
message: "PSI Article Data",
data: articles,
};
};

View 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,
};
};

View 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;
}),
};
};

View 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;
}),
};
};

View File

@@ -9,6 +9,10 @@ import fakeEDI from "./route/fakeEDI.js";
import addressCorrections from "./route/getCityStateData.js";
import fifoIndex from "./route/getFifoIndex.js";
import financeAudit from "./route/getFinanceAudit.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();
@@ -23,6 +27,10 @@ const routes = [
addressCorrections,
fifoIndex,
financeAudit,
psiArticleData,
psiPlanningData,
psiProductionData,
psiInventory,
] as const;
const appRoutes = routes.forEach((route) => {

View File

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

View File

@@ -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;

View 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;

View 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;

View 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,
};
};

View 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,
};
};

View 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,
};
};

View File

@@ -1,15 +0,0 @@
// import {prisma} from "database";
// import {createLog} from "logging";
// export const deleteHistory = async (date: string) => {
// // delete the inventory if it equals this date
// try {
// const remove = await prisma.$executeRaw`
// DELETE FROM historyInventory
// WHERE histDate < ${date}
// `;
// createLog("general/eom", "info", `${remove} were just remove from the historical inventory for date: ${date}`);
// } catch (error) {
// createLog("general/eom", "error", `Removing historical inventory error: ${error}`);
// }
// };

View File

@@ -4,10 +4,48 @@ const app = new OpenAPIHono();
import stats from "./route/stats.js";
import history from "./route/invHistory.js";
const routes = [stats, history] as const;
import { createJob } from "../notifications/utils/processNotifications.js";
import { historicalInvIMmport } from "./utils/historicalInv.js";
import { tryCatch } from "../../globalUtils/tryCatch.js";
import { query } from "../sqlServer/prodSqlServer.js";
import { shiftChange } from "../sqlServer/querys/misc/shiftChange.js";
import { createLog } from "../logger/logger.js";
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) => {
app.route("/eom", route);
});
setTimeout(async () => {
const { data: shift, error: shiftError } = (await tryCatch(
query(shiftChange, "shift change from material.")
)) as any;
if (shiftError) {
createLog(
"error",
"eom",
"eom",
"There was an error getting the shift times will use fallback times"
);
}
// shift split
const shiftTimeSplit = shift?.data[0]?.shiftChange.split(":");
const cronSetup = `${
shiftTimeSplit?.length > 0 ? `${parseInt(shiftTimeSplit[1])}` : "0"
} ${
shiftTimeSplit?.length > 0 ? `${parseInt(shiftTimeSplit[0])}` : "7"
} * * *`;
//console.log(cronSetup);
createJob("eom_historical_inv", cronSetup, historicalInvIMmport);
}, 5 * 1000);
// the time we want to run the hostircal data should be the same time the historical data run on the server
// getting this from the shift time
export default app;

View 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;

View 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;

View File

@@ -1,6 +1,7 @@
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { apiHit } from "../../../globalUtils/apiHits.js";
import { responses } from "../../../globalUtils/routeDefs/responses.js";
import { historicalInvByDate } from "../controller/getHistoricalInvByDate.js";
const app = new OpenAPIHono({ strict: false });
const EomStat = z.object({
@@ -12,20 +13,24 @@ const EomStat = z.object({
app.openapi(
createRoute({
tags: ["eom"],
summary: "Gets the correct eom history.",
method: "post",
summary: "Gets History Data by date.",
method: "get",
path: "/histinv",
request: {
params: EomStat,
},
responses: responses(),
}),
async (c) => {
//const body = await c.req.json();
// make sure we have a vaid user being accessed thats really logged in
const month: string = c.req.query("month") ?? "";
apiHit(c, { endpoint: "/histinv" });
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) {
return c.json(
{

View File

@@ -0,0 +1,114 @@
import { 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";
import { query } from "../../sqlServer/prodSqlServer.js";
import { totalInvNoRn } from "../../sqlServer/querys/dataMart/totalINV.js";
import { format } from "date-fns-tz";
import { serverSettings } from "../../server/controller/settings/getSettings.js";
import { deleteHistory } from "./removeHistorical.js";
import { activeArticle } from "../../sqlServer/querys/dataMart/article.js";
export const historicalInvIMmport = async () => {
const plantToken = serverSettings.filter((n) => n.name === "plantToken");
const { data, error } = (await tryCatch(
db.select().from(invHistoricalData)
)) as any;
if (error) {
createLog(
"error",
"eom",
"eom",
`There was an error getting the historical data`
);
}
// check if we have data already for today this way we dont duplicate anything.
const today = new Date();
today.setDate(today.getDate() - 1);
const dateCheck = data?.filter(
(i: any) => i.histDate === format(today, "yyyy-MM-dd")
);
if (dateCheck.length === 0) {
// get the historical data from the sql
const { data: inv, error: invError } = (await tryCatch(
query(totalInvNoRn, "eom historical data")
)) as any;
if (invError) {
createLog(
"error",
"eom",
"eom",
`There was an error getting the sql data`
);
return;
}
if (inv.data.length === 0) {
createLog("error", "eom", "eom", inv.message);
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 eomImportData = importInv.map((i: any) => {
return {
histDate: sql`(NOW() - INTERVAL '1 day')::date`,
plantToken: plantToken[0].value,
article: i.av,
articleDescription: i.Alias,
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,
avaliable_QTY: i.Avaliable_PalletQTY,
coa_QTY: i.COA_QTY,
held_QTY: i.Held_QTY,
consignment: i.Consigment,
lot_Number: i.lot,
};
});
const { data: dataImport, error: errorImport } = await tryCatch(
db.insert(invHistoricalData).values(eomImportData)
);
if (errorImport) {
createLog(
"error",
"eom",
"eom",
`There was an error importing all the inventory data.`
);
return;
}
if (dataImport) {
createLog(
"info",
"eom",
"eom",
`All data was imported succefully.`
);
return;
}
} else {
createLog("info", "eom", "eom", `Yesterdays Data already in..`);
}
// do the check to delete old data
deleteHistory();
};

View File

@@ -0,0 +1,51 @@
// import {prisma} from "database";
// import {createLog} from "logging";
import { lte, 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";
// export const deleteHistory = async (date: string) => {
// // delete the inventory if it equals this date
// try {
// const remove = await prisma.$executeRaw`
// DELETE FROM historyInventory
// WHERE histDate < ${date}
// `;
// createLog("general/eom", "info", `${remove} were just remove from the historical inventory for date: ${date}`);
// } catch (error) {
// createLog("general/eom", "error", `Removing historical inventory error: ${error}`);
// }
// };
export const deleteHistory = async () => {
const { data, error } = await tryCatch(
db
.delete(invHistoricalData)
.where(
lte(
invHistoricalData.histDate,
sql`(NOW() - INTERVAL '365 day')::date`
)
)
);
if (error) {
createLog(
"error",
"eom",
"eom",
"There was an error deleting the historical data."
);
return;
}
createLog(
"info",
"eom",
"eom",
"Data older than 45 days has been deleted."
);
};

View File

@@ -1,11 +1,13 @@
import {OpenAPIHono} from "@hono/zod-openapi";
import {apiReference} from "@scalar/hono-api-reference";
import {settings} from "../../../../database/schema/settings.js";
import {db} from "../../../../database/dbclient.js";
import {eq} from "drizzle-orm";
import { OpenAPIHono } from "@hono/zod-openapi";
import { apiReference } from "@scalar/hono-api-reference";
import { settings } from "../../../../database/schema/settings.js";
import { db } from "../../../../database/dbclient.js";
import { eq } from "drizzle-orm";
import { getSettings } from "../../server/controller/settings/getSettings.js";
const app = new OpenAPIHono();
const plantToken = await db.select().from(settings).where(eq(settings.name, "plantToken"));
const serverSettings = await getSettings();
const plantToken = serverSettings.filter((n) => n.name === "plantToken") as any; //await db.select().from(settings).where(eq(settings.name, "plantToken"));
let pToken = plantToken[0]?.value;
const testServers = ["test1", "test2", "test3"];
@@ -17,7 +19,7 @@ app.get(
apiReference({
theme: "kepler",
layout: "classic",
defaultHttpClient: {targetKey: "node", clientKey: "axios"},
defaultHttpClient: { targetKey: "node", clientKey: "axios" },
pageTitle: "Lst API Reference",
hiddenClients: [
"libcurl",

View File

@@ -0,0 +1,50 @@
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
import axios from "axios";
import { pino } from "pino";
import build from "pino-abstract-transport";
import { tryCatch } from "../../globalUtils/tryCatch.js";
const pinoLogLevels: any = {
10: "trace",
20: "debug",
30: "info",
40: "warn",
50: "error",
60: "fatal",
};
export default async function buildGoTransport() {
try {
return build(async function (source) {
for await (let obj of source) {
// Insert log entry into the PostgreSQL database using Drizzle ORM
// convert to the name to make it more easy to find later :P
const levelName = pinoLogLevels[obj.level] || "unknown";
// await db.insert(logs).values({
// level: levelName,
// username: obj?.username.toLowerCase(),
// service: obj?.service.toLowerCase(),
// message: obj.msg,
// });
const { data, error } = (await tryCatch(
axios.post(`${process.env.LST_BASE_URL}/api/v1/log`, {
service: obj?.service.toLowerCase(),
level: levelName,
message: obj.msg,
})
)) as any;
if (error) {
console.log(
"The go server must be offline so we cant post the new logs."
);
}
// console.log(`Go log level: ${levelName}`);
}
});
} catch (err) {
console.error("Error inserting log into database:", err);
}
}

View File

@@ -18,6 +18,14 @@ const transport = pino.transport({
{
target: "./dbTransport.js",
},
// Only log to Go if LST_USE_GO=true
...(process.env.LST_USE_GO === "true"
? [
{
target: "./goTransport.js", // New transport for Go
},
]
: []),
],
});

View File

@@ -1,10 +1,10 @@
import {OpenAPIHono} from "@hono/zod-openapi";
import { OpenAPIHono } from "@hono/zod-openapi";
// routes
import clearLog from "./routes/clearLog.js";
import {db} from "../../../database/dbclient.js";
import {settings} from "../../../database/schema/settings.js";
import {logCleanup} from "./controller/logCleanup.js";
import { db } from "../../../database/dbclient.js";
import { settings } from "../../../database/schema/settings.js";
import { logCleanup } from "./controller/logCleanup.js";
import createNewLog from "./routes/createLog.js";
import getLogs from "./routes/getLogs.js";
import stream from "./routes/streamLogs.js";
@@ -12,14 +12,17 @@ import stream from "./routes/streamLogs.js";
const app = new OpenAPIHono();
const routes = [clearLog, createNewLog, getLogs, stream] as const;
const setting = await db.select().from(settings);
//const setting = await db.select().from(settings);
const appRoutes = routes.forEach((route) => {
app.route("/logger", route);
});
app.all("/logger/*", (c) => {
return c.json({success: false, message: "You have encounters a log route that dose not exist."});
return c.json({
success: false,
message: "You have encounters a log route that dose not exist.",
});
});
// run the clean up job ones on server restart/crash/update and then once a date

View File

@@ -7,6 +7,8 @@ import { postForecast } from "../postForecast.js";
import { query } from "../../../../../sqlServer/prodSqlServer.js";
import { activeArticle } from "../../../../../sqlServer/querys/dataMart/article.js";
import { addDays } from "date-fns";
import { sendEmail } from "../../../../../notifications/controller/sendMail.js";
import { createLog } from "../../../../../logger/logger.js";
let customerID = 4;
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 (typeof forcast.customerArticleNo === "number") {
missingSku.push(forcast);
}
continue;
}
@@ -181,6 +186,9 @@ export const lorealForecast = async (data: any, user: any) => {
);
if (activeAV.length === 0) {
if (typeof forcast.customerArticleNo === "number") {
missingSku.push(forcast);
}
continue;
}
@@ -190,6 +198,56 @@ export const lorealForecast = async (data: any, user: any) => {
//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
const predefinedObject = {
receivingPlantId: plantToken[0].value,

View File

@@ -14,7 +14,8 @@ export const postForecast = async (data: any, user: any) => {
url: endpoint,
method: "POST",
headers: {
Authorization: `Basic ${user.prod}`,
"X-API-Key": process.env.TEC_API_KEY || "",
"Content-Type": "application/json",
},
// if a body is sent over it would be like below
data: data,

View File

@@ -157,7 +157,7 @@ export const standardOrders = async (data: any, user: any) => {
deliveryDate: excelDateStuff(o.DeliveryDate),
customerLineItemNo: o.CustomerLineNumber, // this is how it is currently sent over from abbott
customerReleaseNo: o.CustomerRealeaseNumber, // same as above
remark: o.remark === "" ? null : o.remark,
remark: o.Remark === "" ? null : o.Remark,
},
],
};
@@ -169,7 +169,7 @@ export const standardOrders = async (data: any, user: any) => {
orders: [...predefinedObject.orders, ...nOrder],
};
//console.log(updatedPredefinedObject);
//console.log(updatedPredefinedObject.orders[0]);
// post the orders to the server
const posting: any = await postOrders(updatedPredefinedObject, user);

View File

@@ -1,5 +1,6 @@
import axios from "axios";
import { prodEndpointCreation } from "../../../../../globalUtils/createUrl.js";
import { createLog } from "../../../../logger/logger.js";
export const postOrders = async (data: any, user: any) => {
let endpoint = await prodEndpointCreation(
@@ -11,7 +12,8 @@ export const postOrders = async (data: any, user: any) => {
url: endpoint,
method: "POST",
headers: {
Authorization: `Basic ${user.prod}`,
"X-API-Key": process.env.TEC_API_KEY || "",
"Content-Type": "application/json",
},
// if a body is sent over it would be like below
data: data,
@@ -19,6 +21,12 @@ export const postOrders = async (data: any, user: any) => {
//console.log(results.status);
if (results.data.errors) {
createLog(
"error",
user.username,
"logisitcs",
results.data.errors[0].message
);
return {
success: true,
message: "Error processing orders",
@@ -27,6 +35,12 @@ export const postOrders = async (data: any, user: any) => {
}
if (results.status === 200) {
createLog(
"info",
user.username,
"logisitcs",
"Orders were processed please check 2.0 for validation and errors"
);
return {
success: true,
message: "Success on posting orders",
@@ -37,6 +51,7 @@ export const postOrders = async (data: any, user: any) => {
//console.log(`There is an error`, error);
if (error) {
//console.log(error.response.data);
createLog("error", user.username, "logisitcs", error.response.data);
return {
success: false,
message: "There was an error processing data",

View File

@@ -13,10 +13,12 @@ type Data = {
runningNr: string;
lotNum: number;
};
export const consumeMaterial = async (data: Data, prod: any) => {
export const consumeMaterial = async (data: Data) => {
const { runningNr, lotNum } = data;
// replace the rn
console.log(data);
const rnReplace = labelData.replaceAll("[rn]", runningNr);
let barcode;
@@ -26,12 +28,7 @@ export const consumeMaterial = async (data: Data, prod: any) => {
barcode = r?.data;
} catch (error) {
console.log(error);
createLog(
"error",
prod.user.username,
"logistics",
`Error getting barcode: ${error}`
);
createLog("error", "", "logistics", `Error getting barcode: ${error}`);
}
if (barcode.length === 0) {
@@ -54,8 +51,8 @@ export const consumeMaterial = async (data: Data, prod: any) => {
try {
const results = await axios.post(url, consumeSomething, {
headers: {
"X-API-Key": process.env.TEC_API_KEY || "",
"Content-Type": "application/json",
Authorization: `Basic ${prod.user.prod}`,
},
});
//console.log(results);

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