434 lines
14 KiB
TypeScript
434 lines
14 KiB
TypeScript
import { xmlPayloadTI } from "./tiFullFlow/tiXmlPayload.js";
|
|
import axios from "axios";
|
|
import querystring from "querystring";
|
|
import { getOrderToSend } from "../../../sqlServer/querys/notifications/ti/getOrderToSend.js";
|
|
import { getHeaders } from "../../../sqlServer/querys/notifications/ti/getHeaders.js";
|
|
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
|
import { db } from "../../../../../database/dbclient.js";
|
|
import { settings } from "../../../../../database/schema/settings.js";
|
|
import { serverData } from "../../../../../database/schema/serverData.js";
|
|
import { eq, sql } from "drizzle-orm";
|
|
import { notifications } from "../../../../../database/schema/notifications.js";
|
|
import { query } from "../../../sqlServer/prodSqlServer.js";
|
|
import { createLog } from "../../../logger/logger.js";
|
|
import { freightClass } from "../../../../globalUtils/freightClass.js";
|
|
import { delay } from "../../../../globalUtils/delay.js";
|
|
|
|
const dateCorrection = (newDate: any) => {
|
|
return new Date(newDate)
|
|
.toLocaleString("en-US", {
|
|
timeZone: "UTC",
|
|
year: "numeric",
|
|
month: "2-digit",
|
|
day: "2-digit",
|
|
hour: "2-digit",
|
|
minute: "2-digit",
|
|
second: "2-digit",
|
|
hourCycle: "h23", // Ensures 24-hour format
|
|
})
|
|
.replace(",", "");
|
|
};
|
|
|
|
const tiImport = async () => {
|
|
//await initializePool();
|
|
|
|
// get the plant token
|
|
const { data: plantData, error: plantError } = await tryCatch(
|
|
db.select().from(settings)
|
|
);
|
|
//await initializePool();
|
|
if (plantError) return;
|
|
const plantToken = plantData?.filter((n) => n.name === "plantToken");
|
|
|
|
const { data: plantInfo, error: plantEr } = await tryCatch(
|
|
db
|
|
.select()
|
|
.from(serverData)
|
|
.where(eq(serverData.plantToken, plantToken[0].value))
|
|
);
|
|
|
|
// parsing posting window
|
|
const plantI = plantInfo!;
|
|
//const postTime = JSON.parse(plantI[0]?.tiPostTime!);
|
|
|
|
// order notifications
|
|
const { data: notificationSet, error: notificationSettingsErr } =
|
|
await tryCatch(
|
|
db
|
|
.select()
|
|
.from(notifications)
|
|
.where(eq(notifications.name, "tiIntergration"))
|
|
);
|
|
if (notificationSettingsErr) return;
|
|
|
|
const notiSet: any = notificationSet;
|
|
//creds
|
|
const userid = "ALPLAWSTEST";
|
|
const password = "oe39U1LuLX9ZdY0XKobG";
|
|
|
|
// const requestID = `ALPLAPBTEST1`; // production will be alpla01-dateTime - this will be the time it was sent over.
|
|
const requestUser = "ALPLAWSTEST"; // if alplaprod_rs -- confirm we can use a user name vs the AlplapIMPORT // needs to stay the same as provied
|
|
|
|
const customerAccountNum = plantI[0].customerTiAcc as string; // ti
|
|
|
|
// it we dont get anything here we want to make sure we add it in
|
|
|
|
// get current releaes not in the already sent oders
|
|
let orders = getHeaders;
|
|
orders = orders
|
|
.replaceAll("test1", plantToken[0].value)
|
|
.replaceAll("[from]", notiSet?.notifiySettings.start)
|
|
.replaceAll("[to]", notiSet?.notifiySettings.end)
|
|
.replaceAll(
|
|
"[exclude]",
|
|
notiSet.notifiySettings.processed
|
|
.map((num: any) => `'${num}'`)
|
|
.join(", ")
|
|
);
|
|
|
|
//console.log(orders);
|
|
let headerPending = [];
|
|
try {
|
|
headerPending = await query(orders, "Ti get open headers");
|
|
} catch (error) {
|
|
console.log(error);
|
|
}
|
|
|
|
if (headerPending.length === 0) {
|
|
createLog(
|
|
"info",
|
|
"notification",
|
|
"notify",
|
|
"There are no pending orders to be sent over to ti."
|
|
);
|
|
return {
|
|
success: true,
|
|
code: 1,
|
|
message: "There are no pending orders to be sent over to ti.",
|
|
};
|
|
}
|
|
|
|
createLog(
|
|
"info",
|
|
"notification",
|
|
"notify",
|
|
`There are a total of ${headerPending.length} to send over`
|
|
);
|
|
// update query to have the correct plant token
|
|
let orderToSend = getOrderToSend;
|
|
orderToSend = orderToSend
|
|
.replaceAll("test1", plantToken[0].value)
|
|
.replaceAll("[releaseToProcess]", `'${headerPending[0].releaseNumber}'`)
|
|
.replaceAll("[from]", notiSet.notifiySettings.start)
|
|
.replaceAll("[to]", notiSet.notifiySettings.end);
|
|
|
|
// console.log(orderToSend);
|
|
let records = [];
|
|
try {
|
|
records = await query(orderToSend, "Ti send order");
|
|
} catch (error) {
|
|
console.log(error);
|
|
}
|
|
//console.log(headerPending.length);
|
|
|
|
// update the header
|
|
let webHeader = `
|
|
<request-id>[requestID]</request-id>
|
|
<data>
|
|
<WebImport>
|
|
<WebImportHeader>
|
|
<FileName>[requestID].XML</FileName>
|
|
<Type>SOTransportLoader</Type>
|
|
<UserName>[requestUser]</UserName>
|
|
</WebImportHeader>
|
|
`;
|
|
|
|
webHeader = webHeader.replaceAll(
|
|
"[requestID]",
|
|
`${records[0].releaseNumber}-${plantToken[0].value}`
|
|
);
|
|
webHeader = webHeader.replaceAll("[requestUser]", requestUser);
|
|
|
|
// update the special instructions section
|
|
const otherSettings = plantI[0]?.otherSettings as {
|
|
specialInstructions: string;
|
|
active: boolean;
|
|
}[];
|
|
|
|
const specialInfo = otherSettings[0].specialInstructions.replaceAll(
|
|
"[header]",
|
|
records[0].Header
|
|
);
|
|
// this part will link into the <ItemGroups></ItemGroups>
|
|
let itemGroups = "";
|
|
|
|
for (let i = 0; i < records.length; i++) {
|
|
let newItem = `
|
|
<ItemGroup id="" isShipUnit="false" isHandlingUnit="false" sequence="${
|
|
i + 1
|
|
}">
|
|
<ContainedBy id=""/>
|
|
<LineItem lineNumber="${i + 1}"/>
|
|
<Dimensions>
|
|
<Dimension type="Length" uom="IN">${(
|
|
records[i].pkgLengh / 25.4
|
|
).toFixed(2)}</Dimension>
|
|
<Dimension type="Width" uom="IN">${(
|
|
records[i].pkgWidth / 25.4
|
|
).toFixed(2)}</Dimension>
|
|
<Dimension type="Height" uom="IN">${Math.round(
|
|
records[i].pkgHeight / 25.4
|
|
).toFixed(2)}</Dimension>
|
|
</Dimensions>
|
|
<Description>${`av ${records[i].article} ${records[i].articleAlias}`}</Description>
|
|
<FreightClasses>
|
|
<FreightClass type="">${freightClass(
|
|
records[i].pkgWeight,
|
|
records[i].pkgLengh,
|
|
records[i].pkgWidth,
|
|
records[i].pkgHeight
|
|
)}</FreightClass>
|
|
</FreightClasses>
|
|
<Commodity/>
|
|
<NmfcCode/>
|
|
<HazardousMaterial>false</HazardousMaterial>
|
|
<HazMatDetail/>
|
|
<Weights>
|
|
<Weight type="actual" uom="KG">${
|
|
records[i].pkgWeight * records[i].Pallets
|
|
}</Weight>
|
|
</Weights>
|
|
<Quantities>
|
|
<Quantity type="actual" uom="pallet">${
|
|
records[i].Pallets
|
|
}</Quantity>
|
|
</Quantities>
|
|
</ItemGroup>
|
|
`;
|
|
|
|
itemGroups += newItem;
|
|
}
|
|
|
|
// add the full amount of pallets sending over
|
|
let fullPalToSend = records.reduce(
|
|
(acc: any, o: any) => acc + o.Pallets,
|
|
0
|
|
);
|
|
|
|
// rebuild the xml to be properly
|
|
let payload = xmlPayloadTI;
|
|
payload = payload
|
|
.replaceAll(`[WebImportHeader]`, webHeader)
|
|
.replaceAll(`[items]`, itemGroups)
|
|
.replaceAll(`[customerAccountNum]`, customerAccountNum)
|
|
.replaceAll("[fullTotalPal]", fullPalToSend);
|
|
|
|
// update the main release
|
|
//[loadNumber],[shipNumber]
|
|
payload = payload.replaceAll(`[shipNumber]`, records[0].releaseNumber);
|
|
payload = payload.replaceAll(`[loadNumber]`, records[0].releaseNumber);
|
|
|
|
// do the multie release if needed
|
|
// <ReferenceNumber type="Release Number" isPrimary="false">[multieReleaseNumber]</ReferenceNumber>
|
|
|
|
let multiRelease = ``;
|
|
if (records.length > 0) {
|
|
for (let i = 0; i < records.length; i++) {
|
|
const newRelease = `
|
|
<ReferenceNumber type="Release Number" isPrimary="false">${records[i].releaseNumber}</ReferenceNumber>`;
|
|
multiRelease += newRelease;
|
|
}
|
|
|
|
payload = payload.replaceAll("[multieReleaseNumber]", multiRelease);
|
|
} else {
|
|
payload = payload.replaceAll("[multieReleaseNumber]", "");
|
|
}
|
|
|
|
//update the delivery section
|
|
payload = payload.replaceAll(
|
|
"[loadingDate]",
|
|
dateCorrection(records[0].LoadingDate)
|
|
);
|
|
|
|
payload = payload.replaceAll(
|
|
"[deliveryDate]",
|
|
dateCorrection(records[0].DeliveryDate)
|
|
);
|
|
|
|
// shipping hours
|
|
//<Date type="earliest">[shippingHoursEarly]</Date>
|
|
//<Date type="latest">[shippingHoursLate]</Date>
|
|
|
|
// update teh shipping hours
|
|
|
|
const now = new Date();
|
|
const formattedDate = records[0].LoadingDate.toLocaleDateString("en-US", {
|
|
month: "2-digit",
|
|
day: "2-digit",
|
|
year: "numeric",
|
|
});
|
|
|
|
const shippingHours = JSON.parse(plantI[0]?.shippingHours!);
|
|
//console.log(shippingHours);
|
|
|
|
payload = payload
|
|
.replaceAll(
|
|
"[shippingHoursEarly]",
|
|
`${formattedDate} ${shippingHours[0].early}`
|
|
)
|
|
.replaceAll(
|
|
"[shippingHoursLate]",
|
|
`${formattedDate} ${shippingHours[0].late}`
|
|
);
|
|
|
|
payload = payload
|
|
.replaceAll("[plantName]", `Alpla ${plantI[0]?.sName!}`)
|
|
.replaceAll("[plantStreetAddress]", plantI[0]?.streetAddress!)
|
|
.replaceAll("[plantCity]", plantI[0]?.cityState!.split(",")[0])
|
|
.replaceAll("[plantState]", plantI[0]?.cityState!.split(",")[1])
|
|
.replaceAll("[plantZipCode]", plantI[0]?.zipcode!)
|
|
.replaceAll("[contactNum]", plantI[0]?.contactPhone!)
|
|
.replaceAll("[contactEmail]", plantI[0]?.contactEmail!)
|
|
|
|
// customer info
|
|
.replaceAll("[customerName]", records[0].addressAlias)
|
|
.replaceAll("[customerStreetAddress]", records[0].streetAddress)
|
|
.replaceAll("[customerCity]", records[0].city.split(",")[0])
|
|
.replaceAll("[customerState]", records[0].city.split(",")[1])
|
|
.replaceAll("[customerZip]", records[0].zipCode)
|
|
.replaceAll("[customerPO]", records[0].Header)
|
|
.replaceAll(
|
|
"[glCoding]",
|
|
`52410-${
|
|
records[0].artileType.toLowerCase() === "preform" ||
|
|
records[0].artileType.toLowerCase() === "metalCage"
|
|
? 31
|
|
: plantI[0].greatPlainsPlantCode
|
|
}`
|
|
) // {"52410 - " + (artileType.toLowerCase() === "preform" || artileType.toLowerCase() === "metalCage" ? 31: plantInfo[0].greatPlainsPlantCode)}
|
|
.replaceAll(
|
|
"[pfc]",
|
|
`${
|
|
records[0].artileType.toLowerCase() === "preform" ||
|
|
records[0].artileType.toLowerCase() === "metalCage"
|
|
? 40
|
|
: records[0].costCenter
|
|
}`
|
|
);
|
|
|
|
// special instructions
|
|
if (otherSettings[0].specialInstructions.length != 0) {
|
|
payload = payload.replaceAll("[specialInstructions]", specialInfo);
|
|
}
|
|
|
|
// update the carrier info if any is needed.
|
|
|
|
// check the address has a real carrier on it and change to true and put the sacs code in
|
|
const hasCarrier = true;
|
|
|
|
console.log(
|
|
`Checking if ${records[0].addressAlias} has scac: ${
|
|
records[0].remark.split(",")[0] ? "there was one" : "no scac"
|
|
}`
|
|
);
|
|
|
|
const priceSheet = `
|
|
<PriceSheets>
|
|
<PriceSheet type="Carrier" isSelected="${
|
|
records[0].remark.split(",")[0] ? "true" : "false"
|
|
}">
|
|
<ContractId/>
|
|
${
|
|
records[0].remark.split(",")[0]
|
|
? `<SCAC>${records[0].remark
|
|
.split(",")[0]
|
|
.split(":")[1]
|
|
.toUpperCase()}</SCAC>`
|
|
: `<SCAC/>`
|
|
}
|
|
<Mode/>
|
|
</PriceSheet>
|
|
</PriceSheets>
|
|
`;
|
|
|
|
payload = payload.replaceAll("[priceSheet]", priceSheet);
|
|
// console.log(payload);
|
|
//await closePool();
|
|
|
|
//put the xml into a form
|
|
const formBody = querystring.stringify({
|
|
userid,
|
|
password,
|
|
request: payload,
|
|
});
|
|
axios
|
|
.post(
|
|
"https://t-insightws.mercurygate.net/MercuryGate/common/remoteService.jsp",
|
|
formBody,
|
|
{
|
|
headers: {
|
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
},
|
|
}
|
|
)
|
|
.then((response) => {
|
|
//console.log(response.data)
|
|
console.log("Data was sent over to TI");
|
|
})
|
|
.catch((error) => console.error(error));
|
|
|
|
// console.log(payload);
|
|
|
|
// the order is done so we want to update the processed.
|
|
|
|
// add the new processed order to this
|
|
let notiSettingArray = notiSet.notifiySettings;
|
|
|
|
if (
|
|
!notiSettingArray[0].processed.includes(headerPending[0].releaseNumber)
|
|
) {
|
|
notiSettingArray[0].processed.push(headerPending[0].releaseNumber);
|
|
}
|
|
|
|
const { data, error } = await tryCatch(
|
|
db
|
|
.update(notifications)
|
|
.set({
|
|
lastRan: sql`NOW()`,
|
|
notifiySettings: {
|
|
...notiSettingArray,
|
|
prodID: 1,
|
|
},
|
|
})
|
|
.where(eq(notifications.name, "tiIntergration"))
|
|
);
|
|
createLog("info", "ti", "notify", "done with this order");
|
|
return { success: true, code: 0, message: "done with this order" };
|
|
};
|
|
|
|
// add a running check so we cant flag it twice
|
|
export let tiExportRunning = false;
|
|
export const runTiImport = async () => {
|
|
let finished = false;
|
|
let test: any;
|
|
tiExportRunning = true;
|
|
do {
|
|
createLog("info", "ti", "notify", "processing new data");
|
|
// code block to be executed
|
|
test = await tiImport();
|
|
createLog(
|
|
"info",
|
|
"ti",
|
|
"notify",
|
|
`Still more to process? ${test.code === 1 ? "No" : "Yes"}`
|
|
);
|
|
if (test.code === 1) {
|
|
finished = true;
|
|
}
|
|
await delay(1000 * 5);
|
|
} while (!finished);
|
|
tiExportRunning = false;
|
|
};
|
|
|
|
export default tiImport;
|