import { addDays } from "date-fns"; import XLSX from "xlsx"; import { runDatamartQuery } from "../datamart/datamart.controller.js"; import { type SqlQuery, sqlQuerySelector, } from "../prodSql/prodSqlQuerySelector.utils.js"; import { returnFunc } from "../utils/returnHelper.utils.js"; //import { sendEmail } from "../utils/sendEmail.utils.js"; import { tryCatch } from "../utils/trycatch.utils.js"; import { postData } from "./logistics.dm.postData.js"; const customerID = 4; export const lorealForecast = async (data: any, user: any) => { /** * Post a standard forecast based on the standard template. */ const buffer = Buffer.from(data.buffer); const workbook = XLSX.read(buffer, { type: "buffer" }); 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: 1, c: C }); // row 0 = Excel row 1 const cell = sheet[cellAddress]; headers.push(cell ? cell.v : undefined); } 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: 3, }); const petForeCastData: any = XLSX.utils.sheet_to_json(psheet, { defval: "", header: pheaders, range: 3, }); const ebmForecastData: any = []; const missingSku: any = []; const avSQLQuery = sqlQuerySelector(`datamart.activeArticles`) as SqlQuery; if (!avSQLQuery.success) { return returnFunc({ success: false, level: "error", module: "logistics", subModule: "forecast", message: `Error getting Article info`, data: [avSQLQuery.message], notify: true, }); } const { data: a, error: ae } = await tryCatch( runDatamartQuery({ name: "activeArticles", options: {} }), ); if (ae) { return { success: false, message: "Error getting active av", data: [], }; } const article: any = a?.data; //console.log(article); // process the ebm forcast for (let i = 0; i < ebmForeCastData.length; i++) { // bottle code const sku = ebmForeCastData[i]["HDPE 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: ebmForeCastData[i][day] ?? 0, }; 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) { if (typeof forcast.customerArticleNo === "number") { missingSku.push(forcast); } continue; } ebmForecastData.push(forcast); } //console.log(ebmForeCastData.length); } // 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) { if (typeof forcast.customerArticleNo === "number") { missingSku.push(forcast); } continue; } ebmForecastData.push(forcast); } } //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; // }, {}), // ); // TODO: change this to a flagged notification so that he users can subscribe or leave it. this removes the hardcody shit. // 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, // }, // }; // sendEmail(emailSetup); // if the customerarticle number is not matching just ignore it const predefinedObject = { receivingPlantId: process.env.PROD_PLANT_TOKEN ?? "test1", documentName: `ForecastFromLST-${new Date(Date.now()).toLocaleString( "en-US", )}`, sender: user.username || "lst-system", customerId: customerID, positions: [], }; const updatedPredefinedObject = { ...predefinedObject, positions: [...predefinedObject.positions, ...ebmForecastData], }; // console.log(updatedPredefinedObject); // posting the data to the new backend so we can store the data. const posting: any = await postData( { type: "forecast", endpoint: "/public/v1.0/DemandManagement/DELFOR", data: updatedPredefinedObject as any, }, user, ); return { success: posting.success, message: posting.message, data: posting.data === "" ? ebmForecastData : posting.data, }; };