Skip to content

Aditya-feat: Add New Bar Chart Card to the Lessons Learned Section on the Total Construction Summary Page #2092

Closed
Aditya-gam wants to merge 3 commits intodevelopmentfrom
Aditya-feat/Add-New-Bar–Chart-Card-to–the-Lessons-Learned-Section-on-the-Total–Construction-Summary-Page

Hidden character warning

The head ref may contain hidden characters: "Aditya-feat/Add-New-Bar\u2013Chart-Card-to\u2013the-Lessons-Learned-Section-on-the-Total\u2013Construction-Summary-Page"
Closed

Aditya-feat: Add New Bar Chart Card to the Lessons Learned Section on the Total Construction Summary Page #2092
Aditya-gam wants to merge 3 commits intodevelopmentfrom
Aditya-feat/Add-New-Bar–Chart-Card-to–the-Lessons-Learned-Section-on-the-Total–Construction-Summary-Page

Conversation

@Aditya-gam
Copy link
Contributor

@Aditya-gam Aditya-gam commented Mar 7, 2026

Description

This PR hardens and refactors the Lessons Learned bar-chart backend (GET /api/bm/lessons-learnt) introduced in PR 1302. It adds input validation, structured error logging, extracted helpers for maintainability, and full unit test coverage for getLessonsLearnt. No new endpoints or routes are added; the existing endpoint is made production-ready for the Lessons Learned section of the Total Construction Summary page.
IssueDescription

Implements Add New Bar Chart Card to the Lessons Learned Section on the Total Construction Summary Page.

Related PRs (if any):

Main changes explained:

Created/Updated Files:

  • src/controllers/bmdashboard/bmNewLessonController.js
    • Validation (getLessonsLearnt): Before any aggregation, validate projectId (must be ALL or a valid MongoDB ObjectId), startDate, and endDate (must be Date.parse()-able). Return 400 with { error: 'Invalid projectId' }, { error: 'Invalid startDate' }, or { error: 'Invalid endDate' } respectively when invalid; no DB calls on invalid input.
    • Helpers (module-level): Added buildProjectIdFilter(projectId) (returns {} for absent/ALL, else { relatedProject: ObjectId }), calculateChangePercentage(thisMonth, lastMonth) (returns '+100%', '0%', or signed string like '+50.0%'), and constants END_HOUR, END_MINUTE, END_SECOND for month-boundary date construction.
    • getLessonsLearnt refactor: Uses the new helpers to build filters and compute change percentage; simplified aggregation pipeline (single $group stage shape) and Object.fromEntries for thisMonth/lastMonth maps. “This month” / “last month” are derived from endDate when provided; otherwise, they default to the current server date.
    • Logging: All catch blocks in this controller now use logger.logException(error, '<handlerName>', { context }) instead of console.error, including getLessonsLearnt (context: { query: req.query }).
  • src/controllers/bmdashboard/__tests__/bmNewLessonController.test.js
    • getLessonsLearnt suite: New describe('getLessonsLearnt') with mocked BuildingNewLesson.aggregate (three calls per request: lessons-in-range, this-month, last-month).
    • Validation tests: Invalid projectId → 400 and aggregate not called; projectId=ALL → 200 and no relatedProject in first match; invalid startDate / endDate → 400 with correct error key.
    • Happy path / filters: No params → 200 and correct data shape with changePercentage; empty aggregates → 200 and data: []; valid projectIdrelatedProject in match; date range (both, start only, end only, neither) → correct $match.date shape.
    • changePercentage tests: +100% (lastMonth 0, thisMonth > 0), 0% (both 0), positive/negative/same (e.g. +50.0%, -50.0%, +0.0%), and multi-project independence.
    • Error handling: Aggregate throws → 500 and logger.logException called with expected context.

Key Implementation Details:

  • projectId: Only the literal string ALL (case-sensitive) is treated as “all projects.” Any other non-ObjectId value (e.g. all, not-a-valid-objectid) returns 400. Valid 24-char hex ObjectIds are passed through to the filter.
  • Dates: Date.parse() is used for validation; invalid strings (e.g. not-a-date, 2024-13-45) yield NaN and trigger 400. No check that startDate <= endDate; a reversed range simply matches no documents and returns data: [].
  • Response shape unchanged: Success still returns { data: [ { project, projectId, lessonsCount, changePercentage } ] }. lessonsCount is for the optional date range (or all time); changePercentage is month-over-month (this calendar month vs last), with “this month” based on endDate when provided.

How to test:

  1. Check out the current branch:
    Aditya-feat/Add-New-Bar–Chart-Card-to–the-Lessons-Learned-Section-on-the-Total–Construction-Summary-Page.
  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 run dev)
  4. Obtain a JWT by Owner/Admin login:
    • POST http://localhost:4500/api/login with { "email": "...", "password": "..." }
      Use the returned token in the Authorization header for the following requests.
  5. Test GET /api/bm/lessons-learnt:
    • Basic – no params:
      GET http://localhost:4500/api/bm/lessons-learnt
      Expect 200 and { data: [ { project, projectId, lessonsCount, changePercentage }, ... ] }.
    • Basic – projectId=ALL:
      GET http://localhost:4500/api/bm/lessons-learnt?projectId=ALL
      Expect 200, same shape as above.
    • Edge – invalid projectId:
      GET http://localhost:4500/api/bm/lessons-learnt?projectId=not-a-valid-objectid
      Expect 400 and { "error": "Invalid projectId" }.
    • Edge – invalid startDate:
      GET http://localhost:4500/api/bm/lessons-learnt?startDate=not-a-date
      Expect 400 and { "error": "Invalid startDate" }.
    • Edge – invalid endDate:
      GET http://localhost:4500/api/bm/lessons-learnt?endDate=2024-13-45
      Expect 400 and { "error": "Invalid endDate" }.
    • Edge – projectId=all (lowercase):
      GET http://localhost:4500/api/bm/lessons-learnt?projectId=all
      Expect 400 and { "error": "Invalid projectId" } (case-sensitive).
  6. Run unit tests:
    npm test -- --testPathPattern=bmNewLessonController
  7. Verify:
    • Valid projectId (existing ObjectId from your DB) returns 200 and at most one project in data (or [] if that project has no lessons).

Screenshots or videos of changes:

  • Coverage Report:
CoverageReport
  • Test Video:
TestVideo.mov

Note:

  • projectId validated with mongoose.Types.ObjectId.isValid when not ALL; startDate and endDate validated with Number.isNaN(Date.parse(...)). Invalid values return 400 before any DB access.
  • All errors in this controller now go through logger.logException for consistent tracking and debugging.

Validate projectId (ObjectId when not ALL), startDate and endDate
before querying; return 400 for invalid values. Replace console.error
with logger.logException for structured error logging.

Made-with: Cursor
Extract buildProjectIdFilter and calculateChangePercentage; add
end-of-day constants for month boundaries. Simplify getLessonsLearnt
aggregation and map building. Replace console.error with
logger.logException in all handler catch blocks.

Made-with: Cursor
Cover validation (invalid projectId, startDate, endDate), filter
construction (projectId ALL/valid, date range), changePercentage
cases (+100%, 0%, +/-50%, +0.0%, multi-project), and 500 + logger
on aggregate error.

Made-with: Cursor
@Aditya-gam Aditya-gam changed the title Aditya-feat: Add New Bar Chart Card to the Lessons Learned Section on the Total Construction Summary Page Aditya-feat: Add New Bar Chart Card to the Lessons Learned Section on the Total Construction Summary Page Mar 7, 2026
@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 7, 2026

@Aditya-gam
Copy link
Contributor Author

Closing in favor of #2093. The head branch was renamed to remove hidden en-dash characters (Unicode U+2013) that caused GitHub to show: "The head ref may contain hidden characters." New branch name: Aditya-feat/Add-New-Bar-Chart-Card-to-the-Lessons-Learned-Section-on-the-Total-Construction-Summary-Page (ASCII hyphens only). Please review and merge #2093 instead.

@Aditya-gam Aditya-gam closed this Mar 8, 2026
@Aditya-gam Aditya-gam deleted the Aditya-feat/Add-New-Bar–Chart-Card-to–the-Lessons-Learned-Section-on-the-Total–Construction-Summary-Page branch March 8, 2026 00:01
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.

1 participant