From 011678415da23f9adef21b86cd985de9ba6137c2 Mon Sep 17 00:00:00 2001 From: Sarah Taylor <150694563+staysgt@users.noreply.github.com> Date: Thu, 17 Sep 2026 21:44:24 -0400 Subject: [PATCH 1/5] #4502 getSingleExecutiveSummary --- src/backend/index.ts | 2 + .../controllers/exec-summaries.controllers.ts | 15 +++ .../executive-summary.query-args.ts | 33 ++++++ .../src/routes/exec-summaries.routes.ts | 6 + .../src/services/exec-summaries.services.ts | 20 ++++ .../executive-summary.transformer.ts | 105 ++++++++++++++++++ src/backend/src/utils/errors.utils.ts | 3 +- src/backend/tests/test-utils.ts | 5 + src/backend/tests/unit/exec-summaries.test.ts | 44 ++++++++ 9 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 src/backend/src/controllers/exec-summaries.controllers.ts create mode 100644 src/backend/src/prisma-query-args/executive-summary.query-args.ts create mode 100644 src/backend/src/routes/exec-summaries.routes.ts create mode 100644 src/backend/src/services/exec-summaries.services.ts create mode 100644 src/backend/src/transformers/executive-summary.transformer.ts create mode 100644 src/backend/tests/unit/exec-summaries.test.ts diff --git a/src/backend/index.ts b/src/backend/index.ts index cde8783ab0..b442f83c27 100644 --- a/src/backend/index.ts +++ b/src/backend/index.ts @@ -34,6 +34,7 @@ import agentRouter from './src/routes/agent.routes.js'; import { mcpNodeHandler } from './src/mcp/handler.js'; import { attachAuthInfo, requireApiToken } from './src/utils/mcp-auth.utils.js'; import dashboardsRouter from './src/routes/dashboards.routes.js'; +import execSummaryRouter from './src/routes/exec-summaries.routes.js'; const app = express(); @@ -140,6 +141,7 @@ app.use('/calendar', calendarRouter); app.use('/prospective-sponsors', prospectiveSponsorRouter); app.use('/attendance', attendanceRouter); app.use('/dashboards', dashboardsRouter); +app.use('/executive-summaries', execSummaryRouter); app.use('/', (_req, res) => { res.status(200).json('Welcome to FinishLine'); }); diff --git a/src/backend/src/controllers/exec-summaries.controllers.ts b/src/backend/src/controllers/exec-summaries.controllers.ts new file mode 100644 index 0000000000..a4752e15e2 --- /dev/null +++ b/src/backend/src/controllers/exec-summaries.controllers.ts @@ -0,0 +1,15 @@ +import { NextFunction, Request, Response } from 'express'; +import ExecSummaryServices from '../services/exec-summaries.services.js'; + +export default class ExecSummaryController { + static async getSingleExecutiveSummary(req: Request, res: Response, next: NextFunction) { + try { + const { execSummaryId } = req.params as Record; + + const summary = await ExecSummaryServices.getSingleExecutiveSummary(req.organization, execSummaryId); + res.status(200).json(summary); + } catch (error: unknown) { + next(error); + } + } +} diff --git a/src/backend/src/prisma-query-args/executive-summary.query-args.ts b/src/backend/src/prisma-query-args/executive-summary.query-args.ts new file mode 100644 index 0000000000..5980412cd5 --- /dev/null +++ b/src/backend/src/prisma-query-args/executive-summary.query-args.ts @@ -0,0 +1,33 @@ +import { Prisma } from '@prisma/client'; +import { getCarQueryArgs } from './cars.query-args.js'; +import { getUserQueryArgs } from './user.query-args.js'; + +export type ExecutiveSummaryQueryArgs = ReturnType; +export type RecruitmentCycleQueryArgs = ReturnType; +export type RecruitmentDivisionCountQueryArgs = ReturnType; + +export const getExecutiveSummaryQueryArgs = (organizationId: string) => + Prisma.validator()({ + include: { + car: getCarQueryArgs(organizationId), + userCreated: getUserQueryArgs(organizationId), + deletedBy: getUserQueryArgs(organizationId), + competitionPerformances: true, + competitionDocumentsSummary: true, + recruitmentCycles: getRecruitmentCycleQueryArgs() + } + }); + +export const getRecruitmentCycleQueryArgs = () => + Prisma.validator()({ + include: { + divisionCounts: getRecruitmentDivisionCountQueryArgs() + } + }); + +export const getRecruitmentDivisionCountQueryArgs = () => + Prisma.validator()({ + include: { + teamType: true + } + }); diff --git a/src/backend/src/routes/exec-summaries.routes.ts b/src/backend/src/routes/exec-summaries.routes.ts new file mode 100644 index 0000000000..1ce360a153 --- /dev/null +++ b/src/backend/src/routes/exec-summaries.routes.ts @@ -0,0 +1,6 @@ +import express from 'express'; +import ExecSummaryController from '../controllers/exec-summaries.controllers.js'; + +const execSummaryRouter = express.Router(); + +execSummaryRouter.get('/:execSummaryId', ExecSummaryController.getSingleExecutiveSummary); diff --git a/src/backend/src/services/exec-summaries.services.ts b/src/backend/src/services/exec-summaries.services.ts new file mode 100644 index 0000000000..5ae79a5af4 --- /dev/null +++ b/src/backend/src/services/exec-summaries.services.ts @@ -0,0 +1,20 @@ +import { Organization } from '@prisma/client'; +import prisma from '../prisma/prisma.js'; +import { NotFoundException } from '../utils/errors.utils.js'; +import { getExecutiveSummaryQueryArgs } from '../prisma-query-args/executive-summary.query-args.js'; +import { executiveSummaryTransformer } from '../transformers/executive-summary.transformer.js'; + +export default class ExecSummaryServices { + static async getSingleExecutiveSummary(organization: Organization, executiveSummaryId: string) { + const executiveSummary = await prisma.executive_Summary.findUnique({ + where: { executiveSummaryId }, + ...getExecutiveSummaryQueryArgs(organization.organizationId) + }); + + if (!executiveSummary) { + throw new NotFoundException('Executive Summary', executiveSummaryId); + } + + return executiveSummaryTransformer(executiveSummary); + } +} diff --git a/src/backend/src/transformers/executive-summary.transformer.ts b/src/backend/src/transformers/executive-summary.transformer.ts new file mode 100644 index 0000000000..7559f53511 --- /dev/null +++ b/src/backend/src/transformers/executive-summary.transformer.ts @@ -0,0 +1,105 @@ +import { Prisma } from '@prisma/client'; +import { + CompetitionDocumentsSummary, + CompetitionPerformance, + DataSource, + ExecutiveSummary, + RecruitmentCycle, + RecruitmentDivisionCount, + Competition, + Term +} from 'shared'; +import { + ExecutiveSummaryQueryArgs, + RecruitmentCycleQueryArgs, + RecruitmentDivisionCountQueryArgs +} from '../prisma-query-args/executive-summary.query-args.js'; +import { carTransformer } from './cars.transformer.js'; +import { teamTypeTransformer } from './team-types.transformer.js'; +import { userTransformer } from './user.transformer.js'; + +export const executiveSummaryTransformer = ( + executiveSummary: Prisma.Executive_SummaryGetPayload +): ExecutiveSummary => { + return { + executiveSummaryId: executiveSummary.executiveSummaryId, + car: carTransformer(executiveSummary.car), + seasonStartDate: executiveSummary.seasonStartDate ?? undefined, + seasonEndDate: executiveSummary.seasonEndDate ?? undefined, + goals: executiveSummary.goals, + winsAndImprovements: executiveSummary.winsAndImprovements, + budgetNotes: executiveSummary.budgetNotes, + recruitmentNotes: executiveSummary.recruitmentNotes, + dateCreated: executiveSummary.dateCreated, + userCreated: userTransformer(executiveSummary.userCreated), + dateDeleted: executiveSummary.dateDeleted ?? undefined, + deletedBy: executiveSummary.deletedBy ? userTransformer(executiveSummary.deletedBy) : undefined, + competitionPerformances: executiveSummary.competitionPerformances.map(competitionPerformanceTransformer), + competitionDocumentsSummary: executiveSummary.competitionDocumentsSummary + ? competitionDocumentsSummaryTransformer(executiveSummary.competitionDocumentsSummary) + : undefined, + recruitmentCycles: executiveSummary.recruitmentCycles.map(recruitmentCycleTransformer) + }; +}; + +export const competitionPerformanceTransformer = ( + competitionPerformance: Prisma.Competition_PerformanceGetPayload +): CompetitionPerformance => { + return { + competitionPerformanceId: competitionPerformance.competitionPerformanceId, + executiveSummaryId: competitionPerformance.executiveSummaryId, + competition: competitionPerformance.competition as Competition, + finalPlace: competitionPerformance.finalPlace ?? undefined, + totalPointsEarned: competitionPerformance.totalPointsEarned ?? undefined, + maxPoints: competitionPerformance.maxPoints ?? undefined, + bestStaticEvent: competitionPerformance.bestStaticEvent ?? undefined, + worstStaticEvent: competitionPerformance.worstStaticEvent ?? undefined, + bestDynamicEvent: competitionPerformance.bestDynamicEvent ?? undefined, + worstDynamicEvent: competitionPerformance.worstDynamicEvent ?? undefined, + accelerationTopTimeSeconds: competitionPerformance.accelerationTopTimeSeconds ?? undefined, + autocrossTopTimeSeconds: competitionPerformance.autocrossTopTimeSeconds ?? undefined, + enduranceLapsCompleted: competitionPerformance.enduranceLapsCompleted ?? undefined, + maxLaps: competitionPerformance.maxLaps ?? undefined, + enduranceAvgLapTimeSeconds: competitionPerformance.enduranceAvgLapTimeSeconds ?? undefined + }; +}; + +export const competitionDocumentsSummaryTransformer = ( + competitionDocumentsSummary: Prisma.Competition_Documents_SummaryGetPayload +): CompetitionDocumentsSummary => { + return { + competitionDocumentsSummaryId: competitionDocumentsSummary.competitionDocumentsSummaryId, + executiveSummaryId: competitionDocumentsSummary.executiveSummaryId, + submittedOnTimeCount: competitionDocumentsSummary.submittedOnTimeCount ?? undefined, + firstSubmissionRejectedCount: competitionDocumentsSummary.firstSubmissionRejectedCount ?? undefined, + source: competitionDocumentsSummary.source as DataSource, + dateSynced: competitionDocumentsSummary.dateSynced ?? undefined + }; +}; + +export const recruitmentCycleTransformer = ( + recruitmentCycle: Prisma.Recruitment_CycleGetPayload +): RecruitmentCycle => { + return { + recruitmentCycleId: recruitmentCycle.recruitmentCycleId, + executiveSummaryId: recruitmentCycle.executiveSummaryId, + term: recruitmentCycle.term as Term, + eventsHeld: recruitmentCycle.eventsHeld ?? undefined, + signUps: recruitmentCycle.signUps ?? undefined, + onboarded: recruitmentCycle.onboarded ?? undefined, + activeMembers: recruitmentCycle.activeMembers ?? undefined, + divisionCounts: recruitmentCycle.divisionCounts.map(recruitmentDivisionCountTransformer) + }; +}; + +export const recruitmentDivisionCountTransformer = ( + divisionCount: Prisma.Recruitment_Division_CountGetPayload +): RecruitmentDivisionCount => { + return { + recruitmentDivisionCountId: divisionCount.recruitmentDivisionCountId, + recruitmentCycleId: divisionCount.recruitmentCycleId, + teamType: teamTypeTransformer(divisionCount.teamType), + newMembers: divisionCount.newMembers ?? undefined, + returningMembers: divisionCount.returningMembers ?? undefined + }; +}; diff --git a/src/backend/src/utils/errors.utils.ts b/src/backend/src/utils/errors.utils.ts index a83c036a1b..a2bf10440b 100644 --- a/src/backend/src/utils/errors.utils.ts +++ b/src/backend/src/utils/errors.utils.ts @@ -220,4 +220,5 @@ export type ExceptionObjectNames = | 'Task Label' | 'Notification Channel' | 'Dashboard' - | 'Team Join Request'; + | 'Team Join Request' + | 'Executive Summary'; diff --git a/src/backend/tests/test-utils.ts b/src/backend/tests/test-utils.ts index c90ffabb4d..ffa8788f7b 100644 --- a/src/backend/tests/test-utils.ts +++ b/src/backend/tests/test-utils.ts @@ -134,6 +134,11 @@ export const resetUsers = async () => { await prisma.reimbursement.deleteMany(); await prisma.vendor.deleteMany(); await prisma.account_Code.deleteMany(); + await prisma.recruitment_Division_Count.deleteMany(); + await prisma.recruitment_Cycle.deleteMany(); + await prisma.competition_Documents_Summary.deleteMany(); + await prisma.competition_Performance.deleteMany(); + await prisma.executive_Summary.deleteMany(); await prisma.car.deleteMany(); await prisma.task_Label.deleteMany(); await prisma.task.deleteMany(); diff --git a/src/backend/tests/unit/exec-summaries.test.ts b/src/backend/tests/unit/exec-summaries.test.ts new file mode 100644 index 0000000000..8675c5faff --- /dev/null +++ b/src/backend/tests/unit/exec-summaries.test.ts @@ -0,0 +1,44 @@ +import { createTestCar, createTestOrganization, createTestUser, resetUsers } from '../test-utils.js'; +import { Car, Organization, User } from '@prisma/client'; +import prisma from '../../src/prisma/prisma.js'; +import { supermanAdmin } from '../test-data/users.test-data.js'; +import ExecSummaryServices from '../../src/services/exec-summaries.services.js'; +import { executiveSummaryTransformer } from '../../src/transformers/executive-summary.transformer.js'; +import { getExecutiveSummaryQueryArgs } from '../../src/prisma-query-args/executive-summary.query-args.js'; +import { NotFoundException } from '../../src/utils/errors.utils.js'; + +describe('Executive Summaries Tests', () => { + let organization: Organization; + let user: User; + let car: Car; + + beforeEach(async () => { + organization = await createTestOrganization(); + user = await createTestUser(supermanAdmin, organization.organizationId); + car = await createTestCar(organization.organizationId, user.userId); + }); + + afterEach(async () => { + await resetUsers(); + }); + + describe('Get single executive sumamary', () => { + it('successful get single exec summary', async () => { + const createdSummary = await prisma.executive_Summary.create({ + data: { + carId: car.carId, + userCreatedId: user.userId + }, + ...getExecutiveSummaryQueryArgs(organization.organizationId) + }); + + const summary = await ExecSummaryServices.getSingleExecutiveSummary(organization, createdSummary.executiveSummaryId); + expect(summary).toStrictEqual(executiveSummaryTransformer(createdSummary)); + }); + it('invalid id get single exec summary', async () => { + await expect(async () => ExecSummaryServices.getSingleExecutiveSummary(organization, 'badid')).rejects.toThrow( + new NotFoundException('Executive Summary', 'badid') + ); + }); + }); +}); From 358480b26b1582f80a221832e70bc060d09d7b7d Mon Sep 17 00:00:00 2001 From: Sarah Taylor <150694563+staysgt@users.noreply.github.com> Date: Thu, 17 Sep 2026 21:53:07 -0400 Subject: [PATCH 2/5] #4502 export default router --- src/backend/src/routes/exec-summaries.routes.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/backend/src/routes/exec-summaries.routes.ts b/src/backend/src/routes/exec-summaries.routes.ts index 1ce360a153..7c3e6f7d82 100644 --- a/src/backend/src/routes/exec-summaries.routes.ts +++ b/src/backend/src/routes/exec-summaries.routes.ts @@ -4,3 +4,5 @@ import ExecSummaryController from '../controllers/exec-summaries.controllers.js' const execSummaryRouter = express.Router(); execSummaryRouter.get('/:execSummaryId', ExecSummaryController.getSingleExecutiveSummary); + +export default execSummaryRouter; From 218302ea5bf51bfc903d3e9ca3e8c5f2b7f8b992 Mon Sep 17 00:00:00 2001 From: Sarah Taylor <150694563+staysgt@users.noreply.github.com> Date: Thu, 17 Sep 2026 22:11:13 -0400 Subject: [PATCH 3/5] #4502 add deleted and org check --- src/backend/src/services/exec-summaries.services.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/backend/src/services/exec-summaries.services.ts b/src/backend/src/services/exec-summaries.services.ts index 5ae79a5af4..5e5b801b41 100644 --- a/src/backend/src/services/exec-summaries.services.ts +++ b/src/backend/src/services/exec-summaries.services.ts @@ -1,6 +1,6 @@ import { Organization } from '@prisma/client'; import prisma from '../prisma/prisma.js'; -import { NotFoundException } from '../utils/errors.utils.js'; +import { DeletedException, InvalidOrganizationException, NotFoundException } from '../utils/errors.utils.js'; import { getExecutiveSummaryQueryArgs } from '../prisma-query-args/executive-summary.query-args.js'; import { executiveSummaryTransformer } from '../transformers/executive-summary.transformer.js'; @@ -14,6 +14,12 @@ export default class ExecSummaryServices { if (!executiveSummary) { throw new NotFoundException('Executive Summary', executiveSummaryId); } + if (executiveSummary.car.wbsElement.organizationId !== organization.organizationId) { + throw new InvalidOrganizationException('Executive Summary'); + } + if (executiveSummary.dateDeleted) { + throw new DeletedException('Executive Summary', executiveSummaryId); + } return executiveSummaryTransformer(executiveSummary); } From d1a471988337dc33b2e60652d164ea0b5b106247 Mon Sep 17 00:00:00 2001 From: Sarah Taylor <150694563+staysgt@users.noreply.github.com> Date: Sun, 20 Sep 2026 21:15:58 -0400 Subject: [PATCH 4/5] #4502 fixes from review --- .../src/controllers/exec-summaries.controllers.ts | 2 +- .../prisma-query-args/executive-summary.query-args.ts | 3 +-- src/backend/src/services/exec-summaries.services.ts | 11 +++++++++-- .../src/transformers/executive-summary.transformer.ts | 3 +-- src/backend/tests/unit/exec-summaries.test.ts | 6 +++--- src/shared/src/types/exec-summary-shared-types.ts | 7 +++++-- 6 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/backend/src/controllers/exec-summaries.controllers.ts b/src/backend/src/controllers/exec-summaries.controllers.ts index a4752e15e2..bc53e37f6f 100644 --- a/src/backend/src/controllers/exec-summaries.controllers.ts +++ b/src/backend/src/controllers/exec-summaries.controllers.ts @@ -6,7 +6,7 @@ export default class ExecSummaryController { try { const { execSummaryId } = req.params as Record; - const summary = await ExecSummaryServices.getSingleExecutiveSummary(req.organization, execSummaryId); + const summary = await ExecSummaryServices.getSingleExecutiveSummary(req.organization, execSummaryId, req.currentUser); res.status(200).json(summary); } catch (error: unknown) { next(error); diff --git a/src/backend/src/prisma-query-args/executive-summary.query-args.ts b/src/backend/src/prisma-query-args/executive-summary.query-args.ts index 5980412cd5..76a5520b3d 100644 --- a/src/backend/src/prisma-query-args/executive-summary.query-args.ts +++ b/src/backend/src/prisma-query-args/executive-summary.query-args.ts @@ -1,5 +1,4 @@ import { Prisma } from '@prisma/client'; -import { getCarQueryArgs } from './cars.query-args.js'; import { getUserQueryArgs } from './user.query-args.js'; export type ExecutiveSummaryQueryArgs = ReturnType; @@ -9,7 +8,7 @@ export type RecruitmentDivisionCountQueryArgs = ReturnType Prisma.validator()({ include: { - car: getCarQueryArgs(organizationId), + car: { select: { wbsElement: { select: { organizationId: true, name: true } } } }, userCreated: getUserQueryArgs(organizationId), deletedBy: getUserQueryArgs(organizationId), competitionPerformances: true, diff --git a/src/backend/src/services/exec-summaries.services.ts b/src/backend/src/services/exec-summaries.services.ts index 5e5b801b41..a79a018795 100644 --- a/src/backend/src/services/exec-summaries.services.ts +++ b/src/backend/src/services/exec-summaries.services.ts @@ -1,11 +1,18 @@ import { Organization } from '@prisma/client'; +import { notGuest, User } from 'shared'; import prisma from '../prisma/prisma.js'; -import { DeletedException, InvalidOrganizationException, NotFoundException } from '../utils/errors.utils.js'; +import { AccessDeniedException, DeletedException, InvalidOrganizationException, NotFoundException } from '../utils/errors.utils.js'; import { getExecutiveSummaryQueryArgs } from '../prisma-query-args/executive-summary.query-args.js'; import { executiveSummaryTransformer } from '../transformers/executive-summary.transformer.js'; +import { userHasPermission } from '../utils/users.utils.js'; export default class ExecSummaryServices { - static async getSingleExecutiveSummary(organization: Organization, executiveSummaryId: string) { + static async getSingleExecutiveSummary(organization: Organization, executiveSummaryId: string, viewer: User) { + const hasPermission = await userHasPermission(viewer.userId, organization.organizationId, notGuest); + if (!hasPermission) { + throw new AccessDeniedException('Only members can view executive summaries'); + } + const executiveSummary = await prisma.executive_Summary.findUnique({ where: { executiveSummaryId }, ...getExecutiveSummaryQueryArgs(organization.organizationId) diff --git a/src/backend/src/transformers/executive-summary.transformer.ts b/src/backend/src/transformers/executive-summary.transformer.ts index 7559f53511..257ba23e2a 100644 --- a/src/backend/src/transformers/executive-summary.transformer.ts +++ b/src/backend/src/transformers/executive-summary.transformer.ts @@ -14,7 +14,6 @@ import { RecruitmentCycleQueryArgs, RecruitmentDivisionCountQueryArgs } from '../prisma-query-args/executive-summary.query-args.js'; -import { carTransformer } from './cars.transformer.js'; import { teamTypeTransformer } from './team-types.transformer.js'; import { userTransformer } from './user.transformer.js'; @@ -23,7 +22,7 @@ export const executiveSummaryTransformer = ( ): ExecutiveSummary => { return { executiveSummaryId: executiveSummary.executiveSummaryId, - car: carTransformer(executiveSummary.car), + car: { name: executiveSummary.car.wbsElement.name }, seasonStartDate: executiveSummary.seasonStartDate ?? undefined, seasonEndDate: executiveSummary.seasonEndDate ?? undefined, goals: executiveSummary.goals, diff --git a/src/backend/tests/unit/exec-summaries.test.ts b/src/backend/tests/unit/exec-summaries.test.ts index 8675c5faff..1b3558b29f 100644 --- a/src/backend/tests/unit/exec-summaries.test.ts +++ b/src/backend/tests/unit/exec-summaries.test.ts @@ -22,7 +22,7 @@ describe('Executive Summaries Tests', () => { await resetUsers(); }); - describe('Get single executive sumamary', () => { + describe('Get single executive summary', () => { it('successful get single exec summary', async () => { const createdSummary = await prisma.executive_Summary.create({ data: { @@ -32,11 +32,11 @@ describe('Executive Summaries Tests', () => { ...getExecutiveSummaryQueryArgs(organization.organizationId) }); - const summary = await ExecSummaryServices.getSingleExecutiveSummary(organization, createdSummary.executiveSummaryId); + const summary = await ExecSummaryServices.getSingleExecutiveSummary(organization, createdSummary.executiveSummaryId, user); expect(summary).toStrictEqual(executiveSummaryTransformer(createdSummary)); }); it('invalid id get single exec summary', async () => { - await expect(async () => ExecSummaryServices.getSingleExecutiveSummary(organization, 'badid')).rejects.toThrow( + await expect(async () => ExecSummaryServices.getSingleExecutiveSummary(organization, 'badid', user)).rejects.toThrow( new NotFoundException('Executive Summary', 'badid') ); }); diff --git a/src/shared/src/types/exec-summary-shared-types.ts b/src/shared/src/types/exec-summary-shared-types.ts index 91fe2965da..5b0ae34e7f 100644 --- a/src/shared/src/types/exec-summary-shared-types.ts +++ b/src/shared/src/types/exec-summary-shared-types.ts @@ -2,7 +2,6 @@ import { GraphData } from './statistics-types.js'; import { TeamType } from './calendar-types.js'; import { TeamPreview } from './team-types.js'; import { User } from './user-types.js'; -import { Car } from './project-types.js'; export enum Competition { FSAE = 'FSAE', @@ -19,9 +18,13 @@ export enum DataSource { MANUAL = 'MANUAL' } +export interface ExecutiveSummaryCar { + name: string; +} + export interface ExecutiveSummary { executiveSummaryId: string; - car: Car; + car: ExecutiveSummaryCar; seasonStartDate?: Date; seasonEndDate?: Date; goals: string; From 2a33c2cde12d8f1abe86ddf2d7aab6382c9dcacf Mon Sep 17 00:00:00 2001 From: Sarah Taylor <150694563+staysgt@users.noreply.github.com> Date: Sun, 20 Sep 2026 21:19:28 -0400 Subject: [PATCH 5/5] #4502 prettier --- src/backend/src/services/exec-summaries.services.ts | 7 ++++++- src/backend/tests/unit/exec-summaries.test.ts | 6 +++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/backend/src/services/exec-summaries.services.ts b/src/backend/src/services/exec-summaries.services.ts index a79a018795..eff718221d 100644 --- a/src/backend/src/services/exec-summaries.services.ts +++ b/src/backend/src/services/exec-summaries.services.ts @@ -1,7 +1,12 @@ import { Organization } from '@prisma/client'; import { notGuest, User } from 'shared'; import prisma from '../prisma/prisma.js'; -import { AccessDeniedException, DeletedException, InvalidOrganizationException, NotFoundException } from '../utils/errors.utils.js'; +import { + AccessDeniedException, + DeletedException, + InvalidOrganizationException, + NotFoundException +} from '../utils/errors.utils.js'; import { getExecutiveSummaryQueryArgs } from '../prisma-query-args/executive-summary.query-args.js'; import { executiveSummaryTransformer } from '../transformers/executive-summary.transformer.js'; import { userHasPermission } from '../utils/users.utils.js'; diff --git a/src/backend/tests/unit/exec-summaries.test.ts b/src/backend/tests/unit/exec-summaries.test.ts index 1b3558b29f..137cd5d133 100644 --- a/src/backend/tests/unit/exec-summaries.test.ts +++ b/src/backend/tests/unit/exec-summaries.test.ts @@ -32,7 +32,11 @@ describe('Executive Summaries Tests', () => { ...getExecutiveSummaryQueryArgs(organization.organizationId) }); - const summary = await ExecSummaryServices.getSingleExecutiveSummary(organization, createdSummary.executiveSummaryId, user); + const summary = await ExecSummaryServices.getSingleExecutiveSummary( + organization, + createdSummary.executiveSummaryId, + user + ); expect(summary).toStrictEqual(executiveSummaryTransformer(createdSummary)); }); it('invalid id get single exec summary', async () => {