From c9729130fe2c52e765c0ab1b7ef2b90f5de27370 Mon Sep 17 00:00:00 2001 From: Jake Kasper Date: Thu, 4 Sep 2025 09:01:54 -0500 Subject: [PATCH] asdfasf --- backend/src/routes/applications.js | 63 ++++++++++++++++------- frontend/src/pages/Dashboard/Dashboard.js | 4 +- 2 files changed, 45 insertions(+), 22 deletions(-) diff --git a/backend/src/routes/applications.js b/backend/src/routes/applications.js index f67edd5..48dbbf7 100644 --- a/backend/src/routes/applications.js +++ b/backend/src/routes/applications.js @@ -1174,36 +1174,59 @@ router.get('/stats', async (req, res, next) => { try { const { year = new Date().getFullYear() } = req.query; - const statsQuery = ` + // Compute plan stats and log stats without FULL JOIN to satisfy Postgres + const combinedStatsQuery = ` + WITH log_stats AS ( + SELECT + COUNT(*)::int AS total_applications, + COALESCE(SUM(area_covered), 0)::float AS total_area_treated, + COALESCE(AVG(average_speed), 0)::float AS avg_application_speed + FROM application_logs + WHERE user_id = $1 + AND EXTRACT(YEAR FROM application_date) = $2 + ), + plan_stats AS ( + SELECT + COUNT(*)::int AS total_plans, + COUNT(*) FILTER (WHERE status = 'completed')::int AS completed_plans, + COUNT(*) FILTER (WHERE status = 'planned')::int AS planned_applications + FROM application_plans + WHERE user_id = $1 + AND EXTRACT(YEAR FROM planned_date) = $2 + ) SELECT - COUNT(DISTINCT al.id) as total_applications, - COUNT(DISTINCT ap.id) as total_plans, - COUNT(DISTINCT CASE WHEN ap.status = 'completed' THEN ap.id END) as completed_plans, - COUNT(DISTINCT CASE WHEN ap.status = 'planned' THEN ap.id END) as planned_applications, - COALESCE(SUM(al.area_covered), 0) as total_area_treated, - COALESCE(AVG(al.average_speed), 0) as avg_application_speed - FROM application_logs al - FULL OUTER JOIN application_plans ap ON al.plan_id = ap.id OR ap.user_id = $1 - WHERE EXTRACT(YEAR FROM COALESCE(al.application_date, ap.planned_date)) = $2 - AND (al.user_id = $1 OR ap.user_id = $1) + ls.total_applications, + ps.total_plans, + ps.completed_plans, + ps.planned_applications, + ls.total_area_treated, + ls.avg_application_speed + FROM log_stats ls + CROSS JOIN plan_stats ps; `; - const statsResult = await pool.query(statsQuery, [req.user.id, year]); - const stats = statsResult.rows[0]; + const statsResult = await pool.query(combinedStatsQuery, [req.user.id, year]); + const stats = statsResult.rows[0] || { + total_applications: 0, + total_plans: 0, + completed_plans: 0, + planned_applications: 0, + total_area_treated: 0, + avg_application_speed: 0, + }; - // Get monthly breakdown + // Monthly breakdown from logs const monthlyQuery = ` SELECT - EXTRACT(MONTH FROM al.application_date) as month, - COUNT(*) as applications, - COALESCE(SUM(al.area_covered), 0) as area_covered + EXTRACT(MONTH FROM al.application_date) AS month, + COUNT(*) AS applications, + COALESCE(SUM(al.area_covered), 0) AS area_covered FROM application_logs al WHERE al.user_id = $1 AND EXTRACT(YEAR FROM al.application_date) = $2 GROUP BY EXTRACT(MONTH FROM al.application_date) ORDER BY month `; - const monthlyResult = await pool.query(monthlyQuery, [req.user.id, year]); res.json({ @@ -1216,8 +1239,8 @@ router.get('/stats', async (req, res, next) => { plannedApplications: parseInt(stats.planned_applications) || 0, totalAreaTreated: parseFloat(stats.total_area_treated) || 0, avgApplicationSpeed: parseFloat(stats.avg_application_speed) || 0, - completionRate: stats.total_plans > 0 ? - Math.round((stats.completed_plans / stats.total_plans) * 100) : 0 + completionRate: (parseInt(stats.total_plans) || 0) > 0 ? + Math.round((parseInt(stats.completed_plans) / parseInt(stats.total_plans)) * 100) : 0 }, monthlyBreakdown: monthlyResult.rows.map(row => ({ month: parseInt(row.month), diff --git a/frontend/src/pages/Dashboard/Dashboard.js b/frontend/src/pages/Dashboard/Dashboard.js index d47ee05..7e333b3 100644 --- a/frontend/src/pages/Dashboard/Dashboard.js +++ b/frontend/src/pages/Dashboard/Dashboard.js @@ -140,8 +140,8 @@ const Dashboard = () => { const appLogs = (appLogsRes.data?.data?.logs || []).map(l => ({ id: `app-${l.id}`, type: 'application', - title: `${l.productNames?.length ? 'Applied ' + l.productNames.join(', ') : 'Application'} on ${l.section_names || 'section'}`, - property: l.property_name, + title: `Application on ${l.sectionName || 'section'}`, + property: l.propertyName, date: l.applicationDate || l.createdAt, status: 'completed' }));