/
diloytd
/
shield
Обзор
Документация
Войти
/
diloytd
/
shield
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/services/journalService.js
156 строк
5 KB
diloytd
Перепроектировать shields.json и поддержать ТУ, сертификаты и новые условия.
22 июл 2026, 17:14
22 июл 2026, 17:14
fb8b887
Код
Авторство
О чём код?
/** * Сервис формирования журнала шильдов. * Вся логика получения и преобразования данных журнала находится здесь. * Данные берутся только из SQLite. */ const { getDatabase } = require('../database/database'); const { formatCertificatesForDisplay, parseCertificates } = require('../utils/certificateUtils'); /** * SQL-запрос для получения строк журнала из связанных таблиц. * Одна строка Shields — одна строка журнала. * Сортировка по номеру записи и заводскому номеру шильда — как в Excel. * @type {string} */ const JOURNAL_SELECT_SQL = ` SELECT je.entryNumber, je.productionDate, o.number AS orderNumber, s.shieldNumber, op.number AS positionNumber, pi.number AS instanceNumber, lp.type AS productType, ROW_NUMBER() OVER ( PARTITION BY je.id ORDER BY CAST(s.shieldNumber AS INTEGER) ) AS itemNumber, s.shieldType, s.marking, s.fireResistance, s.TU, s.certificates FROM Shields s INNER JOIN ProductInstances pi ON s.instanceId = pi.id INNER JOIN LogicalProducts lp ON pi.logicalProductId = lp.id INNER JOIN OrderPositions op ON lp.positionId = op.id INNER JOIN Orders o ON op.orderId = o.id INNER JOIN JournalEntries je ON je.orderId = o.id WHERE s.shieldNumber IS NOT NULL AND s.shieldNumber != '' ORDER BY je.entryNumber, CAST(s.shieldNumber AS INTEGER) `; /** * Формирует маркировку из типа шильда и класса огнестойкости. * Используется как запасной вариант для старых записей без сохранённой маркировки. * @param {string|null|undefined} shieldType - Тип шильда. * @param {string|null|undefined} fireResistance - Класс огнестойкости. * @returns {string} Маркировка, например «ДАПО EIW60». */ const buildMarking = (shieldType, fireResistance) => { const typePart = shieldType ?? ''; const resistancePart = fireResistance ?? ''; if (typePart === '' && resistancePart === '') { return ''; } if (typePart === '') { return resistancePart; } if (resistancePart === '') { return typePart; } return `${typePart} ${resistancePart}`; }; /** * Возвращает маркировку шильда: сохранённую в базе или вычисленную из типа и класса. * @param {unknown} storedMarking - Маркировка из таблицы Shields. * @param {string|null|undefined} shieldType - Тип шильда. * @param {string|null|undefined} fireResistance - Класс огнестойкости. * @returns {string} Маркировка для отображения в UI. */ const resolveMarking = (storedMarking, shieldType, fireResistance) => { const marking = toDisplayValue(storedMarking); if (marking !== '') { return marking; } return buildMarking(shieldType, fireResistance); }; /** * Преобразует значение из SQLite в строку для отображения в журнале. * @param {unknown} value - Значение из базы данных. * @returns {string} Строка для ячейки таблицы или пустая строка. */ const toDisplayValue = (value) => { if (value === null || value === undefined) { return ''; } return String(value); }; /** * Преобразует строку из SQLite в объект строки журнала. * @param {Object} dbRow - Строка результата SQL-запроса. * @returns {Object} Строка журнала для передачи в UI. */ const mapDbRowToJournalRow = (dbRow) => { const shieldType = toDisplayValue(dbRow.shieldType); const fireResistance = toDisplayValue(dbRow.fireResistance); return { entryNumber: dbRow.entryNumber, productionDate: toDisplayValue(dbRow.productionDate), orderNumber: toDisplayValue(dbRow.orderNumber), shieldNumber: toDisplayValue(dbRow.shieldNumber), itemNumber: dbRow.itemNumber, positionNumber: dbRow.positionNumber, instanceNumber: dbRow.instanceNumber, productType: toDisplayValue(dbRow.productType), shieldType, fireResistance, marking: resolveMarking(dbRow.marking, shieldType, fireResistance), tu: toDisplayValue(dbRow.TU), certificates: formatCertificatesForDisplay(parseCertificates(dbRow.certificates)), }; }; /** * Получает сырые строки журнала из SQLite. * @param {import('better-sqlite3').Database} db - Подключение к SQLite. * @returns {Array<Object>} Строки результата SQL-запроса. */ const fetchJournalRowsFromDb = (db) => { const selectJournal = db.prepare(JOURNAL_SELECT_SQL); return selectJournal.all(); }; /** * Формирует журнал шильдов на основе данных из SQLite. * @returns {{ rows: Array<Object>, rowCount: number }} Готовые строки журнала и их количество. */ const buildJournal = () => { const db = getDatabase(); const dbRows = fetchJournalRowsFromDb(db); const rows = dbRows.map(mapDbRowToJournalRow); return { rows, rowCount: rows.length, }; }; module.exports = { JOURNAL_SELECT_SQL, buildMarking, buildJournal, resolveMarking, };