mirror of
https://github.com/sergeyyarkov/asu_tools_service.git
synced 2026-10-11 10:29:22 +03:00
128 lines
3.9 KiB
JavaScript
128 lines
3.9 KiB
JavaScript
import { BadRequestError } from "#root/errors/index.js";
|
||
import db from "#root/db.js";
|
||
import xlsx from "xlsx";
|
||
|
||
const sheetName = "Отчеты";
|
||
|
||
/** @type {xlsx.ParsingOptions} */
|
||
const xlsxParseOptions = {
|
||
sheets: sheetName,
|
||
cellHTML: false,
|
||
cellFormula: false,
|
||
cellDates: true,
|
||
dateNF: "yyyy-mm-dd"
|
||
};
|
||
|
||
/**
|
||
* URL: /api/reports_excel_file_parse
|
||
* Method: POST
|
||
* Description: Читает Excel файл отчетов и возвращает его в формате JSON. Принимает на вход файл
|
||
* отчетов в формате Excel.
|
||
*
|
||
* @type {HTTPRouteHandler}
|
||
*/
|
||
export default async (ctx) => {
|
||
const { res } = ctx;
|
||
|
||
if (!ctx.data) throw new BadRequestError("Cannot proceed uploaded file");
|
||
|
||
const [, files] = ctx.data;
|
||
const excelFilePath = files?.report?.at(0)?.filepath;
|
||
|
||
/** @type {{ markedReports: ReportModel[], reports: ReportModel[] }} */
|
||
const ret = { reports: [], markedReports: [] };
|
||
|
||
let foundEqupments = 0;
|
||
|
||
ctx.res.res.setHeaders(
|
||
new Headers({
|
||
Connection: "keep-alive",
|
||
"Cache-Control": "no-cache",
|
||
"Content-Type": "text/event-stream"
|
||
})
|
||
);
|
||
|
||
if (excelFilePath) {
|
||
const workbook = xlsx.readFile(excelFilePath, xlsxParseOptions);
|
||
const sheet = workbook.Sheets[sheetName];
|
||
|
||
if (!sheet) throw new Error("Invalid reports workbook.", { cause: { statusCode: 400 } });
|
||
|
||
const data = xlsx.utils.sheet_to_json(sheet, { raw: false, blankrows: true });
|
||
|
||
for (let i = 0; i < data.length; i++) {
|
||
const cols = Object.keys(data[i]);
|
||
|
||
if (i === 0) continue;
|
||
|
||
/** Несинхронизированные помеченные отчеты */
|
||
if ("__EMPTY_3" in data[i] && data[i]["__EMPTY_3"] === "r") {
|
||
ret.markedReports.push({
|
||
date: data[i][cols[0]],
|
||
equipment: data[i][cols[1]],
|
||
reason_call: data[i][cols[3]].split("\r\r\n")[1] || "",
|
||
job_description: data[i][cols[4]].split("\r\r\n")[1] || "",
|
||
root_cause: data[i]["__EMPTY_2"] || "",
|
||
applicantName: data[i][cols[3]].split("\r\r\n")[0] || "",
|
||
executorNames: data[i][cols[4]].split("\r\r\n")[0] || ""
|
||
});
|
||
|
||
continue;
|
||
}
|
||
|
||
/** Остальные отчеты */
|
||
ret.reports.push({
|
||
date: data[i][cols[0]],
|
||
equipment: data[i][cols[1]],
|
||
reason_call: parseReasonCallAndJobDesc(data[i][cols[3]]),
|
||
job_description: parseReasonCallAndJobDesc(data[i][cols[4]]),
|
||
root_cause: data[i]["__EMPTY_2"] || "",
|
||
applicantName: parseNames(data[i][cols[3]]),
|
||
executorNames: parseNames(data[i][cols[4]])
|
||
});
|
||
}
|
||
|
||
/** @param {ReportModel} report */
|
||
const checkReportAssigments = async (report) => {
|
||
const equipment = await db
|
||
.request()
|
||
.query(`select id, name from dbo.asu_system_api_subsystemlist where name like N'%${report.equipment}%';`);
|
||
|
||
if (equipment.recordset.length !== 0) foundEqupments++;
|
||
|
||
res.sendSSEJson(report, "reportParseProgress");
|
||
|
||
return equipment;
|
||
};
|
||
|
||
console.log("Total reports:", ret.reports.concat(ret.markedReports).length);
|
||
await Promise.allSettled(ret.reports.concat(ret.markedReports).map((r) => checkReportAssigments(r)));
|
||
ctx.res.sendSSEJson({ foundEqupments }, "reportParseDone");
|
||
console.log("Parse done");
|
||
} else {
|
||
throw new BadRequestError();
|
||
}
|
||
|
||
res.res.end();
|
||
};
|
||
|
||
function parseReasonCallAndJobDesc(str = "") {
|
||
const splitted = splitLongSpacedSentence(str);
|
||
if (splitted.length > 1) return splitted.slice(1).join(" ");
|
||
return str.split("\r\n").slice(1).join(" ");
|
||
}
|
||
|
||
function parseNames(str = "") {
|
||
const splitted = splitLongSpacedSentence(str);
|
||
if (splitted.length > 1) return splitted[0];
|
||
return str.split("\r\n")[0];
|
||
}
|
||
|
||
/**
|
||
* @param {string} str
|
||
* @param {number} min
|
||
*/
|
||
function splitLongSpacedSentence(str, min = 5) {
|
||
return str.split(new RegExp(`\\s{${min},}`));
|
||
}
|