Go refactoring: - Split handlers/pricing.go (2446→291 lines) into 5 focused files - Split services/stock_import.go (1334→~400 lines) into stock_mappings.go + stock_parse.go - Split services/sync/service.go (1290→~250 lines) into 3 files JS extraction: - Move all inline <script> blocks to web/static/js/ (6 files) - Templates reduced: admin_pricing 2873→521, lot 1531→304, vendor_mappings 1063→169, etc. Competitor pricelists (migrations 033-039): - qt_competitors + partnumber_log_competitors tables - Excel import with column mapping, dedup, bulk insert - p/n→lot resolution via weighted_median, discount applied - Unmapped p/ns written to qt_vendor_partnumber_seen - Quote counts (unique/total) shown on /admin/competitors - price_method="weighted_median", price_period_days=0 stored explicitly Fix price_method/price_period_days for warehouse items: - warehouse: weighted_avg, period=0 - competitor: weighted_median, period=0 - Removes misleading DB defaults (was: median/90) Update bible: architecture.md, pricelist.md, history.md Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
108 lines
5.4 KiB
HTML
108 lines
5.4 KiB
HTML
{{define "title"}}Прайслист - PriceForge{{end}}
|
|
|
|
{{define "content"}}
|
|
<div class="space-y-6">
|
|
<div class="flex items-center justify-between">
|
|
<div class="flex items-center space-x-4">
|
|
<a href="/pricelists" class="text-gray-500 hover:text-gray-700">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
|
|
</svg>
|
|
</a>
|
|
<h1 id="page-title" class="text-2xl font-bold text-gray-900">Загрузка...</h1>
|
|
</div>
|
|
<div class="flex items-center gap-2">
|
|
<button onclick="openPriceChangesReport()" class="px-4 py-2 border border-gray-300 text-gray-700 rounded-md hover:bg-gray-50">
|
|
Отчет по изменениям
|
|
</button>
|
|
<button onclick="exportToCSV()" class="px-4 py-2 bg-orange-600 text-white rounded-md hover:bg-orange-700 flex items-center space-x-2">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
|
|
</svg>
|
|
<span>Экспорт в CSV</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="pricelist-info" class="bg-white rounded-lg shadow p-6">
|
|
<div id="pl-notification" class="hidden mb-4 p-3 bg-yellow-50 border border-yellow-200 rounded-lg text-yellow-800"></div>
|
|
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
|
|
<div>
|
|
<p class="text-sm text-gray-500">Версия</p>
|
|
<p id="pl-version" class="font-mono">-</p>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm text-gray-500">Дата создания</p>
|
|
<p id="pl-date">-</p>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm text-gray-500">Автор</p>
|
|
<p id="pl-author">-</p>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm text-gray-500">Позиций</p>
|
|
<p id="pl-items">-</p>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm text-gray-500">Использований</p>
|
|
<p id="pl-usage">-</p>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm text-gray-500">Статус</p>
|
|
<p id="pl-status">-</p>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm text-gray-500">Истекает</p>
|
|
<p id="pl-expires">-</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="bg-white rounded-lg shadow overflow-hidden">
|
|
<div class="p-4 border-b">
|
|
<input type="text" id="search-input" placeholder="Поиск по артикулу..."
|
|
class="w-full md:w-64 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-orange-500">
|
|
</div>
|
|
|
|
<table class="min-w-full divide-y divide-gray-200">
|
|
<thead class="bg-gray-50">
|
|
<tr>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">Артикул</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">Категория</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">Описание</th>
|
|
<th id="th-qty" class="hidden px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase">Доступно</th>
|
|
<th id="th-partnumbers" class="hidden px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">Partnumbers</th>
|
|
<th class="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase">Цена, $</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">Настройки</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="items-body" class="bg-white divide-y divide-gray-200">
|
|
<tr>
|
|
<td colspan="7" class="px-6 py-4 text-center text-gray-500">Загрузка...</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<div id="items-pagination" class="p-4 border-t flex justify-between items-center">
|
|
<span id="items-info" class="text-sm text-gray-500"></span>
|
|
<div id="items-pages" class="space-x-2"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="price-changes-modal" class="fixed inset-0 bg-black bg-opacity-50 hidden items-center justify-center z-50">
|
|
<div class="bg-white rounded-lg p-6 max-w-4xl w-full mx-4 max-h-[85vh] overflow-hidden flex flex-col">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h2 class="text-xl font-bold">Отчет по изменениям цен</h2>
|
|
<button type="button" onclick="closePriceChangesModal()" class="text-gray-500 hover:text-gray-700">Закрыть</button>
|
|
</div>
|
|
<div id="price-changes-summary" class="text-sm text-gray-600 mb-4"></div>
|
|
<div id="price-changes-content" class="overflow-auto space-y-4"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="/static/js/pricelist_detail.js"></script>
|
|
{{end}}
|
|
|
|
{{template "base" .}}
|