Skip to content

Conversation

@Aditya-gam
Copy link
Contributor

@Aditya-gam Aditya-gam commented Dec 5, 2025


Description

Implements a complete backend API for the Paid Labor Cost grouped-bar graph feature. The controller was previously a stub returning an empty array. This PR provides a fully functional GET /api/labor-cost endpoint supporting date filtering, project filtering, task filtering, and proper data formatting with comprehensive validation and error handling.
IssueDescription


Related PRs (if any):


Main changes explained:

Created/Updated Files:

  1. src/controllers/bmdashboard/bmPaidLaborCostController.js
    Complete controller implementation with:

    • Helper functions: looksLikeJson(), parseArrayParam(), parseDateRangeParam(), isValidDateValue()
    • Parameter extraction & validation: Extracts and validates projects, tasks, date_range from query params
    • MongoDB query building: Supports partial date ranges, project/task filters using the $in operator
    • Database querying: Uses LaborCost.find() with .lean() and .sort({ date: 1 })
    • Response formatting: Maps DB fields (project_nameproject) and calculates totalCost
    • Error handling: Distinguishes database vs unexpected errors, logs with context
    • Edge cases: Handles null params, empty results, invalid dates (e.g., "2025-13-01"), UTC timezone handling
  2. src/routes/bmdashboard/bmPaidLaborCostRouter.js

    • Changed route method from POST to GET to align with frontend requirements.
  3. src/controllers/bmdashboard/__tests__/bmPaidLaborCostController.test.js
    119 unit tests covering:

    • Helper functions (59 tests): JSON detection, array parsing, date validation
    • Controller logic (60 tests): Parameter validation, query building, response formatting, error handling, edge cases
    • Coverage: 97% (above 90% target)
  4. src/__tests__/integration/bmPaidLaborCostRoutes.integration.test.js (+113 lines)
    Integration tests for route configuration, authentication (401 without auth), and GET method verification.

  5. package.json

    • Added @aws-sdk/client-s3 dependency for integration tests.

Key Implementation Details:

API Endpoint: GET /api/labor-cost.

Request Parameters (query string):

  • projects: Optional array (empty = all projects)
  • tasks: Optional array (empty = all tasks)
  • date_range: Optional object with start_date and/or end_date (null = all dates)

Response Structure:

{
	"totalCost": 15000,
	"data": [
		{ "project": "Project A", "task": "Task 1", "date": "2025-04-01T00:00:00.000Z", "cost": 5000 }
	]
}

Key Features:

  • Partial date ranges: Supports only start_date, only end_date, or both
  • UTC timezone handling: Uses UTC methods for consistent date filtering
  • Flexible parameter parsing: Accepts JSON strings, comma-separated values, or parsed arrays
  • Comprehensive validation: Date format (ISO 8601), date values (catches "2025-13-01"), date range logic, array formats
  • Error responses: 400 (invalid params), 422 (invalid dates), 500 (server errors)

How to test:

  1. Check into branch: Aditya-fix/implement-paid-labor-cost-controller.
  2. Reinstall dependencies and clean cache using rm -rf node_modules package-lock.json && npm cache clean --force.
  3. Run npm install to install dependencies, then start the backend locally (npm start or npm run dev)
  4. Test API Endpoint GET /api/labor-cost:

Basic functionality:

# Get all data
curl "http://localhost:3000/api/labor-cost"

# Filter by date range
curl "http://localhost:3000/api/labor-cost?date_range={\"start_date\":\"2025-04-01\",\"end_date\":\"2025-04-30\"}"

# Filter by projects and tasks
curl "http://localhost:3000/api/labor-cost?projects=[\"Project A\"]&tasks=[\"Task 1\"]"

Edge cases:

# Partial date range (only start_date)
curl "http://localhost:3000/api/labor-cost?date_range={\"start_date\":\"2025-04-01\",\"end_date\":null}"

# Empty results (future dates)
curl "http://localhost:3000/api/labor-cost?date_range={\"start_date\":\"2030-01-01\",\"end_date\":\"2030-12-31\"}"

# Invalid date format (should return 422)
curl "http://localhost:3000/api/labor-cost?date_range={\"start_date\":\"2025-13-01\",\"end_date\":\"2025-04-30\"}"
  1. Run test suite:
# Unit tests (119 tests, 97% coverage)
npm test -- src/controllers/bmdashboard/__tests__/bmPaidLaborCostController.test.js

# Integration tests
npm test -- src/__tests__/integration/bmPaidLaborCostRoutes.integration.test.js

Screenshots or videos of changes:

TestVideo.mov

Note:

  • Database Changes: Added some mock data to the dev database, so testing this endpoint is easier.
  • Performance: Uses .lean() for better performance. Consider adding indexes on date, project_name, and task if the dataset is very large
  • Validation: Comprehensive validation for dates (ISO 8601, invalid months/days), arrays (format detection), and date ranges
  • Error Handling: User-friendly messages with error codes. Internal details not exposed. Errors logged with full context
  • Testing: 97% coverage (119 unit tests + integration tests). All edge cases and error conditions covered

…st controller

- Import LaborCost model for database queries
- Import logger utility for error tracking
- Wrap controller function in try-catch block for error handling
- Set up foundation for complete controller implementation
…troller

- Extract projects, tasks, and date_range from query parameters
- Add helper functions to parse arrays and date_range objects from query strings
- Validate projects and tasks are arrays with string values
- Validate date_range is object or null
- Validate ISO 8601 date format for start_date and end_date
- Validate date range logic (start_date <= end_date)
- Return appropriate error responses (400, 422) for validation failures
- Build date filter with support for null date_range, partial ranges (only start or end), and full ranges
- Use MongoDB operators $gte and $lte for date filtering with inclusive boundaries
- Build project filter using $in operator when projects array has values
- Build task filter using $in operator when tasks array has values
- Combine all filters into single query object with AND logic
- Convert date strings to Date objects and set appropriate time boundaries for inclusive filtering
- Execute MongoDB query using LaborCost.find() with combined filters
- Sort results chronologically by date using .sort({ date: 1 })
- Use .lean() for better query performance
- Return individual records without aggregation (frontend handles grouping)
- Database errors handled gracefully by existing try-catch block
- Map database fields to frontend structure (project_name → project)
- Convert date objects to ISO 8601 string format
- Ensure cost values are numbers (not strings)
- Calculate totalCost as sum of all cost values
- Return response with totalCost and data array structure
- Handle empty results case (totalCost = 0)
- Explicitly construct response object with totalCost and data fields
- Return 200 OK status code on successful response
- Handle empty results case (totalCost: 0, data: [])
- Ensure response is valid JSON using res.json() method
- Add clear comments documenting response structure
- Distinguish between database errors and unexpected errors
- Add error context logging with request parameters (query, method, URL)
- Return user-friendly error messages without exposing internal details
- Handle MongoDB/database connection errors with specific error code
- Maintain existing validation error handling (400, 422 status codes)
- Log errors with sufficient detail for debugging using logger utility
- Explicitly handle null/undefined request query parameters
- Enhance date validation to catch invalid months/days (e.g., "2025-13-01")
- Document empty results handling (valid case, not error)
- Document partial date range support (open-ended ranges)
- Add comments clarifying edge case behaviors
- Ensure dates far in past/future return empty results gracefully
- Validate date components match parsed values to prevent silent adjustments
- Update route to use GET method as per frontend requirements
- Controller already reads from req.query which is appropriate for GET requests
…t controller

- Fix date validation to use UTC methods for accurate date-only string comparison
- Add validation to detect JSON parsing failures for date_range parameter
- Add validation to ensure date values are strings (not numbers or other types)
- Improve error messages with examples for invalid date_range JSON format
- Add comments clarifying UTC method usage for date-only string parsing
- Add validation to detect JSON objects provided instead of arrays
- Add validation to detect mixed formats (JSON objects/arrays with plain strings)
- Add helper function to detect JSON-like strings in comma-separated values
- Return descriptive error messages for invalid array parameter formats
- Improve validation for both projects and tasks array parameters
…troller

- Change setHours to setUTCHours for start date boundary
- Change setHours to setUTCHours for end date boundary
- Add comments clarifying UTC method usage for consistent timezone handling
- Ensure date filters work correctly across different timezones
- Export helper functions via testExports for direct unit testing
- Add comprehensive tests for looksLikeJson() (12 test cases)
- Add comprehensive tests for parseArrayParam() (15 test cases)
- Add comprehensive tests for parseDateRangeParam() (10 test cases)
- Add comprehensive tests for isValidDateValue() (22 test cases)
- All 59 test cases passing, covering edge cases and error conditions
- Add comprehensive tests for parameter validation (projects, tasks, date_range)
- Add tests for MongoDB query building with various filter combinations
- Add tests for response formatting and data transformation
- Add tests for error handling (database errors and unexpected errors)
- Achieve 97% code coverage with 105 test cases
- All tests passing, covering edge cases and error conditions
- Add authorization tests for GET /api/labor-cost (401 without auth)
- Add route functionality tests (POST method, route existence)
- Follow same pattern as existing integration tests
- Tests verify route configuration and authentication requirements
- Install @aws-sdk/client-s3 dependency required for integration tests
- Add boundary condition tests (empty strings, long names, Unicode, special chars)
- Add tests for large arrays (100+ projects)
- Add tests for dates far in past/future
- Add request object edge case tests (missing/null/empty query)
- All 115 tests passing with 97% coverage maintained
- Add comprehensive JSDoc comments and section headers to test files
- Consolidate request object edge case tests into parameterized test
- Maintain 97% coverage (well above 90% target)
- All 119 tests passing
- Improve test file readability and maintainability
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.

2 participants