Skip to content

Commit 2784ce6

Browse files
authored
Merge pull request #4139 from Northeastern-Electric-Racing/#3937-RichardFeng-GuestDefinition
#3937 richard feng guest definition
2 parents a551ce8 + 662114d commit 2784ce6

4 files changed

Lines changed: 214 additions & 0 deletions

File tree

src/backend/src/controllers/recruitment.controllers.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,28 @@ export default class RecruitmentController {
116116
}
117117
}
118118

119+
static async editGuestDefinition(req: Request, res: Response, next: NextFunction) {
120+
try {
121+
const { definitionId } = req.params as Record<string, string>;
122+
const { term, description, order, icon, buttonText, buttonLink } = req.body;
123+
124+
const definition = await RecruitmentServices.editGuestDefinition(
125+
req.currentUser,
126+
req.organization,
127+
term,
128+
description,
129+
definitionId,
130+
order,
131+
icon,
132+
buttonText,
133+
buttonLink
134+
);
135+
res.status(200).json(definition);
136+
} catch (error: unknown) {
137+
next(error);
138+
}
139+
}
140+
119141
static async deleteGuestDefinition(req: Request, res: Response, next: NextFunction) {
120142
try {
121143
const { definitionId } = req.params as Record<string, string>;

src/backend/src/routes/recruitment.routes.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,18 @@ recruitmentRouter.post(
6464
RecruitmentController.createGuestDefinition
6565
);
6666

67+
recruitmentRouter.post(
68+
'/guestDefinition/:guestId/edit',
69+
nonEmptyString(body('term')),
70+
nonEmptyString(body('description')),
71+
body('order').isInt(),
72+
nonEmptyString(body('icon')).optional(),
73+
nonEmptyString(body('buttonText')).optional(),
74+
nonEmptyString(body('buttonLink')).optional(),
75+
validateInputs,
76+
RecruitmentController.editGuestDefinition
77+
);
78+
6779
recruitmentRouter.delete('/guestdefinition/:definitionId/delete', RecruitmentController.deleteGuestDefinition);
6880
recruitmentRouter.get('/guestdefinitions', RecruitmentController.getAllGuestDefintions);
6981

src/backend/src/services/recruitment.services.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,4 +282,60 @@ export default class RecruitmentServices {
282282
data: { dateDeleted: new Date(), userDeletedId: deleter.userId }
283283
});
284284
}
285+
286+
/**
287+
* Edits guest definition
288+
* @param creator user editing the definition
289+
* @param organization org the definition is being edited
290+
* @param term the term we are editing
291+
* @param description the definition of the term
292+
* @param order the order the term appears on the page
293+
* @param icon the icon associated with the term
294+
* @param buttonText the text displayed on the terms button
295+
* @param buttonLink where the terms button links to
296+
* @returns
297+
*/
298+
static async editGuestDefinition(
299+
creator: User,
300+
organization: Organization,
301+
term: string,
302+
description: string,
303+
definitionId: string,
304+
order: number,
305+
icon?: string,
306+
buttonText?: string,
307+
buttonLink?: string
308+
) {
309+
if (!(await userHasPermission(creator.userId, organization.organizationId, isAdmin)))
310+
throw new AccessDeniedAdminOnlyException('edit a guest definition');
311+
312+
const currentGuestDefinition = await prisma.guest_Definition.findUnique({
313+
where: {
314+
definitionId
315+
}
316+
});
317+
318+
if (!currentGuestDefinition) {
319+
throw new NotFoundException('Guest Definition', definitionId);
320+
}
321+
322+
if (currentGuestDefinition.dateDeleted) {
323+
throw new DeletedException('Guest Definition', definitionId);
324+
}
325+
326+
const updatedGuest = await prisma.guest_Definition.update({
327+
where: {
328+
definitionId
329+
},
330+
data: {
331+
term,
332+
description,
333+
order,
334+
icon,
335+
buttonText,
336+
buttonLink
337+
}
338+
});
339+
return guestDefinitionTransformer(updatedGuest);
340+
}
285341
}

src/backend/tests/unit/recruitment.test.ts

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,130 @@ describe('Recruitment Tests', () => {
379379
).rejects.toThrow(new AccessDeniedAdminOnlyException('create a guest definition'));
380380
});
381381
});
382+
describe('Edit Guest Definition', () => {
383+
it('Fails if user is not an admin', async () => {
384+
await expect(
385+
async () =>
386+
await RecruitmentServices.editGuestDefinition(
387+
await createTestUser(member, orgId),
388+
organization,
389+
'test term',
390+
'test description',
391+
'test definition id',
392+
2,
393+
'buttonTxt',
394+
'buttonLink'
395+
)
396+
).rejects.toThrow(new AccessDeniedAdminOnlyException('edit a guest definition'));
397+
});
398+
399+
it('Fails if guest definition doesn`t exist', async () => {
400+
await expect(
401+
async () =>
402+
await RecruitmentServices.editGuestDefinition(
403+
await createTestUser(batmanAppAdmin, orgId),
404+
organization,
405+
'term',
406+
'description',
407+
'definition id',
408+
2,
409+
'buttonTxt',
410+
'buttonLink'
411+
)
412+
).rejects.toThrow(new NotFoundException('Guest Definition', 'definition id'));
413+
});
414+
415+
it('Successful edit guest definition', async () => {
416+
const def = await RecruitmentServices.createGuestDefinition(
417+
superman,
418+
organization,
419+
'test term',
420+
'test description',
421+
2,
422+
'iconname',
423+
'buttonTxt',
424+
'buttonLink'
425+
);
426+
427+
const edited = await RecruitmentServices.editGuestDefinition(
428+
await createTestUser(batmanAppAdmin, orgId),
429+
organization,
430+
'new term',
431+
'new description',
432+
def.definitionId,
433+
4,
434+
'new icon',
435+
'new text',
436+
'new link'
437+
);
438+
439+
expect(edited.term).toBe('new term');
440+
expect(edited.description).toBe('new description');
441+
expect(edited.order).toBe(4);
442+
expect(edited.icon).toBe('new icon');
443+
expect(edited.buttonText).toBe('new text');
444+
expect(edited.buttonLink).toBe('new link');
445+
});
446+
447+
it('Edit guest definition fails if defintion is deleted', async () => {
448+
const def = await RecruitmentServices.createGuestDefinition(
449+
superman,
450+
organization,
451+
'test term',
452+
'test description',
453+
2,
454+
'iconname',
455+
'buttonTxt',
456+
'buttonLink'
457+
);
458+
459+
const batman = await createTestUser(batmanAppAdmin, orgId);
460+
461+
await RecruitmentServices.deleteGuestDefinition(batman, def.definitionId, organization);
462+
463+
await expect(
464+
async () =>
465+
await RecruitmentServices.editGuestDefinition(
466+
batman,
467+
organization,
468+
'term',
469+
'description',
470+
def.definitionId,
471+
2,
472+
'buttonTxt',
473+
'buttonLink'
474+
)
475+
).rejects.toThrow(new DeletedException('Guest Definition', def.definitionId));
476+
});
477+
478+
it('Fails if milestone is deleted', async () => {
479+
const milestone = await RecruitmentServices.createMilestone(
480+
await createTestUser(batmanAppAdmin, orgId),
481+
'name',
482+
'description',
483+
new Date('11/12/24'),
484+
organization
485+
);
486+
487+
await prisma.milestone.delete({
488+
where: {
489+
milestoneId: milestone.milestoneId
490+
}
491+
});
492+
493+
await expect(
494+
async () =>
495+
await RecruitmentServices.editMilestone(
496+
superman,
497+
'name',
498+
'description',
499+
new Date('11/12/24'),
500+
milestone.milestoneId,
501+
organization
502+
)
503+
).rejects.toThrow(new NotFoundException('Milestone', milestone.milestoneId));
504+
});
505+
});
382506

383507
describe('Delete Guest Definition', () => {
384508
it('Fails if user is not an admin', async () => {

0 commit comments

Comments
 (0)