Update backend/frontend
This commit is contained in:
@@ -85,9 +85,7 @@ export function DataManagement() {
|
||||
const [] = useState<ImportProgress | null>(null);
|
||||
const [eventSource, setEventSource] = useState<EventSource | null>(null);
|
||||
const [importHistory, setImportHistory] = useState<ImportHistoryRecord[]>([]);
|
||||
const [calculateHistory, setCalculateHistory] = useState<
|
||||
CalculateHistoryRecord[]
|
||||
>([]);
|
||||
const [calculateHistory, setCalculateHistory] = useState<CalculateHistoryRecord[]>([]);
|
||||
const [moduleStatus, setModuleStatus] = useState<ModuleStatus[]>([]);
|
||||
const [tableStatus, setTableStatus] = useState<TableStatus[]>([]);
|
||||
const [scriptOutput, setScriptOutput] = useState<string[]>([]);
|
||||
@@ -368,6 +366,10 @@ export function DataManagement() {
|
||||
fetch(`${config.apiUrl}/csv/status/tables`),
|
||||
]);
|
||||
|
||||
if (!importRes.ok || !calcRes.ok || !moduleRes.ok || !tableRes.ok) {
|
||||
throw new Error('One or more requests failed');
|
||||
}
|
||||
|
||||
const [importData, calcData, moduleData, tableData] = await Promise.all([
|
||||
importRes.json(),
|
||||
calcRes.json(),
|
||||
@@ -375,52 +377,66 @@ export function DataManagement() {
|
||||
tableRes.json(),
|
||||
]);
|
||||
|
||||
setImportHistory(importData);
|
||||
setCalculateHistory(calcData);
|
||||
setModuleStatus(moduleData);
|
||||
setTableStatus(tableData);
|
||||
// Ensure we're setting arrays even if the response is empty or invalid
|
||||
setImportHistory(Array.isArray(importData) ? importData : []);
|
||||
setCalculateHistory(Array.isArray(calcData) ? calcData : []);
|
||||
setModuleStatus(Array.isArray(moduleData) ? moduleData : []);
|
||||
setTableStatus(Array.isArray(tableData) ? tableData : []);
|
||||
} catch (error) {
|
||||
console.error("Error fetching history:", error);
|
||||
// Set empty arrays as fallback
|
||||
setImportHistory([]);
|
||||
setCalculateHistory([]);
|
||||
setModuleStatus([]);
|
||||
setTableStatus([]);
|
||||
}
|
||||
};
|
||||
|
||||
const refreshTableStatus = async () => {
|
||||
try {
|
||||
const response = await fetch(`${config.apiUrl}/csv/status/tables`);
|
||||
if (!response.ok) throw new Error('Failed to fetch table status');
|
||||
const data = await response.json();
|
||||
setTableStatus(data);
|
||||
setTableStatus(Array.isArray(data) ? data : []);
|
||||
} catch (error) {
|
||||
toast.error("Failed to refresh table status");
|
||||
setTableStatus([]);
|
||||
}
|
||||
};
|
||||
|
||||
const refreshModuleStatus = async () => {
|
||||
try {
|
||||
const response = await fetch(`${config.apiUrl}/csv/status/modules`);
|
||||
if (!response.ok) throw new Error('Failed to fetch module status');
|
||||
const data = await response.json();
|
||||
setModuleStatus(data);
|
||||
setModuleStatus(Array.isArray(data) ? data : []);
|
||||
} catch (error) {
|
||||
toast.error("Failed to refresh module status");
|
||||
setModuleStatus([]);
|
||||
}
|
||||
};
|
||||
|
||||
const refreshImportHistory = async () => {
|
||||
try {
|
||||
const response = await fetch(`${config.apiUrl}/csv/history/import`);
|
||||
if (!response.ok) throw new Error('Failed to fetch import history');
|
||||
const data = await response.json();
|
||||
setImportHistory(data);
|
||||
setImportHistory(Array.isArray(data) ? data : []);
|
||||
} catch (error) {
|
||||
toast.error("Failed to refresh import history");
|
||||
setImportHistory([]);
|
||||
}
|
||||
};
|
||||
|
||||
const refreshCalculateHistory = async () => {
|
||||
try {
|
||||
const response = await fetch(`${config.apiUrl}/csv/history/calculate`);
|
||||
if (!response.ok) throw new Error('Failed to fetch calculate history');
|
||||
const data = await response.json();
|
||||
setCalculateHistory(data);
|
||||
setCalculateHistory(Array.isArray(data) ? data : []);
|
||||
} catch (error) {
|
||||
toast.error("Failed to refresh calculate history");
|
||||
setCalculateHistory([]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ export default function PurchaseOrders() {
|
||||
statuses: string[];
|
||||
}>({
|
||||
vendors: [],
|
||||
statuses: [],
|
||||
statuses: []
|
||||
});
|
||||
const [pagination, setPagination] = useState({
|
||||
total: 0,
|
||||
@@ -153,15 +153,57 @@ export default function PurchaseOrders() {
|
||||
fetch('/api/purchase-orders/cost-analysis')
|
||||
]);
|
||||
|
||||
const [
|
||||
purchaseOrdersData,
|
||||
vendorMetricsData,
|
||||
costAnalysisData
|
||||
] = await Promise.all([
|
||||
purchaseOrdersRes.json() as Promise<PurchaseOrdersResponse>,
|
||||
vendorMetricsRes.json(),
|
||||
costAnalysisRes.json()
|
||||
]);
|
||||
// Initialize default data
|
||||
let purchaseOrdersData: PurchaseOrdersResponse = {
|
||||
orders: [],
|
||||
summary: {
|
||||
order_count: 0,
|
||||
total_ordered: 0,
|
||||
total_received: 0,
|
||||
fulfillment_rate: 0,
|
||||
total_value: 0,
|
||||
avg_cost: 0
|
||||
},
|
||||
pagination: {
|
||||
total: 0,
|
||||
pages: 0,
|
||||
page: 1,
|
||||
limit: 100
|
||||
},
|
||||
filters: {
|
||||
vendors: [],
|
||||
statuses: []
|
||||
}
|
||||
};
|
||||
|
||||
let vendorMetricsData: VendorMetrics[] = [];
|
||||
let costAnalysisData: CostAnalysis = {
|
||||
unique_products: 0,
|
||||
avg_cost: 0,
|
||||
min_cost: 0,
|
||||
max_cost: 0,
|
||||
cost_variance: 0,
|
||||
total_spend_by_category: []
|
||||
};
|
||||
|
||||
// Only try to parse responses if they were successful
|
||||
if (purchaseOrdersRes.ok) {
|
||||
purchaseOrdersData = await purchaseOrdersRes.json();
|
||||
} else {
|
||||
console.error('Failed to fetch purchase orders:', await purchaseOrdersRes.text());
|
||||
}
|
||||
|
||||
if (vendorMetricsRes.ok) {
|
||||
vendorMetricsData = await vendorMetricsRes.json();
|
||||
} else {
|
||||
console.error('Failed to fetch vendor metrics:', await vendorMetricsRes.text());
|
||||
}
|
||||
|
||||
if (costAnalysisRes.ok) {
|
||||
costAnalysisData = await costAnalysisRes.json();
|
||||
} else {
|
||||
console.error('Failed to fetch cost analysis:', await costAnalysisRes.text());
|
||||
}
|
||||
|
||||
setPurchaseOrders(purchaseOrdersData.orders);
|
||||
setPagination(purchaseOrdersData.pagination);
|
||||
@@ -171,6 +213,27 @@ export default function PurchaseOrders() {
|
||||
setCostAnalysis(costAnalysisData);
|
||||
} catch (error) {
|
||||
console.error('Error fetching data:', error);
|
||||
// Set default values in case of error
|
||||
setPurchaseOrders([]);
|
||||
setPagination({ total: 0, pages: 0, page: 1, limit: 100 });
|
||||
setFilterOptions({ vendors: [], statuses: [] });
|
||||
setSummary({
|
||||
order_count: 0,
|
||||
total_ordered: 0,
|
||||
total_received: 0,
|
||||
fulfillment_rate: 0,
|
||||
total_value: 0,
|
||||
avg_cost: 0
|
||||
});
|
||||
setVendorMetrics([]);
|
||||
setCostAnalysis({
|
||||
unique_products: 0,
|
||||
avg_cost: 0,
|
||||
min_cost: 0,
|
||||
max_cost: 0,
|
||||
cost_variance: 0,
|
||||
total_spend_by_category: []
|
||||
});
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
@@ -310,7 +373,7 @@ export default function PurchaseOrders() {
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="all">All Vendors</SelectItem>
|
||||
{filterOptions.vendors.map(vendor => (
|
||||
{filterOptions?.vendors?.map(vendor => (
|
||||
<SelectItem key={vendor} value={vendor}>
|
||||
{vendor}
|
||||
</SelectItem>
|
||||
|
||||
@@ -3,10 +3,10 @@ export interface Product {
|
||||
title: string;
|
||||
SKU: string;
|
||||
stock_quantity: number;
|
||||
price: string; // DECIMAL(15,3)
|
||||
regular_price: string; // DECIMAL(15,3)
|
||||
cost_price: string; // DECIMAL(15,3)
|
||||
landing_cost_price: string | null; // DECIMAL(15,3)
|
||||
price: string; // numeric(15,3)
|
||||
regular_price: string; // numeric(15,3)
|
||||
cost_price: string; // numeric(15,3)
|
||||
landing_cost_price: string | null; // numeric(15,3)
|
||||
barcode: string;
|
||||
vendor: string;
|
||||
vendor_reference: string;
|
||||
@@ -24,32 +24,32 @@ export interface Product {
|
||||
updated_at: string;
|
||||
|
||||
// Metrics
|
||||
daily_sales_avg?: string; // DECIMAL(15,3)
|
||||
weekly_sales_avg?: string; // DECIMAL(15,3)
|
||||
monthly_sales_avg?: string; // DECIMAL(15,3)
|
||||
avg_quantity_per_order?: string; // DECIMAL(15,3)
|
||||
daily_sales_avg?: string; // numeric(15,3)
|
||||
weekly_sales_avg?: string; // numeric(15,3)
|
||||
monthly_sales_avg?: string; // numeric(15,3)
|
||||
avg_quantity_per_order?: string; // numeric(15,3)
|
||||
number_of_orders?: number;
|
||||
first_sale_date?: string;
|
||||
last_sale_date?: string;
|
||||
last_purchase_date?: string;
|
||||
days_of_inventory?: string; // DECIMAL(15,3)
|
||||
weeks_of_inventory?: string; // DECIMAL(15,3)
|
||||
reorder_point?: string; // DECIMAL(15,3)
|
||||
safety_stock?: string; // DECIMAL(15,3)
|
||||
avg_margin_percent?: string; // DECIMAL(15,3)
|
||||
total_revenue?: string; // DECIMAL(15,3)
|
||||
inventory_value?: string; // DECIMAL(15,3)
|
||||
cost_of_goods_sold?: string; // DECIMAL(15,3)
|
||||
gross_profit?: string; // DECIMAL(15,3)
|
||||
gmroi?: string; // DECIMAL(15,3)
|
||||
avg_lead_time_days?: string; // DECIMAL(15,3)
|
||||
days_of_inventory?: string; // numeric(15,3)
|
||||
weeks_of_inventory?: string; // numeric(15,3)
|
||||
reorder_point?: string; // numeric(15,3)
|
||||
safety_stock?: string; // numeric(15,3)
|
||||
avg_margin_percent?: string; // numeric(15,3)
|
||||
total_revenue?: string; // numeric(15,3)
|
||||
inventory_value?: string; // numeric(15,3)
|
||||
cost_of_goods_sold?: string; // numeric(15,3)
|
||||
gross_profit?: string; // numeric(15,3)
|
||||
gmroi?: string; // numeric(15,3)
|
||||
avg_lead_time_days?: string; // numeric(15,3)
|
||||
last_received_date?: string;
|
||||
abc_class?: string;
|
||||
stock_status?: string;
|
||||
turnover_rate?: string; // DECIMAL(15,3)
|
||||
current_lead_time?: string; // DECIMAL(15,3)
|
||||
target_lead_time?: string; // DECIMAL(15,3)
|
||||
turnover_rate?: string; // numeric(15,3)
|
||||
current_lead_time?: string; // numeric(15,3)
|
||||
target_lead_time?: string; // numeric(15,3)
|
||||
lead_time_status?: string;
|
||||
reorder_qty?: number;
|
||||
overstocked_amt?: string; // DECIMAL(15,3)
|
||||
overstocked_amt?: string; // numeric(15,3)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user