mirror of
https://github.com/sergeyyarkov/asu_tools_service.git
synced 2026-10-11 10:29:22 +03:00
del reports before import
This commit is contained in:
parent
1f73377e33
commit
44fd57ef2c
@ -10,10 +10,10 @@ import { reportsSchema } from "#schemas/report.schema.js";
|
|||||||
* @type {import("#root/http-server/types/http-server.js").HttpRouteHandler}
|
* @type {import("#root/http-server/types/http-server.js").HttpRouteHandler}
|
||||||
*/
|
*/
|
||||||
export default async ({ res, data }) => {
|
export default async ({ res, data }) => {
|
||||||
const { reports } = await reportsSchema.validate(data).catch((err) => {
|
const payload = await reportsSchema.validate(data).catch((err) => {
|
||||||
throw new BadRequestError(err.message);
|
throw new BadRequestError(err.message);
|
||||||
});
|
});
|
||||||
|
|
||||||
const rows = await reportsService.syncReportsWithDatabase(reports);
|
const rows = await reportsService.syncReportsWithDatabase(payload);
|
||||||
res.sendJson({ data: { rows } });
|
res.sendJson({ data: { rows } });
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1 +1,2 @@
|
|||||||
|
export * from "./uow.js";
|
||||||
export * from "./report.repository.js";
|
export * from "./report.repository.js";
|
||||||
|
|||||||
@ -1,13 +1,12 @@
|
|||||||
import sql from "mssql";
|
|
||||||
import db from "#root/db.js";
|
|
||||||
import { ReportModel } from "#models/index.js";
|
import { ReportModel } from "#models/index.js";
|
||||||
import { ReportExecutorTable, ReportTable } from "#tables/index.js";
|
import { ReportExecutorTable, ReportTable } from "#tables/index.js";
|
||||||
|
import { UOW } from "./index.js";
|
||||||
|
|
||||||
/** @import { ReportColumns } from "#tables/report.table.js" */
|
/** @import { ReportColumns } from "#tables/report.table.js" */
|
||||||
|
|
||||||
export const reportRepository = {
|
export const reportRepository = {
|
||||||
async getAll() {
|
async getAll() {
|
||||||
const request = new sql.Request(db);
|
const request = UOW.request;
|
||||||
const result = await request.query(`select * from dbo.${ReportTable.tableName};`);
|
const result = await request.query(`select * from dbo.${ReportTable.tableName};`);
|
||||||
const reports = ReportModel.fromRecordset(result.recordset);
|
const reports = ReportModel.fromRecordset(result.recordset);
|
||||||
|
|
||||||
@ -15,18 +14,29 @@ export const reportRepository = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
async getLast() {
|
async getLast() {
|
||||||
const request = new sql.Request(db);
|
const request = UOW.request;
|
||||||
const result = await request.query(`select top 1 * from ${ReportTable.tableName} order by id desc`);
|
const result = await request.query(`select top 1 * from ${ReportTable.tableName} order by id desc`);
|
||||||
const report = ReportModel.fromRecordset(result.recordset);
|
const report = ReportModel.fromRecordset(result.recordset);
|
||||||
|
|
||||||
return report.at(0);
|
return report.at(0);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async delAll() {
|
||||||
|
await UOW.run(async () => {
|
||||||
|
const request = UOW.request;
|
||||||
|
|
||||||
|
await request.query(`delete from ${ReportExecutorTable.tableName};`);
|
||||||
|
await request.query(`delete from ${ReportTable.tableName};`);
|
||||||
|
await request.query(`DBCC CHECKIDENT ('${ReportExecutorTable.tableName}', RESEED, 0);`);
|
||||||
|
await request.query(`DBCC CHECKIDENT ('${ReportTable.tableName}', RESEED, 0);`);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {ReportColumns} entry
|
* @param {ReportColumns} entry
|
||||||
*/
|
*/
|
||||||
async create(entry) {
|
async create(entry) {
|
||||||
const request = new sql.Request(db);
|
const request = UOW.request;
|
||||||
const report = new ReportModel(entry);
|
const report = new ReportModel(entry);
|
||||||
|
|
||||||
request.input("date", ReportTable.getColumn("date"), report.date);
|
request.input("date", ReportTable.getColumn("date"), report.date);
|
||||||
@ -51,10 +61,9 @@ export const reportRepository = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Record<string, Array<string | number>>[]} links
|
* @param {Record<string, Array<string | number>>[]} links
|
||||||
* @param {sql.Transaction} [trx]
|
|
||||||
*/
|
*/
|
||||||
async attachExecutors(links, trx) {
|
async attachExecutors(links) {
|
||||||
const request = trx ? new sql.Request(trx) : new sql.Request(db);
|
const request = UOW.request;
|
||||||
const table = ReportExecutorTable.createInstance();
|
const table = ReportExecutorTable.createInstance();
|
||||||
|
|
||||||
for (const report of Object.values(links)) {
|
for (const report of Object.values(links)) {
|
||||||
@ -69,10 +78,9 @@ export const reportRepository = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {ReportColumns[]} entries
|
* @param {ReportColumns[]} entries
|
||||||
* @param {sql.Transaction} [trx]
|
|
||||||
*/
|
*/
|
||||||
async bulk(entries, trx) {
|
async bulk(entries) {
|
||||||
const request = trx ? new sql.Request(trx) : new sql.Request(db);
|
const request = UOW.request;
|
||||||
const table = ReportTable.createInstance();
|
const table = ReportTable.createInstance();
|
||||||
const lastReportId = (await this.getLast())?.id || 0;
|
const lastReportId = (await this.getLast())?.id || 0;
|
||||||
let nextAddId = typeof lastReportId === "string" ? Number.parseInt(lastReportId, 10) : lastReportId;
|
let nextAddId = typeof lastReportId === "string" ? Number.parseInt(lastReportId, 10) : lastReportId;
|
||||||
|
|||||||
27
repositories/uow.js
Normal file
27
repositories/uow.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { AsyncLocalStorage } from "node:async_hooks";
|
||||||
|
import sql from "mssql";
|
||||||
|
import db from "#root/db.js";
|
||||||
|
|
||||||
|
export class UOW {
|
||||||
|
/** @type {AsyncLocalStorage<sql.Transaction>} */
|
||||||
|
static #als = new AsyncLocalStorage();
|
||||||
|
|
||||||
|
/** @param {() => Promise<unknown>} callback */
|
||||||
|
static async run(callback) {
|
||||||
|
const trx = new sql.Transaction(db);
|
||||||
|
try {
|
||||||
|
await trx.begin();
|
||||||
|
const ret = await this.#als.run(trx, callback);
|
||||||
|
await trx.commit();
|
||||||
|
return ret;
|
||||||
|
} catch (error) {
|
||||||
|
await trx.rollback();
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static get request() {
|
||||||
|
const trx = this.#als.getStore();
|
||||||
|
return trx ? new sql.Request(trx) : new sql.Request(db);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -23,4 +23,6 @@ export const reportItemSchema = y.object({
|
|||||||
executors: y.array(y.object({ id: y.number().required(), fullname: y.string().required() })).required()
|
executors: y.array(y.object({ id: y.number().required(), fullname: y.string().required() })).required()
|
||||||
});
|
});
|
||||||
|
|
||||||
export const reportsSchema = y.object({ reports: y.array(reportItemSchema).min(1).required() }).required();
|
export const reportsSchema = y
|
||||||
|
.object({ reports: y.array(reportItemSchema).min(1).required(), deleteAllBeforeImport: y.boolean().required() })
|
||||||
|
.required();
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
import xlsx from "xlsx";
|
import xlsx from "xlsx";
|
||||||
import pLimit from "p-limit";
|
import pLimit from "p-limit";
|
||||||
import db from "#root/db.js";
|
import db from "#root/db.js";
|
||||||
import mssql from "mssql";
|
import { reportRepository, UOW } from "#repositories/index.js";
|
||||||
import { reportRepository } from "#repositories/index.js";
|
|
||||||
import * as utilsDate from "#utils/date.js";
|
import * as utilsDate from "#utils/date.js";
|
||||||
|
|
||||||
/** @import { reportsSchema } from "#schemas/report.schema.js" */
|
/** @import { reportsSchema } from "#schemas/report.schema.js" */
|
||||||
@ -172,34 +171,42 @@ export const reportsService = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {InferType<typeof reportsSchema>['reports']} inReports
|
* @param {InferType<typeof reportsSchema>} payload
|
||||||
*/
|
*/
|
||||||
async syncReportsWithDatabase(inReports) {
|
async syncReportsWithDatabase(payload) {
|
||||||
const INVALID_DATE_FALLBACK = new Date("2016-10-24"); // дата для постановки вместо неверной. (колонка `date` в таблице имеет ограничение not null)
|
const INVALID_DATE_FALLBACK = new Date("2016-10-24"); // дата для постановки вместо неверной. (колонка `date` в таблице имеет ограничение not null)
|
||||||
const trx = new mssql.Transaction(db);
|
const { reports: inReports, deleteAllBeforeImport } = payload;
|
||||||
const reports = await reportRepository.getAll();
|
|
||||||
|
|
||||||
/** Отфильтровывание дубликатов по полям. */
|
/** @type {typeof payload['reports']} */
|
||||||
const filteredInReports = inReports.filter((inputR) => {
|
let unImportedReports = [];
|
||||||
const isDub = reports.some((dbR) => {
|
|
||||||
return (
|
if (!deleteAllBeforeImport) {
|
||||||
inputR.reason_call === dbR.reason_call &&
|
const reports = await reportRepository.getAll();
|
||||||
inputR.job_description === dbR.job_description &&
|
|
||||||
inputR.root_cause === dbR.root_cause &&
|
/** Отфильтровывание дубликатов по полям. */
|
||||||
inputR.equipment?.id == dbR.equipment_id &&
|
unImportedReports = inReports.filter((inputR) => {
|
||||||
inputR.applicant?.id == dbR.applicant_id
|
const isDub = reports.some((dbR) => {
|
||||||
);
|
return (
|
||||||
|
inputR.reason_call === dbR.reason_call &&
|
||||||
|
inputR.job_description === dbR.job_description &&
|
||||||
|
inputR.root_cause === dbR.root_cause &&
|
||||||
|
inputR.equipment?.id == dbR.equipment_id &&
|
||||||
|
inputR.applicant?.id == dbR.applicant_id
|
||||||
|
);
|
||||||
|
});
|
||||||
|
return !isDub;
|
||||||
});
|
});
|
||||||
return !isDub;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (filteredInReports.length === 0) return 0;
|
if (unImportedReports.length === 0) return 0;
|
||||||
|
} else {
|
||||||
|
await reportRepository.delAll();
|
||||||
|
unImportedReports = inReports;
|
||||||
|
}
|
||||||
|
|
||||||
/** Добавление отчетов и связей с исполнителями к ним */
|
/** Добавление отчетов и связей с исполнителями к ним */
|
||||||
try {
|
const ret = await UOW.run(async () => {
|
||||||
await trx.begin();
|
|
||||||
const bulkResult = await reportRepository.bulk(
|
const bulkResult = await reportRepository.bulk(
|
||||||
filteredInReports.map((r) => {
|
unImportedReports.map((r) => {
|
||||||
const reportDate = new Date(r.date || "");
|
const reportDate = new Date(r.date || "");
|
||||||
return {
|
return {
|
||||||
applicant_id: r.applicant?.id || null,
|
applicant_id: r.applicant?.id || null,
|
||||||
@ -209,22 +216,19 @@ export const reportsService = {
|
|||||||
reason_call: r.reason_call || "",
|
reason_call: r.reason_call || "",
|
||||||
root_cause: r.root_cause || ""
|
root_cause: r.root_cause || ""
|
||||||
};
|
};
|
||||||
}),
|
})
|
||||||
trx
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const executorsLinks = filteredInReports.map((r, i) => {
|
const executorsLinks = unImportedReports.map((r, i) => {
|
||||||
return Object.fromEntries([[`${bulkResult.addedRowIds[i]}`, r.executors.map((e) => e.id)]]);
|
return Object.fromEntries([[`${bulkResult.addedRowIds[i]}`, r.executors.map((e) => e.id)]]);
|
||||||
});
|
});
|
||||||
|
|
||||||
await reportRepository.attachExecutors(executorsLinks, trx);
|
await reportRepository.attachExecutors(executorsLinks);
|
||||||
await trx.commit();
|
|
||||||
return bulkResult.rowsAffected;
|
return bulkResult.rowsAffected;
|
||||||
} catch (error) {
|
});
|
||||||
console.error(error);
|
|
||||||
await trx.rollback();
|
return ret;
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user