fix: always use fresh Dropbox Excel values on load

This commit is contained in:
Christian Vidal Wolf
2026-04-23 16:12:09 +02:00
parent 605b93c445
commit 6bcf697165
+20 -53
View File
@@ -158,65 +158,32 @@ export default function App() {
}
});
const articleNoIdx = resolvedCols.ARTICLE_NO;
const articleNoIdx = resolvedCols.ARTICLE_NO;
const processedRows = rows.map(row => {
const articleNo = String(row[articleNoIdx]);
const synced = syncedData[articleNo];
// Start with Dropbox values (default) - fresh from Excel
// Simply use Dropbox values - no merge logic
// Manual edits are preserved in Supabase and shown in Change History
// but fresh Excel data takes precedence on reload
let finalRow = [...row];
// Only preserve Supabase value if it's DIFFERENT from Dropbox (meaning someone edited it intentionally)
// This keeps the TYPE = "Surprise Bath bomb" edits while avoiding stale SRP/UVP values
if (synced) {
const oldData = synced.data;
const valAt12 = oldData[12];
const needsShift = typeof valAt12 === 'number' || (typeof valAt12 === 'string' && /^[0-9.]+$/.test(valAt12));
editableColumns.forEach(idx => {
let mergeIdx = idx;
if (needsShift && idx >= 12) {
mergeIdx = idx - 1;
}
const dbxValue = row[idx];
const supabaseValue = oldData[mergeIdx];
// Only use Supabase value if it's different from Dropbox (edited intentionally)
if (supabaseValue !== undefined && supabaseValue !== null) {
// Compare as strings to handle numeric formatting differences
const dbxStr = String(dbxValue ?? '');
const supabaseStr = String(supabaseValue);
// Keep Supabase value only if it was actually edited (different from Excel)
if (dbxStr !== supabaseStr) {
finalRow[idx] = supabaseValue;
}
}
});
setRowStatuses(prev => ({ ...prev, [articleNo]: synced.status || 'synced' }));
}
// Otherwise use Dropbox values (don't merge, just process formatting)
return finalRow.map((val: any, idx: number) => {
if (val === undefined || val === null || val === '') return val;
const header = (headers[idx] || '').toLowerCase();
if ((header.includes('id') || header.includes('no') || header.includes('code') ||
header.includes('art.') || header.includes('barcode') || header.includes('article')) &&
!(header.includes('nw') || header.includes('gw') || header.includes('weight') || header.includes('kg'))) {
return val;
}
const formatKeywords = ['price', 'eur', 'cost', 'msrp', 'net', 'gross', 'netto', 'brutto', 'pp', 'pph', 'uvp', 'vpe', 'stk', 'nw', 'gw', 'weight', 'kg'];
const shouldFormat = formatKeywords.some(kw => header.includes(kw));
if (typeof val === 'number') {
return Number(val.toFixed(2));
}
if (typeof val === 'string') {
const normalized = val.trim().replace(',', '.');
if ((header.includes('id') || header.includes('no') || header.includes('code') ||
header.includes('art.') || header.includes('barcode') || header.includes('article')) &&
!(header.includes('nw') || header.includes('gw') || header.includes('weight') || header.includes('kg'))) {
return val;
}
const formatKeywords = ['price', 'eur', 'cost', 'msrp', 'net', 'gross', 'netto', 'brutto', 'pp', 'pph', 'uvp', 'vpe', 'stk', 'nw', 'gw', 'weight', 'kg'];
const shouldFormat = formatKeywords.some(kw => header.includes(kw));
if (typeof val === 'number') {
return Number(val.toFixed(2));
}
if (typeof val === 'string') {
const normalized = val.trim().replace(',', '.');
const num = parseFloat(normalized);
if (!isNaN(num) && (shouldFormat || val.includes('.') || val.includes(','))) {
return num.toFixed(2);