#3907 automatic change requests updating roles#3965
#3907 automatic change requests updating roles#3965cielbellerose wants to merge 11 commits intodevelopfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This pull request implements automatic change requests for updating leads and managers of projects and work packages. Instead of requiring manual approval, leadership changes are now automatically approved and immediately applied. This streamlines the process of assigning or changing project and work package leadership.
Changes:
- Adds a new "Leadership" change request type that is auto-approved when created
- Implements frontend logic to detect when only leadership fields have changed and triggers automatic CR creation
- Adds backend service, controller, and database schema for leadership change requests
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/shared/src/types/change-request-types.ts | Adds Leadership change request type and interface definitions |
| src/frontend/src/utils/urls.ts | Adds URL endpoint for leadership CR creation |
| src/frontend/src/utils/enum-pipes.ts | Adds text transformation for Leadership CR type |
| src/frontend/src/pages/WorkPackageForm/WorkPackageFormView.tsx | Implements leadership-only change detection and automatic CR submission for work packages |
| src/frontend/src/pages/WorkPackageForm/WorkPackageForm.tsx | Passes leadership CR creation function to form view |
| src/frontend/src/pages/WorkPackageForm/EditWorkPackageForm.tsx | Adds leadership CR hook and passes to form |
| src/frontend/src/pages/WorkPackageForm/CreateWorkPackageForm.tsx | Provides no-op leadership CR function (not applicable for new work packages) |
| src/frontend/src/pages/ProjectDetailPage/ProjectForm/ProjectForm.tsx | Updates button states based on leadership-only changes |
| src/frontend/src/pages/ProjectDetailPage/ProjectForm/ProjectEditContainer.tsx | Implements leadership-only change detection and automatic CR submission for projects |
| src/frontend/src/hooks/change-requests.hooks.ts | Adds React hook for creating leadership change requests |
| src/frontend/src/apis/change-requests.api.ts | Adds API function for leadership CR creation |
| src/backend/src/transformers/change-requests.transformer.ts | Updates transformers to include leadership CR lead/manager fields |
| src/backend/src/services/change-requests.services.ts | Implements service methods to create and apply leadership change requests |
| src/backend/src/routes/change-requests.routes.ts | Adds route for leadership CR creation |
| src/backend/src/prisma/schema.prisma | Adds Leadership_CR model and CR_Type enum value |
| src/backend/src/prisma/migrations/20260223001543_leadership_cr/migration.sql | Database migration for leadership CR table |
| src/backend/src/prisma-query-args/change-requests.query-args.ts | Includes leadership CR in query arguments |
| src/backend/src/controllers/change-requests.controllers.ts | Adds controller method for leadership CR creation |
Comments suppressed due to low confidence (1)
src/frontend/src/hooks/change-requests.hooks.ts:244
- Typo: "Custome" should be "Custom"
* Custome React hook to create a leadership change request
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| </NERFailButton> | ||
| <NERSuccessButton | ||
| disabled={!changeRequestInputExists && !!project} | ||
| disabled={!changeRequestInputExists && !!project && onlyLeadershipChanged} |
There was a problem hiding this comment.
The Submit button disable logic is incorrect. The button should be enabled when onlyLeadershipChanged is true (to allow submitting the automatic CR), but the current logic disables it. Change the condition to: disabled={!changeRequestInputExists && !!project && !onlyLeadershipChanged}
| disabled={!changeRequestInputExists && !!project && onlyLeadershipChanged} | |
| disabled={!changeRequestInputExists && !!project && !onlyLeadershipChanged} |
| onClick={() => setIsModalOpen(true)} | ||
| sx={{ mx: 1 }} | ||
| disabled={changeRequestInputExists} | ||
| disabled={changeRequestInputExists || !onlyLeadershipChanged} |
There was a problem hiding this comment.
The "Create Change Request" button disable logic is inverted. It should be disabled when onlyLeadershipChanged is true (to prevent creating a manual CR when an automatic one should be used), not when it's false. Change the condition to: disabled={changeRequestInputExists || onlyLeadershipChanged}
| disabled={changeRequestInputExists || !onlyLeadershipChanged} | |
| disabled={changeRequestInputExists || onlyLeadershipChanged} |
| static async createLeadershipChangeRequest( | ||
| submitter: User, | ||
| carNumber: number, | ||
| projectNumber: number, | ||
| workPackageNumber: number, | ||
| leadId: string | undefined, | ||
| managerId: string | undefined, | ||
| organization: Organization | ||
| ): Promise<string> { | ||
| if (await userHasPermission(submitter.userId, organization.organizationId, isGuest)) | ||
| throw new AccessDeniedGuestException('create leadership change requests'); | ||
|
|
||
| // verify wbs element exists | ||
| const wbsElement = await prisma.wBS_Element.findUnique({ | ||
| where: { | ||
| wbsNumber: { | ||
| carNumber, | ||
| projectNumber, | ||
| workPackageNumber, | ||
| organizationId: organization.organizationId | ||
| } | ||
| } | ||
| }); | ||
|
|
||
| if (!wbsElement) throw new NotFoundException('WBS Element', wbsPipe({ carNumber, projectNumber, workPackageNumber })); | ||
| if (wbsElement.dateDeleted) | ||
| throw new DeletedException('WBS Element', wbsPipe({ carNumber, projectNumber, workPackageNumber })); | ||
| if (wbsElement.organizationId !== organization.organizationId) throw new InvalidOrganizationException('WBS Element'); | ||
|
|
||
| // avoid merge conflicts | ||
| await validateNoUnreviewedOpenCRs(wbsElement.wbsElementId); | ||
|
|
||
| const numChangeRequests = await prisma.change_Request.count({ | ||
| where: { organizationId: organization.organizationId } | ||
| }); | ||
|
|
||
| const createdCR = await prisma.change_Request.create({ | ||
| data: { | ||
| submitter: { connect: { userId: submitter.userId } }, | ||
| wbsElement: { connect: { wbsElementId: wbsElement.wbsElementId } }, | ||
| type: CR_Type.LEADERSHIP, | ||
| organization: { connect: { organizationId: organization.organizationId } }, | ||
| identifier: numChangeRequests + 1, | ||
| leadershipChangeRequest: { | ||
| create: { | ||
| ...(leadId && { lead: { connect: { userId: leadId } } }), | ||
| ...(managerId && { manager: { connect: { userId: managerId } } }) | ||
| } | ||
| } | ||
| } | ||
| }); | ||
|
|
||
| await ChangeRequestsService.applyLeadershipChangeRequest(createdCR.crId, wbsElement, submitter, leadId, managerId); | ||
|
|
||
| return createdCR.crId; | ||
| } |
There was a problem hiding this comment.
Missing validation to ensure at least one of leadId or managerId is provided. A leadership change request with neither field set is meaningless. Add validation to check that at least one field is defined before creating the change request.
| if (leadId !== undefined) { | ||
| const oldLead = await getUserFullName(wbsElement.leadId ?? null); | ||
| const newLead = await getUserFullName(leadId); | ||
| changes.push({ | ||
| changeRequestId: crId, | ||
| implementerId: submitter.userId, | ||
| wbsElementId: wbsElement.wbsElementId, | ||
| detail: buildChangeDetail('lead', oldLead, newLead) | ||
| }); | ||
| } | ||
|
|
||
| if (managerId !== undefined) { | ||
| const oldManager = await getUserFullName(wbsElement.managerId ?? null); | ||
| const newManager = await getUserFullName(managerId); | ||
| changes.push({ | ||
| changeRequestId: crId, | ||
| implementerId: submitter.userId, | ||
| wbsElementId: wbsElement.wbsElementId, | ||
| detail: buildChangeDetail('manager', oldManager, newManager) | ||
| }); | ||
| } |
There was a problem hiding this comment.
Creating change records for fields that haven't actually changed. The code creates a change record if leadId is defined (line 1112) or managerId is defined (line 1123), but doesn't check if the value actually changed from the original. This will create misleading change records like "manager changed from Bob to Bob" when only the lead was changed. Add a check to compare the new value with wbsElement.leadId or wbsElement.managerId before creating the change record. For example: if (leadId !== undefined && leadId !== wbsElement.leadId)
Changes
Updating a lead/manager of a project or work package is now an automatic change request
Screenshots
Screen.Recording.2026-02-24.at.10.36.08.AM.mov
Checklist
It can be helpful to check the
ChecksandFiles changedtabs.Please review the contributor guide and reach out to your Tech Lead if anything is unclear.
Please request reviewers and ping on slack only after you've gone through this whole checklist.
yarn.lockchanges (unless dependencies have changed)Closes #3907