Skip to content

Commit df35084

Browse files
authored
Merge pull request #3962 from Northeastern-Electric-Racing/3776-maintenence---description-field-for-rr
3776 maintenence Description field for rr
2 parents 228e546 + a8893d1 commit df35084

13 files changed

Lines changed: 116 additions & 16 deletions

File tree

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ export default class ReimbursementRequestsController {
8383
otherReimbursementProducts,
8484
wbsReimbursementProducts,
8585
accountCodeId,
86-
totalCost
86+
totalCost,
87+
description
8788
} = req.body;
8889
const user = await getCurrentUserWithUserSettings(res);
8990

@@ -96,7 +97,8 @@ export default class ReimbursementRequestsController {
9697
accountCodeId,
9798
totalCost,
9899
req.organization,
99-
dateOfExpense
100+
dateOfExpense,
101+
description
100102
);
101103
res.status(200).json(createdReimbursementRequest);
102104
} catch (error: unknown) {
@@ -130,7 +132,8 @@ export default class ReimbursementRequestsController {
130132
totalCost,
131133
otherReimbursementProducts,
132134
wbsReimbursementProducts,
133-
receiptPictures
135+
receiptPictures,
136+
description
134137
} = req.body;
135138

136139
const updatedReimbursementRequestId = await ReimbursementRequestService.editReimbursementRequest(
@@ -144,7 +147,8 @@ export default class ReimbursementRequestsController {
144147
receiptPictures,
145148
req.currentUser,
146149
req.organization,
147-
dateOfExpense
150+
dateOfExpense,
151+
description
148152
);
149153
res.status(200).json(updatedReimbursementRequestId);
150154
} catch (error: unknown) {
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-- AlterTable
2+
ALTER TABLE "Reimbursement_Request" ADD COLUMN "description" TEXT NOT NULL DEFAULT '';

src/backend/src/prisma/schema.prisma

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,7 @@ model Reimbursement_Request {
723723
dateCreated DateTime @default(now())
724724
dateDeleted DateTime?
725725
dateOfExpense DateTime?
726+
description String @default("")
726727
reimbursementStatuses Reimbursement_Status[]
727728
recipientId String
728729
recipient User @relation(name: "reimbursementRequestRecipient", fields: [recipientId], references: [userId])

src/backend/src/prisma/seed-data/reimbursement-requests.seed.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ export const seedReimbursementRequests = async (
9797
accountCodes.equipment.accountCodeId,
9898
3500,
9999
organization,
100-
new Date('2024-10-01')
100+
new Date('2024-10-01'),
101+
'Reimbursement request for high performance battery pack'
101102
);
102103
reimbursementRequests.push(rr1);
103104

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ export default class ReimbursementRequestService {
226226
* @param accountCodeId the id of the account code the user made
227227
* @param totalCost the total cost of the reimbursement with tax
228228
* @param organizationId the organization the user is currently in
229+
* @param description the description of the reimbursement request
229230
* @returns the created reimbursement request
230231
*/
231232
static async createReimbursementRequest(
@@ -237,7 +238,8 @@ export default class ReimbursementRequestService {
237238
acccountCodeId: string,
238239
totalCost: number,
239240
organization: Organization,
240-
dateOfExpense?: Date
241+
dateOfExpense?: Date,
242+
description?: string
241243
): Promise<ReimbursementRequest> {
242244
if (await userHasPermission(recipient.userId, organization.organizationId, isGuest))
243245
throw new AccessDeniedGuestException('create a reimbursement request');
@@ -278,7 +280,8 @@ export default class ReimbursementRequestService {
278280
}
279281
},
280282
identifier: numReimbursementRequests + 1,
281-
organization: { connect: { organizationId: organization.organizationId } }
283+
organization: { connect: { organizationId: organization.organizationId } },
284+
description
282285
}
283286
});
284287

@@ -356,6 +359,7 @@ export default class ReimbursementRequestService {
356359
* @param receiptPictures the old receipts that haven't been deleted (new receipts must be separately uploaded)
357360
* @param submitter the person editing the reimbursement request
358361
* @param organizationId the organization the user is currently in
362+
* @param description the updated description of the reimbursement request
359363
* @returns the edited reimbursement request
360364
*/
361365
static async editReimbursementRequest(
@@ -369,7 +373,8 @@ export default class ReimbursementRequestService {
369373
receiptPictures: ReimbursementReceiptCreateArgs[],
370374
submitter: User,
371375
organization: Organization,
372-
dateOfExpense?: Date
376+
dateOfExpense?: Date,
377+
description?: string
373378
): Promise<Reimbursement_Request> {
374379
const oldReimbursementRequest = await prisma.reimbursement_Request.findUnique({
375380
where: { reimbursementRequestId: requestId },
@@ -408,6 +413,7 @@ export default class ReimbursementRequestService {
408413
where: { reimbursementRequestId: oldReimbursementRequest.reimbursementRequestId },
409414
data: {
410415
dateOfExpense: dateOfExpense ?? null,
416+
description,
411417
indexCodeId,
412418
totalCost,
413419
accountCodeId: accountCode.accountCodeId,
@@ -498,6 +504,7 @@ export default class ReimbursementRequestService {
498504
* @param reimbursementId The id of the reimbursement to be edited
499505
* @param editor The user editing the reimbursement
500506
* @param amount The new amount of the reimbursement
507+
* @param description The new description of the reimbursement
501508
* @param dateCreated The new date the reimbursement was created
502509
* @param organizationId The organization the user is currently in
503510
* @returns The updated reimbursement

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export const reimbursementRequestTransformer = (
5151
saboId: reimbursementRequest.saboId ?? undefined,
5252
dateCreated: reimbursementRequest.dateCreated,
5353
dateOfExpense: reimbursementRequest.dateOfExpense ?? undefined,
54+
description: reimbursementRequest.description,
5455
reimbursementStatuses: reimbursementRequest.reimbursementStatuses.map(reimbursementStatusTransformer),
5556
recipient: userTransformer(reimbursementRequest.recipient),
5657
vendor: vendorTransformer(reimbursementRequest.vendor),

src/frontend/src/pages/FinancePage/EditReimbursementRequest/EditReimbursementRequestRenderedDefaultValues.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ const EditReimbursementRequestRenderedDefaultValues: React.FC<{
4141
vendorId: reimbursementRequest.vendor.vendorId,
4242
indexCodeId: reimbursementRequest.indexCode.indexCodeId,
4343
dateOfExpense: reimbursementRequest.dateOfExpense ? new Date(reimbursementRequest.dateOfExpense) : undefined,
44+
description: reimbursementRequest.description,
4445
accountCodeId: reimbursementRequest.accountCode.accountCodeId,
4546
reimbursementProducts: reimbursementRequest.reimbursementProducts.map((product) => ({
4647
id: product.reimbursementProductId,

src/frontend/src/pages/FinancePage/FinanceComponents/ReimbursementRequestInfo.tsx

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Box } from '@mui/material';
1+
import { Box, Tooltip, IconButton } from '@mui/material';
22
import { useLocation, useHistory, useParams } from 'react-router-dom';
33
import { useState, useEffect } from 'react';
44
import { isGuest, ReimbursementRequest } from 'shared';
@@ -14,6 +14,7 @@ import SidePage from './SidePagePopup';
1414
import ReimbursementRequestDetails from '../ReimbursementRequestDetailPage/ReimbursementRequestDetails';
1515
import NERDataGrid, { MapRowResult } from '../../../components/NERDataGrid';
1616
import { GridColDef, GridRenderCellParams } from '@mui/x-data-grid';
17+
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
1718

1819
interface ReimbursementRequestInfoProps {
1920
userReimbursementRequests: ReimbursementRequest[];
@@ -169,6 +170,28 @@ const ReimbursementRequestInfo = ({
169170
flex: 0.7,
170171
minWidth: 180,
171172
valueGetter: (params: any) => dateUndefinedPipe(params.row.dateSubmittedToSabo)
173+
},
174+
{
175+
field: 'description',
176+
headerName: 'Description',
177+
flex: 0.7,
178+
minWidth: 180,
179+
valueGetter: (params: any) => params.row.description,
180+
renderCell: (params: any) => {
181+
const { description } = params.row;
182+
183+
if (!description || description.trim() === '') {
184+
return null;
185+
}
186+
187+
return (
188+
<Tooltip title={description} arrow placement="left">
189+
<IconButton size="small" sx={{ p: 0.5, color: 'white' }}>
190+
<InfoOutlinedIcon fontSize="small" />
191+
</IconButton>
192+
</Tooltip>
193+
);
194+
}
172195
}
173196
);
174197

@@ -212,7 +235,8 @@ const ReimbursementRequestInfo = ({
212235
('$' + centsToDollar((rowData as any).amount)).toLowerCase().includes(lowercase_query) ||
213236
('' + (rowData as any).reimbursementProducts.map((product: any) => product.name))
214237
.toLowerCase()
215-
.includes(lowercase_query)
238+
.includes(lowercase_query) ||
239+
('' + (rowData as any).description).toLowerCase().includes(lowercase_query)
216240
);
217241
});
218242
};

src/frontend/src/pages/FinancePage/ReimbursementRequestDetailPage/ReimbursementRequestDetailsView.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import LocalAtmIcon from '@mui/icons-material/LocalAtm';
1919
import StoreIcon from '@mui/icons-material/Store';
2020
import SellIcon from '@mui/icons-material/Sell';
2121
import CurrencyExchangeIcon from '@mui/icons-material/CurrencyExchange';
22+
import Description from '@mui/icons-material/Description';
2223

2324
import { Typography, useTheme, Link, IconButton } from '@mui/material';
2425
import { Box } from '@mui/system';
@@ -435,7 +436,8 @@ const ReimbursementRequestDetailsView: React.FC<ReimbursementRequestDetailsViewP
435436
{ label: 'SABO Number', icon: <SellIcon fontSize="small" /> },
436437
{ label: 'Refund Source', icon: <CurrencyExchangeIcon fontSize="small" /> },
437438
{ label: 'Expense Type', icon: <CurrencyExchangeIcon fontSize="small" /> },
438-
{ label: 'Assigned To', icon: <PersonOutlineIcon fontSize="small" /> }
439+
{ label: 'Assigned To', icon: <PersonOutlineIcon fontSize="small" /> },
440+
{ label: 'Description', icon: <Description fontSize="small" /> }
439441
];
440442

441443
// grab all unique refund source names
@@ -470,7 +472,8 @@ const ReimbursementRequestDetailsView: React.FC<ReimbursementRequestDetailsViewP
470472
content: refundSourceNames.join(', ')
471473
},
472474
{ content: accountCodePipe(reimbursementRequest.accountCode) },
473-
{ content: fullNamePipe(reimbursementRequest.assignee) }
475+
{ content: fullNamePipe(reimbursementRequest.assignee) },
476+
{ content: reimbursementRequest.description }
474477
];
475478

476479
const { id } = useParams<{ id: string }>();

src/frontend/src/pages/FinancePage/ReimbursementRequestForm/ReimbursementFormView.tsx

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -744,7 +744,26 @@ const ReimbursementRequestFormView: React.FC<ReimbursementRequestFormViewProps>
744744

745745
{/* Receipt Previews */}
746746
<Box sx={{ mt: 2 }}>
747-
<Grid container spacing={2}>
747+
<Box
748+
sx={{
749+
display: 'flex',
750+
gap: 2,
751+
overflowX: 'auto',
752+
overflowY: 'hidden',
753+
maxHeight: '250px',
754+
paddingBottom: '10px',
755+
'&::-webkit-scrollbar': {
756+
height: '0.55rem' // Adjust the the thickness of the scrollbar
757+
},
758+
'&::-webkit-scrollbar-thumb': {
759+
backgroundColor: '#EF4345', //FinishLine 'red' color
760+
borderRadius: '50px' //make the scrollbar rounded
761+
},
762+
'&::-webkit-scrollbar-thumb:hover': {
763+
backgroundColor: '#b0191a' // Change to a darker shade of red on hover
764+
}
765+
}}
766+
>
748767
{receiptFiles.map((receiptFile, index) => {
749768
let previewUrl = '';
750769
// if file is newly uploaded, show local preview, else show google drive preview
@@ -755,7 +774,7 @@ const ReimbursementRequestFormView: React.FC<ReimbursementRequestFormViewProps>
755774
}
756775

757776
return (
758-
<Grid item xs={6} key={index}>
777+
<Grid item xs={6} key={index} sx={{ minWidth: '250px' }}>
759778
<Stack
760779
direction="column"
761780
spacing={1}
@@ -835,9 +854,40 @@ const ReimbursementRequestFormView: React.FC<ReimbursementRequestFormViewProps>
835854
</Grid>
836855
);
837856
})}
838-
</Grid>
857+
</Box>
839858
</Box>
840859
</FormControl>
860+
861+
{/* Description */}
862+
<FormControl sx={{ borderRadius: '25px', width: '100%' }}>
863+
<FormLabel
864+
sx={{
865+
color: '#dd524c',
866+
textShadow: '1.5px 0 #dd524c',
867+
letterSpacing: '0.5px',
868+
textDecoration: 'underline',
869+
textUnderlineOffset: '3.5px',
870+
textDecorationThickness: '0.6px',
871+
fontSize: 'x-large',
872+
fontWeight: 'bold'
873+
}}
874+
>
875+
Description
876+
</FormLabel>
877+
<Controller
878+
name="description"
879+
control={control}
880+
render={({ field: { onChange, value } }) => (
881+
<TextField
882+
value={value || ''}
883+
onChange={onChange}
884+
placeholder="Enter Description"
885+
multiline
886+
rows={3}
887+
/>
888+
)}
889+
/>
890+
</FormControl>
841891
</Stack>
842892
</Grid>
843893
</Grid>

0 commit comments

Comments
 (0)