Добавлена функция сохранения истории обработки территорий
This commit is contained in:
241
api/middleware/genReportTerritories.js
Normal file
241
api/middleware/genReportTerritories.js
Normal file
@@ -0,0 +1,241 @@
|
||||
const db = require("../config/db");
|
||||
const ExcelJS = require('exceljs');
|
||||
|
||||
async function getTable() {
|
||||
const workbook = new ExcelJS.Workbook();
|
||||
const sheet = workbook.addWorksheet('Опрацювання територій');
|
||||
|
||||
// Обычная тонкая рамка
|
||||
function setThinBorder(cell) {
|
||||
cell.border = {
|
||||
top: { style: 'thin', color: { argb: 'FF000000' } },
|
||||
left: { style: 'thin', color: { argb: 'FF000000' } },
|
||||
bottom: { style: 'thin', color: { argb: 'FF000000' } },
|
||||
right: { style: 'thin', color: { argb: 'FF000000' } },
|
||||
};
|
||||
}
|
||||
|
||||
// Жирные рамки для Вісників
|
||||
function setTopCellBorder(cell) {
|
||||
cell.border = {
|
||||
top: { style: 'thick', color: { argb: 'FF000000' } },
|
||||
left: { style: 'thick', color: { argb: 'FF000000' } },
|
||||
right: { style: 'thick', color: { argb: 'FF000000' } },
|
||||
bottom: { style: 'thin', color: { argb: 'FF000000' } },
|
||||
};
|
||||
}
|
||||
|
||||
function setStartColBorder(cell) {
|
||||
cell.border = {
|
||||
top: { style: 'thin', color: { argb: 'FF000000' } },
|
||||
left: { style: 'thick', color: { argb: 'FF000000' } },
|
||||
bottom: { style: 'thick', color: { argb: 'FF000000' } },
|
||||
right: { style: 'thin', color: { argb: 'FF000000' } },
|
||||
};
|
||||
}
|
||||
|
||||
function setEndColBorder(cell) {
|
||||
cell.border = {
|
||||
top: { style: 'thin', color: { argb: 'FF000000' } },
|
||||
left: { style: 'thin', color: { argb: 'FF000000' } },
|
||||
bottom: { style: 'thick', color: { argb: 'FF000000' } },
|
||||
right: { style: 'thick', color: { argb: 'FF000000' } },
|
||||
};
|
||||
}
|
||||
|
||||
sheet.addRow([]);
|
||||
sheet.addRow([]);
|
||||
|
||||
// № объекта
|
||||
sheet.getCell('A1').value = '№';
|
||||
sheet.mergeCells('A1:A2');
|
||||
sheet.getCell('A1').alignment = { vertical: 'middle', horizontal: 'center' };
|
||||
sheet.getCell('A1').font = { bold: true };
|
||||
setThinBorder(sheet.getCell('A1'));
|
||||
sheet.getColumn(1).width = 5;
|
||||
|
||||
// "Об’єкт"
|
||||
sheet.getCell('B1').value = 'Територія';
|
||||
sheet.mergeCells('B1:B2');
|
||||
sheet.getCell('B1').alignment = { vertical: 'middle', horizontal: 'center' };
|
||||
sheet.getCell('B1').font = { bold: true };
|
||||
setThinBorder(sheet.getCell('B1'));
|
||||
sheet.getColumn(2).width = 40;
|
||||
|
||||
// "Остання дата опрацювання"
|
||||
sheet.getCell('C1').value = 'Остання дата опрацювання';
|
||||
sheet.mergeCells('C1:C2');
|
||||
sheet.getCell('C1').alignment = { vertical: 'middle', horizontal: 'center', wrapText: true };
|
||||
sheet.getCell('C1').font = { bold: true };
|
||||
setThinBorder(sheet.getCell('C1'));
|
||||
sheet.getColumn(3).width = 20;
|
||||
|
||||
// Вісники
|
||||
for (let i = 0; i < 4; i++) {
|
||||
const startCol = 4 + i * 2;
|
||||
const endCol = startCol + 1;
|
||||
|
||||
sheet.mergeCells(1, startCol, 1, endCol);
|
||||
const topCell = sheet.getCell(1, startCol);
|
||||
topCell.value = `Вісник (група) ${i + 1}`;
|
||||
topCell.alignment = { horizontal: 'center', vertical: 'middle' };
|
||||
topCell.font = { bold: true };
|
||||
setThinBorder(topCell);
|
||||
|
||||
const recvCell = sheet.getCell(2, startCol);
|
||||
recvCell.value = 'Дата отримання';
|
||||
recvCell.alignment = { horizontal: 'center', vertical: 'middle', wrapText: true };
|
||||
recvCell.font = { bold: true };
|
||||
setThinBorder(recvCell);
|
||||
|
||||
const procCell = sheet.getCell(2, endCol);
|
||||
procCell.value = 'Дата опрацювання';
|
||||
procCell.alignment = { horizontal: 'center', vertical: 'middle', wrapText: true };
|
||||
procCell.font = { bold: true };
|
||||
setThinBorder(procCell);
|
||||
|
||||
sheet.getColumn(startCol).width = 16;
|
||||
sheet.getColumn(endCol).width = 16;
|
||||
}
|
||||
|
||||
const objects = await new Promise((resolve, reject) => {
|
||||
db.all(`
|
||||
SELECT
|
||||
e.id as object_id,
|
||||
e.entrance_number as number,
|
||||
h.number as house_number,
|
||||
h.title as house_title,
|
||||
NULL as settlement,
|
||||
'entrance' as type
|
||||
FROM entrance e
|
||||
JOIN house h ON e.house_id = h.id
|
||||
UNION ALL
|
||||
SELECT
|
||||
hm.id as object_id,
|
||||
hm.number as number,
|
||||
NULL as house_number,
|
||||
hm.title as house_title,
|
||||
hm.settlement,
|
||||
'homestead' as type
|
||||
FROM homestead hm
|
||||
`, (err, rows) => {
|
||||
if (err) return reject(err);
|
||||
resolve(rows);
|
||||
});
|
||||
});
|
||||
|
||||
let currentRow = 3;
|
||||
let objIndex = 1;
|
||||
|
||||
for (const obj of objects) {
|
||||
const table = obj.type === 'entrance' ? 'entrance_history' : 'homestead_history';
|
||||
const idField = obj.type === 'entrance' ? 'entrance_id' : 'homestead_id';
|
||||
|
||||
const history = await new Promise((resolve, reject) => {
|
||||
db.all(`
|
||||
SELECT date_start, date_end, name, group_id
|
||||
FROM ${table}
|
||||
WHERE ${idField} = ?
|
||||
ORDER BY date_start DESC
|
||||
LIMIT 4
|
||||
`, [obj.object_id], (err, rows) => {
|
||||
if (err) return reject(err);
|
||||
resolve(rows);
|
||||
});
|
||||
});
|
||||
|
||||
// № объекта
|
||||
const numCell = sheet.getCell(currentRow, 1);
|
||||
numCell.value = objIndex;
|
||||
numCell.alignment = { vertical: 'middle', horizontal: 'center' };
|
||||
setThinBorder(numCell);
|
||||
sheet.mergeCells(currentRow, 1, currentRow + 1, 1);
|
||||
|
||||
// Название объекта
|
||||
let objectName;
|
||||
if (obj.type === 'homestead' && obj.settlement) {
|
||||
objectName = `(${obj.settlement}) ${obj.house_title} ${obj.number}`;
|
||||
} else if (obj.type === 'homestead') {
|
||||
objectName = `${obj.house_title} ${obj.number}`;
|
||||
} else {
|
||||
objectName = `${obj.house_title} ${obj.house_number} (П. ${obj.number + 1})`;
|
||||
}
|
||||
|
||||
const objCell = sheet.getCell(currentRow, 2);
|
||||
objCell.value = objectName;
|
||||
sheet.mergeCells(currentRow, 2, currentRow + 1, 2);
|
||||
objCell.alignment = { vertical: 'middle', horizontal: 'left' };
|
||||
setThinBorder(objCell);
|
||||
|
||||
// Последняя дата обработки
|
||||
let lastDate = null;
|
||||
for (const h of history) {
|
||||
if (h.date_end && h.date_end !== 0) {
|
||||
lastDate = new Date(h.date_end);
|
||||
break;
|
||||
}
|
||||
}
|
||||
const lastDateCell = sheet.getCell(currentRow, 3);
|
||||
lastDateCell.value = lastDate;
|
||||
lastDateCell.numFmt = 'dd.mm.yyyy';
|
||||
sheet.mergeCells(currentRow, 3, currentRow + 1, 3);
|
||||
lastDateCell.alignment = { vertical: 'middle', horizontal: 'center' };
|
||||
setThinBorder(lastDateCell);
|
||||
|
||||
// История Вісників
|
||||
history.forEach((h, idx) => {
|
||||
const startCol = 4 + idx * 2;
|
||||
const endCol = startCol + 1;
|
||||
|
||||
let name = h.name;
|
||||
if (h.name === 'Групова') name = `${h.name} (${h.group_id})`;
|
||||
|
||||
// Верхняя ячейка имени
|
||||
const nameCell = sheet.getCell(currentRow, startCol);
|
||||
sheet.mergeCells(currentRow, startCol, currentRow, endCol);
|
||||
nameCell.value = name;
|
||||
nameCell.alignment = { horizontal: 'center' };
|
||||
setTopCellBorder(nameCell);
|
||||
|
||||
// Дата получения
|
||||
const startDate = h.date_start ? new Date(h.date_start) : null;
|
||||
const recvCell = sheet.getCell(currentRow + 1, startCol);
|
||||
recvCell.value = startDate;
|
||||
recvCell.numFmt = 'dd.mm.yyyy';
|
||||
recvCell.alignment = { horizontal: 'center' };
|
||||
setStartColBorder(recvCell);
|
||||
|
||||
// Дата опрацювання
|
||||
const endDate = h.date_end ? new Date(h.date_end) : null;
|
||||
const procCell = sheet.getCell(currentRow + 1, endCol);
|
||||
procCell.value = endDate;
|
||||
procCell.numFmt = 'dd.mm.yyyy';
|
||||
procCell.alignment = { horizontal: 'center' };
|
||||
setEndColBorder(procCell);
|
||||
});
|
||||
|
||||
// Чётное затемнение только для блока данных
|
||||
if (objIndex % 2 === 0) {
|
||||
for (let col = 1; col <= 11; col++) {
|
||||
sheet.getCell(currentRow, col).fill = {
|
||||
type: 'pattern',
|
||||
pattern: 'solid',
|
||||
fgColor: { argb: 'FFEFEFEF' },
|
||||
};
|
||||
sheet.getCell(currentRow + 1, col).fill = {
|
||||
type: 'pattern',
|
||||
pattern: 'solid',
|
||||
fgColor: { argb: 'FFEFEFEF' },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
currentRow += 2;
|
||||
objIndex++;
|
||||
}
|
||||
|
||||
const buffer = await workbook.xlsx.writeBuffer();
|
||||
return buffer;
|
||||
}
|
||||
|
||||
module.exports = getTable;
|
||||
Reference in New Issue
Block a user