Skip to content

Commit 5838fd6

Browse files
committed
Merge branch 'develop' into gantt-chart-tasks
2 parents 4326e88 + 2846ab1 commit 5838fd6

57 files changed

Lines changed: 2292 additions & 579 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.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
},
6868
"dependencies": {
6969
"@types/multer": "^1.4.12",
70+
"canvas-confetti": "^1.9.3",
7071
"mitt": "^3.0.1",
7172
"react-hook-form-persist": "^3.0.0",
7273
"recharts": "^2.15.3",
@@ -77,6 +78,7 @@
7778
"@babel/plugin-transform-object-assign": "^7.18.6",
7879
"@babel/preset-react": "^7.18.6",
7980
"@babel/preset-typescript": "^7.18.6",
81+
"@types/canvas-confetti": "^1.9.0",
8082
"@types/jest": "^29.5.14",
8183
"@types/node": "20.0.0",
8284
"@typescript-eslint/eslint-plugin": "8.20.0",

src/backend/src/controllers/organizations.controllers.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,4 +217,27 @@ export default class OrganizationsController {
217217
next(error);
218218
}
219219
}
220+
221+
static async getFinanceDelegates(req: Request, res: Response, next: NextFunction) {
222+
try {
223+
const financeDelegates = await OrganizationsService.getFinanceDelegates(req.organization.organizationId);
224+
res.status(200).json(financeDelegates);
225+
} catch (error: unknown) {
226+
next(error);
227+
}
228+
}
229+
230+
static async setFinanceDelegates(req: Request, res: Response, next: NextFunction) {
231+
try {
232+
const { userIds } = req.body;
233+
const updatedDelegates = await OrganizationsService.setFinanceDelegates(
234+
req.currentUser,
235+
req.organization.organizationId,
236+
userIds
237+
);
238+
res.status(200).json(updatedDelegates);
239+
} catch (error: unknown) {
240+
next(error);
241+
}
242+
}
220243
}

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

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,8 @@ export default class ReimbursementRequestsController {
217217
req.currentUser,
218218
name,
219219
req.organization,
220-
taxExempt,
221-
twoFactorContacts,
220+
taxExempt ?? false,
221+
twoFactorContacts ?? [],
222222
notes,
223223
username,
224224
password,
@@ -300,11 +300,26 @@ export default class ReimbursementRequestsController {
300300
}
301301
}
302302

303-
static async approveReimbursementRequest(req: Request, res: Response, next: NextFunction) {
303+
static async inputReimbursementRequestInSabo(req: Request, res: Response, next: NextFunction) {
304+
try {
305+
const { requestId } = req.params;
306+
307+
const reimbursementStatus = await ReimbursementRequestService.inputReimbursementRequestInSabo(
308+
requestId,
309+
req.currentUser,
310+
req.organization
311+
);
312+
res.status(200).json(reimbursementStatus);
313+
} catch (error: unknown) {
314+
next(error);
315+
}
316+
}
317+
318+
static async markReimbursementRequestAsSaboSubmitted(req: Request, res: Response, next: NextFunction) {
304319
try {
305320
const { requestId } = req.params;
306321

307-
const reimbursementStatus = await ReimbursementRequestService.approveReimbursementRequest(
322+
const reimbursementStatus = await ReimbursementRequestService.markReimbursementRequestAsSaboSubmitted(
308323
requestId,
309324
req.currentUser,
310325
req.organization
@@ -525,6 +540,23 @@ export default class ReimbursementRequestsController {
525540
}
526541
}
527542

543+
static async editIndexCode(req: Request, res: Response, next: NextFunction) {
544+
try {
545+
const { name, code } = req.body;
546+
const { indexCodeId } = req.params;
547+
const updatedIndexCode = await ReimbursementRequestService.editIndexCode(
548+
req.currentUser,
549+
req.organization,
550+
indexCodeId,
551+
name,
552+
code
553+
);
554+
res.status(200).json(updatedIndexCode);
555+
} catch (error: unknown) {
556+
next(error);
557+
}
558+
}
559+
528560
static async deleteIndexCode(req: Request, res: Response, next: NextFunction) {
529561
try {
530562
const { indexCodeId } = req.params;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
-- AlterEnum
2+
ALTER TYPE "public"."Reimbursement_Status_Type" ADD VALUE 'PENDING_SABO_SUBMISSION';
3+
4+
-- CreateTable
5+
CREATE TABLE "public"."_financeDelegates" (
6+
"A" TEXT NOT NULL,
7+
"B" TEXT NOT NULL,
8+
9+
CONSTRAINT "_financeDelegates_AB_pkey" PRIMARY KEY ("A","B")
10+
);
11+
12+
-- CreateIndex
13+
CREATE INDEX "_financeDelegates_B_index" ON "public"."_financeDelegates"("B");
14+
15+
-- AddForeignKey
16+
ALTER TABLE "public"."_financeDelegates" ADD CONSTRAINT "_financeDelegates_A_fkey" FOREIGN KEY ("A") REFERENCES "public"."Organization"("organizationId") ON DELETE CASCADE ON UPDATE CASCADE;
17+
18+
-- AddForeignKey
19+
ALTER TABLE "public"."_financeDelegates" ADD CONSTRAINT "_financeDelegates_B_fkey" FOREIGN KEY ("B") REFERENCES "public"."User"("userId") ON DELETE CASCADE ON UPDATE CASCADE;

src/backend/src/prisma/schema.prisma

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ enum Reimbursement_Status_Type {
7878
PENDING_LEADERSHIP_APPROVAL
7979
LEADERSHIP_APPROVED
8080
PENDING_FINANCE
81+
PENDING_SABO_SUBMISSION
8182
SABO_SUBMITTED
8283
ADVISOR_APPROVED
8384
REIMBURSED
@@ -258,6 +259,7 @@ model User {
258259
reimbursementRequestComments Reimbursement_Request_Comment[] @relation(name: "createdReimbursementRequestComments")
259260
deletedReimbursementRequestComments Reimbursement_Request_Comment[] @relation(name: "deletedReimbursementRequestComments")
260261
deletedSponsorTiers Sponsor_Tier[]
262+
financeDelegateForOrganizations Organization[] @relation(name: "financeDelegates")
261263
}
262264

263265
model Role {
@@ -1206,6 +1208,7 @@ model Organization {
12061208
sponsors Sponsor[]
12071209
sponsorTiers Sponsor_Tier[]
12081210
indexCodes Index_Code[]
1211+
financeDelegates User[] @relation(name: "financeDelegates")
12091212
}
12101213

12111214
model FrequentlyAskedQuestion {

src/backend/src/prisma/seed-data/teams.seed.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const ravens = (headId: string, organizationId: string): Prisma.TeamCreateArgs =
2323
return {
2424
data: {
2525
teamName: 'Ravens',
26-
slackId: 'asdf',
26+
slackId: 'C06HR7WTTKM',
2727
description: ravensDescription,
2828
headId,
2929
organizationId
@@ -35,7 +35,7 @@ const orioles = (headId: string, organizationId: string): Prisma.TeamCreateArgs
3535
return {
3636
data: {
3737
teamName: 'Orioles',
38-
slackId: 'jkl;',
38+
slackId: 'C06HR7WTTKM',
3939
description: oriolesDescription,
4040
headId,
4141
organizationId
@@ -47,7 +47,7 @@ const justiceLeague = (headId: string, organizationId: string): Prisma.TeamCreat
4747
return {
4848
data: {
4949
teamName: 'Justice League',
50-
slackId: 'dc',
50+
slackId: 'C06HR7WTTKM',
5151
headId,
5252
organizationId
5353
}
@@ -58,7 +58,7 @@ const avatarBenders = (headId: string, teamTypeId: string, organizationId: strin
5858
return {
5959
data: {
6060
teamName: 'Avatar: The Last Airbender',
61-
slackId: 'avatar',
61+
slackId: 'C06HR7WTTKM',
6262
headId,
6363
teamTypeId,
6464
organizationId
@@ -70,7 +70,7 @@ const plLegends = (headId: string, organizationId: string): Prisma.TeamCreateArg
7070
return {
7171
data: {
7272
teamName: 'PlTeams',
73-
slackId: 'Pl',
73+
slackId: 'C06HR7WTTKM',
7474
headId,
7575
organizationId
7676
}
@@ -81,7 +81,7 @@ const huskies = (headId: string, teamTypeId: string, organizationId: string): Pr
8181
return {
8282
data: {
8383
teamName: 'Huskies',
84-
slackId: 'neu',
84+
slackId: 'C06HR7WTTKM',
8585
headId,
8686
description:
8787
'# Welcome!\nThanks for joining our team! Here are some onboarding docs or something idk:\n\n[very important please read](https://crouton.net)',
@@ -95,7 +95,7 @@ const financeTeam = (headId: string, organizationId: string): Prisma.TeamCreateA
9595
return {
9696
data: {
9797
teamName: 'financeTeam',
98-
slackId: 'financerand',
98+
slackId: 'C06HR7WTTKM',
9999
headId,
100100
organizationId,
101101
financeTeam: true

src/backend/src/prisma/seed-data/users.seed.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ const joeShmoe: Prisma.UserCreateInput = {
4444
userSettings: {
4545
create: {
4646
defaultTheme: Theme.LIGHT,
47-
slackId: 'asdf'
47+
slackId: currentEnv && currentEnv.SLACK_ID ? currentEnv.SLACK_ID : 'shmoe'
4848
}
4949
}
5050
};
@@ -58,7 +58,7 @@ const joeBlow: Prisma.UserCreateInput = {
5858
userSettings: {
5959
create: {
6060
defaultTheme: Theme.DARK,
61-
slackId: 'blow'
61+
slackId: currentEnv && currentEnv.SLACK_ID ? currentEnv.SLACK_ID : 'blow'
6262
}
6363
}
6464
};
@@ -159,7 +159,7 @@ const batman: Prisma.UserCreateInput = {
159159
userSettings: {
160160
create: {
161161
defaultTheme: Theme.DARK,
162-
slackId: 'batman'
162+
slackId: currentEnv && currentEnv.SLACK_ID ? currentEnv.SLACK_ID : 'batman'
163163
}
164164
}
165165
};
@@ -172,7 +172,7 @@ const superman: Prisma.UserCreateInput = {
172172
userSettings: {
173173
create: {
174174
defaultTheme: Theme.LIGHT,
175-
slackId: 'superman'
175+
slackId: currentEnv && currentEnv.SLACK_ID ? currentEnv.SLACK_ID : 'superman'
176176
}
177177
}
178178
};
@@ -705,7 +705,7 @@ const monopolyMan: Prisma.UserCreateInput = {
705705
userSettings: {
706706
create: {
707707
defaultTheme: Theme.LIGHT,
708-
slackId: 'monopolyman'
708+
slackId: currentEnv && currentEnv.SLACK_ID ? currentEnv.SLACK_ID : 'monopolyman'
709709
}
710710
}
711711
};
@@ -718,7 +718,7 @@ const mrKrabs: Prisma.UserCreateInput = {
718718
userSettings: {
719719
create: {
720720
defaultTheme: Theme.LIGHT,
721-
slackId: 'mrkrabs'
721+
slackId: currentEnv && currentEnv.SLACK_ID ? currentEnv.SLACK_ID : 'mrkrabs'
722722
}
723723
}
724724
};
@@ -731,7 +731,7 @@ const richieRich: Prisma.UserCreateInput = {
731731
userSettings: {
732732
create: {
733733
defaultTheme: Theme.LIGHT,
734-
slackId: 'richietherich'
734+
slackId: currentEnv && currentEnv.SLACK_ID ? currentEnv.SLACK_ID : 'richietherich'
735735
}
736736
}
737737
};

src/backend/src/routes/organizations.routes.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ import { linkValidators, nonEmptyString, validateInputs } from '../utils/validat
33
import OrganizationsController from '../controllers/organizations.controllers';
44
import multer, { memoryStorage } from 'multer';
55
import { body } from 'express-validator';
6+
import { MAX_FILE_SIZE } from 'shared';
67

78
const organizationRouter = express.Router();
8-
const upload = multer({ limits: { fileSize: 30000000 }, storage: memoryStorage() });
9+
const upload = multer({ limits: { fileSize: MAX_FILE_SIZE }, storage: memoryStorage() });
910

1011
organizationRouter.get('/current', OrganizationsController.getCurrentOrganization);
1112
organizationRouter.post('/useful-links/set', ...linkValidators, validateInputs, OrganizationsController.setUsefulLinks);
@@ -73,4 +74,14 @@ organizationRouter.post(
7374
validateInputs,
7475
OrganizationsController.setSlackSponsorshipNotificationsSlackId
7576
);
77+
78+
organizationRouter.get('/finance-delegates', OrganizationsController.getFinanceDelegates);
79+
organizationRouter.post(
80+
'/finance-delegates/set',
81+
body('userIds').isArray(),
82+
nonEmptyString(body('userIds.*')),
83+
validateInputs,
84+
OrganizationsController.setFinanceDelegates
85+
);
86+
7687
export default organizationRouter;

src/backend/src/routes/parts.routes.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,10 @@ import {
1010
} from '../utils/validation.utils';
1111
import { body } from 'express-validator';
1212
import PartReviewController from '../controllers/part-review.controllers';
13-
import { Review_Status } from 'shared';
13+
import { Review_Status, MAX_FILE_SIZE } from 'shared';
1414
import multer, { memoryStorage } from 'multer';
1515

16-
//limit uploads to 5 mb per file
17-
const upload = multer({ limits: { fileSize: 5 * 1024 * 1024 }, storage: memoryStorage() });
16+
const upload = multer({ limits: { fileSize: MAX_FILE_SIZE }, storage: memoryStorage() });
1817

1918
const partsRouter = express.Router();
2019

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

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@ import {
1515
} from '../utils/validation.utils';
1616
import ReimbursementRequestController from '../controllers/reimbursement-requests.controllers';
1717
import multer, { memoryStorage } from 'multer';
18+
import { MAX_FILE_SIZE } from 'shared';
1819

1920
const reimbursementRequestsRouter = express.Router();
2021

21-
const upload = multer({ limits: { fileSize: 30000000 }, storage: memoryStorage() });
22+
const upload = multer({ limits: { fileSize: MAX_FILE_SIZE }, storage: memoryStorage() });
2223

2324
reimbursementRequestsRouter.get('/vendors', ReimbursementRequestController.getAllVendors);
2425

@@ -32,6 +33,13 @@ reimbursementRequestsRouter.post(
3233
ReimbursementRequestController.createIndexCode
3334
);
3435

36+
reimbursementRequestsRouter.post(
37+
'/index-codes/:indexCodeId/edit',
38+
nonEmptyString(body('name')),
39+
nonEmptyString(body('code')),
40+
validateInputs,
41+
ReimbursementRequestController.editIndexCode
42+
);
3543
reimbursementRequestsRouter.get('/index-codes/:indexCodeId', ReimbursementRequestController.getSingleIndexCode);
3644

3745
reimbursementRequestsRouter.get('/index-codes', ReimbursementRequestController.getAllIndexCodes);
@@ -144,8 +152,8 @@ reimbursementRequestsRouter.post(
144152
nonEmptyString(body('username')).optional(),
145153
nonEmptyString(body('password')).optional(),
146154
nonEmptyString(body('discountCode')).optional(),
147-
body('taxExempt').isBoolean(),
148-
body('twoFactorContacts').isArray(),
155+
body('taxExempt').optional().isBoolean(),
156+
body('twoFactorContacts').optional().isArray(),
149157
nonEmptyString(body('twoFactorContacts.*')),
150158
nonEmptyString(body('notes')).optional(),
151159
validateInputs,
@@ -200,7 +208,14 @@ reimbursementRequestsRouter.post(
200208
ReimbursementRequestController.uploadReceipt
201209
);
202210

203-
reimbursementRequestsRouter.post('/:requestId/approve', ReimbursementRequestController.approveReimbursementRequest);
211+
reimbursementRequestsRouter.post(
212+
'/:requestId/input-in-sabo',
213+
ReimbursementRequestController.inputReimbursementRequestInSabo
214+
);
215+
reimbursementRequestsRouter.post(
216+
'/:requestId/mark-sabo-submitted',
217+
ReimbursementRequestController.markReimbursementRequestAsSaboSubmitted
218+
);
204219
reimbursementRequestsRouter.post(
205220
'/:requestId/leadership-approve',
206221
ReimbursementRequestController.leadershipApproveReimbursementRequest

0 commit comments

Comments
 (0)