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:
co-authored by
Claude Sonnet 5
parent
3348008198
commit
ee92c3b392
@@ -0,0 +1,55 @@
|
||||
// Shared LOT price-quality color scale, used everywhere price_quality is
|
||||
// displayed (pricelist detail page, configurator search dropdown, configurator
|
||||
// table, pricing tab). price_quality is a 0-9 score set by the external
|
||||
// pricing tool (see bible-local/03-database.md, qt_pricelist_items.price_quality)
|
||||
// — QF only displays it, never computes it. Single source of the color scale
|
||||
// so every view stays visually consistent.
|
||||
//
|
||||
// Gradient: 0 = red, 5 = yellow, 9 = green.
|
||||
(function () {
|
||||
const RED = [220, 38, 38];
|
||||
const YELLOW = [234, 179, 8];
|
||||
const GREEN = [22, 163, 74];
|
||||
|
||||
function lerp(c1, c2, t) {
|
||||
return c1.map((v, i) => Math.round(v + (c2[i] - v) * t));
|
||||
}
|
||||
|
||||
// Returns "r, g, b" (no rgb() wrapper) so callers can build rgb()/rgba() themselves.
|
||||
function priceQualityRgb(quality) {
|
||||
if (typeof quality !== 'number' || Number.isNaN(quality)) return null;
|
||||
const q = Math.max(0, Math.min(9, quality));
|
||||
const [r, g, b] = q <= 5 ? lerp(RED, YELLOW, q / 5) : lerp(YELLOW, GREEN, (q - 5) / 4);
|
||||
return `${r}, ${g}, ${b}`;
|
||||
}
|
||||
|
||||
function priceQualityColor(quality) {
|
||||
const rgb = priceQualityRgb(quality);
|
||||
return rgb ? `rgb(${rgb})` : null;
|
||||
}
|
||||
|
||||
// Small colored dot for compact contexts (search dropdown, configurator table cell).
|
||||
function qualityDotHtml(quality) {
|
||||
const color = priceQualityColor(quality);
|
||||
if (!color) return '';
|
||||
return `<span class="inline-block w-2 h-2 rounded-full" style="background-color: ${color}" title="Качество цены: ${quality}/9"></span>`;
|
||||
}
|
||||
|
||||
// Colored number badge for a dedicated "quality" column/cell.
|
||||
function qualityBadgeHtml(quality) {
|
||||
if (typeof quality !== 'number') return '<span class="text-gray-400">-</span>';
|
||||
const color = priceQualityColor(quality);
|
||||
return `<span class="font-semibold" style="color: ${color}" title="Качество цены: ${quality}/9">${quality}</span>`;
|
||||
}
|
||||
|
||||
// Light row-tint background for table rows, e.g. the pricing tab.
|
||||
function qualityRowStyle(quality) {
|
||||
const rgb = priceQualityRgb(quality);
|
||||
return rgb ? `background-color: rgba(${rgb}, 0.10)` : '';
|
||||
}
|
||||
|
||||
window.priceQualityColor = priceQualityColor;
|
||||
window.qualityDotHtml = qualityDotHtml;
|
||||
window.qualityBadgeHtml = qualityBadgeHtml;
|
||||
window.qualityRowStyle = qualityRowStyle;
|
||||
})();
|
||||
Reference in New Issue
Block a user