Skip to content

feat: Implement Persistence for User Problem Reports#306

Open
AhmedAlian7 wants to merge 5 commits intoOneBusAway:mainfrom
AhmedAlian7:feat/store-problem-reports
Open

feat: Implement Persistence for User Problem Reports#306
AhmedAlian7 wants to merge 5 commits intoOneBusAway:mainfrom
AhmedAlian7:feat/store-problem-reports

Conversation

@AhmedAlian7
Copy link
Contributor

@AhmedAlian7 AhmedAlian7 commented Feb 3, 2026

Description

closes #292

Previously, the report-problem-with-stop and report-problem-with-trip API endpoints only logged problem reports without persisting them to the database. This meant all user-submitted reports were lost on application restart, making it impossible to analyze patterns, respond to user feedback, or track transit issues over time.

This PR adds database persistence for problem reports while maintaining the existing logging behavior for real-time observability.

Changes

Database Schema (gtfsdb/schema.sql)

  • Added problem_reports_trip table with fields:
    • id (auto-increment primary key)
    • trip_id, service_date, vehicle_id, stop_id (trip context)
    • code (problem type)
    • user_comment, user_lat, user_lon, user_location_accuracy (user input)
    • user_on_vehicle, user_vehicle_number (trip-specific fields)
    • created_at, submitted_at (timestamps)
  • Added problem_reports_stop table with similar fields for stop-specific reports.
  • Added indexes on trip_id, stop_id, and created_at for efficient querying.

SQL Queries (gtfsdb/query.sql)

  • CreateProblemReportTrip / CreateProblemReportStop: Insert new reports.
  • GetProblemReportsByTrip / GetProblemReportsByStop: Retrieve reports by ID.
  • GetProblemReportsTripByDateRange / GetProblemReportsStopByDateRange: Filter by date.
  • GetProblemReportsTripByCode / GetProblemReportsStopByCode: Filter by problem type.
  • GetRecentProblemReportsTrip / GetRecentProblemReportsStop: Paginated recent reports.

Manual Go Implementation (gtfsdb/problem_reports.go)

  • Added Model structs: ProblemReportsTrip, ProblemReportsStop.
  • Added Parameter structs: CreateProblemReportTripParams, CreateProblemReportStopParams.
  • Implemented CRUD methods attached to the Queries struct.

Handler Updates

  • report_problem_with_trip_handler.go: Updated to parse all trip-specific fields and store reports.
  • report_problem_with_stop_handler.go: Updated to parse location fields and store reports.
  • Note: Both handlers include defensive nil checks to gracefully handle cases where database tables don't exist yet.

Shared Helpers (gtfsdb/helpers.go)
Consolidated duplicate helper functions into a shared location:

  • ToNullString(string) sql.NullString: Converts empty strings to NULL.
  • ParseNullFloat(string) sql.NullFloat64: Parses floats with NULL for invalid values.
  • ParseNullBool(string) sql.NullInt64: Parses booleans to 0/1 with NULL fallback.

Testing

  • report_problem_with_trip_handler_test.go
    • Added TestReportProblemWithTrip_MinimalParams: Verifies handler works with only required parameters.
    • Updated variable naming for consistency (tripId).
  • report_problem_with_stop_handler_test.go
    • Added TestReportProblemWithStop_MinimalParams: Verifies handler works with minimal parameters.
    • Added TestReportProblemWithStop_InvalidCoordinates: Verifies graceful handling of invalid lat/lon values.
    • Updated variable naming for consistency (stopId).
  • go build ./... passes
  • make lint passes

Follow-up Work

  • Add retrieval API endpoints for problem reports (Read layer).

Copy link
Member

@aaronbrethorst aaronbrethorst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahmed, great work: your implementation is well-structured and correctly scoped to write-only operations (no retrieval endpoints exposed). However, there are lint failures that must be fixed before merging.


Critical Issues

1. Lint Failures: Unchecked Error Return Values

Files: gtfsdb/problem_reports.go:167 and gtfsdb/problem_reports.go:212

The linter reports unchecked error return values for rows.Close():

gtfsdb/problem_reports.go:167:18: Error return value of `rows.Close` is not checked (errcheck)
gtfsdb/problem_reports.go:212:18: Error return value of `rows.Close` is not checked (errcheck)

Current code:

defer rows.Close()

Suggested fix: While the error from rows.Close() is rarely actionable, we should follow the project's lint requirements. The common pattern is:

defer func() {
    _ = rows.Close()
}()

This explicitly discards the error, satisfying the linter while acknowledging we're intentionally not handling it.


Important Issues

2. Formatting Issue: Trailing Whitespace

File: internal/restapi/report_problem_with_stop_handler.go:42

There's a trailing tab character on the blank line after the DB initialization check. Running go fmt ./... will fix this.


Fit and Finish

3. Positive: Correctly Scoped to Write-Only Operations

I want to call out that the PR correctly implements only the persistence layer without exposing retrieval endpoints via HTTP. While the database layer includes GetProblemReportsByTrip and GetProblemReportsByStop queries (which is fine for future internal use), no HTTP handlers expose these methods to external callers.

This is the correct approach. Retrieval endpoints would need careful consideration around authentication, authorization, rate limiting, and data privacy before being exposed publicly.

4. Good Test Coverage

The tests properly cover:

  • End-to-end happy path for both trip and stop reports
  • Missing ID validation (empty ID returns 400)
  • Minimal parameters (only required fields)
  • Invalid coordinates are handled gracefully

5. Clean Helper Functions

The exported helper functions in gtfsdb/helpers.go (ToNullString, ParseNullFloat, ParseNullBool) are well-implemented and follow existing patterns in the codebase.


Required Actions Before Merge

  1. Fix lint errors in gtfsdb/problem_reports.go (lines 167 and 212)
  2. Run go fmt ./... to fix formatting

Thank you for this contribution! The implementation is well-designed and follows the project patterns. Just need those lint fixes and we're good to go.

@AhmedAlian7
Copy link
Contributor Author

Thanks for the detailed review, Aron! I've addressed the linting failures and run go fmt to clean up whitespaces.
The updates are pushed and ready for a final look.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement Persistence for User Problem Reports

2 participants