From a709be838f65a750065269b4dd83a4ffd64c2feb Mon Sep 17 00:00:00 2001 From: Blake Matthes Date: Fri, 2 May 2025 07:51:16 -0500 Subject: [PATCH] feat(loreal): vmi file can be sent over now --- .../src/components/logistics/dm/DMButtons.tsx | 6 +- .../logistics/dm/ForecastImport.tsx | 2 +- .../dm/forecast/mappings/loralForecast.ts | 188 ++++++++++++++---- 3 files changed, 159 insertions(+), 37 deletions(-) diff --git a/frontend/src/components/logistics/dm/DMButtons.tsx b/frontend/src/components/logistics/dm/DMButtons.tsx index 0678a70..68158b4 100644 --- a/frontend/src/components/logistics/dm/DMButtons.tsx +++ b/frontend/src/components/logistics/dm/DMButtons.tsx @@ -1,3 +1,4 @@ +import ForecastImport from "./ForecastImport"; import OrderImport from "./OrderImport"; import { useSettingStore } from "@/lib/store/useSettings"; @@ -20,6 +21,7 @@ export default function DMButtons() { fileType={"energizer"} name={"Energizer Truck List"} /> + )} {plantToken[0]?.value === "usday1" && ( @@ -35,7 +37,9 @@ export default function DMButtons() { )} {plantToken[0]?.value === "usflo1" && ( -
+
+ +
)} {plantToken[0]?.value === "usstp1" && (
diff --git a/frontend/src/components/logistics/dm/ForecastImport.tsx b/frontend/src/components/logistics/dm/ForecastImport.tsx index 0752f4c..37f65af 100644 --- a/frontend/src/components/logistics/dm/ForecastImport.tsx +++ b/frontend/src/components/logistics/dm/ForecastImport.tsx @@ -21,7 +21,7 @@ export default function ForecastImport(props: any) { formData.append("postForecast", e.target.files[0]); formData.append("fileType", props.fileType); // extra field // console.log(formData); - + toast.success("Import started."); try { const response = await axios.post( "/api/logistics/postforecastin", diff --git a/server/services/logistics/controller/dm/forecast/mappings/loralForecast.ts b/server/services/logistics/controller/dm/forecast/mappings/loralForecast.ts index ce560ae..683dc65 100644 --- a/server/services/logistics/controller/dm/forecast/mappings/loralForecast.ts +++ b/server/services/logistics/controller/dm/forecast/mappings/loralForecast.ts @@ -4,6 +4,9 @@ import { tryCatch } from "../../../../../../globalUtils/tryCatch.js"; import XLSX from "xlsx"; import { excelDateStuff } from "../../../../utils/excelDateStuff.js"; import { postForecast } from "../postForecast.js"; +import { query } from "../../../../../sqlServer/prodSqlServer.js"; +import { activeArticle } from "../../../../../sqlServer/querys/dataMart/article.js"; +import { addDays } from "date-fns"; let customerID = 4; export const lorealForecast = async (data: any, user: any) => { @@ -31,59 +34,163 @@ export const lorealForecast = async (data: any, user: any) => { const sheet: any = workbook.Sheets["Alpla HDPE"]; const range = XLSX.utils.decode_range(sheet["!ref"]); + const psheet: any = workbook.Sheets["Alpla PET"]; + const prange = XLSX.utils.decode_range(psheet["!ref"]); + const headers = []; for (let C = range.s.c; C <= range.e.c; ++C) { - const cellAddress = XLSX.utils.encode_cell({ r: 0, c: C }); // row 0 = Excel row 1 + const cellAddress = XLSX.utils.encode_cell({ r: 1, c: C }); // row 0 = Excel row 1 const cell = sheet[cellAddress]; headers.push(cell ? cell.v : undefined); } - const forecastData: any = XLSX.utils.sheet_to_json(sheet, { + const pheaders = []; + for (let C = prange.s.c; C <= prange.e.c; ++C) { + const cellAddress = XLSX.utils.encode_cell({ r: 1, c: C }); // row 0 = Excel row 1 + const cell = psheet[cellAddress]; + pheaders.push(cell ? cell.v : undefined); + } + + const ebmForeCastData: any = XLSX.utils.sheet_to_json(sheet, { defval: "", header: headers, - range: 2, + range: 3, }); - // Extract the customer code (assuming it's always present) - const customerCode = forecastData["NORTH HDPE BOTTLES"]; + const petForeCastData: any = XLSX.utils.sheet_to_json(psheet, { + defval: "", + header: pheaders, + range: 3, + }); - // Filter out non-date properties (these are your metadata fields) - const metadataFields = [ - "NORTH HDPE BOTTLES", - "BLOCKED", - "INVENTORY", - "CALL-OFF", - "PALLET CONSUMPTION", - ]; + const ebmForecastData: any = []; + const missingSku: any = []; - const foreCastData: any = []; + const { data: a, error: ae } = await tryCatch( + query(activeArticle, "Loreal calling active av") + ); - // process the forcast - forecastData.forEach((item: any, index: any) => { - //console.log(`Processing item ${index + 1} of ${forecastData.length}`); + if (ae) { + return { + success: false, + message: "Error getting active av", + data: [], + }; + } - // Extract the customer code - const customerCode = item["NORTH HDPE BOTTLES"]; + const article: any = a?.data; - // Process each date in the current object - for (const [date, qty] of Object.entries(item)) { - // Skip metadata fields - if (metadataFields.includes(date)) continue; + // process the ebm forcast + for (let i = 0; i < ebmForeCastData.length; i++) { + // bottle code + const sku = ebmForeCastData[i]["HDPE Bottle Code"]; - if (qty === 0) continue; + // ignore the blanks + if (sku === "") continue; - // Create your transformed record - const record = { - customerArticleNo: customerCode, - requirementDate: excelDateStuff(parseInt(date)), - quantity: qty, + // ignore zero qty + // if (ebmForeCastData[i][`Day ${i}`]) continue; + + for (let f = 0; f <= 90; f++) { + const day = `Day ${f + 1}`; + // if (ebmForeCastData[i][day] === 0) continue; + + const forcast = { + customerArticleNo: sku, + requirementDate: addDays(new Date(Date.now()), f), //excelDateStuff(parseInt(date)), + quantity: ebmForeCastData[i][day] ?? 0, }; - // Do something with this record - foreCastData.push(record); - } - }); + if (forcast.quantity === 0) continue; + // checking to make sure there is a real av to add to. + const activeAV = article.filter( + (c: any) => + c?.CustomerArticleNumber === + forcast.customerArticleNo.toString() + ); + + if (activeAV.length === 0) { + continue; + } + + ebmForecastData.push(forcast); + } + + //console.log(ebmForeCastData.length); + } + + // petForeCastData.forEach((item: any, index: any) => { + // //console.log(`Processing item ${index + 1} of ${forecastData.length}`); + + // // Extract the customer code + // const customerCode = item["SOUTH PET BOTTLES"]; + + // // Process each date in the current object + // for (const [date, qty] of Object.entries(item)) { + // // Skip metadata fields + // if (petMetadataFields.includes(date)) continue; + + // if (qty === 0) continue; + + // // Create your transformed record + // const record = { + // customerArticleNo: customerCode, + // requirementDate: excelDateStuff(parseInt(date)), + // quantity: qty, + // }; + + // // Do something with this record + // petForecastData.push(record); + // } + // }); + + // pet forecast + for (let i = 0; i < petForeCastData.length; i++) { + // bottle code + const sku = petForeCastData[i]["South PET Bottle Code"]; + + // ignore the blanks + if (sku === "") continue; + + // ignore zero qty + // if (ebmForeCastData[i][`Day ${i}`]) continue; + + for (let f = 0; f <= 90; f++) { + const day = `Day ${f + 1}`; + // if (ebmForeCastData[i][day] === 0) continue; + + const forcast = { + customerArticleNo: sku, + requirementDate: addDays(new Date(Date.now()), f), //excelDateStuff(parseInt(date)), + quantity: petForeCastData[i][day] ?? 0, + }; + + if (forcast.quantity === 0 || forcast.quantity === "") continue; + + if (forcast.customerArticleNo < 99999) { + //console.log(`Sku a normal av ${forcast.customerArticleNo}`); + continue; + } + + // checking to make sure there is a real av to add to. + const activeAV = article.filter( + (c: any) => + c?.CustomerArticleNumber === + forcast.customerArticleNo.toString() + ); + + if (activeAV.length === 0) { + continue; + } + + ebmForecastData.push(forcast); + } + } + + //console.log(comForecast); + + // if the customerarticle number is not matching just ignore it const predefinedObject = { receivingPlantId: plantToken[0].value, documentName: `ForecastFromLST-${new Date(Date.now()).toLocaleString( @@ -98,13 +205,24 @@ export const lorealForecast = async (data: any, user: any) => { ...predefinedObject, positions: [ ...predefinedObject.positions, - ...foreCastData.filter((q: any) => q.customerArticleNo != ""), + ...ebmForecastData, + + // ...ebmForecastData.filter( + // (q: any) => + // q.customerArticleNo != "" && q.customerArticleNo != "Total" + // ), + // ...petForecastData.filter( + // (q: any) => + // q.customerArticleNo != "" && q.customerArticleNo != "Total" + // ), ], }; + // console.log(updatedPredefinedObject); const posting: any = await postForecast(updatedPredefinedObject, user); + return { success: posting.success, message: posting.message, - data: posting.data, + data: posting.data === "" ? ebmForecastData : posting.data, }; };