Обновлены поля: бюджет из Бюджет закупок, исполнение из Сумма поставки, экономия, тип бюджета БКВ/ОБ

This commit is contained in:
Rollan_Tuleuov 2026-08-18 10:11:12 +00:00
parent 56205d6cf4
commit f27a8b95de
2 changed files with 41 additions and 21 deletions

View File

@ -78,7 +78,7 @@
<div class="about-card">
<div class="about-icon">📈</div>
<h3>Данные</h3>
<p>Код статьи бюджета, наименование услуг/работ, подразделение-заказчик, плановые суммы и фактическое исполнение</p>
<p>Краткий текст материала, подразделение (МВЗ), тип бюджета (БКВ/ОБ), бюджет закупок, сумма поставки, экономия</p>
</div>
<div class="about-card">
<div class="about-icon">🎯</div>
@ -117,11 +117,12 @@
<table>
<thead>
<tr>
<th onclick="sort('articleCode')">Код статьи ↕</th>
<th onclick="sort('serviceName')">Наименование услуги ↕</th>
<th onclick="sort('serviceName')">Наименование ↕</th>
<th onclick="sort('department')">Подразделение ↕</th>
<th class="amount" onclick="sort('budgetSum')">Бюджет ↕</th>
<th class="amount" onclick="sort('executedSum')">Исполнено ↕</th>
<th onclick="sort('budgetType')">Тип бюджета ↕</th>
<th class="amount" onclick="sort('budgetSum')">Бюджет закупок, тг ↕</th>
<th class="amount" onclick="sort('executedSum')">Сумма поставки, тг ↕</th>
<th class="amount" onclick="sort('economy')">Экономия, тг ↕</th>
<th class="percent" onclick="sort('execPercent')">Исполнение % ↕</th>
<th onclick="sort('status')">Статус ↕</th>
</tr>
@ -180,14 +181,19 @@
function renderStats() {
const totalBudget = allData.reduce((sum, r) => sum + (r.budgetSum || 0), 0);
const totalExecuted = allData.reduce((sum, r) => sum + (r.executedSum || 0), 0);
const totalEconomy = allData.reduce((sum, r) => sum + (r.economy || 0), 0);
const avgPercent = totalBudget > 0 ? (totalExecuted / totalBudget) * 100 : 0;
const fullyExecuted = allData.filter(r => r.execPercent >= 95).length;
const bkvCount = allData.filter(r => r.budgetType === 'БКВ').length;
const obCount = allData.filter(r => r.budgetType === 'ОБ').length;
document.getElementById('stats').innerHTML =
'<div class="stat-card"><div class="value">' + formatAmount(totalBudget) + '</div><div class="label">Всего бюджет</div></div>' +
'<div class="stat-card"><div class="value">' + formatAmount(totalExecuted) + '</div><div class="label">Исполнено</div></div>' +
'<div class="stat-card"><div class="value">' + formatAmount(totalBudget) + '</div><div class="label">Бюджет закупок, тг</div></div>' +
'<div class="stat-card"><div class="value">' + formatAmount(totalExecuted) + '</div><div class="label">Сумма поставки, тг</div></div>' +
'<div class="stat-card"><div class="value">' + formatAmount(totalEconomy) + '</div><div class="label">Экономия, тг</div></div>' +
'<div class="stat-card"><div class="value">' + formatAmount(avgPercent) + '%</div><div class="label">Среднее исполнение</div></div>' +
'<div class="stat-card"><div class="value">' + fullyExecuted + '</div><div class="label">Полностью исполнено</div></div>';
'<div class="stat-card"><div class="value">' + bkvCount + '</div><div class="label">БКВ</div></div>' +
'<div class="stat-card"><div class="value">' + obCount + '</div><div class="label">ОБ</div></div>';
}
function renderTable() {
@ -205,11 +211,12 @@
const statusClass = getStatusClass(r.execPercent || 0);
const statusText = getStatusText(r.execPercent || 0);
return '<tr>' +
'<td>' + (r.articleCode || '-') + '</td>' +
'<td>' + (r.serviceName || '-') + '</td>' +
'<td>' + (r.department || '-') + '</td>' +
'<td>' + (r.budgetType || '-') + '</td>' +
'<td class="amount">' + formatAmount(r.budgetSum || 0) + '</td>' +
'<td class="amount">' + formatAmount(r.executedSum || 0) + '</td>' +
'<td class="amount" style="color: ' + (r.economy > 0 ? '#22c55e' : '#666') + '">' + formatAmount(r.economy || 0) + '</td>' +
'<td class="percent">' + formatAmount(r.execPercent || 0) + '%</td>' +
'<td><span class="status-badge ' + statusClass + '">' + statusText + '</span></td>' +
'</tr>';
@ -297,13 +304,14 @@
}
function exportToExcel() {
const head = ["Код статьи", "Наименование услуги", "Подразделение", "Бюджет", "Исполнено", "Исполнение %", "Статус"];
const head = ["Наименование", "Подразделение", "Тип бюджета", "Бюджет закупок, тг", "Сумма поставки, тг", "Экономия, тг", "Исполнение %", "Статус"];
const body = filteredData.map(r => [
r.articleCode || '',
r.serviceName || '',
r.department || '',
r.budgetType || '',
r.budgetSum || 0,
r.executedSum || 0,
r.economy || 0,
(r.execPercent || 0).toFixed(2),
getStatusText(r.execPercent || 0)
]);

View File

@ -25,18 +25,19 @@ function parseExcelData() {
const findColumn = (names) => {
for (const name of names) {
const idx = headers.findIndex(h => h.includes(name.toLowerCase()));
const idx = headers.findIndex(h => h.toLowerCase().includes(name.toLowerCase()));
if (idx !== -1) return idx;
}
return -1;
};
const articleCodeIdx = findColumn(['код статьи', 'статья', 'код']);
const serviceNameIdx = findColumn(['наименование', 'услуг', 'работ', 'название']);
const departmentIdx = findColumn(['подраздел', 'центр', 'департамент', 'управление']);
const budgetSumIdx = findColumn(['бюджет', 'план', 'сумма план']);
const executedSumIdx = findColumn(['исполн', 'факт', 'оплачено']);
const execPercentIdx = findColumn(['исполнение', '%', 'процент']);
const serviceNameIdx = findColumn(['Краткий текст материала']);
const budgetSumIdx = findColumn(['Бюджет закупок,тг']);
const executedSumIdx = findColumn(['Сумма поставки,тг']);
const economyIdx = findColumn(['Экономия от проведенного закупа']);
const sppElementIdx = findColumn(['СПП-элемент']);
const departmentIdx = findColumn(['Завод', 'МВЗ', 'Текст МВЗ']);
const execPercentIdx = findColumn(['% исполнения']);
const data = [];
for (let i = 1; i < rows.length; i++) {
@ -45,8 +46,17 @@ function parseExcelData() {
const budgetSum = parseFloat(String(row[budgetSumIdx] || 0).replace(/\s/g, '')) || 0;
const executedSum = parseFloat(String(row[executedSumIdx] || 0).replace(/\s/g, '')) || 0;
let execPercent = 0;
const economy = parseFloat(String(row[economyIdx] || 0).replace(/\s/g, '')) || 0;
const sppElement = String(row[sppElementIdx] || '').trim();
let budgetType = '';
if (sppElement.startsWith('I')) {
budgetType = 'БКВ';
} else if (sppElement.startsWith('O')) {
budgetType = 'ОБ';
}
let execPercent = 0;
if (execPercentIdx !== -1 && row[execPercentIdx]) {
execPercent = parseFloat(String(row[execPercentIdx]).replace('%', '').replace(/\s/g, '')) || 0;
} else if (budgetSum > 0) {
@ -54,15 +64,17 @@ function parseExcelData() {
}
const item = {
articleCode: String(row[articleCodeIdx] || '').trim(),
serviceName: String(row[serviceNameIdx] || '').trim(),
department: String(row[departmentIdx] || '').trim(),
budgetType: budgetType,
sppElement: sppElement,
budgetSum: budgetSum,
executedSum: executedSum,
economy: economy,
execPercent: Math.round(execPercent * 100) / 100
};
if (item.serviceName || item.articleCode) {
if (item.serviceName) {
data.push(item);
}
}