Skip to content

Commit

Permalink
Merge pull request #3123 from Northeastern-Electric-Racing/#3121-recr…
Browse files Browse the repository at this point in the history
…uitment-onboarding-bugs

#3121 recruitment onboarding bugs
  • Loading branch information
Aaryan1203 authored Jan 19, 2025
2 parents a7d4b3e + 04b0560 commit e790ea5
Show file tree
Hide file tree
Showing 46 changed files with 460 additions and 521 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
"@typescript-eslint/eslint-plugin": "8.20.0",
"@typescript-eslint/parser": "8.20.0",
"concurrently": "^9.1.0",
"eslint": "^9.18.0",
"eslint": "^7.0.0",
"eslint-config-prettier": "^10.0.1",
"eslint-config-react-app": "^7.0.1",
"eslint-plugin-cypress": "latest",
Expand Down
30 changes: 14 additions & 16 deletions src/backend/src/controllers/teams.controllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,6 @@ export default class TeamsController {
}
}

static async setInitialTeamMember(req: Request, res: Response, next: NextFunction) {
try {
const { userId } = req.body;
const { teamId } = req.params;

const team = await TeamsService.setInitialTeamMember(teamId, userId, req.organization);
res.status(200).json(team);
} catch (error: unknown) {
next(error);
}
}

static async setTeamMembers(req: Request, res: Response, next: NextFunction) {
try {
const { userIds } = req.body;
Expand Down Expand Up @@ -150,15 +138,25 @@ export default class TeamsController {
}
}

static async toggleOnboardingUser(req: Request, res: Response, next: NextFunction) {
static async setOnboardingUser(req: Request, res: Response, next: NextFunction) {
try {
const { teamTypeId } = req.params;

const updatedTeamType = await TeamsService.toggleOnboardingUser(req.currentUser, teamTypeId, req.organization);
const updatedTeamType = await TeamsService.setOnboardingUser(req.currentUser, teamTypeId, req.organization);

res.status(200).json(updatedTeamType);
res.status(200).json(updatedTeamType);
} catch (error: unknown) {
next(error);
next(error);
}
}

static async completeOnboarding(req: Request, res: Response, next: NextFunction) {
try {
await TeamsService.completeOnboarding(req.currentUser, req.organization);

res.status(200).json({ message: 'Successfully completed onboarding' });
} catch (error: unknown) {
next(error);
}
}

Expand Down
10 changes: 3 additions & 7 deletions src/backend/src/routes/teams.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,6 @@ teamsRouter.get('/', TeamsController.getAllTeams);
teamsRouter.get('/archive', TeamsController.getAllArchivedTeams);
teamsRouter.get('/:teamId', TeamsController.getSingleTeam);

teamsRouter.post(
'/:teamId/set-initial-member',
nonEmptyString(body('userId')),
validateInputs,
TeamsController.setInitialTeamMember
);
teamsRouter.post(
'/:teamId/set-members',
body('userIds').isArray(),
Expand Down Expand Up @@ -60,7 +54,9 @@ teamsRouter.get('/teamType/:teamTypeId/single', TeamsController.getSingleTeamTyp

teamsRouter.post('/:teamId/set-team-type', nonEmptyString(body('teamTypeId')), validateInputs, TeamsController.setTeamType);

teamsRouter.post('/teamType/:teamTypeId/toggle-onboarding-user', TeamsController.toggleOnboardingUser);
teamsRouter.post('/teamType/:teamTypeId/set-onboarding-user', TeamsController.setOnboardingUser);

teamsRouter.post('/teamType/complete-onboarding', TeamsController.completeOnboarding);

teamsRouter.post(
'/teamType/create',
Expand Down
4 changes: 2 additions & 2 deletions src/backend/src/services/description-bullets.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import prisma from '../prisma/prisma';
import { hasBulletCheckingPermissions } from '../utils/description-bullets.utils';
import { AccessDeniedException, HttpException, NotFoundException, DeletedException } from '../utils/errors.utils';
import descriptionBulletTransformer from '../transformers/description-bullets.transformer';
import { DescriptionBullet, DescriptionBulletType, OrganizationPreview, isAdmin } from 'shared';
import { DescriptionBullet, DescriptionBulletType, isAdmin } from 'shared';
import { getDescriptionBulletQueryArgs } from '../prisma-query-args/description-bullets.query-args';
import { userHasPermission } from '../utils/users.utils';

Expand All @@ -19,7 +19,7 @@ export default class DescriptionBulletsService {
static async checkDescriptionBullet(
user: User,
descriptionId: string,
organization: OrganizationPreview
organization: Organization
): Promise<DescriptionBullet> {
const originalDB = await prisma.description_Bullet.findUnique({
where: { descriptionId },
Expand Down
2 changes: 1 addition & 1 deletion src/backend/src/services/notifications.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ export default class NotificationsService {
designReviews.forEach((designReview) => {
const teamSlackIds = designReview.wbsElement.project
? designReview.wbsElement.project.teams.map((team) => team.slackId)
: designReview.wbsElement.workPackage?.project.teams.map((team) => team.slackId) ?? [];
: (designReview.wbsElement.workPackage?.project.teams.map((team) => team.slackId) ?? []);

teamSlackIds.forEach((teamSlackId) => {
const currentTasks = designReviewTeamMap.get(teamSlackId);
Expand Down
27 changes: 19 additions & 8 deletions src/backend/src/services/onboarding.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,25 +46,36 @@ export default class OnboardingServices {
* @returns all the checklists for the given teamType Ids
*/
static async getUsersChecklists(userId: string, organization: Organization) {
const user = await prisma.user.findUnique({ where: { userId } });
const user = await prisma.user.findUnique({ where: { userId }, include: { onboardingTeamTypes: true } });
if (!user) {
throw new NotFoundException('User', userId);
}

const teamTypes = await prisma.team_Type.findMany({
const teamTypeIds = user.onboardingTeamTypes.map((teamType) => teamType.teamTypeId);

const teamTypeChecklists = await prisma.checklist.findMany({
where: {
organizationId: organization.organizationId,
usersOnboarding: { some: { userId } }
dateDeleted: null,
teamTypeId: { in: teamTypeIds },
parentChecklistId: null
},
include: {
subtasks: {
include: {
usersChecked: true
}
},
teamType: true
}
});

const teamTypeIds = teamTypes.map((teamType) => teamType.teamTypeId);

const teamTypeChecklists = await prisma.checklist.findMany({
const generalChecklists = await prisma.checklist.findMany({
where: {
organizationId: organization.organizationId,
dateDeleted: null,
teamTypeId: { in: teamTypeIds },
teamTypeId: null,
teamId: null,
parentChecklistId: null
},
include: {
Expand All @@ -77,7 +88,7 @@ export default class OnboardingServices {
}
});

return teamTypeChecklists;
return [...generalChecklists, ...teamTypeChecklists];
}

/**
Expand Down
88 changes: 28 additions & 60 deletions src/backend/src/services/teams.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,36 +66,6 @@ export default class TeamsService {
return teamTransformer(team);
}

/**
* Sets the initial team member for a team
* @param teamId the id of the team to add the user to
* @param userId the id of the user to add to the team
* @param organizationId The organization the user is currently in
* @returns the updated team
*/
static async setInitialTeamMember(teamId: string, userId: string, organization: Organization) {
const team = await TeamsService.getSingleTeam(teamId, organization);
if (team.dateArchived) throw new HttpException(400, 'Cannot edit the members of an archived team');

const user = await prisma.user.findUnique({
where: { userId }
});

if (!user) throw new NotFoundException('User', userId);

const updateTeam = await prisma.team.update({
where: { teamId },
data: {
members: {
connect: { userId }
}
},
...getTeamQueryArgs(organization.organizationId)
});

return teamTransformer(updateTeam);
}

/**
* Update the given teamId's team's members
* @param submitter a user who's making this request
Expand Down Expand Up @@ -611,7 +581,7 @@ export default class TeamsService {
* @param organization the organization the user is currently in
* @returns the updated team type
*/
static async toggleOnboardingUser(submitter: User, teamTypeId: string, organization: Organization): Promise<TeamType> {
static async setOnboardingUser(submitter: User, teamTypeId: string, organization: Organization): Promise<TeamType> {
const teamType = await prisma.team_Type.findUnique({
where: { teamTypeId, organizationId: organization.organizationId },
include: { usersOnboarding: true }
Expand All @@ -620,51 +590,49 @@ export default class TeamsService {
if (!teamType) throw new NotFoundException('Team Type', teamTypeId);

// if the user is in any onboarding team type, remove them
const user = await prisma.user.update({
await prisma.user.update({
where: { userId: submitter.userId },
include: {
roles: true
},
data: {
onboardingTeamTypes: {
set: []
}
}
});

const isUserInTeam = teamType.usersOnboarding.some((user) => user.userId === submitter.userId);

await prisma.team_Type.update({
const updatedTeamType = await prisma.team_Type.update({
where: { teamTypeId },
data: {
usersOnboarding: isUserInTeam
? { disconnect: { userId: submitter.userId } }
: { connect: { userId: submitter.userId } }
usersOnboarding: { connect: { userId: submitter.userId } }
}
});

// update the users role to member after they complete their onboarding
if (isUserInTeam) {
const currentRole = user.roles.find((role) => role.organizationId === organization.organizationId);
if (currentRole && currentRole.roleType !== RoleEnum.MEMBER) {
await prisma.role.update({
where: {
uniqueRole: { userId: user.userId, organizationId: organization.organizationId }
},
data: {
roleType: RoleEnum.MEMBER
}
});
}
}
return teamTypeTransformer(updatedTeamType);
}

const updatedTeamType = await prisma.team_Type.findUnique({
where: { teamTypeId }
static async completeOnboarding(submitter: User, organization: Organization) {
// remove the user from any onboardingTeamTypes they are a part of
const user = await prisma.user.update({
where: { userId: submitter.userId },
include: { roles: true },
data: {
onboardingTeamTypes: {
set: []
}
}
});

if (!updatedTeamType) throw new NotFoundException('Team Type', teamTypeId);

return teamTypeTransformer(updatedTeamType);
// update the users role to member after they complete their onboarding
const currentRole = user.roles.find((role) => role.organizationId === organization.organizationId);
if (currentRole && currentRole.roleType !== RoleEnum.MEMBER) {
await prisma.role.update({
where: {
uniqueRole: { userId: user.userId, organizationId: organization.organizationId }
},
data: {
roleType: RoleEnum.MEMBER
}
});
}
}

static async setTeamTypeImage(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ const changeRequestTransformer = (
budgetImpact: changeRequest.scopeChangeRequest?.budgetImpact ?? undefined,
timelineImpact: changeRequest.scopeChangeRequest?.timelineImpact ?? undefined,
proposedSolutions: changeRequest.scopeChangeRequest
? changeRequest.scopeChangeRequest?.proposedSolutions.map(proposedSolutionTransformer) ?? []
? (changeRequest.scopeChangeRequest?.proposedSolutions.map(proposedSolutionTransformer) ?? [])
: undefined,
originalProjectData: changeRequest.scopeChangeRequest?.wbsOriginalData?.projectProposedChanges
? projectProposedChangesTransformer(changeRequest.scopeChangeRequest.wbsOriginalData)
Expand Down
2 changes: 1 addition & 1 deletion src/backend/src/utils/change-requests.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export const convertCRScopeWhyType = (whyType: Scope_CR_Why_Type): ChangeRequest
MAINTENANCE: ChangeRequestReason.Maintenance,
OTHER_PROJECT: ChangeRequestReason.OtherProject,
OTHER: ChangeRequestReason.Other
}[whyType]);
})[whyType];

/**
* This function updates the start date of all the blockings (and nested blockings) of the initial given work package.
Expand Down
4 changes: 2 additions & 2 deletions src/backend/src/utils/slack.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -384,8 +384,8 @@ export const sendDRScheduledSlackNotif = async (
zoomLink && designReview.isInPerson
? `in ${designReview.location} and ${zoomLink}`
: designReview.isInPerson
? `in ${designReview.location}`
: zoomLink;
? `in ${designReview.location}`
: zoomLink;

const msg = `:spiral_calendar_pad: Design Review for *${drName}* has been scheduled for *${drTime}* ${location} by ${drSubmitter}`;
const docLink = designReview.docTemplateLink ? `<${designReview.docTemplateLink}|Doc Link>` : '';
Expand Down
4 changes: 2 additions & 2 deletions src/backend/src/utils/tasks.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ export const convertTaskPriority = (priority: Task_Priority): TaskPriority =>
LOW: TaskPriority.Low,
MEDIUM: TaskPriority.Medium,
HIGH: TaskPriority.High
}[priority]);
})[priority];

export const convertTaskStatus = (status: Task_Status): TaskStatus =>
({
IN_BACKLOG: TaskStatus.IN_BACKLOG,
IN_PROGRESS: TaskStatus.IN_PROGRESS,
DONE: TaskStatus.DONE
}[status]);
})[status];

export const hasPermissionToEditTask = async (user: User, taskId: string): Promise<boolean> => {
const task = await prisma.task.findUnique({
Expand Down
2 changes: 1 addition & 1 deletion src/backend/src/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ export const convertStatus = (status: WBS_Element_Status): WbsElementStatus =>
INACTIVE: WbsElementStatus.Inactive,
ACTIVE: WbsElementStatus.Active,
COMPLETE: WbsElementStatus.Complete
}[status]);
})[status];
10 changes: 5 additions & 5 deletions src/backend/tests/unmocked/statistics.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ describe('Statistics Tests', () => {
new Date(new Date('12/12/2024').getTime() + 10000)
);

expect(result).toContain({
expect(result).toMatchObject({
...expectedCreatedGraphBase,
graphType: 'PROJECT_BUDGET_BY_DIVISION',
graphDisplayType: 'BAR'
Expand Down Expand Up @@ -141,7 +141,7 @@ describe('Statistics Tests', () => {
new Date(new Date('12/12/2024').getTime() + 10000)
);

expect(result).toContain({
expect(result).toMatchObject({
...expectedCreatedGraphBase,
graphType: 'PROJECT_BUDGET_BY_DIVISION',
graphDisplayType: 'PIE',
Expand Down Expand Up @@ -178,7 +178,7 @@ describe('Statistics Tests', () => {
new Date(new Date().getTime() + 100000)
);

expect(result).toContain({
expect(result).toMatchObject({
...expectedCreatedGraphBase,
graphType: 'PROJECT_BUDGET_BY_DIVISION',
graphDisplayType: 'BAR',
Expand Down Expand Up @@ -213,7 +213,7 @@ describe('Statistics Tests', () => {
[]
);

expect(result).toContain({
expect(result).toMatchObject({
...expectedCreatedGraphBase,
graphType: 'PROJECT_BUDGET_BY_DIVISION',
graphDisplayType: 'BAR',
Expand Down Expand Up @@ -250,7 +250,7 @@ describe('Statistics Tests', () => {
new Date('12/12/1971')
);

expect(result).toContain({
expect(result).toMatchObject({
...expectedCreatedGraphBase,
graphType: 'PROJECT_BUDGET_BY_DIVISION',
graphDisplayType: 'BAR',
Expand Down
6 changes: 4 additions & 2 deletions src/backend/vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
include: ['**/*.test.ts'],
singleThread: true,
globals: true
globals: true,
maxConcurrency: 1,
maxWorkers: 1,
minWorkers: 1
}
});
Loading

0 comments on commit e790ea5

Please sign in to comment.