From 3a6bb8be82b33efc5ad6795208e0881c66a36047 Mon Sep 17 00:00:00 2001 From: Mike Vesprini <11034827+mikevespi@users.noreply.github.com> Date: Wed, 16 Oct 2024 12:10:51 -0700 Subject: [PATCH] feat: CE-1045 Add getLeadsByActionTaken query (#95) --- backend/src/app.module.ts | 2 + backend/src/lead/lead.graphql | 3 ++ backend/src/lead/lead.module.ts | 10 +++++ backend/src/lead/lead.resolver.ts | 18 ++++++++ backend/src/lead/lead.service.spec.ts | 20 +++++++++ backend/src/lead/lead.service.ts | 59 +++++++++++++++++++++++++++ 6 files changed, 112 insertions(+) create mode 100644 backend/src/lead/lead.graphql create mode 100644 backend/src/lead/lead.module.ts create mode 100644 backend/src/lead/lead.resolver.ts create mode 100644 backend/src/lead/lead.service.spec.ts create mode 100644 backend/src/lead/lead.service.ts diff --git a/backend/src/app.module.ts b/backend/src/app.module.ts index 9d6138cb..580062e7 100644 --- a/backend/src/app.module.ts +++ b/backend/src/app.module.ts @@ -31,6 +31,7 @@ import { SectorCodeModule } from "./code-tables/sector_code/sector_code.module"; import { CEEBDecisionActionModule } from "./ceeb_decision_action/ceeb_decision_action.module"; import { AgencyCodeModule } from "./agency_code/agency_code.module"; import { ScheduleSectorXrefModule } from "./schedule_sector_xref/schedule_sector_xref.module"; +import { LeadModule } from "./lead/lead.module"; @Module({ imports: [ @@ -63,6 +64,7 @@ import { ScheduleSectorXrefModule } from "./schedule_sector_xref/schedule_sector SectorCodeModule, CEEBDecisionActionModule, ScheduleSectorXrefModule, + LeadModule, ], controllers: [AppController], providers: [AppService, DateScalar], diff --git a/backend/src/lead/lead.graphql b/backend/src/lead/lead.graphql new file mode 100644 index 00000000..03b6bac7 --- /dev/null +++ b/backend/src/lead/lead.graphql @@ -0,0 +1,3 @@ +type Query { + getLeadsByActionTaken(actionCode: String!): [String] +} diff --git a/backend/src/lead/lead.module.ts b/backend/src/lead/lead.module.ts new file mode 100644 index 00000000..c636370e --- /dev/null +++ b/backend/src/lead/lead.module.ts @@ -0,0 +1,10 @@ +import { Module } from "@nestjs/common"; +import { LeadService } from "./lead.service"; +import { LeadResolver } from "./lead.resolver"; +import { PrismaModule } from "nestjs-prisma"; + +@Module({ + imports: [PrismaModule], + providers: [LeadResolver, LeadService], +}) +export class LeadModule {} diff --git a/backend/src/lead/lead.resolver.ts b/backend/src/lead/lead.resolver.ts new file mode 100644 index 00000000..83919136 --- /dev/null +++ b/backend/src/lead/lead.resolver.ts @@ -0,0 +1,18 @@ +import { Resolver, Query, Args } from "@nestjs/graphql"; +import { LeadService } from "./lead.service"; +import { JwtRoleGuard } from "../auth/jwtrole.guard"; +import { UseGuards } from "@nestjs/common"; +import { Role } from "../enum/role.enum"; +import { Roles } from "../auth/decorators/roles.decorator"; + +@UseGuards(JwtRoleGuard) +@Resolver("Lead") +export class LeadResolver { + constructor(private readonly leadService: LeadService) {} + + @Query("getLeadsByActionTaken") + @Roles(Role.CEEB) + findOne(@Args("actionCode") actionCode: string) { + return this.leadService.getLeadsByActionTaken(actionCode); + } +} diff --git a/backend/src/lead/lead.service.spec.ts b/backend/src/lead/lead.service.spec.ts new file mode 100644 index 00000000..d04dbe19 --- /dev/null +++ b/backend/src/lead/lead.service.spec.ts @@ -0,0 +1,20 @@ +import { Test, TestingModule } from "@nestjs/testing"; +import { LeadService } from "./lead.service"; +import { PrismaModule } from "nestjs-prisma"; + +describe("LeadService", () => { + let service: LeadService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + imports: [PrismaModule], + providers: [LeadService], + }).compile(); + + service = module.get(LeadService); + }); + + it("should be defined", () => { + expect(service).toBeDefined(); + }); +}); diff --git a/backend/src/lead/lead.service.ts b/backend/src/lead/lead.service.ts new file mode 100644 index 00000000..55cbc594 --- /dev/null +++ b/backend/src/lead/lead.service.ts @@ -0,0 +1,59 @@ +import { Injectable } from "@nestjs/common"; +import { PrismaService } from "nestjs-prisma"; +import { GraphQLError } from "graphql"; +import { ACTION_TYPE_CODES } from "../common/action_type_codes"; +import { ACTION_CODES } from "../common/action_codes"; + +@Injectable() +export class LeadService { + constructor(private prisma: PrismaService) {} + + async getLeadsByActionTaken(actionCode: string): Promise { + /** + * Provided an action taken, returns the lead_identifier for each lead whose case_file has had that action taken + * on it. + * actionCode: the action_code to filter actions by + */ + const actionCodeXrefContext = this.prisma.action_type_action_xref; + const xrefResult = await actionCodeXrefContext.findFirst({ + where: { + action_code: actionCode, + // Filtering by action taken is currently exclusive to CEEB which allows us to filter on CEEBACTION type + action_type_code: ACTION_TYPE_CODES.CEEBACTION, + }, + select: { + action_type_action_xref_guid: true, + }, + }); + + const actionResults = await this.prisma.action.findMany({ + where: { + action_type_action_xref_guid: xrefResult.action_type_action_xref_guid, + }, + select: { + case_guid: true, + }, + }); + + const caseGuids: string[] = []; + for (let action of actionResults) { + caseGuids.push(action.case_guid); + } + + const leadResults = await this.prisma.lead.findMany({ + where: { + case_identifier: { + in: caseGuids, + }, + }, + select: { + lead_identifier: true, + }, + }); + const leadIdentifiers: string[] = []; + for (let leadId of leadResults) { + leadIdentifiers.push(leadId.lead_identifier); + } + return leadIdentifiers; + } +}