8.2 KiB
Pilot Dashboard Backend Summary
Superseded — This document was the initial design analysis and planning doc. The definitive API specification (including frontend integration guide) is now in: PILOT_DASHBOARD_API.md
The content below is retained for historical context (original requirements analysis, open decisions log, and delivery plan).
Document Info
- Scope: Backend support for Pilot Analytics Dashboard (Phase 1)
- Source inputs: Product Owner brief v1.5 and Requirements Analysis v1.5
- Validation status: aligned with current server codebase (models, constants, routes, middleware)
- Date: 2026-04-29
1. Objective
Build backend APIs and aggregation logic for a pilot-only analytics dashboard, using existing AgMission data (Job, Application, Application_Detail), with strict role/data isolation and production-safe query patterns.
2. Current Backend Baseline (Verified)
2.1 What already exists
- Pilot CRUD/search routes exist at /api/pilots via routes/pilot.js and controllers/pilot.js.
- Global route registration follows function-based mounting in routes/index.js.
- Auth middleware checkUser is applied globally before route mounting in server.js.
- Standard centralized error handling is already in place.
2.2 What does not exist yet
- No dashboard analytics controller/routes for pilots.
- No endpoints currently serving KPI/summary/trend/active-jobs/performance payloads.
- No implemented status transition endpoint for Mark as Completed.
2.3 Key model and constant facts
- Job status constants exist in helpers/job_constants.js:
- NEW 0, READY 1, DOWNLOADED 2, SPRAYED 3, COMPLETED 4, INVOICED 5, ARCHIVED 9.
- Job pilot assignment is by Job.operator (optional ObjectId).
- Job ownership is by Job.byPuid (Applicator account).
- Aircraft display source is Job.vehicle.
- Job_Assign is assignment workflow data and should not be used as pilot-job source of truth for dashboard metrics.
- Application links to job by numeric jobId.
- Application aggregates needed for dashboard already exist: totalSprayed, totalFlightTime, totalSprLength, totalSprayMat, avgSpraySpeed.
- Application_Detail contains xTrack, sprayHeight, radarAlt, gpsAlt and has primary index on fileId.
3. Confirmed Design Direction So Far
3.1 Pilot scoping model
The only reliable pilot scope for dashboard metrics is:
- Resolve jobIds from Job where operator = current pilot user id.
- Aggregate Application records where jobId is in that list.
- For quality gauges, resolve recent app files and aggregate Application_Detail by fileId.
This avoids wrong assumptions around uploader identity and keeps logic aligned with how pilot assignment is represented.
3.2 Dashboard modules (backend perspective)
- KPI cards: assigned jobs/ha + sprayed today + flight hours today.
- Daily summary: today vs yesterday deltas for hectares, hours, ha/hr, speed, volume.
- Operations today: distance and spray volume totals.
- Active jobs panel: per-job progress and actual applied volume with status mapping.
- Trend: daily hours and hectares over date range (default current week).
- Performance indicators: average XT error and altitude, with threshold bands.
- Mark Job as Completed: manual SPRAYED to COMPLETED transition.
4. Proposed API Surface (Phase 1)
Suggested new route group:
- /api/dashboard/pilot
Suggested endpoints:
- GET /api/dashboard/pilot/kpi
- GET /api/dashboard/pilot/summary
- GET /api/dashboard/pilot/trend
- GET /api/dashboard/pilot/active-jobs
- GET /api/dashboard/pilot/performance
Job completion action:
- PATCH /api/jobs/:jobId/complete
Implementation notes:
- Keep endpoint naming camelCase where needed in path segments to match existing project conventions.
- Reuse existing auth middleware and error classes for consistency.
5. Query and Aggregation Approach
5.1 KPI and summary
- Base filter: Job.find({ operator: pilotId, markedDelete: { $ne: true } }).
- Read assigned hectares from Job.ttSprArea.
- Aggregate Applications by jobId with time-window filtering for today/yesterday.
- Convert units in backend responses:
- hours = seconds / 3600
- distance = meters / 1000
- speed = m/s to km/h when needed
5.2 Active jobs
- Start from pilot-scoped jobs.
- Aggregate per job from Application:
- haSprayed = sum totalSprayed
- volumeApplied = sum totalSprayMat
- Compute progressPct = min(100, max(0, haSprayed / haTotal * 100)).
- Status display mapping:
- NEW (0): no progress bar
- READY/DOWNLOADED/SPRAYED: IN PROGRESS behavior
- COMPLETED (4): full bar
5.3 Trend
- Accept startDate/endDate (max 90 days recommended).
- Default to current calendar week (Mon-Sun) in user timezone policy.
- Group by day and fill missing dates with zero values.
5.4 Performance
- Use recent application files only (for bounded cost).
- Fetch recent pilot-scoped Application records, then map to related fileIds.
- Query Application_Detail with fileId IN [...].
- Compute:
- avgXtErrorMeters = avg(abs(xTrack))
- altitude with source priority sprayHeight then radarAlt
- Return no-data state when sample is empty or sensor fields unavailable.
6. Authorization and Data Isolation
6.1 Pilot dashboard endpoints
- Must be pilot-only.
- Always derive pilotId from authenticated user context, never trust client-provided user ids.
- Never expose other pilots or global Applicator data.
6.2 Mark as Completed endpoint
- Allowed transition: SPRAYED (3) to COMPLETED (4) only.
- Recommended permission for Phase 1: Applicator owner only (Job.byPuid match).
- Return 409 for invalid state transition.
- Return 403 when caller is not authorized.
7. Performance and Scalability Considerations
- Application_Detail is large-scale; avoid broad scans.
- Always drive quality queries by fileId-scoped subsets.
- Keep performance endpoint sample bounded (for example, last 10 files as proposed).
- Ensure lean reads for read-only queries where practical.
- Add/validate indexes only where query plans prove necessary after measurement.
8. Key Product Decisions Still Open (Affect Backend)
- Active Jobs cutoff status set (exact statuses to include).
- Assigned Jobs KPI business meaning (all-time vs open vs season).
- Altitude fallback policy when sprayHeight/radarAlt is absent.
- Whether pilot can trigger completion action or Applicator-only.
- Final timezone policy for Today/Yesterday windows (requirements currently point to browser timezone).
9. Recommended Delivery Plan
Phase A - Foundation
- Add dashboard route/controller/service skeleton.
- Add shared pilot scope resolver (pilot to jobIds).
- Add consistent response DTO contracts.
Phase B - Core endpoints
- Implement kpi, summary, trend, active-jobs.
- Add input validation for date range/timezone params.
- Add empty-state and zero-safe calculations.
Phase C - Performance indicators
- Implement performance endpoint with bounded recent-file strategy.
- Add explicit source label and no-data states.
Phase D - Job completion workflow
- Implement PATCH complete endpoint with strict state and auth checks.
- Add/update JSDoc for API docs.
Phase E - Verification
- Create tests scripts in tests/ for each endpoint and transition scenarios.
- Validate role isolation, response shapes, and edge cases (no jobs, no apps, missing altitude).
- Run scripts and record execution output.
10. Risks and Mitigations
-
Risk: Missing Job.operator on some jobs leads to undercount.
- Mitigation: surface this as known data-quality dependency in API/docs.
-
Risk: Inconsistent device coverage for altitude metrics.
- Mitigation: deterministic source priority + explicit no-data response.
-
Risk: Heavy Application_Detail scans.
- Mitigation: strict fileId-scoped querying and bounded sample windows.
-
Risk: Frontend status mismatch for COMPLETED/INVOICED labels.
- Mitigation: coordinate backend constants and frontend enum alignment before rollout.
11. Definition of Done for Backend
- Pilot dashboard endpoints implemented and documented.
- Mark Complete transition endpoint implemented with auth and state guards.
- APIs return stable contracts for all normal and empty-data scenarios.
- Endpoint behavior validated via executed test scripts.
- Relevant docs updated in docs/ and JSDoc included for apidoc generation.