fix: экспорт конфига через GetByUUIDNoAuth, формат чисел с запятой как разделителем

- ExportConfigCSV и ExportConfigPricingCSV: GetByUUID → GetByUUIDNoAuth,
  чтобы не падать с ErrConfigForbidden на конфигах с чужим OriginalUsername
- ConfigurationGetter: добавлен GetByUUIDNoAuth в интерфейс
- Шаблоны: toLocaleString('en-US') → 'ru-RU' во всех местах отображения цен;
  процентные значения: .toFixed(1) → .toFixed(1).replace('.', ',')

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-11 05:00:37 +03:00
parent 09d694234d
commit e548305396
8 changed files with 16 additions and 11 deletions

View File

@@ -247,7 +247,7 @@ function renderConfigs(configs) {
configs.forEach(c => {
const date = new Date(c.created_at).toLocaleDateString('ru-RU');
const total = c.total_price ? '$' + c.total_price.toLocaleString('en-US', {minimumFractionDigits: 2}) : '—';
const total = c.total_price ? '$' + c.total_price.toLocaleString('ru-RU', {minimumFractionDigits: 2}) : '—';
const serverCount = c.server_count ? c.server_count : 1;
const author = c.owner_username || (c.user && c.user.username) || '—';
const projectName = c.project_uuid && projectNameByUUID[c.project_uuid]
@@ -258,7 +258,7 @@ function renderConfigs(configs) {
let pricePerUnit = '—';
if (c.total_price && serverCount > 0) {
const unitPrice = c.total_price / serverCount;
pricePerUnit = '$' + unitPrice.toLocaleString('en-US', {minimumFractionDigits: 2});
pricePerUnit = '$' + unitPrice.toLocaleString('ru-RU', {minimumFractionDigits: 2});
}
html += '<tr class="hover:bg-gray-50">';

View File

@@ -2584,7 +2584,7 @@ function formatDiffPercent(baseTotal, compareTotal, compareLabel) {
}
const pct = ((baseTotal - compareTotal) / compareTotal) * 100;
const sign = pct > 0 ? '+' : '';
return `${sign}${pct.toFixed(1)}% от ${compareLabel}`;
return `${sign}${pct.toFixed(1).replace('.', ',')}% от ${compareLabel}`;
}
function getTotalClass(current, references) {
@@ -2709,7 +2709,7 @@ function calculateCustomPrice() {
// Show discount info
discountInfoEl.classList.remove('hidden');
discountPercentEl.textContent = discountPercent.toFixed(1) + '%';
discountPercentEl.textContent = discountPercent.toFixed(1).replace('.', ',') + '%';
// Update discount color based on value
const discountEl = discountPercentEl;
@@ -4272,7 +4272,7 @@ function applyCustomPrice(table) {
if (est <= 0) return '';
const pct = ((est - custom) / est * 100);
const sign = pct >= 0 ? '-' : '+';
return ` (${sign}${Math.abs(pct).toFixed(1)}%)`;
return ` (${sign}${Math.abs(pct).toFixed(1).replace('.', ',')}%)`;
};
const _pctClass = (custom, est) => custom <= est ? 'text-green-600' : 'text-red-600';
@@ -4365,7 +4365,7 @@ function setPricingCustomPriceFromVendor() {
const totalEl = document.getElementById('pricing-total-buy-vendor');
if (hasAny) {
document.getElementById('pricing-custom-price-buy').value = total.toFixed(2);
const pct = estimateTotal > 0 ? ` (-${((estimateTotal - total) / estimateTotal * 100).toFixed(1)}%)` : '';
const pct = estimateTotal > 0 ? ` (-${((estimateTotal - total) / estimateTotal * 100).toFixed(1).replace('.', ',')}%)` : '';
totalEl.textContent = formatCurrency(total) + pct;
totalEl.className = totalEl.className.replace(/\btext-(?:green|red)-\d+\b/g, '').trim();
totalEl.classList.add(total <= estimateTotal ? 'text-green-600' : 'text-red-600');

View File

@@ -243,7 +243,7 @@
const descMax = stock ? 30 : 60;
const html = items.map(item => {
const price = item.price.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
const price = item.price.toLocaleString('ru-RU', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
const description = item.lot_description || '-';
const truncatedDesc = description.length > descMax ? description.substring(0, descMax) + '...' : description;

View File

@@ -339,7 +339,7 @@ function escapeHtml(text) {
function formatMoneyNoDecimals(value) {
const safe = Number.isFinite(Number(value)) ? Number(value) : 0;
return '$' + Math.round(safe).toLocaleString('en-US');
return '$' + Math.round(safe).toLocaleString('ru-RU');
}
function resolveProjectTrackerURL(projectData) {

View File

@@ -81,7 +81,7 @@ function escapeHtml(text) {
}
function formatMoney(v) {
return '$' + (v || 0).toLocaleString('en-US', {minimumFractionDigits: 2});
return '$' + (v || 0).toLocaleString('ru-RU', {minimumFractionDigits: 2});
}
function formatDateTime(value) {