feat: кнопка "Обновить цены" использует последний скачанный прайслист без синхронизации и показывает diff
- убрать вызовы /api/sync/components и /api/sync/pricelists из обеих кнопок - брать самый свежий прайслист из уже скачанных (active_only) - проверять галочку disable_price_refresh (пропускать конфиг если включена) - показывать модальное окно diff: компонент / цена за шт. / сумма (было → стало) + итог конфиги - общие утилиты (fetchLatestEstimatePricelistId, showPriceDiffModal) вынесены в base.html - обе кнопки вызывают refreshPrices() без дублирования кода Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2817,7 +2817,6 @@ async function exportCSVWithCustomPrice() {
|
||||
}
|
||||
|
||||
async function refreshPrices() {
|
||||
// RBAC disabled - no token check required
|
||||
if (!configUUID) return;
|
||||
if (disablePriceRefresh) {
|
||||
showToast('Обновление цен отключено в настройках', 'error');
|
||||
@@ -2834,30 +2833,7 @@ async function refreshPrices() {
|
||||
refreshBtn.className = 'px-4 py-2 bg-gray-300 text-gray-500 rounded cursor-not-allowed';
|
||||
}
|
||||
|
||||
let serverSyncSkipped = false;
|
||||
try {
|
||||
const statusResp = await fetch('/api/sync/status');
|
||||
const statusData = statusResp.ok ? await statusResp.json() : null;
|
||||
if (statusData && statusData.is_online) {
|
||||
const componentSyncResp = await fetch('/api/sync/components', { method: 'POST' });
|
||||
if (!componentSyncResp.ok) throw new Error('component sync failed');
|
||||
|
||||
const pricelistSyncResp = await fetch('/api/sync/pricelists', { method: 'POST' });
|
||||
if (!pricelistSyncResp.ok) throw new Error('pricelist sync failed');
|
||||
} else {
|
||||
serverSyncSkipped = true;
|
||||
}
|
||||
} catch(syncErr) {
|
||||
if (syncErr.message === 'component sync failed' || syncErr.message === 'pricelist sync failed') {
|
||||
throw syncErr;
|
||||
}
|
||||
serverSyncSkipped = true;
|
||||
}
|
||||
|
||||
await Promise.all([
|
||||
loadActivePricelists(true),
|
||||
loadAllComponents()
|
||||
]);
|
||||
await loadActivePricelists(true);
|
||||
|
||||
['estimate', 'warehouse', 'competitor'].forEach(source => {
|
||||
const latest = activePricelistsBySource[source]?.[0];
|
||||
@@ -2871,22 +2847,44 @@ async function refreshPrices() {
|
||||
renderPricelistSettingsSummary();
|
||||
persistLocalPriceSettings();
|
||||
|
||||
// Snapshot prices before refresh for diff
|
||||
const beforePricesMap = {};
|
||||
let beforeTotal = 0;
|
||||
for (const item of cart) {
|
||||
const p = getDisplayPrice(item);
|
||||
beforePricesMap[item.lot_name] = { price: p, qty: item.quantity };
|
||||
beforeTotal += p * item.quantity;
|
||||
}
|
||||
beforeTotal *= serverCount;
|
||||
|
||||
await saveConfig(false);
|
||||
await refreshPriceLevels({ force: true, noCache: true });
|
||||
renderTab();
|
||||
updateCartUI();
|
||||
|
||||
// Compute diff after refresh
|
||||
const itemDiffs = [];
|
||||
let afterTotal = 0;
|
||||
for (const item of cart) {
|
||||
const newPrice = getDisplayPrice(item);
|
||||
afterTotal += newPrice * item.quantity;
|
||||
const before = beforePricesMap[item.lot_name];
|
||||
if (before && Math.abs(before.price - newPrice) > 0.01) {
|
||||
itemDiffs.push({ lot_name: item.lot_name, quantity: item.quantity, prevPrice: before.price, newPrice });
|
||||
}
|
||||
}
|
||||
afterTotal *= serverCount;
|
||||
|
||||
if (configUUID) {
|
||||
const configResp = await fetch('/api/configs/' + configUUID);
|
||||
if (configResp.ok) {
|
||||
const config = await configResp.json();
|
||||
if (config.price_updated_at) {
|
||||
updatePriceUpdateDate(config.price_updated_at);
|
||||
}
|
||||
if (config.price_updated_at) updatePriceUpdateDate(config.price_updated_at);
|
||||
}
|
||||
}
|
||||
|
||||
showToast(serverSyncSkipped ? 'Цены обновлены (без связи с сервером)' : 'Цены обновлены', 'success');
|
||||
showToast('Цены обновлены', 'success');
|
||||
showPriceDiffModal([{ configName: configName || 'Конфигурация', prevTotal: beforeTotal, newTotal: afterTotal, serverCount, itemDiffs }]);
|
||||
} catch(e) {
|
||||
showToast('Ошибка обновления цен', 'error');
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user