asdfasf
This commit is contained in:
@@ -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),
|
||||
|
||||
@@ -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'
|
||||
}));
|
||||
|
||||
Reference in New Issue
Block a user