mirror of
https://github.com/christianvidalwolf-prog/Craze-Data-check.git
synced 2026-08-03 13:45:24 +02:00
fix: merge history data into rows when products table is empty
This commit is contained in:
+15
-9
@@ -9,7 +9,7 @@ import { TopBar } from './components/TopBar';
|
|||||||
import { ProductDescriptions } from './components/ProductDescriptions';
|
import { ProductDescriptions } from './components/ProductDescriptions';
|
||||||
import { MatrixView } from './components/MatrixView';
|
import { MatrixView } from './components/MatrixView';
|
||||||
import { EditPanel } from './components/EditPanel';
|
import { EditPanel } from './components/EditPanel';
|
||||||
import { getAllSyncedRows, saveRowToSupabase, resetAllPendingRows, saveHistoryEntry, deleteHistoryEntry } from './lib/supabase';
|
import { getAllSyncedRows, saveRowToSupabase, resetAllPendingRows, saveHistoryEntry, deleteHistoryEntry, getHistoryDataForMerge } from './lib/supabase';
|
||||||
import { getStoredSession, signOut, type AuthSession } from './lib/auth';
|
import { getStoredSession, signOut, type AuthSession } from './lib/auth';
|
||||||
import { LoginPage } from './components/LoginPage';
|
import { LoginPage } from './components/LoginPage';
|
||||||
import { DimensionsView } from './components/DimensionsView';
|
import { DimensionsView } from './components/DimensionsView';
|
||||||
@@ -134,6 +134,9 @@ export default function App() {
|
|||||||
|
|
||||||
console.log('Fetching synced data from Supabase...');
|
console.log('Fetching synced data from Supabase...');
|
||||||
const syncedData = await getAllSyncedRows();
|
const syncedData = await getAllSyncedRows();
|
||||||
|
console.log('Fetching history data from Supabase for merge...');
|
||||||
|
const historyData = await getHistoryDataForMerge();
|
||||||
|
console.log('Supabase synced rows:', Object.keys(syncedData).length, '| History rows:', Object.keys(historyData).length);
|
||||||
|
|
||||||
// Extend headers with virtual columns if the Excel is shorter than the saved data.
|
// Extend headers with virtual columns if the Excel is shorter than the saved data.
|
||||||
// COLUMNS hardcoded indices (PRODUCT_TYPE=103, ITEM_TO_LOGISTIC=104, etc.) are used
|
// COLUMNS hardcoded indices (PRODUCT_TYPE=103, ITEM_TO_LOGISTIC=104, etc.) are used
|
||||||
@@ -186,33 +189,36 @@ const articleNoIdx = resolvedCols.ARTICLE_NO;
|
|||||||
const processedRows = rows.map(row => {
|
const processedRows = rows.map(row => {
|
||||||
const articleNo = String(row[articleNoIdx]);
|
const articleNo = String(row[articleNoIdx]);
|
||||||
const synced = syncedData[articleNo];
|
const synced = syncedData[articleNo];
|
||||||
|
const hist = historyData[articleNo];
|
||||||
|
|
||||||
// Start with fresh Dropbox values (prices from Excel)
|
// Start with fresh Dropbox values (prices from Excel)
|
||||||
let finalRow = [...row];
|
let finalRow = [...row];
|
||||||
|
|
||||||
// Merge logic: Prioritize internal control columns and active session edits
|
// Merge logic: Prioritize internal control columns from syncedData or historyData
|
||||||
if (synced && synced.data) {
|
const sourceForInternal = synced?.data || hist;
|
||||||
|
|
||||||
|
if (sourceForInternal) {
|
||||||
// 1. ALWAYS restore Internal Control Columns (indices >= 100)
|
// 1. ALWAYS restore Internal Control Columns (indices >= 100)
|
||||||
// These are the "TYPE", "Item to Logistic", "Checking", etc.
|
// These are the "TYPE", "Item to Logistic", "Checking", etc.
|
||||||
// We use hardcoded indices from COLUMNS to ensure they stay at the end.
|
// We use hardcoded indices from COLUMNS to ensure they stay at the end.
|
||||||
Object.values(COLUMNS).forEach(idx => {
|
Object.values(COLUMNS).forEach(idx => {
|
||||||
if (idx >= 100 && synced.data[idx] !== undefined && synced.data[idx] !== null) {
|
if (idx >= 100 && sourceForInternal[idx] !== undefined && sourceForInternal[idx] !== null) {
|
||||||
finalRow[idx] = synced.data[idx];
|
finalRow[idx] = sourceForInternal[idx];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 2. For Master Data (indices < 100, like UVP/SRP), only restore if it's an active edit (pending)
|
// 2. For Master Data (indices < 100, like UVP/SRP), only restore if it's an active edit (pending)
|
||||||
// This protects against the "Column Shift" bug where old saved indices might be wrong.
|
// This protects against the "Column Shift" bug where old saved indices might be wrong.
|
||||||
if (synced.status === 'pending') {
|
if (synced?.status === 'pending') {
|
||||||
editableColumns.forEach(idx => {
|
editableColumns.forEach(idx => {
|
||||||
if (idx < 100 && synced.data[idx] !== undefined && synced.data[idx] !== null) {
|
if (idx < 100 && sourceForInternal[idx] !== undefined && sourceForInternal[idx] !== null) {
|
||||||
finalRow[idx] = synced.data[idx];
|
finalRow[idx] = sourceForInternal[idx];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update row status in UI if it's not the default 'excel'
|
// Update row status in UI if it's not the default 'excel'
|
||||||
if (synced.status && synced.status !== 'excel') {
|
if (synced?.status && synced.status !== 'excel') {
|
||||||
setRowStatuses(prev => ({ ...prev, [articleNo]: synced.status! }));
|
setRowStatuses(prev => ({ ...prev, [articleNo]: synced.status! }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -194,6 +194,35 @@ export async function getHistory(): Promise<HistoryEntry[]> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getHistoryDataForMerge(): Promise<Record<string, ExcelRow>> {
|
||||||
|
try {
|
||||||
|
const response = await safeFetch(
|
||||||
|
`${SUPABASE_URL}/rest/v1/products_history?select=product_id,new_data&order=changed_at.desc`,
|
||||||
|
{ cache: 'no-store' }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
console.error('[getHistoryDataForMerge] Error:', response.status);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const entries: Array<{ product_id: string; new_data: ExcelRow }> = await response.json();
|
||||||
|
|
||||||
|
const result: Record<string, ExcelRow> = {};
|
||||||
|
const seen = new Set<string>();
|
||||||
|
for (const entry of entries) {
|
||||||
|
if (seen.has(entry.product_id)) continue;
|
||||||
|
seen.add(entry.product_id);
|
||||||
|
if (entry.new_data && entry.new_data.length > 0) {
|
||||||
|
result[entry.product_id] = entry.new_data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('[getHistoryDataForMerge] Exception:', error.message);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function deleteHistoryEntry(id: string): Promise<boolean> {
|
export async function deleteHistoryEntry(id: string): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
const response = await safeFetch(
|
const response = await safeFetch(
|
||||||
|
|||||||
Reference in New Issue
Block a user