Skip to content

Commit 499f637

Browse files
committed
#4025 guest change requests type + getAllGuestCrs endpoint + hooks now used on guest cr page
1 parent b40ecb1 commit 499f637

13 files changed

Lines changed: 161 additions & 59 deletions

File tree

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,15 @@ export default class ChangeRequestsController {
2323
}
2424
}
2525

26+
static async getAllGuestChangeRequests(req: Request, res: Response, next: NextFunction) {
27+
try {
28+
const changeRequests = await ChangeRequestsService.getAllGuestChangeRequests(req.organization);
29+
res.status(200).json(changeRequests);
30+
} catch (error: unknown) {
31+
next(error);
32+
}
33+
}
34+
2635
static async getToReviewChangeRequests(req: Request, res: Response, next: NextFunction) {
2736
try {
2837
const changeRequests = await ChangeRequestsService.getToReviewChangeRequests(req.currentUser, req.organization);

src/backend/src/prisma-query-args/change-requests.query-args.ts

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -50,41 +50,65 @@ export const getManyChangeRequestQueryArgs = (organizationId: string) =>
5050
Prisma.validator<Prisma.Change_RequestDefaultArgs>()({
5151
include: {
5252
submitter: getUserQueryArgs(organizationId),
53+
wbsElement: true,
54+
category: getReimbursementProductOtherReasonQueryArgs(organizationId),
55+
accountCode: getAccountCodeQueryArgs(organizationId),
56+
reviewer: getUserQueryArgs(organizationId),
57+
stageGateChangeRequest: true,
58+
changes: true,
59+
activationChangeRequest: {
60+
include: { lead: getUserQueryArgs(organizationId), manager: getUserQueryArgs(organizationId) }
61+
},
62+
budgetChangeRequest: true,
63+
deletedBy: getUserQueryArgs(organizationId),
64+
requestedReviewers: getUserQueryArgs(organizationId),
65+
leadershipChangeRequest: {
66+
include: { lead: getUserQueryArgs(organizationId), manager: getUserQueryArgs(organizationId) }
67+
}
68+
}
69+
});
70+
71+
export type ChangeRequestGuestQueryArgs = ReturnType<typeof getGuestChangeRequestQueryArgs>;
72+
73+
export const getGuestChangeRequestQueryArgs = (organizationId: string) =>
74+
Prisma.validator<Prisma.Change_RequestDefaultArgs>()({
75+
select: {
76+
crId: true,
77+
identifier: true,
78+
dateSubmitted: true,
79+
type: true,
80+
accepted: true,
81+
dateReviewed: true,
82+
submitter: getUserQueryArgs(organizationId),
83+
reviewer: getUserQueryArgs(organizationId),
84+
changes: { select: { changeId: true } },
5385
wbsElement: {
54-
include: {
86+
select: {
87+
carNumber: true,
88+
projectNumber: true,
89+
workPackageNumber: true,
90+
name: true,
5591
project: {
56-
include: {
92+
select: {
93+
wbsElement: { select: { name: true } },
5794
teams: {
58-
include: { teamType: true }
95+
select: { teamType: { select: { name: true } } }
5996
}
6097
}
6198
},
6299
workPackage: {
63-
include: {
100+
select: {
64101
project: {
65-
include: {
102+
select: {
103+
wbsElement: { select: { name: true } },
66104
teams: {
67-
include: { teamType: true }
105+
select: { teamType: { select: { name: true } } }
68106
}
69107
}
70108
}
71109
}
72110
}
73111
}
74-
},
75-
category: getReimbursementProductOtherReasonQueryArgs(organizationId),
76-
accountCode: getAccountCodeQueryArgs(organizationId),
77-
reviewer: getUserQueryArgs(organizationId),
78-
stageGateChangeRequest: true,
79-
changes: true,
80-
activationChangeRequest: {
81-
include: { lead: getUserQueryArgs(organizationId), manager: getUserQueryArgs(organizationId) }
82-
},
83-
budgetChangeRequest: true,
84-
deletedBy: getUserQueryArgs(organizationId),
85-
requestedReviewers: getUserQueryArgs(organizationId),
86-
leadershipChangeRequest: {
87-
include: { lead: getUserQueryArgs(organizationId), manager: getUserQueryArgs(organizationId) }
88112
}
89113
}
90114
});
@@ -98,9 +122,7 @@ export const getChangeRequestWithProjectAndWorkPackageQueryArgs = (organizationI
98122
workPackage: getWorkPackageQueryArgs(organizationId),
99123
project: {
100124
include: {
101-
teams: {
102-
include: { teamType: true }
103-
}
125+
teams: true
104126
}
105127
},
106128
descriptionBullets: { where: { dateDeleted: null } },

src/backend/src/prisma/schema.prisma

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -739,11 +739,11 @@ model Receipt {
739739
model Reimbursement_Request {
740740
reimbursementRequestId String @id @default(uuid())
741741
identifier Int
742-
saboId String? @unique
742+
saboId String? @unique
743743
dateCreated DateTime @default(now())
744744
dateDeleted DateTime?
745745
dateOfExpense DateTime?
746-
description String @default("")
746+
description String @default("")
747747
reimbursementStatuses Reimbursement_Status[]
748748
recipientId String
749749
recipient User @relation(name: "reimbursementRequestRecipient", fields: [recipientId], references: [userId])

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
const changeRequestsRouter = express.Router();
1515

1616
changeRequestsRouter.get('/', ChangeRequestsController.getAllChangeRequests);
17+
changeRequestsRouter.get('/guest', ChangeRequestsController.getAllGuestChangeRequests);
1718

1819
changeRequestsRouter.get('/to-review', ChangeRequestsController.getToReviewChangeRequests);
1920
changeRequestsRouter.get('/unreviewed', ChangeRequestsController.getUnreviewedChangeRequests);

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

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ import {
2828
DeletedException,
2929
InvalidOrganizationException
3030
} from '../utils/errors.utils.js';
31-
import changeRequestTransformer, { changeRequestManyTransformer } from '../transformers/change-requests.transformer.js';
31+
import changeRequestTransformer, {
32+
changeRequestManyTransformer,
33+
guestChangeRequestTransformer
34+
} from '../transformers/change-requests.transformer.js';
3235
import {
3336
allChangeRequestsReviewed,
3437
validateProposedChangesFields,
@@ -55,11 +58,13 @@ import {
5558
ChangeRequestWithProjectAndWorkPackageQueryArgs,
5659
getChangeRequestQueryArgs,
5760
getChangeRequestWithProjectAndWorkPackageQueryArgs,
61+
getGuestChangeRequestQueryArgs,
5862
getManyChangeRequestQueryArgs
5963
} from '../prisma-query-args/change-requests.query-args.js';
6064
import proposedSolutionTransformer from '../transformers/proposed-solutions.transformer.js';
6165
import { getProposedSolutionQueryArgs } from '../prisma-query-args/proposed-solutions.query-args.js';
6266
import { sendCrRequestReviewPopUp, sendCrReviewedPopUp } from '../utils/pop-up.utils.js';
67+
import { GuestChangeRequest } from '../../../shared/src/types/change-request-types.js';
6368

6469
export default class ChangeRequestsService {
6570
/**
@@ -97,6 +102,20 @@ export default class ChangeRequestsService {
97102
return changeRequests.map(changeRequestManyTransformer);
98103
}
99104

105+
/**
106+
* gets all the change requests in the database for the given organization, tailored to the guest cr page
107+
* @param organization The organization the user is currently in
108+
* @returns All of the change requests
109+
*/
110+
static async getAllGuestChangeRequests(organization: Organization): Promise<GuestChangeRequest[]> {
111+
const changeRequests = await prisma.change_Request.findMany({
112+
where: { dateDeleted: null, organizationId: organization.organizationId },
113+
...getGuestChangeRequestQueryArgs(organization.organizationId)
114+
});
115+
116+
return changeRequests.map(guestChangeRequestTransformer);
117+
}
118+
100119
/**
101120
* Gets a users change requests that they have been requested reviewer for or, if they are leadership, their teams change requests as well
102121
*

src/backend/src/transformers/change-requests.transformer.ts

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ import {
1010
WorkPackageStage,
1111
BudgetChangeRequest,
1212
isWorkPackageWbs,
13-
LeadershipChangeRequest
13+
LeadershipChangeRequest,
14+
ChangeRequestStatus
1415
} from 'shared';
1516
import { wbsNumOf } from '../utils/utils.js';
1617
import { calculateChangeRequestStatus, convertCRScopeWhyType } from '../utils/change-requests.utils.js';
@@ -25,10 +26,12 @@ import {
2526
} from '../prisma-query-args/scope-change-requests.query-args.js';
2627
import { HttpException } from '../utils/errors.utils.js';
2728
import {
29+
ChangeRequestGuestQueryArgs,
2830
ChangeRequestManyQueryArgs,
2931
ChangeRequestWithProjectAndWorkPackageQueryArgs
3032
} from '../prisma-query-args/change-requests.query-args.js';
3133
import { accountCodeTransformer, otherProductReasonTransformer } from './reimbursement-requests.transformer.js';
34+
import { GuestChangeRequest } from '../../../shared/src/types/change-request-types.js';
3235

3336
const projectProposedChangesTransformer = (
3437
wbsProposedChanges: Prisma.Wbs_Proposed_ChangesGetPayload<WbsProposedChangeQueryArgs>
@@ -133,14 +136,7 @@ export const changeRequestManyTransformer = (
133136
confirmDone: changeRequest.stageGateChangeRequest?.confirmDone ?? undefined,
134137
requestedReviewers: changeRequest.requestedReviewers.map(userTransformer) ?? [],
135138
//budget cr fields
136-
proposedBudget: changeRequest.budgetChangeRequest?.proposedBudget ?? undefined,
137-
teamTypeNames: [
138-
...new Set(
139-
(changeRequest.wbsElement?.project ?? changeRequest.wbsElement?.workPackage?.project)?.teams
140-
.map((t) => t.teamType?.name)
141-
.filter((name): name is string => name != null) ?? []
142-
)
143-
]
139+
proposedBudget: changeRequest.budgetChangeRequest?.proposedBudget ?? undefined
144140
};
145141
};
146142

@@ -231,15 +227,46 @@ const changeRequestTransformer = (
231227
confirmDone: changeRequest.stageGateChangeRequest?.confirmDone ?? undefined,
232228
requestedReviewers: changeRequest.requestedReviewers.map(userTransformer) ?? [],
233229
//budget cr fields
234-
proposedBudget: changeRequest.budgetChangeRequest?.proposedBudget ?? undefined,
235-
teamTypeNames: [
236-
...new Set(
237-
(changeRequest.wbsElement?.project ?? changeRequest.wbsElement?.workPackage?.project)?.teams
238-
.map((t) => t.teamType?.name)
239-
.filter((name): name is string => name != null) ?? []
240-
)
241-
]
230+
proposedBudget: changeRequest.budgetChangeRequest?.proposedBudget ?? undefined
242231
};
243232
};
244233

245234
export default changeRequestTransformer;
235+
236+
export const guestChangeRequestTransformer = (
237+
changeRequest: Prisma.Change_RequestGetPayload<ChangeRequestGuestQueryArgs>
238+
): GuestChangeRequest => {
239+
const status = changeRequest.changes.length
240+
? ChangeRequestStatus.Implemented
241+
: changeRequest.accepted && changeRequest.dateReviewed
242+
? ChangeRequestStatus.Accepted
243+
: changeRequest.dateReviewed
244+
? ChangeRequestStatus.Denied
245+
: ChangeRequestStatus.Open;
246+
247+
const wbsName = changeRequest.wbsElement
248+
? !isWorkPackageWbs(changeRequest.wbsElement)
249+
? changeRequest.wbsElement?.name
250+
: `${changeRequest.wbsElement?.workPackage?.project.wbsElement.name} - ${changeRequest.wbsElement?.name}`
251+
: undefined;
252+
253+
return {
254+
crId: changeRequest.crId,
255+
submitter: userTransformer(changeRequest.submitter),
256+
identifier: changeRequest.identifier,
257+
type: changeRequest.type,
258+
status,
259+
teamTypeNames: changeRequest.wbsElement
260+
? isWorkPackageWbs(changeRequest.wbsElement)
261+
? (changeRequest.wbsElement.workPackage?.project?.teams
262+
.map((team) => team.teamType?.name)
263+
.filter((name) => name !== undefined) ?? [])
264+
: (changeRequest.wbsElement.project?.teams.map((team) => team.teamType?.name).filter((name) => name !== undefined) ??
265+
[])
266+
: [],
267+
accepted: changeRequest.accepted ?? undefined,
268+
reviewer: changeRequest.reviewer ? userTransformer(changeRequest.reviewer) : undefined,
269+
wbsNum: changeRequest.wbsElement ? wbsNumOf(changeRequest.wbsElement) : undefined,
270+
wbsName
271+
};
272+
};

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,5 @@ export const sharedChangeRequest: SharedChangeRequest = {
5959
type: ChangeRequestType.Redefinition,
6060
status: ChangeRequestStatus.Open,
6161
requestedReviewers: [],
62-
identifier: 1,
63-
teamTypeNames: []
62+
identifier: 1
6463
};

src/frontend/src/apis/change-requests.api.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55

66
import axios from '../utils/axios';
7-
import { ChangeRequest, WbsNumber, ChangeRequestType } from 'shared';
7+
import { ChangeRequest, WbsNumber, ChangeRequestType, GuestChangeRequest } from 'shared';
88
import { apiUrls } from '../utils/urls';
99
import { changeRequestTransformer } from './transformers/change-requests.transformers';
1010
import { CreateStandardChangeRequestPayload } from '../hooks/change-requests.hooks';
@@ -18,6 +18,12 @@ export const getAllChangeRequests = () => {
1818
});
1919
};
2020

21+
export const getAllGuestChangeRequests = () => {
22+
return axios.get<GuestChangeRequest[]>(apiUrls.guestChangeRequests(), {
23+
transformResponse: (data) => JSON.parse(data)
24+
});
25+
};
26+
2127
export const getToReviewChangeRequests = () => {
2228
return axios.get<ChangeRequest[]>(apiUrls.toReviewChangeRequests(), {
2329
transformResponse: (data) => JSON.parse(data).map(changeRequestTransformer)

src/frontend/src/hooks/change-requests.hooks.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ import {
1212
ProposedSolutionCreateArgs,
1313
WbsNumber,
1414
WorkPackageProposedChangesCreateArgs,
15-
LeadershipChangeCreateArgs
15+
LeadershipChangeCreateArgs,
16+
GuestChangeRequest
1617
} from 'shared';
1718
import {
1819
createActivationChangeRequest,
@@ -28,7 +29,8 @@ import {
2829
getUnreviewedChangeRequests,
2930
getApprovedChangeRequests,
3031
createBudgetChangeRequest,
31-
createLeadershipChangeRequest
32+
createLeadershipChangeRequest,
33+
getAllGuestChangeRequests
3234
} from '../apis/change-requests.api';
3335

3436
/**
@@ -41,6 +43,13 @@ export const useAllChangeRequests = () => {
4143
});
4244
};
4345

46+
export const useAllGuestChangeRequests = () => {
47+
return useQuery<GuestChangeRequest[], Error>(['guest change requests'], async () => {
48+
const { data } = await getAllGuestChangeRequests();
49+
return data;
50+
});
51+
};
52+
4453
export const useGetToReviewChangeRequests = () => {
4554
return useQuery<ChangeRequest[], Error>(['change requests', 'to-review'], async () => {
4655
const { data } = await getToReviewChangeRequests();

src/frontend/src/pages/ChangeRequestsPage/GuestChangeRequestsPage.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import PageLayout from '../../components/PageLayout';
55
import { useAllTeamTypes } from '../../hooks/team-types.hooks';
66
import { Chip, Typography } from '@mui/material';
77
import { useState } from 'react';
8-
import { useAllChangeRequests } from '../../hooks/change-requests.hooks';
8+
import { useAllChangeRequests, useAllGuestChangeRequests } from '../../hooks/change-requests.hooks';
99
import { ChangeRequest, wbsPipe } from 'shared';
1010
import { ChangeRequestTypeTextPipe, ChangeRequestStatusTextPipe } from '../../utils/enum-pipes';
1111

@@ -58,7 +58,7 @@ const CrCard = ({ cr }: { cr: ChangeRequest }) => {
5858
};
5959

6060
const GuestChangeRequestsPage: React.FC = () => {
61-
const { data: allCrs, isLoading, isError, error } = useAllChangeRequests();
61+
const { data: allCrs, isLoading, isError, error } = useAllGuestChangeRequests();
6262
const [selectedTeamTypes, setSelectedTeamTypes] = useState<string[]>([]);
6363
const isMobilePortrait = useMediaQuery('(max-width:480px)');
6464
const {

0 commit comments

Comments
 (0)