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
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"
Conversation
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
|
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: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



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 forgetLessonsLearnt. 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.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.jsprojectId(must beALLor a valid MongoDB ObjectId),startDate, andendDate(must beDate.parse()-able). Return400with{ error: 'Invalid projectId' },{ error: 'Invalid startDate' }, or{ error: 'Invalid endDate' }respectively when invalid; no DB calls on invalid input.buildProjectIdFilter(projectId)(returns{}for absent/ALL, else{ relatedProject: ObjectId }),calculateChangePercentage(thisMonth, lastMonth)(returns'+100%','0%', or signed string like'+50.0%'), and constantsEND_HOUR,END_MINUTE,END_SECONDfor month-boundary date construction.$groupstage shape) andObject.fromEntriesfor thisMonth/lastMonth maps. “This month” / “last month” are derived fromendDatewhen provided; otherwise, they default to the current server date.logger.logException(error, '<handlerName>', { context })instead ofconsole.error, includinggetLessonsLearnt(context:{ query: req.query }).src/controllers/bmdashboard/__tests__/bmNewLessonController.test.jsdescribe('getLessonsLearnt')with mockedBuildingNewLesson.aggregate(three calls per request: lessons-in-range, this-month, last-month).projectId→ 400 andaggregatenot called;projectId=ALL→ 200 and norelatedProjectin first match; invalidstartDate/endDate→ 400 with correct error key.datashape withchangePercentage; empty aggregates → 200 anddata: []; validprojectId→relatedProjectin match; date range (both, start only, end only, neither) → correct$match.dateshape.logger.logExceptioncalled with expected context.Key Implementation Details:
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.Date.parse()is used for validation; invalid strings (e.g.not-a-date,2024-13-45) yield NaN and trigger 400. No check thatstartDate <= endDate; a reversed range simply matches no documents and returnsdata: [].{ data: [ { project, projectId, lessonsCount, changePercentage } ] }.lessonsCountis for the optional date range (or all time);changePercentageis month-over-month (this calendar month vs last), with “this month” based onendDatewhen provided.How to test:
Aditya-feat/Add-New-Bar–Chart-Card-to–the-Lessons-Learned-Section-on-the-Total–Construction-Summary-Page.rm -rf node_modules package-lock.json && npm cache clean --force.npm installto install dependencies, then start the backend locally (npm run dev)POST http://localhost:4500/api/loginwith{ "email": "...", "password": "..." }Use the returned token in the
Authorizationheader for the following requests.GET http://localhost:4500/api/bm/lessons-learntExpect 200 and
{ data: [ { project, projectId, lessonsCount, changePercentage }, ... ] }.GET http://localhost:4500/api/bm/lessons-learnt?projectId=ALLExpect 200, same shape as above.
GET http://localhost:4500/api/bm/lessons-learnt?projectId=not-a-valid-objectidExpect 400 and
{ "error": "Invalid projectId" }.GET http://localhost:4500/api/bm/lessons-learnt?startDate=not-a-dateExpect 400 and
{ "error": "Invalid startDate" }.GET http://localhost:4500/api/bm/lessons-learnt?endDate=2024-13-45Expect 400 and
{ "error": "Invalid endDate" }.GET http://localhost:4500/api/bm/lessons-learnt?projectId=allExpect 400 and
{ "error": "Invalid projectId" }(case-sensitive).npm test -- --testPathPattern=bmNewLessonControllerprojectId(existing ObjectId from your DB) returns 200 and at most one project indata(or[]if that project has no lessons).Screenshots or videos of changes:
TestVideo.mov
Note:
projectIdvalidated withmongoose.Types.ObjectId.isValidwhen notALL;startDateandendDatevalidated withNumber.isNaN(Date.parse(...)). Invalid values return 400 before any DB access.logger.logExceptionfor consistent tracking and debugging.