Files
driver-revenue-reconciliation/index.html
T

235 lines
12 KiB
HTML

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Сверка выручки водителей</title>
<link rel="stylesheet" href="styles.css">
<!-- Библиотека XLSX для чтения/записи Excel-файлов -->
<script src="https://cdn.jsdelivr.net/npm/xlsx@0.19.2/dist/xlsx.full.min.js"></script>
</head>
<body>
<div class="container">
<header class="hero">
<div class="hero-badge">🔒 Работает офлайн — файлы не отправляются на сервер</div>
<h1>Сверка выручки водителей</h1>
<p class="hero-subtitle">Загрузите ведомости приёма наличных и выгрузку транзакций — получите сводную таблицу, расхождения и готовый Excel-отчёт</p>
</header>
<!-- Статус-бар -->
<div class="status-bar" id="statusBar" style="display:none"></div>
<!-- Файлы -->
<section class="card">
<div class="card-head">
<div class="step-badge">1</div>
<h2>Файлы</h2>
</div>
<div class="card-body">
<div class="dropzone" id="dropzone">
<div class="dropzone-icon">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="#6366f1" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
<polyline points="17 8 12 3 7 8"/>
<line x1="12" y1="3" x2="12" y2="15"/>
</svg>
</div>
<div class="dropzone-title">Перетащите файлы сюда или нажмите для выбора</div>
<div class="dropzone-hint">
Любое число ведомостей (<strong>.xlsx</strong>) + выгрузка <strong>TRANSACTIONS_EXT</strong>.
Тип определяется автоматически.
</div>
</div>
<input type="file" id="fileInput" multiple accept=".xlsx,.xls" style="display:none">
<div class="file-list" id="fileList"></div>
<div class="actions">
<button class="btn btn-primary" id="btnReconcile" disabled>✓ Провести сверку</button>
<button class="btn btn-outline" id="btnClear" disabled>✕ Очистить</button>
<button class="btn btn-export" id="btnExportCsv" disabled>⬇ Экспорт CSV</button>
<button class="btn btn-theme" id="btnToggleTheme">🌙 Тёмная тема</button>
</div>
<div class="progress-bar" id="progressBar">
<div class="progress-fill" id="progressFill"></div>
</div>
</div>
</section>
<!-- Результат -->
<section class="card" id="resultCard">
<div class="card-head">
<div class="step-badge">2</div>
<h2>Результат</h2>
</div>
<div class="card-body">
<div id="emptyState" class="empty-state">
<div class="empty-state-icon">📋</div>
<p>Загрузите файлы и нажмите «Провести сверку»</p>
</div>
<div id="resultActions" style="display:none;margin-bottom:1.5rem;">
<button class="btn btn-success" id="btnDownload">📥 Скачать Excel-отчёт</button>
</div>
<div id="tabsContainer" style="display:none;">
<div class="tabs-wrapper">
<button class="tab-btn active" data-tab="discrepancies">
Расхождения <span class="count" id="countDisc">0</span>
</button>
<button class="tab-btn" data-tab="all">
Все водители <span class="count" id="countAll">0</span>
</button>
<button class="tab-btn" data-tab="cashiers">По кассирам</button>
<button class="tab-btn" data-tab="routes">По маршрутам</button>
<button class="tab-btn" data-tab="conclusions">Выводы</button>
</div>
<!-- Вкладка: Расхождения -->
<div class="tab-panel active" id="panel-discrepancies">
<div class="table-wrap">
<table>
<thead>
<tr>
<th data-key="driver">Водитель</th>
<th data-key="car">Гос. номер</th>
<th data-key="given">Сдано (₽)</th>
<th data-key="collected">Собрано (₽)</th>
<th data-key="diff">Расхождение</th>
<th>Статус</th>
</tr>
</thead>
<tbody id="tableDiscrepancies"></tbody>
</table>
</div>
</div>
<!-- Вкладка: Все водители -->
<div class="tab-panel" id="panel-all">
<div class="table-wrap">
<table>
<thead>
<tr>
<th data-key="date">Дата</th>
<th data-key="driver">Водитель</th>
<th data-key="route">Маршрут</th>
<th data-key="section">Тип</th>
<th data-key="given">Сдано (₽)</th>
<th data-key="collected">Собрано (₽)</th>
<th data-key="txCount">Транзакций</th>
</tr>
</thead>
<tbody id="tableAll"></tbody>
</table>
</div>
</div>
<!-- Вкладка: По кассирам -->
<div class="tab-panel" id="panel-cashiers">
<div class="table-wrap">
<table>
<thead>
<tr>
<th data-key="cashier">Кассир</th>
<th>Ведомостей</th>
<th data-key="given">Сдано (₽)</th>
<th data-key="collected">Собрано (₽)</th>
<th data-key="diff">Расхождение</th>
</tr>
</thead>
<tbody id="tableCashiers"></tbody>
</table>
</div>
</div>
<!-- Вкладка: По маршрутам -->
<div class="tab-panel" id="panel-routes">
<div class="table-wrap">
<table>
<thead>
<tr>
<th data-key="route">Маршрут</th>
<th>Тип</th>
<th>Водителей</th>
<th data-key="sum">Сумма (₽)</th>
</tr>
</thead>
<tbody id="tableRoutes"></tbody>
</table>
</div>
</div>
<!-- Вкладка: Выводы -->
<div class="tab-panel" id="panel-conclusions">
<div id="conclusionsContent"></div>
</div>
</div>
</div>
</section>
<!-- Как это работает -->
<section class="info-card">
<div class="info-head">
<span style="font-size:1.4rem">💡</span>
<h2>Как это работает</h2>
</div>
<div class="info-grid">
<div class="info-block">
<div class="info-block-icon blue">📄</div>
<div>
<div class="info-block-title">Определение типа файла</div>
<div class="info-block-text">
Ведомость распознаётся по заголовку «ВЕДОМОСТЬ ПРИЕМА НАЛИЧНЫХ СРЕДСТВ»;
из неё берутся номер документа, дата, ФИО кассира, разделы «Город» / «Пригород»
и строки водителей. Выгрузка распознаётся по столбцам CONDUCTOR, DATE и TARIF_SUM.
</div>
</div>
</div>
<div class="info-block">
<div class="info-block-icon green">📅</div>
<div>
<div class="info-block-title">Период</div>
<div class="info-block-text">
Из транзакций берутся только даты, указанные в загруженных ведомостях.
Остальные даты в сверку не входят.
</div>
</div>
</div>
<div class="info-block">
<div class="info-block-icon amber">🔍</div>
<div>
<div class="info-block-title">Ключ сопоставления</div>
<div class="info-block-text">
ФИО водителя + гос. номер ТС. Номера нормализуются (латинские A, B, C, E, H, K, M, O, P, T, X, Y
заменяются на кириллические), ФИО — верхний регистр, Ё→Е.
Опечатки в ФИО сводятся нечётким сравнением при схожести ≥ 88%.
</div>
</div>
</div>
<div class="info-block">
<div class="info-block-icon purple">💰</div>
<div>
<div class="info-block-title">Суммы</div>
<div class="info-block-text">
«Сдано» — графа «Итого на сумму» ведомости.
«Собрано» — TARIF_SUM ÷ 100 (копейки → рубли) по всем транзакциям водителя за выбранные даты.
</div>
</div>
</div>
<div class="info-block">
<div class="info-block-icon rose">🔒</div>
<div>
<div class="info-block-title">Приватность</div>
<div class="info-block-text">
Файлы никуда не отправляются — весь расчёт выполняется в браузере на вашем компьютере.
Приложение работает полностью офлайн.
</div>
</div>
</div>
</div>
</section>
<div class="footer">
Сверка выручки водителей — все вычисления выполняются локально в вашем браузере
</div>
</div>
<script type="module" src="main.js"></script>
</body>
</html>