Skip to content

Commit 34d521b

Browse files
committed
#1203: fixed denied cr review error and combined the work from develop
2 parents 705cf46 + 9ee0455 commit 34d521b

26 files changed

Lines changed: 158 additions & 162 deletions

File tree

Dockerfile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ COPY yarn.lock .
66
COPY tsconfig.build.json .
77
COPY ./src/backend/package.json src/backend/
88
COPY ./src/shared/package.json src/shared/
9-
RUN yarn plugin import workspace-tools
10-
RUN yarn workspace focus --production backend
9+
RUN yarn install
1110
COPY ./src/backend src/backend
1211
COPY ./src/shared src/shared
1312
RUN yarn prisma:generate

src/backend/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
"jsonwebtoken": "^8.5.1",
2626
"multer": "^1.4.5-lts.1",
2727
"nodemailer": "^6.9.1",
28-
"prisma": "^4.4.0",
2928
"shared": "1.0.0"
3029
},
3130
"devDependencies": {

src/backend/src/controllers/projects.controllers.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ export default class ProjectsController {
3131
const user: User = await getCurrentUser(res);
3232
const { crId, carNumber, name, summary, teamId } = req.body;
3333

34-
const createdWbsNumber: WbsNumber = await ProjectsService.createProject(user, crId, carNumber, name, summary, teamId);
34+
const createdWbsNumber: WbsNumber = await ProjectsService.createProject(user, crId, carNumber, name, summary, [
35+
teamId
36+
]);
3537

3638
return res.status(200).json(wbsPipe(createdWbsNumber));
3739
} catch (error: unknown) {

src/backend/src/controllers/reimbursement-requests.controllers.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,10 @@ export default class ReimbursementRequestsController {
182182

183183
const receipt = await ReimbursementRequestService.uploadReceipt(requestId, file, user);
184184

185+
const isProd = process.env.NODE_ENV === 'production';
186+
const origin = isProd ? 'https://finishlinebyner.com' : 'http://localhost:3000';
187+
188+
res.header('Access-Control-Allow-Origin', origin);
185189
res.status(200).json(receipt);
186190
} catch (error: unknown) {
187191
next(error);

src/backend/src/services/change-requests.services.ts

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -118,16 +118,12 @@ export default class ChangeRequestsService {
118118
await prisma.project.update({
119119
where: { projectId: foundCR.wbsElement.project.projectId },
120120
data: {
121-
budget: newBudget,
122-
wbsElement: {
123-
update: {
124-
changes: {
125-
create: change
126-
}
127-
}
128-
}
121+
budget: newBudget
129122
}
130123
});
124+
125+
//Make the associated budget change if there was a change
126+
if (change) await prisma.change.create({ data: change });
131127
} else if (foundCR.wbsElement.workPackage) {
132128
// get the project for the work package
133129
const wpProj = await prisma.project.findUnique({
@@ -167,26 +163,22 @@ export default class ChangeRequestsService {
167163
update: {
168164
where: { workPackageId: foundCR.wbsElement.workPackage.workPackageId },
169165
data: {
170-
duration: updatedDuration,
171-
wbsElement: {
172-
update: {
173-
changes: {
174-
create: changes[1]
175-
}
176-
}
177-
}
178-
}
179-
}
180-
},
181-
wbsElement: {
182-
update: {
183-
changes: {
184-
create: changes[0]
166+
duration: updatedDuration
185167
}
186168
}
187169
}
188170
}
189171
});
172+
173+
//Making associated changes
174+
const changePromises = changes.map(async (change) => {
175+
//Checking if change is not zero so we dont make changes for zero budget or timeline impact
176+
if (change) {
177+
await prisma.change.create({ data: change });
178+
}
179+
});
180+
181+
await Promise.all(changePromises);
190182
}
191183

192184
// finally update the proposed solution
@@ -298,12 +290,6 @@ export default class ChangeRequestsService {
298290
});
299291
}
300292

301-
// send the creator of the cr a slack notification that their cr was reviewed
302-
const creatorUserSettings = await prisma.user_Settings.findUnique({ where: { userId: foundCR.submitterId } });
303-
if (creatorUserSettings && creatorUserSettings.slackId) {
304-
await sendSlackCRReviewedNotification(creatorUserSettings.slackId, foundCR.crId);
305-
}
306-
307293
// finally we can update change request
308294
const updated = await prisma.change_Request.update({
309295
where: { crId },
@@ -316,6 +302,18 @@ export default class ChangeRequestsService {
316302
include: { activationChangeRequest: true, wbsElement: { include: { workPackage: true } } }
317303
});
318304

305+
// send the creator of the cr a slack notification that their cr was reviewed
306+
const creatorUserSettings = await prisma.user_Settings.findUnique({ where: { userId: foundCR.submitterId } });
307+
if (creatorUserSettings && creatorUserSettings.slackId) {
308+
try {
309+
await sendSlackCRReviewedNotification(creatorUserSettings.slackId, foundCR.crId);
310+
} catch (err: unknown) {
311+
if (err instanceof Error) {
312+
throw new HttpException(500, `Failed to send slack notification: ${err.message}`);
313+
}
314+
}
315+
}
316+
319317
return updated.crId;
320318
}
321319

src/backend/src/services/users.services.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,15 +147,15 @@ export default class UsersService {
147147
});
148148

149149
if (!payload['given_name']) {
150-
throw new HttpException(400, 'First Name not Found on Google Account');
150+
throw new HttpException(400, 'First Name was not Found on Google Account');
151151
}
152152

153153
if (!payload['family_name']) {
154-
throw new HttpException(400, 'Last Name not Found on Google Account');
154+
throw new HttpException(400, 'Last Name was not Found on Google Account');
155155
}
156156

157157
if (!payload['email']) {
158-
throw new HttpException(400, 'Email not Found on Google Account');
158+
throw new HttpException(400, 'Email was not Found on Google Account');
159159
}
160160

161161
// if not in database, create user in database

src/backend/src/services/work-packages.services.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,12 @@ export default class WorkPackagesService {
154154
throw new HttpException(400, 'A Work Package cannot have its own project as a blocker');
155155
}
156156

157+
blockedBy.forEach((dep: WbsNumber) => {
158+
if (dep.workPackageNumber === 0) {
159+
throw new HttpException(400, 'A Project cannot be a Blocker');
160+
}
161+
});
162+
157163
const wbsElem = await prisma.wBS_Element.findUnique({
158164
where: {
159165
wbsNumber: {
@@ -287,6 +293,12 @@ export default class WorkPackagesService {
287293
// verify user is allowed to edit work packages
288294
if (isGuest(user.role)) throw new AccessDeniedGuestException('edit work packages');
289295

296+
blockedBy.forEach((dep: WbsNumber) => {
297+
if (dep.workPackageNumber === 0) {
298+
throw new HttpException(400, 'A Project cannot be a Blocker');
299+
}
300+
});
301+
290302
const { userId } = user;
291303

292304
// get the original work package so we can compare things

src/backend/tests/change-requests.test.ts

Lines changed: 8 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -174,51 +174,21 @@ describe('Change Requests', () => {
174174
vi.spyOn(prisma.project, 'findUnique').mockResolvedValue(prismaProject1);
175175
vi.spyOn(prisma.project, 'update').mockResolvedValue(prismaProject1);
176176
vi.spyOn(prisma.change_Request, 'update').mockResolvedValueOnce({ ...prismaChangeRequest1, accepted: true });
177+
vi.spyOn(prisma.change, 'create').mockResolvedValue({
178+
changeId: 1,
179+
changeRequestId: 2,
180+
detail: 'Changed Duration from "10" to "20"',
181+
implementerId: 2,
182+
wbsElementId: 65,
183+
dateImplemented: new Date()
184+
});
177185
const response = await ChangeRequestsService.reviewChangeRequest(superman, crId, reviewNotes, accepted, '1');
178186
expect(response).toStrictEqual(prismaChangeRequest1.crId);
179187
expect(prisma.user_Settings.findUnique).toHaveBeenCalledTimes(1);
180188
expect(prisma.change_Request.findUnique).toHaveBeenCalledTimes(1);
181189
expect(prisma.proposed_Solution.findUnique).toHaveBeenCalledTimes(1);
182190
expect(prisma.project.findUnique).toHaveBeenCalledTimes(1);
183191
expect(prisma.project.update).toHaveBeenCalledTimes(1);
184-
expect(prisma.project.update).toHaveBeenCalledWith({
185-
data: {
186-
budget: 1003,
187-
wbsElement: {
188-
update: {
189-
changes: {
190-
create: {
191-
changeRequestId: 2,
192-
detail: 'Changed Budget from "3" to "1003"',
193-
implementerId: 2,
194-
wbsElementId: 65
195-
}
196-
}
197-
}
198-
},
199-
workPackages: {
200-
update: {
201-
data: {
202-
duration: 20,
203-
wbsElement: {
204-
update: {
205-
changes: {
206-
create: {
207-
changeRequestId: 2,
208-
detail: 'Changed Duration from "10" to "20"',
209-
implementerId: 2,
210-
wbsElementId: 65
211-
}
212-
}
213-
}
214-
}
215-
},
216-
where: { workPackageId: 1 }
217-
}
218-
}
219-
},
220-
where: { projectId: 1 }
221-
});
222192
expect(prisma.change_Request.update).toHaveBeenCalledTimes(1);
223193
});
224194

@@ -240,24 +210,6 @@ describe('Change Requests', () => {
240210
expect(prisma.change_Request.findUnique).toHaveBeenCalledTimes(1);
241211
expect(prisma.proposed_Solution.findUnique).toHaveBeenCalledTimes(1);
242212
expect(prisma.user_Settings.findUnique).toHaveBeenCalledTimes(1);
243-
expect(prisma.project.update).toHaveBeenCalledWith({
244-
data: {
245-
budget: 1003,
246-
wbsElement: {
247-
update: {
248-
changes: {
249-
create: {
250-
changeRequestId: 2,
251-
detail: 'Changed Budget from "3" to "1003"',
252-
implementerId: 2,
253-
wbsElementId: 65
254-
}
255-
}
256-
}
257-
}
258-
},
259-
where: { projectId: 2 }
260-
});
261213
expect(prisma.change_Request.update).toHaveBeenCalledTimes(1);
262214
});
263215

src/frontend/src/components/ActionsMenu.tsx

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -41,23 +41,21 @@ const ActionsMenu: React.FC<ActionsMenuProps> = ({ buttons, title = 'Actions' })
4141
{title}
4242
</NERButton>
4343
<Menu open={dropdownOpen} anchorEl={anchorEl} onClose={handleDropdownClose}>
44-
{buttons.map((button, index) => {
45-
return (
46-
<>
47-
{button.dividerTop ? <Divider /> : <></>}
48-
<MenuItem
49-
key={index}
50-
onClick={() => {
51-
handleDropdownClose();
52-
button.onClick();
53-
}}
54-
disabled={button.disabled}
55-
>
56-
<ListItemIcon>{button.icon}</ListItemIcon>
57-
{button.title}
58-
</MenuItem>
59-
</>
60-
);
44+
{buttons.flatMap((button, index) => {
45+
return [
46+
button.dividerTop && <Divider key={`${index}-divider`} />,
47+
<MenuItem
48+
key={index}
49+
onClick={() => {
50+
handleDropdownClose();
51+
button.onClick();
52+
}}
53+
disabled={button.disabled}
54+
>
55+
<ListItemIcon>{button.icon}</ListItemIcon>
56+
{button.title}
57+
</MenuItem>
58+
];
6159
})}
6260
</Menu>
6361
</Box>

src/frontend/src/hooks/work-packages.hooks.ts

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -37,22 +37,6 @@ export const useSingleWorkPackage = (wbsNum: WbsNumber) => {
3737
});
3838
};
3939

40-
/**
41-
* Custom React Hook to supply multiple work packages
42-
*
43-
* @param wbsNums WBS numbers of the requested work packages
44-
*/
45-
export const useManyWorkPackages = (wbsNums: WbsNumber[]) => {
46-
return useQuery<WorkPackage[], Error>(['work packages', wbsNums], async () => {
47-
const workPackagePromises = wbsNums.map(async (wbsNum) => {
48-
const { data } = await getSingleWorkPackage(wbsNum);
49-
return data;
50-
});
51-
const workPackages = await Promise.all(workPackagePromises);
52-
return workPackages;
53-
});
54-
};
55-
5640
/**
5741
* Custom React Hook to create a new work package.
5842
*

0 commit comments

Comments
 (0)