Skip to content

Commit ae9fae5

Browse files
authored
Merge branch 'develop' into #1183-delete-team-endpoint
2 parents 47c2e47 + 0754b1c commit ae9fae5

76 files changed

Lines changed: 1111 additions & 424 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

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

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ A project management web application built in Typescript, React, and Express.
88

99
All of our documentation is on [our Confluence page](https://nerdocs.atlassian.net/wiki/spaces/NER/pages/5603329/Software). Start there to learn what the project is all about.
1010

11-
All questions can be directed to `#software` in the [NER Slack](https://nu-electric-racing.slack.com) (backup contact: [`@anthonybernardi`](https://github.com/anthonybernardi)).
11+
All questions can be directed to `#software` in the [NER Slack](https://nu-electric-racing.slack.com) (backup contact: [`@RChandler234`](https://github.com/RChandler234)).
1212

1313
## Environment Setup
1414

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: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,9 @@ export default class ReimbursementRequestsController {
7272
static async reimburseUser(req: Request, res: Response, next: NextFunction) {
7373
try {
7474
const user = await getCurrentUser(res);
75-
const { amount } = req.body;
75+
const { amount, dateReceived } = req.body;
7676

77-
const reimbursement = await ReimbursementRequestService.reimburseUser(amount, user);
77+
const reimbursement = await ReimbursementRequestService.reimburseUser(amount, dateReceived, user);
7878
res.status(200).json(reimbursement);
7979
} catch (error: unknown) {
8080
next(error);
@@ -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/controllers/teams.controllers.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,27 @@ export default class TeamsController {
6262
next(error);
6363
}
6464
}
65-
65+
66+
static async setTeamLeads(req: Request, res: Response, next: NextFunction) {
67+
try {
68+
const { userIds } = req.body;
69+
const { teamId } = req.params;
70+
const submitter = await getCurrentUser(res);
71+
const team = await TeamsService.setTeamLeads(submitter, teamId, userIds);
72+
return res.status(200).json(team);
73+
} catch (error: unknown) {
74+
next(error);
75+
}
76+
}
77+
6678
static async deleteTeam(req: Request, res: Response, next: NextFunction) {
6779
try {
6880
const { teamId } = req.params;
6981
const deleter = await getCurrentUser(res);
7082
await TeamsService.deleteTeam(deleter, teamId);
7183
return res.status(204).json({ message: `Successfully deleted team with id ${teamId}` });
72-
} catch (error: unknown) {
84+
} catch (error: unknown) {
7385
next(error);
74-
}
86+
}
7587
}
7688
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ reimbursementRequestsRouter.post(
111111
reimbursementRequestsRouter.post(
112112
'/reimburse',
113113
intMinZero(body('amount')),
114+
isDate(body('dateReceived')),
114115
validateInputs,
115116
ReimbursementRequestController.reimburseUser
116117
);

src/backend/src/routes/teams.routes.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ teamsRouter.post(
1515
validateInputs,
1616
TeamsController.setTeamMembers
1717
);
18+
teamsRouter.post(
19+
'/:teamId/set-leads',
20+
body('userIds').isArray(),
21+
intMinZero(body('userIds.*')),
22+
validateInputs,
23+
TeamsController.setTeamLeads
24+
);
1825
teamsRouter.post(
1926
'/:teamId/edit-description',
2027
body('newDescription').isString(),

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/reimbursement-requests.services.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ export default class ReimbursementRequestService {
130130

131131
if (!expenseType) throw new NotFoundException('Expense Type', expenseTypeId);
132132

133+
if (!expenseType.allowed) throw new HttpException(400, `The expense type ${expenseType.name} is not allowed!`);
134+
133135
const validatedReimbursementProudcts = await validateReimbursementProducts(reimbursementProducts);
134136

135137
const createdReimbursementRequest = await prisma.reimbursement_Request.create({
@@ -167,10 +169,11 @@ export default class ReimbursementRequestService {
167169
* Function to reimburse a user for their expenses.
168170
*
169171
* @param amount the amount to be reimbursed
172+
* @param dateReceived the date the amount was received
170173
* @param submitter the person performing the reimbursement
171174
* @returns the created reimbursement
172175
*/
173-
static async reimburseUser(amount: number, submitter: User): Promise<Reimbursement> {
176+
static async reimburseUser(amount: number, dateReceived: string, submitter: User): Promise<Reimbursement> {
174177
if (isGuest(submitter.role)) {
175178
throw new AccessDeniedException('Guests cannot reimburse a user for their expenses.');
176179
}
@@ -195,11 +198,16 @@ export default class ReimbursementRequestService {
195198
if (amount > totalOwed - totalReimbursed) {
196199
throw new HttpException(400, 'Reimbursement is greater than the total amount owed to the user');
197200
}
201+
202+
// make the date object but add 12 hours so that the time isn't 00:00 to avoid timezone problems
203+
const dateCreated = new Date(dateReceived.split('T')[0]);
204+
dateCreated.setTime(dateCreated.getTime() + 12 * 60 * 60 * 1000);
205+
198206
const newReimbursement = await prisma.reimbursement.create({
199207
data: {
200208
purchaserId: submitter.userId,
201209
amount,
202-
dateCreated: new Date(),
210+
dateCreated: dateReceived,
203211
userSubmittedId: submitter.userId
204212
},
205213
...reimbursementQueryArgs

0 commit comments

Comments
 (0)