Skip to content

Commit 9a1e828

Browse files
committed
#1522: resolved merge conflict from develop branch
2 parents e61d1d1 + c54b0b2 commit 9a1e828

25 files changed

Lines changed: 261 additions & 89 deletions

src/backend/src/controllers/projects.controllers.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,17 @@ export default class ProjectsController {
128128
}
129129
}
130130

131+
static async createManufacturer(req: Request, res: Response, next: NextFunction) {
132+
try {
133+
const { name } = req.body;
134+
const user = await getCurrentUser(res);
135+
const createdManufacturer = await ProjectsService.createManufacturer(user, name);
136+
res.status(200).json(createdManufacturer);
137+
} catch (error: unknown) {
138+
next(error);
139+
}
140+
}
141+
131142
static async createMaterialType(req: Request, res: Response, next: NextFunction) {
132143
try {
133144
const { name } = req.body;

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

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,15 @@ export default class ReimbursementRequestsController {
162162

163163
static async createExpenseType(req: Request, res: Response, next: NextFunction) {
164164
try {
165-
const { name, code, allowed } = req.body;
165+
const { name, code, allowed, allowedRefundSources } = req.body;
166166
const user = await getCurrentUser(res);
167-
const createdExpenseType = await ReimbursementRequestService.createExpenseType(user, name, code, allowed);
167+
const createdExpenseType = await ReimbursementRequestService.createExpenseType(
168+
user,
169+
name,
170+
code,
171+
allowed,
172+
allowedRefundSources
173+
);
168174
res.status(200).json(createdExpenseType);
169175
} catch (error: unknown) {
170176
next(error);
@@ -269,14 +275,15 @@ export default class ReimbursementRequestsController {
269275
static async editExpenseTypeCode(req: Request, res: Response, next: NextFunction) {
270276
try {
271277
const { expenseTypeId } = req.params;
272-
const { name, code, allowed } = req.body;
278+
const { name, code, allowed, allowedRefundSources } = req.body;
273279
const submitter = await getCurrentUser(res);
274280
const expenseTypeUpdated = await ReimbursementRequestService.editExpenseType(
275281
expenseTypeId,
276282
code,
277283
name,
278284
allowed,
279-
submitter
285+
submitter,
286+
allowedRefundSources
280287
);
281288
res.status(200).json(expenseTypeUpdated);
282289
} 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 "Expense_Type" ADD COLUMN "allowedRefundSources" "Club_Accounts"[];

src/backend/src/prisma/schema.prisma

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -429,11 +429,12 @@ model Vendor {
429429
}
430430

431431
model Expense_Type {
432-
expenseTypeId String @id @default(uuid())
433-
name String
434-
code Int
435-
allowed Boolean
436-
requests Reimbursement_Request[]
432+
expenseTypeId String @id @default(uuid())
433+
name String
434+
code Int
435+
allowed Boolean
436+
allowedRefundSources Club_Accounts[]
437+
requests Reimbursement_Request[]
437438
}
438439

439440
model Reimbursement {

src/backend/src/prisma/seed.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import {
99
CR_Type,
10+
Club_Accounts,
1011
PrismaClient,
1112
Scope_CR_Why_Type,
1213
Task_Priority,
@@ -750,7 +751,10 @@ const performSeed: () => Promise<void> = async () => {
750751

751752
const vendors: Vendor[] = [vendor, vendor2, vendor3];
752753

753-
const expenseType = await ReimbursementRequestService.createExpenseType(thomasEmrax, 'Equipment', 123, true);
754+
const expenseType = await ReimbursementRequestService.createExpenseType(thomasEmrax, 'Equipment', 123, true, [
755+
Club_Accounts.CASH,
756+
Club_Accounts.BUDGET
757+
]);
754758

755759
await ReimbursementRequestService.createReimbursementRequest(
756760
thomasEmrax,

src/backend/src/routes/projects.routes.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ projectRouter.delete('/:wbsNum/delete', ProjectsController.deleteProject);
4949
projectRouter.post('/:wbsNum/favorite', ProjectsController.toggleFavorite);
5050

5151
/**************** BOM Section ****************/
52+
projectRouter.post(
53+
'/bom/manufacturer/create',
54+
nonEmptyString(body('name')),
55+
validateInputs,
56+
ProjectsController.createManufacturer
57+
);
5258
projectRouter.post('/bom/material-type/create', nonEmptyString(body('name')), ProjectsController.createMaterialType);
5359

5460
export default projectRouter;

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ reimbursementRequestsRouter.post(
8686
reimbursementRequestsRouter.post(
8787
'/vendors/create',
8888
nonEmptyString(body('name')),
89+
body('allowedRefundSources').isArray(),
90+
isAccount(body('allowedRefundSources.*')),
8991
validateInputs,
9092
ReimbursementRequestController.createVendor
9193
);
@@ -95,6 +97,8 @@ reimbursementRequestsRouter.post(
9597
nonEmptyString(body('name')),
9698
intMinZero(body('code')),
9799
body('allowed').isBoolean(),
100+
body('allowedRefundSources').isArray(),
101+
isAccount(body('allowedRefundSources.*')),
98102
validateInputs,
99103
ReimbursementRequestController.createExpenseType
100104
);

src/backend/src/services/projects.services.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,31 @@ export default class ProjectsService {
604604
).map(linkTypeTransformer);
605605
}
606606

607+
/**
608+
* Creates a new Manufacturer
609+
* @param submitter the user who's creating the manufacturer
610+
* @param name the name of the manufacturer
611+
* @returns the newly created manufacturer
612+
* @throws if the submitter is a guest or the given manufacturer name already exists
613+
*/
614+
static async createManufacturer(submitter: User, name: string) {
615+
if (isGuest(submitter.role)) throw new AccessDeniedGuestException('create manufacturers');
616+
617+
const manufacturer = await prisma.manufacturer.findUnique({
618+
where: {
619+
name
620+
}
621+
});
622+
623+
if (manufacturer) throw new HttpException(400, `${name} already exists as a manufacturer!`);
624+
625+
const newManufacturer = await prisma.manufacturer.create({
626+
data: { name, dateCreated: new Date(), creatorId: submitter.userId }
627+
});
628+
629+
return newManufacturer;
630+
}
631+
607632
/**
608633
* Create a new material type
609634
* @param name the name of the new material type

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

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
// eslint-disable-next-line @typescript-eslint/no-unused-vars
77
import type { Multer } from 'multer';
8-
import { Reimbursement_Request, Reimbursement_Status_Type, User } from '@prisma/client';
8+
import { Club_Accounts, Reimbursement_Request, Reimbursement_Status_Type, User } from '@prisma/client';
99
import {
1010
ClubAccount,
1111
ExpenseType,
@@ -131,6 +131,10 @@ export default class ReimbursementRequestService {
131131

132132
if (!expenseType.allowed) throw new HttpException(400, `The expense type ${expenseType.name} is not allowed!`);
133133

134+
if (!expenseType.allowedRefundSources.includes(account)) {
135+
throw new HttpException(400, 'The submitted refund source is not allowed to be used with the submitted expense type');
136+
}
137+
134138
const validatedReimbursementProudcts = await validateReimbursementProducts(reimbursementProducts);
135139

136140
const createdReimbursementRequest = await prisma.reimbursement_Request.create({
@@ -268,6 +272,9 @@ export default class ReimbursementRequestService {
268272

269273
if (!expenseType) throw new NotFoundException('Expense Type', expenseTypeId);
270274
if (!expenseType.allowed) throw new HttpException(400, 'Expense Type Not Allowed');
275+
if (!expenseType.allowedRefundSources.includes(account)) {
276+
throw new HttpException(400, 'The submitted refund source is not allowed to be used with the submitted expense type');
277+
}
271278

272279
await updateReimbursementProducts(
273280
oldReimbursementRequest.reimbursementProducts,
@@ -463,15 +470,23 @@ export default class ReimbursementRequestService {
463470
* @param name The name of the expense type
464471
* @param code the expense type's SABO code
465472
* @param allowed whether or not this expense type is allowed
473+
* @param allowedRefundSources an array of Club_Accounts representing allowed refund sources
466474
* @returns the created expense type
467475
*/
468-
static async createExpenseType(submitter: User, name: string, code: number, allowed: boolean) {
476+
static async createExpenseType(
477+
submitter: User,
478+
name: string,
479+
code: number,
480+
allowed: boolean,
481+
allowedRefundSources: Club_Accounts[]
482+
) {
469483
if (!isAdmin(submitter.role)) throw new AccessDeniedAdminOnlyException('create expense types');
470484
const expense = await prisma.expense_Type.create({
471485
data: {
472486
name,
473487
allowed,
474-
code
488+
code,
489+
allowedRefundSources
475490
}
476491
});
477492

@@ -487,7 +502,14 @@ export default class ReimbursementRequestService {
487502
* @param submitter the person editing expense type code number
488503
* @returns the updated expense type
489504
*/
490-
static async editExpenseType(expenseTypeId: string, code: number, name: string, allowed: boolean, submitter: User) {
505+
static async editExpenseType(
506+
expenseTypeId: string,
507+
code: number,
508+
name: string,
509+
allowed: boolean,
510+
submitter: User,
511+
allowedRefundSources: Club_Accounts[]
512+
) {
491513
if (!isHead(submitter.role))
492514
throw new AccessDeniedException('Only the head or admin can update account code number and name');
493515

@@ -502,7 +524,8 @@ export default class ReimbursementRequestService {
502524
data: {
503525
name,
504526
code,
505-
allowed
527+
allowed,
528+
allowedRefundSources
506529
}
507530
});
508531

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ export const expenseTypeTransformer = (expenseType: Prisma.Expense_TypeGetPayloa
8383
expenseTypeId: expenseType.expenseTypeId,
8484
name: expenseType.name,
8585
code: expenseType.code,
86-
allowed: expenseType.allowed
86+
allowed: expenseType.allowed,
87+
allowedRefundSources: expenseType.allowedRefundSources as ClubAccount[]
8788
};
8889
};
8990

0 commit comments

Comments
 (0)