feat: price_quality в конфигураторе; фикс пустого lot_description в экспорте цен

price_quality теперь синхронизируется не только в прайслист, но и в
LocalComponent/services.ComponentView (/api/components) — виден в
выпадающем списке поиска (цветная точка), в таблице конфигуратора
(левая колонка-пиктограмма) и на вкладке «Ценообразование» (подсветка
строки). Цветовая шкала вынесена в один модуль web/static/price-quality.js
(подключён в base.html), чтобы не дублировать расчёт цвета по шаблонам.
Шкала — градиент 0 (красный) → 5 (жёлтый) → 9 (зелёный).

Экспорт цен (internal/services/export.go): resolveLotDescriptions был
заглушкой, всегда возвращавшей пустую карту — строки BOM/не-BOM в
экспорте всегда оставались без описания LOT. Заменён на реальный
запрос к local_pricelist_items текущего выбранного прайслиста
(LocalDB.GetLocalDescriptionsForLots), по аналогии с уже существующим
GetLocalLotCategoriesByServerPricelistID.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Mikhail Chusavitin
2026-07-22 19:01:47 +03:00
co-authored by Claude Sonnet 5
parent 3348008198
commit ee92c3b392
11 changed files with 169 additions and 24 deletions
+4 -10
View File
@@ -59,6 +59,7 @@
<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-right text-xs font-medium text-gray-500 uppercase">Цена, $</th>
<th class="px-6 py-3 text-center text-xs font-medium text-gray-500 uppercase">Качество</th>
</tr>
</thead>
<tbody id="items-body" class="bg-white divide-y divide-gray-200">
@@ -155,14 +156,7 @@
}
function itemsColspan() {
return 4;
}
function formatPriceQualityWarning(quality) {
if (typeof quality !== 'number') return '';
if (quality >= 7) return '';
const color = quality >= 4 ? 'text-amber-500' : 'text-red-600';
return ` <span class="${color} font-bold" title="Качество цены: ${quality}/9">&#33;</span>`;
return 5;
}
function escapeHtml(text) {
@@ -198,12 +192,11 @@
// Price cell — add spread badge for competitor, plus a price-quality warning
// Price cell — add spread badge for competitor
let priceHtml = price;
if (!isWarehouseSource() && item.price_spread_pct > 0) {
priceHtml += ` <span class="text-xs text-amber-600 font-medium" title="Разброс цен конкурентов">±${item.price_spread_pct.toFixed(0)}%</span>`;
}
priceHtml += formatPriceQualityWarning(item.price_quality);
return `
<tr class="hover:bg-gray-50">
@@ -215,6 +208,7 @@
</td>
<td class="${p} text-sm text-gray-500" title="${escapeHtml(description)}">${escapeHtml(truncatedDesc)}</td>
<td class="${p} whitespace-nowrap text-right font-mono">${priceHtml}</td>
<td class="${p} whitespace-nowrap text-center">${qualityBadgeHtml(item.price_quality)}</td>
</tr>
`;
}).join('');