Skip to content

Commit 43e2ca4

Browse files
Merge branch 'develop' into #1509-Create-Assembly-Endpoint
2 parents 895a6e9 + ba58ae6 commit 43e2ca4

42 files changed

Lines changed: 429 additions & 183 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.

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,26 @@ export default class ProjectsController {
135135
try {
136136
const createAssembly = await ProjectsService.createAssembly(name, pdmFileName, user, wbsNum);
137137
res.status(200).json(createAssembly);
138+
}
139+
}
140+
141+
static async createManufacturer(req: Request, res: Response, next: NextFunction) {
142+
try {
143+
const { name } = req.body;
144+
const user = await getCurrentUser(res);
145+
const createdManufacturer = await ProjectsService.createManufacturer(user, name);
146+
res.status(200).json(createdManufacturer);
147+
} catch (error: unknown) {
148+
next(error);
149+
}
150+
}
151+
152+
static async createMaterialType(req: Request, res: Response, next: NextFunction) {
153+
try {
154+
const { name } = req.body;
155+
const user = await getCurrentUser(res);
156+
const createdMaterialType = await ProjectsService.createMaterialType(name, user);
157+
res.status(200).json(createdMaterialType);
138158
} catch (error: unknown) {
139159
next(error);
140160
}

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"[];
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
-- AlterEnum
2+
CREATE TYPE "Work_Package_Stage_new" AS ENUM ('RESEARCH', 'DESIGN', 'MANUFACTURING', 'INSTALL');
3+
ALTER TABLE "Work_Package" ALTER COLUMN "stage" TYPE "Work_Package_Stage_new" USING (
4+
CASE "stage"::text
5+
WHEN 'INTEGRATION' THEN 'INSTALL'::"Work_Package_Stage_new"
6+
ELSE "stage"::text::"Work_Package_Stage_new"
7+
END);
8+
ALTER TYPE "Work_Package_Stage" RENAME TO "Work_Package_Stage_old";
9+
ALTER TYPE "Work_Package_Stage_new" RENAME TO "Work_Package_Stage";
10+
DROP TYPE "Work_Package_Stage_old";

src/backend/src/prisma/migrations/20231011234802_add_bom/migration.sql renamed to src/backend/src/prisma/migrations/20231019013832_add_bom/migration.sql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ CREATE TABLE "Assembly" (
2525
-- CreateTable
2626
CREATE TABLE "Material" (
2727
"materialId" TEXT NOT NULL,
28-
"assembyId" TEXT,
28+
"assemblyId" TEXT,
2929
"name" TEXT NOT NULL,
3030
"wbsElementId" INTEGER NOT NULL,
3131
"dateDeleted" TIMESTAMP(3),
@@ -81,7 +81,7 @@ ALTER TABLE "Assembly" ADD CONSTRAINT "Assembly_userCreatedId_fkey" FOREIGN KEY
8181
ALTER TABLE "Assembly" ADD CONSTRAINT "Assembly_wbsElementId_fkey" FOREIGN KEY ("wbsElementId") REFERENCES "WBS_Element"("wbsElementId") ON DELETE RESTRICT ON UPDATE CASCADE;
8282

8383
-- AddForeignKey
84-
ALTER TABLE "Material" ADD CONSTRAINT "Material_assembyId_fkey" FOREIGN KEY ("assembyId") REFERENCES "Assembly"("assemblyId") ON DELETE SET NULL ON UPDATE CASCADE;
84+
ALTER TABLE "Material" ADD CONSTRAINT "Material_assemblyId_fkey" FOREIGN KEY ("assemblyId") REFERENCES "Assembly"("assemblyId") ON DELETE SET NULL ON UPDATE CASCADE;
8585

8686
-- AddForeignKey
8787
ALTER TABLE "Material" ADD CONSTRAINT "Material_wbsElementId_fkey" FOREIGN KEY ("wbsElementId") REFERENCES "WBS_Element"("wbsElementId") ON DELETE RESTRICT ON UPDATE CASCADE;

src/backend/src/prisma/schema.prisma

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ enum Work_Package_Stage {
6767
RESEARCH
6868
DESIGN
6969
MANUFACTURING
70-
INTEGRATION
70+
INSTALL
7171
}
7272

7373
model User {
@@ -256,7 +256,7 @@ model WBS_Element {
256256
tasks Task[]
257257
reimbursementProducts Reimbursement_Product[]
258258
links Link[] @relation(name: "links")
259-
assembies Assembly[]
259+
assemblies Assembly[]
260260
materials Material[]
261261
262262
@@unique([carNumber, projectNumber, workPackageNumber], name: "wbsNumber")
@@ -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 {
@@ -487,8 +488,8 @@ model Assembly {
487488

488489
model Material {
489490
materialId String @id @default(uuid())
490-
assemby Assembly? @relation(fields: [assembyId], references: [assemblyId])
491-
assembyId String?
491+
assembly Assembly? @relation(fields: [assemblyId], references: [assemblyId])
492+
assemblyId String?
492493
name String @unique
493494
wbsElement WBS_Element @relation(fields: [wbsElementId], references: [wbsElementId])
494495
wbsElementId Int

src/backend/src/prisma/seed.ts

Lines changed: 23 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,
@@ -447,6 +448,24 @@ const performSeed: () => Promise<void> = async () => {
447448
);
448449
const workPackage3WbsNumber = validateWBS(workPackage3WbsString);
449450

451+
/** Work Package 4 */
452+
const { workPackageWbsNumber: workPackage4WbsNumber, workPackage: workPackage4 } = await seedWorkPackage(
453+
thomasEmrax,
454+
project5WbsNumber,
455+
'Install Wiring Harness',
456+
changeRequest1Id,
457+
WorkPackageStage.Install,
458+
'04/01/2023',
459+
7,
460+
[],
461+
['Assemble and install wiring harness', 'Confirm the installation was successful'],
462+
['Wiring harness is functional and installed in the car'],
463+
thomasEmrax,
464+
WbsElementStatus.Active,
465+
joeShmoe.userId,
466+
thomasEmrax.userId
467+
);
468+
450469
/**
451470
* Change Requests
452471
*/
@@ -732,7 +751,10 @@ const performSeed: () => Promise<void> = async () => {
732751

733752
const vendors: Vendor[] = [vendor, vendor2, vendor3];
734753

735-
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+
]);
736758

737759
await ReimbursementRequestService.createReimbursementRequest(
738760
thomasEmrax,

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,13 @@ projectRouter.post('/:wbsNum/set-team', nonEmptyString(body('teamId')), validate
5555
projectRouter.delete('/:wbsNum/delete', ProjectsController.deleteProject);
5656
projectRouter.post('/:wbsNum/favorite', ProjectsController.toggleFavorite);
5757

58+
/**************** BOM Section ****************/
59+
projectRouter.post(
60+
'/bom/manufacturer/create',
61+
nonEmptyString(body('name')),
62+
validateInputs,
63+
ProjectsController.createManufacturer
64+
);
65+
projectRouter.post('/bom/material-type/create', nonEmptyString(body('name')), ProjectsController.createMaterialType);
66+
5867
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: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { User, Assembly } from '@prisma/client';
2-
import { isAdmin, isGuest, isProject, LinkCreateArgs, LinkType, Project, WbsNumber, wbsPipe } from 'shared';
1+
import { Material_Type, User, Assembly } from '@prisma/client';
2+
import { isAdmin, isGuest, isLeadership, isProject, LinkCreateArgs, LinkType, Project, WbsNumber, wbsPipe } from 'shared';
33
import projectQueryArgs from '../prisma-query-args/projects.query-args';
44
import prisma from '../prisma/prisma';
55
import projectTransformer from '../transformers/projects.transformer';
@@ -10,7 +10,8 @@ import {
1010
AccessDeniedException,
1111
HttpException,
1212
NotFoundException,
13-
DeletedException
13+
DeletedException,
14+
AccessDeniedException
1415
} from '../utils/errors.utils';
1516
import {
1617
addDescriptionBullets,
@@ -656,4 +657,57 @@ export default class ProjectsService {
656657

657658
return assembly;
658659
}
660+
661+
* Creates a new Manufacturer
662+
* @param submitter the user who's creating the manufacturer
663+
* @param name the name of the manufacturer
664+
* @returns the newly created manufacturer
665+
* @throws if the submitter is a guest or the given manufacturer name already exists
666+
*/
667+
static async createManufacturer(submitter: User, name: string) {
668+
if (isGuest(submitter.role)) throw new AccessDeniedGuestException('create manufacturers');
669+
670+
const manufacturer = await prisma.manufacturer.findUnique({
671+
where: {
672+
name
673+
}
674+
});
675+
676+
if (manufacturer) throw new HttpException(400, `${name} already exists as a manufacturer!`);
677+
678+
const newManufacturer = await prisma.manufacturer.create({
679+
data: { name, dateCreated: new Date(), creatorId: submitter.userId }
680+
});
681+
682+
return newManufacturer;
683+
}
684+
685+
/**
686+
* Create a new material type
687+
* @param name the name of the new material type
688+
* @param submitter the user who is creating the material type
689+
* @throws if the submitter is not a leader or the material type with the given name already exists
690+
*/
691+
static async createMaterialType(name: string, submitter: User): Promise<Material_Type> {
692+
if (!isLeadership(submitter.role))
693+
throw new AccessDeniedException('Only leadership or above can create a material type');
694+
695+
const materialType = await prisma.material_Type.findUnique({
696+
where: {
697+
name
698+
}
699+
});
700+
701+
if (!!materialType) throw new HttpException(400, `The following material type already exists: ${name}`);
702+
703+
const newMaterialType = await prisma.material_Type.create({
704+
data: {
705+
name,
706+
dateCreated: new Date(),
707+
creatorId: submitter.userId
708+
}
709+
});
710+
711+
return newMaterialType;
712+
}
659713
}

0 commit comments

Comments
 (0)