Aditya-feat: Phase 2 - API for interactive list of open issues with filters and actions#2032
Open
Aditya-gam wants to merge 24 commits intodevelopmentfrom
Open
Aditya-feat: Phase 2 - API for interactive list of open issues with filters and actions#2032Aditya-gam wants to merge 24 commits intodevelopmentfrom
Aditya-gam wants to merge 24 commits intodevelopmentfrom
Conversation
…ist_of_open_issues
…ist_of_open_issues
…ist_of_open_issues
- Fixes grammatical error in status enum value - Maintains compatibility with original schema from development branch - Resolves validation errors for existing documents with status='closed' - Aligns with standard REST API conventions The incorrect enum value 'close' (verb) has been changed to 'closed' (past participle), which is the grammatically correct form and matches the original implementation before this feature branch.
- Fixes aggregation pipeline errors in bmGetIssueChart controller - Enables proper use of $year operator (line 176) which requires Date type - Resolves incorrect date comparisons using $gte/$lte operators - Ensures chronological sorting instead of lexicographic string sorting - Improves type safety and prevents invalid date strings The String type was causing the $year aggregation to return null values, resulting in empty chart data. Date type enables proper date operations and maintains compatibility with MongoDB date operators.
…er functions - Add 46 comprehensive tests covering all 8 controller functions - Test bmGetOpenIssue with projectIds, date range, and tag filters - Test getUniqueProjectIds aggregation and Unknown Project fallback - Test bmUpdateIssue validation, 400/404/500 error handling - Test bmDeleteIssue success and error paths - Test bmGetIssueChart with issueType and year filters - Test getLongestOpenIssues with date/project filtering and sorting - Achieve 99.21% statement and 94.23% branch coverage
…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)
…losedDate Update existing tests and add new test cases to cover the new date filtering logic and automatic closedDate tracking functionality. Changes: - Update existing date filter tests to match new query structure ($and/$or) - Add test: show issue created before range and still open - Add test: show issue created before range and closed during range - Add test: NOT show issue closed before range - Add test: show issue created during range regardless of closed status - Add test: auto-set closedDate when closing an issue - Add test: auto-clear closedDate when reopening an issue - Update "combine all filters" test for new query structure - Update "update issue successfully" test to expect closedDate All 52 tests passing with 100% coverage of new functionality.
…er, tests Co-authored-by: Cursor <cursoragent@cursor.com>
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 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.