Skip to content

Commit

Permalink
Merge pull request #2402 from Northeastern-Electric-Racing/#2392-auto…
Browse files Browse the repository at this point in the history
…-cr-post-release

#2392 auto cr post release
  • Loading branch information
Peyton-McKee authored May 25, 2024
2 parents 54ffc97 + e972902 commit 1f5bc20
Show file tree
Hide file tree
Showing 16 changed files with 254 additions and 107 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,13 @@ export const getChangeRequestQueryArgs = (organizationId: string) =>
wbsElement: {
include: {
workPackage: getWorkPackageQueryArgs(organizationId),
project: true,
descriptionBullets: true
project: {
include: {
teams: true
}
},
descriptionBullets: true,
links: true
}
},
reviewer: getUserQueryArgs(organizationId),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export const getScopeChangeRequestQueryArgs = (organizationId: string) =>
include: {
why: true,
proposedSolutions: getProposedSolutionQueryArgs(organizationId),
wbsProposedChanges: getWbsProposedChangeQueryArgs(organizationId)
wbsProposedChanges: getWbsProposedChangeQueryArgs(organizationId),
wbsOriginalData: getWbsProposedChangeQueryArgs(organizationId)
}
});
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,6 @@ CREATE TABLE "Scope_CR" (
"scopeImpact" TEXT NOT NULL,
"timelineImpact" INTEGER NOT NULL,
"budgetImpact" INTEGER NOT NULL,
"wbsProposedChangesId" TEXT,

CONSTRAINT "Scope_CR_pkey" PRIMARY KEY ("scopeCrId")
);
Expand Down Expand Up @@ -559,8 +558,9 @@ CREATE TABLE "Wbs_Proposed_Changes" (
"status" "WBS_Element_Status" NOT NULL,
"leadId" INTEGER,
"managerId" INTEGER,
"changeRequestId" INTEGER NOT NULL,
"changeRequestId" INTEGER,
"dateDeleted" TIMESTAMP(3),
"changeRequestAsOriginalDataId" INTEGER,

CONSTRAINT "Wbs_Proposed_Changes_pkey" PRIMARY KEY ("wbsProposedChangesId")
);
Expand All @@ -570,7 +570,6 @@ CREATE TABLE "Project_Proposed_Changes" (
"projectProposedChangesId" TEXT NOT NULL,
"budget" INTEGER NOT NULL,
"summary" TEXT NOT NULL,
"rules" TEXT[],
"wbsProposedChangesId" TEXT NOT NULL,
"carId" TEXT,

Expand Down Expand Up @@ -806,6 +805,9 @@ CREATE UNIQUE INDEX "Schedule_Settings_userId_key" ON "Schedule_Settings"("userI
-- CreateIndex
CREATE UNIQUE INDEX "Wbs_Proposed_Changes_changeRequestId_key" ON "Wbs_Proposed_Changes"("changeRequestId");

-- CreateIndex
CREATE UNIQUE INDEX "Wbs_Proposed_Changes_changeRequestAsOriginalDataId_key" ON "Wbs_Proposed_Changes"("changeRequestAsOriginalDataId");

-- CreateIndex
CREATE UNIQUE INDEX "Project_Proposed_Changes_wbsProposedChangesId_key" ON "Project_Proposed_Changes"("wbsProposedChangesId");

Expand Down Expand Up @@ -1188,7 +1190,10 @@ ALTER TABLE "Wbs_Proposed_Changes" ADD CONSTRAINT "Wbs_Proposed_Changes_leadId_f
ALTER TABLE "Wbs_Proposed_Changes" ADD CONSTRAINT "Wbs_Proposed_Changes_managerId_fkey" FOREIGN KEY ("managerId") REFERENCES "User"("userId") ON DELETE SET NULL ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "Wbs_Proposed_Changes" ADD CONSTRAINT "Wbs_Proposed_Changes_changeRequestId_fkey" FOREIGN KEY ("changeRequestId") REFERENCES "Scope_CR"("scopeCrId") ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE "Wbs_Proposed_Changes" ADD CONSTRAINT "Wbs_Proposed_Changes_changeRequestId_fkey" FOREIGN KEY ("changeRequestId") REFERENCES "Scope_CR"("scopeCrId") ON DELETE SET NULL ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "Wbs_Proposed_Changes" ADD CONSTRAINT "Wbs_Proposed_Changes_changeRequestAsOriginalDataId_fkey" FOREIGN KEY ("changeRequestAsOriginalDataId") REFERENCES "Scope_CR"("scopeCrId") ON DELETE SET NULL ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "Project_Proposed_Changes" ADD CONSTRAINT "Project_Proposed_Changes_wbsProposedChangesId_fkey" FOREIGN KEY ("wbsProposedChangesId") REFERENCES "Wbs_Proposed_Changes"("wbsProposedChangesId") ON DELETE RESTRICT ON UPDATE CASCADE;
Expand Down
29 changes: 15 additions & 14 deletions src/backend/src/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -258,17 +258,17 @@ model Message_Info {
}

model Scope_CR {
scopeCrId Int @id @default(autoincrement())
changeRequestId Int @unique
changeRequest Change_Request @relation(fields: [changeRequestId], references: [crId])
what String
why Scope_CR_Why[]
scopeImpact String
timelineImpact Int
budgetImpact Int
proposedSolutions Proposed_Solution[]
wbsProposedChangesId String?
wbsProposedChanges Wbs_Proposed_Changes?
scopeCrId Int @id @default(autoincrement())
changeRequestId Int @unique
changeRequest Change_Request @relation(fields: [changeRequestId], references: [crId])
what String
why Scope_CR_Why[]
scopeImpact String
timelineImpact Int
budgetImpact Int
proposedSolutions Proposed_Solution[]
wbsProposedChanges Wbs_Proposed_Changes? @relation(name: "wbsProposedChanges")
wbsOriginalData Wbs_Proposed_Changes? @relation(name: "wbsOriginalData")
}

model Proposed_Solution {
Expand Down Expand Up @@ -748,19 +748,20 @@ model Wbs_Proposed_Changes {
managerId Int?
manager User? @relation(name: "wbsmanager", fields: [managerId], references: [userId])
links Link[] @relation(name: "proposedChangeLinks")
changeRequest Scope_CR @relation(fields: [changeRequestId], references: [scopeCrId])
changeRequestId Int @unique
changeRequest Scope_CR? @relation(name: "wbsProposedChanges", fields: [changeRequestId], references: [scopeCrId])
changeRequestId Int? @unique
projectProposedChanges Project_Proposed_Changes? @relation(name: "projectProposedChanges")
workPackageProposedChanges Work_Package_Proposed_Changes? @relation(name: "wpProposedChanges")
proposedDescriptionBulletChanges Description_Bullet[] @relation(name: "proposedDescriptionBulletChanges")
dateDeleted DateTime?
changeRequestAsOriginalData Scope_CR? @relation(name: "wbsOriginalData", fields: [changeRequestAsOriginalDataId], references: [scopeCrId])
changeRequestAsOriginalDataId Int? @unique
}

model Project_Proposed_Changes {
projectProposedChangesId String @id @default(uuid())
budget Int
summary String
rules String[]
teams Team[] @relation(name: "proposedProjectTeams")
wbsProposedChanges Wbs_Proposed_Changes @relation(name: "projectProposedChanges", fields: [wbsProposedChangesId], references: [wbsProposedChangesId])
wbsProposedChangesId String @unique
Expand Down
78 changes: 69 additions & 9 deletions src/backend/src/services/change-requests.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,21 +179,81 @@ export default class ChangeRequestsService {
// we don't want to have merge conflictS on the wbs element thus we check if there are unreviewed or open CRs on the wbs element
await validateNoUnreviewedOpenCRs(foundCR.wbsElementId);

// must accept and review a change request before using the workpackage and project services
await prisma.change_Request.update({
where: { crId: foundCR.crId },
data: {
accepted: true,
dateReviewed: new Date()
}
});

const associatedProject = foundCR.wbsElement.project;
const associatedWorkPackage = foundCR.wbsElement.workPackage;
const { wbsProposedChanges } = foundCR.scopeChangeRequest;
const { workPackageProposedChanges } = wbsProposedChanges;
const { projectProposedChanges } = wbsProposedChanges;

// must accept and review a change request before using the workpackage and project services
await prisma.scope_CR.update({
where: { changeRequestId: foundCR.crId },
data: {
changeRequest: {
update: {
accepted: true,
dateReviewed: new Date()
}
},
wbsOriginalData: {
create: {
name: foundCR.wbsElement.name,
status: foundCR.wbsElement.status,
lead: {
connect: {
userId: foundCR.wbsElement.leadId ?? undefined
}
},
manager: {
connect: {
userId: foundCR.wbsElement.managerId ?? undefined
}
},
links: {
connect: foundCR.wbsElement.links.map((link) => ({
linkId: link.linkId
}))
},
proposedDescriptionBulletChanges: {
connect: foundCR.wbsElement.descriptionBullets.map((descriptionBullet) => ({
descriptionId: descriptionBullet.descriptionId
}))
},
projectProposedChanges:
projectProposedChanges && associatedProject
? {
create: {
budget: associatedProject.budget,
summary: associatedProject.summary,
teams: {
connect: associatedProject.teams.map((team) => ({ teamId: team.teamId }))
},
car: {
connect: {
carId: associatedProject.carId
}
}
}
}
: undefined,
workPackageProposedChanges:
workPackageProposedChanges && associatedWorkPackage
? {
create: {
startDate: associatedWorkPackage.startDate,
duration: associatedWorkPackage.duration,
blockedBy: {
connect: associatedWorkPackage.blockedBy.map((wbsNumber) => ({ wbsNumber }))
},
stage: associatedWorkPackage.stage
}
}
: undefined
}
}
}
});

if (workPackageProposedChanges) {
await applyWorkPackageProposedChanges(
wbsProposedChanges,
Expand Down
6 changes: 6 additions & 0 deletions src/backend/src/transformers/change-requests.transformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@ const changeRequestTransformer = (
proposedSolutions: changeRequest.scopeChangeRequest
? changeRequest.scopeChangeRequest?.proposedSolutions.map(proposedSolutionTransformer) ?? []
: undefined,
originalProjectData: changeRequest.scopeChangeRequest?.wbsOriginalData?.projectProposedChanges
? projectProposedChangesTransformer(changeRequest.scopeChangeRequest?.wbsOriginalData)
: undefined,
originalWorkPackageData: changeRequest.scopeChangeRequest?.wbsOriginalData?.workPackageProposedChanges
? workPackageProposedChangesTransformer(changeRequest.scopeChangeRequest?.wbsOriginalData)
: undefined,
// activation cr fields
projectLead: changeRequest.activationChangeRequest?.lead
? userTransformer(changeRequest.activationChangeRequest.lead)
Expand Down
2 changes: 1 addition & 1 deletion src/backend/src/utils/description-bullets.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export const descriptionBulletToChangeListValue = (
): ChangeListValue<DescriptionBulletPreview> => {
return {
element: descriptionBullet,
comparator: `${descriptionBullet.id}`,
comparator: `${descriptionBullet.detail}`,
displayValue: descriptionBullet.detail
};
};
Expand Down
3 changes: 1 addition & 2 deletions src/backend/tests/test-data/change-requests.test-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@ export const prismaScopeChangeRequest1: PrismaScopeCR = {
what: 'redesign whip',
scopeImpact: 'huge',
timelineImpact: 10,
budgetImpact: 1000,
wbsProposedChangesId: null
budgetImpact: 1000
};

export const sharedChangeRequest: SharedChangeRequest = {
Expand Down
48 changes: 29 additions & 19 deletions src/frontend/src/components/LinksEditView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,36 @@ import { getRequiredLinkTypeNames } from '../utils/link.utils';
import { ProjectFormInput } from '../pages/ProjectDetailPage/ProjectForm/ProjectForm';
import { Box } from '@mui/system';
import { NERButton } from './NERButton';
import { useEffect, useMemo } from 'react';

const LinksEditView: React.FC<{
ls: FieldArrayWithId[];
register: UseFormRegister<ProjectFormInput>;
watch: UseFormWatch<ProjectFormInput>;
append: UseFieldArrayAppend<ProjectFormInput, 'links'>;
remove: UseFieldArrayRemove;
}> = ({ ls, register, append, remove, watch }) => {
enforceRequired?: boolean;
}> = ({ ls, register, append, remove, watch, enforceRequired }) => {
const { isLoading, isError, error, data: linkTypes } = useAllLinkTypes();
if (isLoading || !linkTypes) return <LoadingIndicator />;
if (isError) return <ErrorPage message={error.message} />;

const requiredLinkTypeNames = getRequiredLinkTypeNames(linkTypes);
const requiredLinkTypeNames = useMemo(() => {
return linkTypes ? getRequiredLinkTypeNames(linkTypes) : [];
}, [linkTypes]);

const links = watch('links');

useEffect(() => {
if (enforceRequired) {
requiredLinkTypeNames.forEach((linkTypeName) => {
if (links.some((link) => link.linkTypeName === linkTypeName)) return;
append({ linkId: '-1', url: '', linkTypeName });
});
}
}, [append, enforceRequired, linkTypes, links, requiredLinkTypeNames]);

if (isLoading || !linkTypes) return <LoadingIndicator />;
if (isError) return <ErrorPage message={error.message} />;

const currentLinkTypeNames = links.map((link) => link.linkTypeName);

/* Checks whether the link at the given index is of a required type and does not already exist */
Expand All @@ -36,8 +50,6 @@ const LinksEditView: React.FC<{
);
};

const availableOptions = linkTypes.filter((linkType) => !currentLinkTypeNames.includes(linkType.name));

return (
<>
{ls.map((_element, i) => {
Expand All @@ -46,18 +58,18 @@ const LinksEditView: React.FC<{
<Select
{...register(`links.${i}.linkTypeName`, { required: true })}
sx={{ minWidth: '200px', mr: '5px' }}
disabled={isRequired(i)}
disabled={enforceRequired && isRequired(i)}
value={watch(`links.${i}.linkTypeName`)}
>
{linkTypes.map((linkType) => (
<MenuItem key={linkType.name} value={linkType.name} disabled={!availableOptions.includes(linkType)}>
<MenuItem key={linkType.name} value={linkType.name}>
{linkType.name}
</MenuItem>
))}
</Select>
<TextField required fullWidth autoComplete="off" {...register(`links.${i}.url`, { required: true })} />
<Box sx={{ minWidth: '56px', height: '40px' }}>
{!isRequired(i) && (
{(!enforceRequired || !isRequired(i)) && (
<IconButton type="button" onClick={() => remove(i)} sx={{ mx: 1, my: 0 }}>
<DeleteIcon />
</IconButton>
Expand All @@ -66,16 +78,14 @@ const LinksEditView: React.FC<{
</Box>
);
})}
{availableOptions.length > 0 && (
<NERButton
variant="contained"
color="primary"
onClick={() => append({ linkId: '-1', url: '', linkTypeName: '-1' })}
sx={{ my: 2, width: 'max-content' }}
>
+ Add New Link
</NERButton>
)}
<NERButton
variant="contained"
color="primary"
onClick={() => append({ linkId: '-1', url: '', linkTypeName: '-1' })}
sx={{ my: 2, width: 'max-content' }}
>
+ Add Link
</NERButton>
</>
);
};
Expand Down
Loading

0 comments on commit 1f5bc20

Please sign in to comment.