Rithika taking over for Aditya-feat: Phase 2 - API for interactive list of open issues with filters and actions#2032
Conversation
There was a problem hiding this comment.
Hi Aditya,
When I applied a future date range (for example, 2026-02-28 to 2026-03-28), the API still returned issues created in 2024 instead of an empty list. It looks like the startDate and endDate filters may not be getting applied correctly in the backend logic. If there are no issues within the selected range, the response should ideally be an empty array. Could you please review the date filtering condition in the query implementation
|
7b9b222 to
919e286
Compare
…flicts, run npm install to regenerate)
…ogic Add closedDate field to track when issues are closed and fix the date filtering logic to correctly show issues that were open during a date range. Changes: - Add closedDate field to BuildingIssue schema with default null - Auto-set closedDate when issue status changes to 'closed' - Auto-clear closedDate when issue is reopened (status -> 'open') - Fix bmGetOpenIssue to show issues "open during range" instead of only "created during range" - Use date-fns endOfDay() for consistent date handling across codebase - Prevent req.body mutation by creating a copy before modification Date filtering now correctly includes: - Issues created before range but still open - Issues created during range (whether open or closed later) - Issues closed during range (even if created before)
87ed803 to
60887ce
Compare
|

























Description
This PR implements the interactive list of open issues feature for the Building Management (BM) dashboard.
It adds a dedicated API surface under
/api/bmto fetch open issues with optional filters (projects, date range, tag), to rename/close/reopen/delete issues, and to list projects for dropdowns. Date filtering follows “ongoing during range” semantics (issues open at any time in the range, usingcreatedDateandclosedDate). The status enum is corrected from'close'to'closed',issueDateis stored as aDate, andclosedDateis set/cleared automatically on close/reopen. The issue chart endpoint is updated to useissueDate(Date) for year filtering. Comprehensive unit tests for the BM issue controller and an automated API test script (with report and verification doc) are included.Related PRs (if any):
Main changes explained:
Created/Updated Files:
src/controllers/bmdashboard/bmIssueController.jsbmGetOpenIssue: Builds a query with optionalprojectIds(comma-separated, validated ObjectIds),startDate,endDate, andtag. With no date filter, returns onlystatus: 'open'. With date range: “ongoing during range” —createdDate <= endDateand eitherstatus === 'open'orclosedDate >= startDate. UsesendOfDayfromdate-fnsfor end date. Returns array or[].bmUpdateIssue: Validates body is an object; onstatus: 'closed'setsclosedDate = new Date(); onstatus: 'open'setsclosedDate = null. UsesfindByIdAndUpdatewith$set, returns 404 when the issue is not found, 400 for invalid update data.bmDeleteIssue:findByIdAndDelete; 404 with{ message: 'Issue not found.' }when not found, 200 with{ message: 'Issue deleted successfully.' }on success.bmGetIssueChart: Filtering byissueTypeandyearapplied viamatchQuery; year filter usesissueDate(Date) with$gte/$ltefor Jan 1–Dec 31 of given year. Aggregation groups byissueTypeand year, returns a formatted object{ [issueType]: { [year]: count } }.getUniqueProjectIds: Unchanged in behavior; returns{ projectId, projectName }from aggregation + lookup onbuildingProjects. Other handlers:bmPostIssue,bmGetIssue,getLongestOpenIssuesretained.src/models/bmdashboard/buildingIssue.jsissueDate: Type changed fromStringtoDate, required.closedDate: New field{ type: Date, default: null }for close/reopen tracking.status: Enum corrected from'close'to'closed'; allowed values['open', 'closed'].person: Added{ name: String, role: String }subdocument.createdDate: Already present; used in open-issues date filtering.src/routes/bmdashboard/bmIssueRouter.jsGET /issues/open→bmGetOpenIssue;POST /issue/add→bmPostIssue;PATCH /issues/:id→bmUpdateIssue;DELETE /issues/:id→bmDeleteIssue;GET /issues/projects→getUniqueProjectIds;GET /issues→bmGetIssue;GET /issue/issue-chart→bmGetIssueChart;GET /issues/longest-open→getLongestOpenIssues. Route order/registration clarified (no path changes).src/startup/routes.jsbuildingIssueandbmIssueRouterwere already required and mounted atapp.use('/api/bm', bmIssueRouter).src/controllers/bmdashboard/__tests__/bmIssueController.test.jsprojectIds(valid/invalid/combined);startDate+endDate,startDateonly,endDateonly; “ongoing during range” cases (created before range still open, closed during range, not closed before range, created during range); tag filter; combined filters; 500 on DB error.closedDateset, open →closedDatenull); 400 invalid body; 404 not found; 500 on error.issueType, byyear, both, neither; result shape; 500 on error.Key Implementation Details:
startDateandendDate, an issue is included ifcreatedDate <= endOfDay(endDate)and eitherstatus === 'open'orclosedDate >= startDate. ForstartDateonly:status === 'open'orclosedDate >= startDate. ForendDateonly:createdDate <= endOfDay(endDate)(no status filter). No date filter ⇒ onlystatus: 'open'.new Date()when PATCH setsstatus: 'closed'; set tonullwhen PATCH setsstatus: 'open'. Enables correct date-range filtering and audit.bmGetIssueChartusesissueDate(Date) for year filter; aggregation groups byissueTypeand year, returns{ [issueType]: { [year]: count } }.projectIdsparsed and validated withObjectId.isValid; invalid IDs dropped. Update body must be a non-null object. 404 for missing issue on PATCH/DELETE; 400 for invalid update data.How to test:
fix/Create_an_interactive_list_of_open_issuesrm -rf node_modules package-lock.json && npm cache clean --forcenpm installto install dependencies, then start the backend locally (npm run dev)GET http://localhost:4500/api/bm/issues/openHeader:
Authorization: <valid JWT>Expect:
200, JSON array of open issues (or[]).GET http://localhost:4500/api/bm/issues/open?projectIds=65419e61105441587e2dec99&startDate=2024-01-01&endDate=2024-12-31&tag=In-personExpect:
200, array of issues ongoing in range and matching project/tag.GET http://localhost:4500/api/bm/issues/projectsExpect:
200, array of{ projectId, projectName }.PATCH http://localhost:4500/api/bm/issues/<id>Body:
{ "status": "closed" }Expect:
200, body includesstatus: "closed"andclosedDateset.Body:
{ "status": "open" }Expect:
200,closedDatenull.Body:
{ "issueTitle": ["New title"] }Expect:
200, updated issue with new title.DELETE http://localhost:4500/api/bm/issues/<id>Expect:
200with{ message: "Issue deleted successfully." }or404with{ message: "Issue not found." }.Authorizationor use an invalid JWT on GET open or GET projects →401.404,message: "Issue not found."npm test -- --testPathPattern=bmIssueController(or project’s Jest config for unit tests)Screenshots or videos of changes:
TestVideo.mov
Note:
status: 'close'or stringissueDate, they must switch to'closed'and Date/ISO string forissueDate.closedDate(default null),issueDateas Date,statusenum['open','closed'],personsubdocument. Existing documents may need a one-time fix if they are storedstatus: 'close'or stringissueDate(handled by app logic where applicable).projectId,status,createdDate,closedDate,tag).projectIdsfiltered to valid ObjectIds; invalid IDs ignored. PATCH body must be an object; 400 otherwise. Model validation (required fields, enums) applies to POST and on PATCH updates.