From c386c5ea8b5500a99c49c2750d9b1f3e2816521a Mon Sep 17 00:00:00 2001 From: Blake Matthes Date: Thu, 13 Mar 2025 15:41:21 -0500 Subject: [PATCH] feat(ocme): added in shipment data with increased checked --- .../ocme/controller/getShipmentData.ts | 30 ++++ .../ocme/controller/getShipmentPallets.ts | 137 ++++++++++++++++++ .../ocme/controller/lotrestriction.ts | 62 ++++++++ .../services/ocme/route/getShipmentPallets.ts | 15 +- 4 files changed, 242 insertions(+), 2 deletions(-) create mode 100644 server/services/ocme/controller/getShipmentData.ts create mode 100644 server/services/ocme/controller/getShipmentPallets.ts create mode 100644 server/services/ocme/controller/lotrestriction.ts diff --git a/server/services/ocme/controller/getShipmentData.ts b/server/services/ocme/controller/getShipmentData.ts new file mode 100644 index 0000000..f4501b1 --- /dev/null +++ b/server/services/ocme/controller/getShipmentData.ts @@ -0,0 +1,30 @@ +import {addDays, format, subDays} from "date-fns"; +import {db} from "../../../../database/dbclient.js"; +import {settings} from "../../../../database/schema/settings.js"; +import {prodEndpointCreation} from "../../../globalUtils/createUrl.js"; +import axios from "axios"; +import {lstAuth} from "../../../index.js"; +import {createLog} from "../../logger/logger.js"; + +export const getShipmentData = async () => { + let shiptmentInfo: any = []; + let url = await prodEndpointCreation("/public/v1.0/Warehousing/GetTrucksAndLoadingPlans"); + const setting = await db.select().from(settings); + const today = new Date(Date.now()); + const checkDays = parseInt(setting.filter((n) => n.name === "dayCheck")[0].value); + + const postData = { + fromDate: `${format(subDays(today, checkDays), "yyyy-MM-dd")}`, + toDate: `${format(addDays(today, checkDays), "yyyy-MM-dd")}`, + }; + + try { + const result = await axios.post(url, postData, {headers: {Authorization: `Basic ${lstAuth}`}}); + shiptmentInfo = result.data; + createLog("info", "ocme", "ocme", `Shipment info based on shipping id was just processed`); + return {success: true, message: "Shipment data", data: shiptmentInfo}; + } catch (error) { + createLog("error", "ocme", "ocme", `There was an error getting the shipment data: ${error}`); + return {success: false, message: "Error in getting shipment data", data: error}; + } +}; diff --git a/server/services/ocme/controller/getShipmentPallets.ts b/server/services/ocme/controller/getShipmentPallets.ts new file mode 100644 index 0000000..402a34b --- /dev/null +++ b/server/services/ocme/controller/getShipmentPallets.ts @@ -0,0 +1,137 @@ +import axios from "axios"; +import {createLog} from "../../logger/logger.js"; +import {shipmentPallets} from "../../sqlServer/querys/ocme/shipmentPallets.js"; +import {getShipmentData} from "./getShipmentData.js"; +import {query} from "../../sqlServer/prodSqlServer.js"; +import {db} from "../../../../database/dbclient.js"; +import {settings} from "../../../../database/schema/settings.js"; +import {lotRestriction} from "./lotrestriction.js"; + +export const getShipmentPallets = async (shipmentID: any) => { + let ocmeLanes: any = []; + const setting = await db.select().from(settings); + // get the current shipments avalible + + let connect; + try { + let res = await axios.get("http://usday1vms010:3250/api/v1/getlanes"); + ocmeLanes = res.data.data; + } catch (error) { + console.log(error); + } + + const shipments = await getShipmentData(); + + // filter the shipment so we can get the correct data from it. + const filteredShipment = shipments.data.filter((order: any) => order.LoadingOrderId === parseInt(shipmentID)); + + // getting the criteria we want to look at. + let tmpCheck: any = []; + if (filteredShipment.length === 0) { + createLog("error", "ocme", "ocme", "Invalid shipment id was provided and cant do anything else."); + return { + success: false, + message: "Invalid shipmentID sent over please try again", + }; + } else { + tmpCheck = filteredShipment[0].Remark.split(",") + .map((item: any) => item.trim()) // removes accedental spaces if there are any + .map((i: any) => i.toLowerCase()); + } + + // removing the agv out of the array + let checks = tmpCheck.filter((i: any) => i !== "agv"); + + let shipmentQ = shipmentPallets + .replaceAll("[article]", filteredShipment[0].LoadingPlan[0].ArticleVariantId) + .replaceAll("[fifo]", setting.filter((n) => n.name === "fifoCheck")[0].value); + + const addressCheck = setting.filter((n) => n.name === "monitorAddress"); + + if (parseInt(addressCheck[0].value) === filteredShipment[0].LoadingPlan[0].AddressId) { + // if there really ends up being more than 5000 pallets then well we need to fix this later, also an insane issue to have this many that would need to be monitored + shipmentQ = shipmentQ.replaceAll("[totalPallets]", "5000"); + } else { + shipmentQ = shipmentQ.replaceAll("[totalPallets]", filteredShipment[0].LoadingPlan[0].PackagingQuantity); + } + + // temp situation only getting the lanes we want to look in + // Convert laneArray to a comma-separated string with each value quoted + let noBlock; + if (checks.includes("all")) { + noBlock = shipmentQ.replaceAll("and GesperrtAktivSum in (0) ", "--and GesperrtAktivSum in (0) "); + } else { + noBlock = shipmentQ; + } + + // getting the lanes we want to pull the info from if we passed over? + let laneString; + if (checks.includes("lanes")) { + // let lanes = checks.slice(2); + let lanes = checks.filter((i: any) => i !== "all"); + laneString = lanes.map((lane: any) => `'${lane}'`).join(","); + // something cool + } else { + // console.log(ocmeLanes); + laneString = ocmeLanes.map((lane: any) => `'${lane}'`).join(","); + } + + let shipmentLane = shipmentQ.replaceAll("[lanes]", laneString); + + let shipmentPals = []; + //console.log(shipmentLane); + try { + shipmentPals = await query(shipmentLane, "Get shipmentPals"); + } catch (err) { + createLog("error", "ocme", "ocme", `Error from running the shippment pallets query: ${err}`); + return {success: false, message: err, data: []}; + } + + let filteredPallets = shipmentPals; + + // if we have all or lanes just send whats in the query + if (tmpCheck.includes("all") || tmpCheck.includes("lanes")) { + return { + success: true, + message: `There are a total of ${filteredPallets.length} pallet(s) that are in this shipment.`, + data: filteredPallets.splice(0, filteredShipment[0].LoadingPlan[0].PackagingQuantity), + }; + } + + // if we have just lanes send whats in the query + if (tmpCheck.includes("lanes")) { + return { + success: true, + message: `There are a total of ${filteredPallets.length} pallet(s) that are in this shipment.`, + data: filteredPallets, + }; + } + + // will return everything in the fifo range and the total amount requested + if (tmpCheck.includes("all")) { + return { + success: true, + message: `There are a total of ${filteredPallets.length} pallet(s) that are in this shipment.`, + data: filteredPallets.splice(0, filteredShipment[0].LoadingPlan[0].PackagingQuantity), + }; + } + + // for "what ever case" follow the logic. to check addresses and resitrions + if (parseInt(addressCheck[0].value) === filteredShipment[0].LoadingPlan[0].AddressId) { + createLog( + "info", + "ocme", + "ocme", + "This shipment has restrictions on it and will go throught the lots filtering process" + ); + filteredPallets = await lotRestriction(shipmentPals, filteredShipment[0].LoadingPlan[0].PackagingQuantity); + } else { + createLog("info", "ocme", "ocme", "This shipment is cleared to send what ever."); + } + + return { + success: true, + message: `There are a total of ${filteredPallets.length} pallet(s) that are in this shipment.`, + data: filteredPallets, + }; +}; diff --git a/server/services/ocme/controller/lotrestriction.ts b/server/services/ocme/controller/lotrestriction.ts new file mode 100644 index 0000000..e7886d5 --- /dev/null +++ b/server/services/ocme/controller/lotrestriction.ts @@ -0,0 +1,62 @@ +import {db} from "../../../../database/dbclient.js"; +import {settings} from "../../../../database/schema/settings.js"; +import {createLog} from "../../logger/logger.js"; + +export const lotRestriction = async (pallets: any, truckQty: number) => { + // get the settings so we have these. + const setting = await db.select().from(settings); + const maxLots = parseInt(setting.filter((n) => n.name === "maxLotPerTruck")[0].value); + // sort by production date so we can get the oldest ones first + pallets.sort((a: any, b: any) => new Date(a.productionDate).getTime() - new Date(b.productionDate).getTime()); + + // group all pallets by the lot numbers + const groupedByLotNum = pallets.reduce((acc: any, item: any) => { + if (!acc[item.lotNum]) { + acc[item.lotNum] = []; + } + acc[item.lotNum].push(item); + return acc; + }, {}); + + // select the oldest lots until we have 3 lots that meet or exceed 22 pallets + const selectedLots = []; + let totalPallets = 0; + + // Sort lots by the oldest productionDate in each lot + const sortedLots = Object.keys(groupedByLotNum).sort((a, b) => { + return ( + new Date(groupedByLotNum[a][0].productionDate).getTime() - + new Date(groupedByLotNum[b][0].productionDate).getTime() + ); + }); + + for (const lotNum of sortedLots) { + // Add the current lot to the selection + selectedLots.push(lotNum); + totalPallets += groupedByLotNum[lotNum].length; + + // If we have 3 lots, check if the total pallets meet or exceed 22 + if (selectedLots.length === maxLots) { + if (totalPallets >= truckQty) { + // We have enough pallets, exit the loop + break; + } else { + // Remove the last added lot and try the next one + const removedLot = selectedLots.pop(); + totalPallets -= groupedByLotNum[removedLot!].length; + } + } + } + + // flatten the selected lots into a single array + let result = selectedLots.flatMap((lotNum) => groupedByLotNum[lotNum]); + + // trim down to be only the the truck qty + if (result.length > truckQty) { + result = result.slice(0, truckQty); + } + + createLog("info", "ocme", "ocme", `Total pallets: ${result.length}`); + createLog("info", "ocme", "ocme", `Unique lotNums:", ${new Set(result.map((pallet) => pallet.lotNum)).size}`); + return result; +}; diff --git a/server/services/ocme/route/getShipmentPallets.ts b/server/services/ocme/route/getShipmentPallets.ts index 4966302..ddcfb0a 100644 --- a/server/services/ocme/route/getShipmentPallets.ts +++ b/server/services/ocme/route/getShipmentPallets.ts @@ -1,5 +1,6 @@ import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi"; import {apiHit} from "../../../globalUtils/apiHits.js"; +import {getShipmentPallets} from "../controller/getShipmentPallets.js"; const app = new OpenAPIHono(); @@ -72,9 +73,19 @@ app.openapi( const data = await c.req.json(); apiHit(c, {endpoint: "api/ocme/getshipmentpallets", lastBody: data}); - const postPallet = {success: true, message: "Something", data: []}; + if (!data.shipmentID) { + return c.json( + {success: false, message: "You are missing the shipment id please try again.", data: []}, + 400 + ); + } - return c.json({success: postPallet.success, message: postPallet.message, data: postPallet.data ?? []}, 200); + const shiptmentData = await getShipmentPallets(data.shipmentID); + + return c.json( + {success: shiptmentData.success, message: shiptmentData.message, data: shiptmentData.data ?? []}, + 200 + ); } catch (error) { return c.json({success: false, message: "There was an error getting the shipment data.", data: error}, 400); }