All checks were successful
Build and Push LST Docker Image / docker (push) Successful in 1m32s
246 lines
6.3 KiB
TypeScript
246 lines
6.3 KiB
TypeScript
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,
|
|
};
|
|
};
|