Optimize imports, fix up tracking records and time overall

This commit is contained in:
2025-06-19 11:15:04 -04:00
parent a97819f4a6
commit 8606a90e34
16 changed files with 601 additions and 85 deletions

View File

@@ -44,17 +44,44 @@ interface HistoryRecord {
interface ImportHistoryRecord extends HistoryRecord {
records_added: number;
records_updated: number;
records_deleted?: number;
records_skipped?: number;
is_incremental?: boolean;
total_processed?: number;
additional_info?: {
step_timings?: Record<string, number>;
details?: {
categories?: { recordsAdded: number; recordsUpdated: number; skippedCategories?: number };
products?: { totalProcessed: number; needsUpdate: number; skippedUnchanged?: number };
orders?: { totalProcessed: number; totalSkipped: number; missingProducts: number };
purchaseOrders?: { recordsAdded: number; recordsUpdated: number; recordsDeleted: number; skippedProducts: number };
};
[key: string]: any;
};
}
interface CalculateHistoryRecord extends HistoryRecord {
total_products: number;
total_orders: number;
total_purchase_orders: number;
processed_products: number;
processed_orders: number;
processed_purchase_orders: number;
total_products?: number;
total_orders?: number;
total_purchase_orders?: number;
processed_products?: number;
processed_orders?: number;
processed_purchase_orders?: number;
duration_minutes?: number;
duration_seconds?: number;
additional_info?: {
type?: string;
steps?: string[];
completed_steps?: Array<{
name: string;
duration: number;
status: string;
rowsAffected?: number;
}>;
step_timings?: Record<string, number>;
step_row_counts?: Record<string, number>;
[key: string]: any;
};
}
interface ModuleStatus {
@@ -369,6 +396,82 @@ export function DataManagement() {
const formatJsonData = (data: Record<string, any>) => {
if (!data) return null;
// Special handling for completed_steps
if (data.completed_steps && Array.isArray(data.completed_steps)) {
return (
<div className="space-y-2 mt-2">
<div className="text-sm font-semibold text-gray-700">Completed Steps:</div>
<div className="space-y-1 bg-gray-50 p-2 rounded">
{data.completed_steps.map((step: any, idx: number) => (
<div key={idx} className="flex justify-between text-sm">
<span className="font-medium">{step.name}</span>
<div className="flex gap-4 text-gray-600">
<span>{step.duration}s</span>
{step.rowsAffected !== undefined && (
<span>{formatNumber(step.rowsAffected)} rows</span>
)}
<span className={step.status === 'completed' ? 'text-green-600' : 'text-red-600'}>
{step.status}
</span>
</div>
</div>
))}
</div>
{/* Show other data if present */}
{Object.keys(data).filter(k => k !== 'completed_steps').length > 0 && (
<div className="mt-2">
{formatJsonDataSimple(Object.fromEntries(
Object.entries(data).filter(([k]) => k !== 'completed_steps')
))}
</div>
)}
</div>
);
}
// Special handling for import details
if (data.details) {
return (
<div className="space-y-2 mt-2">
<div className="text-sm font-semibold text-gray-700">Import Details:</div>
<div className="space-y-2 bg-gray-50 p-2 rounded">
{Object.entries(data.details).map(([table, stats]: [string, any]) => (
<div key={table} className="border-b last:border-0 pb-2 last:pb-0">
<div className="font-medium text-sm capitalize mb-1">{table}:</div>
<div className="grid grid-cols-2 gap-x-4 gap-y-1 text-xs">
{Object.entries(stats).map(([key, value]) => (
<div key={key} className="flex justify-between">
<span className="text-gray-600">{key}:</span>
<span className="font-mono">{typeof value === 'number' ? formatNumber(value) : String(value)}</span>
</div>
))}
</div>
</div>
))}
</div>
{/* Show step timings if present */}
{data.step_timings && (
<div className="mt-2">
<div className="text-sm font-semibold text-gray-700">Step Timings:</div>
<div className="space-y-1 bg-gray-50 p-2 rounded text-sm">
{Object.entries(data.step_timings).map(([step, duration]) => (
<div key={step} className="flex justify-between">
<span className="text-gray-600">{step}:</span>
<span className="font-mono">{String(duration)}s</span>
</div>
))}
</div>
</div>
)}
</div>
);
}
// Default simple format
return formatJsonDataSimple(data);
};
const formatJsonDataSimple = (data: Record<string, any>) => {
// Find the longest key length
const maxKeyLength = Object.keys(data).reduce(
(max, key) => Math.max(max, key.length),
@@ -384,13 +487,13 @@ export function DataManagement() {
style={{ width: `${maxKeyLength + 2}ch` }}
>
{key}:
</span>
</span>
<span className="break-all">
{typeof value === "object"
? JSON.stringify(value)
: value?.toString()}
</span>
</div>
</span>
</div>
))}
</div>
);
@@ -1133,12 +1236,33 @@ export function DataManagement() {
: "N/A"}
</span>
</div>
<div className="flex justify-between text-sm">
<span className="text-gray-600">Records:</span>
<span>
{record.records_added} added,{" "}
{record.records_updated} updated
</span>
<div className="grid grid-cols-2 gap-2 text-sm">
<div className="flex justify-between">
<span className="text-gray-600">Added:</span>
<span className="text-green-600 font-medium">{formatNumber(record.records_added)}</span>
</div>
<div className="flex justify-between">
<span className="text-gray-600">Updated:</span>
<span className="text-blue-600 font-medium">{formatNumber(record.records_updated)}</span>
</div>
{record.records_deleted !== undefined && (
<div className="flex justify-between">
<span className="text-gray-600">Deleted:</span>
<span className="text-red-600 font-medium">{formatNumber(record.records_deleted)}</span>
</div>
)}
{record.records_skipped !== undefined && (
<div className="flex justify-between">
<span className="text-gray-600">Skipped:</span>
<span className="text-yellow-600 font-medium">{formatNumber(record.records_skipped)}</span>
</div>
)}
{record.total_processed !== undefined && (
<div className="flex justify-between col-span-2">
<span className="text-gray-600">Total Processed:</span>
<span className="font-medium">{formatNumber(record.total_processed)}</span>
</div>
)}
</div>
{record.error_message && (
<div className="text-sm text-red-600 mt-2">