feature/IO-2769-Job-Totals-Testing

This commit is contained in:
Dave Richer
2025-04-08 11:42:27 -04:00
parent 5f66488410
commit a18ce18d72
12 changed files with 295 additions and 53 deletions

View File

@@ -1,7 +1,6 @@
const Dinero = require("dinero.js");
const queries = require("../graphql-client/queries");
const logger = require("../utils/logger");
const { captureFixture } = require("./utils/seralizeHelper");
const InstanceMgr = require("../utils/instanceMgr").default;
//****************************************************** */
@@ -31,16 +30,8 @@ exports.totalsSsu = async function (req, res) {
const job = await client.setHeaders({ Authorization: BearerToken }).request(queries.GET_JOB_BY_PK, {
id: id
});
// Extract the job data (the input for TotalsServerSide)
const inputForTotals = job.jobs_by_pk;
const newTotals = await TotalsServerSide({ body: { job: inputForTotals, client: client } }, res, true);
// Capture fixture data (input and output), using job.id for the filename.
if (process.env?.SAVE_TOTALS_DATA === "true") {
captureFixture(inputForTotals, newTotals);
}
p;
const newTotals = await TotalsServerSide({ body: { job: job.jobs_by_pk, client: client } }, res, true);
const result = await client.setHeaders({ Authorization: BearerToken }).request(queries.UPDATE_JOB, {
jobId: id,

View File

@@ -0,0 +1,133 @@
const logger = require("../utils/logger");
const queries = require("../graphql-client/queries");
const moment = require("moment");
const { captureFixture } = require("./utils/seralizeHelper");
const { TotalsServerSide: totalsServerSideCA } = require("./job-totals"); // Canadian version (imex)
const { TotalsServerSide: totalsServerSideUS } = require("./job-totals-USA");
const InstanceMgr = require("../utils/instanceMgr").default;
const { uploadFileToS3 } = require("../utils/s3");
// requires two buckets be made per env, job-totals-test, job-totals-production, locally it will
// use `job-totals` in the owncloud stack
/**
* Returns the environment prefix based on NODE_ENV
* @returns {string}
*/
const getEnvPrefix = () => {
switch (process.env?.NODE_ENV) {
case "test":
return "test";
case "production":
return "production";
default:
return "test";
}
};
const envPrefix = getEnvPrefix();
const S3_BUCKET_NAME = process.env?.NODE_ENV === "development" ? "imex-job-totals" : `job-totals-${envPrefix}`;
/**
* Generates a unique S3 key for the job totals file
* @param {string} jobId - The job ID
* @returns {string} - S3 key with timestamp
*/
const generateS3Key = (jobId) => `${jobId}-${moment().toISOString()}.json`;
/**
* Uploads job totals data to S3
* @param {object} data - The data to upload
* @param {string} jobId - The job ID
* @param {object} userInfo - User information for logging
* @returns {Promise<string>} - The S3 key
*/
const uploadJobTotalsToS3 = async (data, jobId, userInfo) => {
const key = generateS3Key(jobId);
try {
await uploadFileToS3({
bucketName: S3_BUCKET_NAME,
key: key,
content: JSON.stringify(data, null, 2),
contentType: "application/json"
});
logger.log(`Job totals uploaded successfully to ${key}`, "info", userInfo.email, jobId);
return key;
} catch (error) {
logger.log("Failed to upload job totals to S3", "error", userInfo.email, jobId, {
error: error?.message,
stack: error?.stack
});
throw error; // Re-throw for the main handler to catch
}
};
/**
* Fetches job data using GraphQL
* @param {object} client - GraphQL client
* @param {string} token - Bearer token
* @param {string} jobId - Job ID to fetch
* @returns {Promise<object>} - Job data
*/
const fetchJobData = async (client, token, jobId) => {
return client
.setHeaders({ Authorization: token })
.request(queries.GET_JOB_BY_PK, { id: jobId })
.then((response) => response.jobs_by_pk);
};
/**
* This function is used to capture job totals json files.
* @param {object} req - Express request
* @param {object} res - Express response
* @returns {Promise<void>}
*/
const jobTotalsRecorder = async (req, res) => {
const { id: jobId } = req.body;
const bearerToken = req.BearerToken;
const client = req.userGraphQLClient;
const userEmail = req?.user?.email;
logger.log("Starting job totals recording", "debug", userEmail, jobId);
try {
// Fetch job data
const jobData = await fetchJobData(client, bearerToken, jobId);
// Get the appropriate totals function based on instance
const totalsFunction = InstanceMgr({
imex: totalsServerSideCA,
rome: totalsServerSideUS
});
// Calculate the totals
const calculatedTotals = await totalsFunction({ body: { job: jobData, client }, req }, res, true);
// Prepare data for storage
const dataToSave = captureFixture(jobData, calculatedTotals);
// Upload to S3
await uploadJobTotalsToS3(dataToSave, jobId, { email: userEmail });
res.status(200).json({ success: true, message: "Job totals recorded successfully" });
} catch (error) {
logger.log("Failed to record job totals", "error", userEmail, jobId, {
error: error?.message,
stack: error?.stack
});
// Avoid sending response if it's already been sent
if (!res.headersSent) {
res.status(503).json({
success: false,
message: "Error processing job totals",
error: error.message
});
}
}
};
module.exports = jobTotalsRecorder;

View File

@@ -1,7 +1,6 @@
const Dinero = require("dinero.js");
const queries = require("../graphql-client/queries");
const logger = require("../utils/logger");
const { captureFixture } = require("./utils/seralizeHelper");
//****************************************************** */
//****************************************************** */
@@ -31,16 +30,8 @@ exports.totalsSsu = async function (req, res) {
id: id
});
// Extract the job data (the input for TotalsServerSide)
const inputForTotals = job.jobs_by_pk;
// Capture the output of TotalsServerSide
const newTotals = await TotalsServerSide({ body: { job: inputForTotals, client: client } }, res, true);
// Capture fixture data (input and output), using job.id for the filename.
if (process.env?.SAVE_TOTALS_DATA === "true") {
captureFixture(inputForTotals, newTotals);
}
const newTotals = await TotalsServerSide({ body: { job: job.jobs_by_pk, client: client } }, res, true);
const result = await client.setHeaders({ Authorization: BearerToken }).request(queries.UPDATE_JOB, {
jobId: id,

View File

@@ -21,12 +21,9 @@ const serializeDinero = (key, value) => {
* Capture a fixture for job totals.
* @param inputData
* @param outputData
* @param saveLocally
*/
const captureFixture = (inputData, outputData) => {
if (!fs.existsSync(fixtureDir)) {
fs.mkdirSync(fixtureDir, { recursive: true });
}
const captureFixture = (inputData, outputData, saveLocally) => {
const fileName = `${inputData.id}.json`;
const filePath = path.join(fixtureDir, fileName);
@@ -44,7 +41,15 @@ const captureFixture = (inputData, outputData) => {
};
// Save the file using our custom serializer.
fs.writeFileSync(filePath, JSON.stringify(dataToSave, serializeDinero, 2), "utf8");
if (saveLocally) {
if (!fs.existsSync(fixtureDir)) {
fs.mkdirSync(fixtureDir, { recursive: true });
}
fs.writeFileSync(filePath, JSON.stringify(dataToSave, serializeDinero, 2), "utf8");
}
return dataToSave;
};
module.exports = {