From cde03d43a651fd4c05863f3b54636085dfb2c84b Mon Sep 17 00:00:00 2001 From: sergeyyarkov Date: Mon, 16 Mar 2026 16:25:23 +0300 Subject: [PATCH] upd --- models/base.model.js | 13 +++++++ models/report.model.js | 10 ++++-- repositories/report.repository.js | 57 ++++++++++++++++++++++++------- services/reports.service.js | 49 ++++++++++++++++++-------- tables/index.js | 1 + tables/report.table.js | 3 +- tables/reportExecutor.table.js | 19 +++++++++++ 7 files changed, 121 insertions(+), 31 deletions(-) create mode 100644 models/base.model.js create mode 100644 tables/reportExecutor.table.js diff --git a/models/base.model.js b/models/base.model.js new file mode 100644 index 0000000..861ce73 --- /dev/null +++ b/models/base.model.js @@ -0,0 +1,13 @@ +/** @import sql from "mssql" */ + +export class BaseModel { + /** + * @template T + * @this {new (args: any) => T} Model + * @param {sql.IRecordSet} recordset + * @returns {T[]} + */ + static fromRecordset(recordset) { + return recordset.map((row) => new this({ ...row })); + } +} diff --git a/models/report.model.js b/models/report.model.js index e1bedda..f646363 100644 --- a/models/report.model.js +++ b/models/report.model.js @@ -1,8 +1,10 @@ +import { BaseModel } from "./base.model.js"; + /** @import { ReportColumns } from "#tables/report.table.js" */ -export class ReportModel { +export class ReportModel extends BaseModel { /** - * @type {ReportColumns['id'] | undefined} + * @type {ReportColumns['id']} */ id; @@ -37,9 +39,11 @@ export class ReportModel { equipment_id; /** - * @param {Omit} columns + * @param {ReportColumns} columns */ constructor(columns) { + super(); + this.id = columns.id; this.date = columns.date; this.reason_call = columns.reason_call; this.job_description = columns.job_description; diff --git a/repositories/report.repository.js b/repositories/report.repository.js index 0401937..d56690d 100644 --- a/repositories/report.repository.js +++ b/repositories/report.repository.js @@ -1,27 +1,33 @@ import sql from "mssql"; import db from "#root/db.js"; import { ReportModel } from "#models/index.js"; -import { ReportTable } from "#tables/index.js"; +import { ReportExecutorTable, ReportTable } from "#tables/index.js"; /** @import { ReportColumns } from "#tables/report.table.js" */ export const reportRepository = { async getAll() { const request = new sql.Request(db); - console.log(ReportTable.tableName); + const result = await request.query(`select * from dbo.${ReportTable.tableName};`); + const reports = ReportModel.fromRecordset(result.recordset); - const reports = await request.query(`select * from dbo.${ReportTable.tableName};`); - console.log(reports); + return reports; + }, - return reports.recordset; + async getLast() { + const request = new sql.Request(db); + const result = await request.query(`select top 1 * from ${ReportTable.tableName} order by id desc`); + const report = ReportModel.fromRecordset(result.recordset); + + return report[0]; }, /** - * @param {Omit} entry + * @param {ReportColumns} entry */ async create(entry) { - const report = new ReportModel(entry); const request = new sql.Request(db); + const report = new ReportModel(entry); request.input("date", ReportTable.getColumn("date"), report.date); request.input("reasonCall", ReportTable.getColumn("reason_call"), report.reason_call); @@ -44,18 +50,45 @@ export const reportRepository = { }, /** - * @param {Omit[]} entries + * @param {Record>} links + * @param {sql.Transaction} [trx] + */ + async attachExecutors(links, trx) { + const request = trx ? new sql.Request(trx) : new sql.Request(db); + const table = ReportExecutorTable.createInstance(); + + for (const [rId, executorIds] of Object.entries(links)) { + executorIds.forEach((eId) => table.rows.add(rId, eId)); + } + + await request.bulk(table); + return table.rows.length; + }, + + /** + * @param {ReportColumns[]} entries * @param {sql.Transaction} [trx] */ async bulk(entries, trx) { const request = trx ? new sql.Request(trx) : new sql.Request(db); const table = ReportTable.createInstance(); + const lastReportId = (await this.getLast()).id; + let nextAddId = Number.parseInt(lastReportId, 10); - for (const r of entries) { - table.rows.add(r.date, r.reason_call, r.job_description, r.root_cause, r.applicant_id, r.equipment_id); + for (const e of entries) { + table.rows.add( + ++nextAddId, + e.date, + e.reason_call, + e.job_description, + e.root_cause, + e.applicant_id, + e.equipment_id + ); } - await request.bulk(table); - return table.rows.length; + const res = await request.bulk(table); + + return res.rowsAffected; } }; diff --git a/services/reports.service.js b/services/reports.service.js index efdbd79..c581b65 100644 --- a/services/reports.service.js +++ b/services/reports.service.js @@ -3,7 +3,7 @@ import pLimit from "p-limit"; import db from "#root/db.js"; import mssql from "mssql"; 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 { InferType } from "yup" */ @@ -85,7 +85,7 @@ export const reportsService = { */ async checkReportLinks(report, cancelCondFn) { const executorSurnames = extractSurnamesFromExecutorField(report.executorNames); - if (cancelCondFn()) return Promise.reject(); + if (cancelCondFn()) return Promise.reject("Report check rejected"); const equipment = await db.request() .query(`select t1.id, t1.name, t1.location_id, t3.name as base_location_name, t2.name as location_name, t2.base_location_id @@ -172,31 +172,50 @@ export const reportsService = { }, /** - * @param {InferType['reports']} reports + * @param {InferType['reports']} inReports */ - async syncReportsWithDatabase(reports) { + async syncReportsWithDatabase(inReports) { const trx = new mssql.Transaction(db); - const dbReports = await reportRepository.getAll(); + const reports = await reportRepository.getAll(); /** - * 1. проверить на существование дубликатов и отфильтровать - * 2. начать транзакцию на множественную вставку отчетов * 3. установить связь добавленных отчетов с исполнителями и завершить транзакцию */ + /** Отфильтровывание дубликатов по полям. */ + const filteredInReports = inReports.filter((inputR) => { + 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; + }); + + if (filteredInReports.length === 0) return 0; + try { await trx.begin(); const countRows = await reportRepository.bulk( - reports.map((r) => ({ - applicant_id: r.applicant?.id || null, - equipment_id: r.equipment?.id || null, - date: new Date("2026"), - job_description: r.job_description || "", - reason_call: r.reason_call || "", - root_cause: r.root_cause || "" - })), + filteredInReports.map((r) => { + const reportDate = new Date(r.date || ""); + return { + applicant_id: r.applicant?.id || null, + equipment_id: r.equipment?.id || null, + date: utilsDate.isDateValid(reportDate) ? reportDate : new Date("2016-10-24"), + job_description: r.job_description || "", + reason_call: r.reason_call || "", + root_cause: r.root_cause || "" + }; + }), trx ); + // filteredInReports.map((r) => ({ [r.]: "" })); + // await reportRepository.attachExecutors() await trx.commit(); return countRows; } catch (error) { diff --git a/tables/index.js b/tables/index.js index 26f1f3a..743f19f 100644 --- a/tables/index.js +++ b/tables/index.js @@ -1 +1,2 @@ export * from "./report.table.js"; +export * from "./reportExecutor.table.js"; diff --git a/tables/report.table.js b/tables/report.table.js index 497ad3d..fb62fbf 100644 --- a/tables/report.table.js +++ b/tables/report.table.js @@ -2,7 +2,7 @@ import sql from "mssql"; import { BaseTable } from "./base.table.js"; /** - * @typedef {{ id: number; date: Date; reason_call: string; job_description: string; root_cause: string | null; applicant_id: number | null; equipment_id: number | null; }} ReportColumns + * @typedef {{ id?: number | string; date: Date; reason_call: string; job_description: string; root_cause: string | null; applicant_id: number | string | null; equipment_id: number | string | null; }} ReportColumns */ export class ReportTable extends BaseTable { @@ -10,6 +10,7 @@ export class ReportTable extends BaseTable { static table = new sql.Table(this.tableName); static columns = { + id: { type: sql.BigInt, nullable: false }, date: { type: sql.Date, nullable: false }, reason_call: { type: sql.NVarChar(sql.MAX), nullable: false }, job_description: { type: sql.NVarChar(sql.MAX), nullable: false }, diff --git a/tables/reportExecutor.table.js b/tables/reportExecutor.table.js new file mode 100644 index 0000000..d5c325d --- /dev/null +++ b/tables/reportExecutor.table.js @@ -0,0 +1,19 @@ +import sql from "mssql"; +import { BaseTable } from "./base.table.js"; + +/** + * @typedef {{ id: string | number; report_id: string | number; user_id: string | number; }} ReportExecutorTableCols + */ + +export class ReportExecutorTable extends BaseTable { + static tableName = "gpp_report_api_report_executor"; + static table = new sql.Table(this.tableName); + + static columns = { + report_id: { type: sql.BigInt, nullable: false }, + user_id: { type: sql.BigInt, nullable: false } + }; +} + +ReportExecutorTable.table.create = false; +ReportExecutorTable.init();