From ee16eb289b6f08c4b7d4130c48417f7ad14325ca Mon Sep 17 00:00:00 2001 From: Barrett Falk Date: Mon, 25 Mar 2024 13:06:31 -0700 Subject: [PATCH] feat: CE-365 (#36) Co-authored-by: cnesmithsalus <69365683+cnesmithsalus@users.noreply.github.com> Co-authored-by: afwilcox --- .gitignore | 3 +- backend/prisma/schema.prisma | 82 ++-- backend/src/app.module.ts | 2 + backend/src/auth/jwtauth.guard.ts | 4 - backend/src/case_file/case_file.graphql | 45 ++ backend/src/case_file/case_file.resolver.ts | 24 +- backend/src/case_file/case_file.service.ts | 384 ++++++++++++++---- .../case_file/dto/create-case_file.input.ts | 9 + .../case_file/dto/prevention-action.input.ts | 6 + .../case_file/dto/prevention-details.input.ts | 5 + .../case_file/dto/update-case_file.input.ts | 10 + .../case_file/entities/assessment.entity.ts | 4 +- ...action.entity.ts => case-action.entity.ts} | 2 +- .../case_file/entities/case_file.entity.ts | 2 + .../case_file/entities/prevention.entity.ts | 5 + .../hwcr_assessment_action.service.ts | 2 +- .../entities/hwcr_prevention_action.entity.ts | 9 + .../hwcr_prevention_action.graphql | 12 + .../hwcr_prevention_action.module.ts | 10 + .../hwcr_prevention_action.resolver.spec.ts | 21 + .../hwcr_prevention_action.resolver.ts | 19 + .../hwcr_prevention_action.service.spec.ts | 20 + .../hwcr_prevention_action.service.ts | 67 +++ docker-compose.yml | 2 +- .../sql/R__0.15.0__CE-356_seed_data.sql | 37 +- .../sql/R__0.16.1__CE-365_new_seed_data.sql | 23 ++ migrations/sql/V1.16.1__CE-357.sql | 35 ++ migrations/sql/V1.16.2__CE-365.sql | 2 + 28 files changed, 726 insertions(+), 120 deletions(-) create mode 100644 backend/src/case_file/dto/prevention-action.input.ts create mode 100644 backend/src/case_file/dto/prevention-details.input.ts rename backend/src/case_file/entities/{assessment-action.entity.ts => case-action.entity.ts} (82%) create mode 100644 backend/src/case_file/entities/prevention.entity.ts create mode 100644 backend/src/hwcr_prevention_action/entities/hwcr_prevention_action.entity.ts create mode 100644 backend/src/hwcr_prevention_action/hwcr_prevention_action.graphql create mode 100644 backend/src/hwcr_prevention_action/hwcr_prevention_action.module.ts create mode 100644 backend/src/hwcr_prevention_action/hwcr_prevention_action.resolver.spec.ts create mode 100644 backend/src/hwcr_prevention_action/hwcr_prevention_action.resolver.ts create mode 100644 backend/src/hwcr_prevention_action/hwcr_prevention_action.service.spec.ts create mode 100644 backend/src/hwcr_prevention_action/hwcr_prevention_action.service.ts create mode 100644 migrations/sql/R__0.16.1__CE-365_new_seed_data.sql create mode 100644 migrations/sql/V1.16.1__CE-357.sql create mode 100644 migrations/sql/V1.16.2__CE-365.sql diff --git a/.gitignore b/.gitignore index 66a05f95..ba4d6073 100644 --- a/.gitignore +++ b/.gitignore @@ -119,4 +119,5 @@ test-report.xml .vscode/ # Mac -.DS_Store \ No newline at end of file +.DS_Store +backend/nr-compliance-enforcement-cm.code-workspace diff --git a/backend/prisma/schema.prisma b/backend/prisma/schema.prisma index beca752c..0c5eb143 100644 --- a/backend/prisma/schema.prisma +++ b/backend/prisma/schema.prisma @@ -120,15 +120,16 @@ model sex_code { } model equipment_code { - equipment_code String @id(map: "PK_equipmntcd") @db.VarChar(10) - short_description String @db.VarChar(50) - long_description String? @db.VarChar(250) - display_order Int - active_ind Boolean - create_user_id String @db.VarChar(32) - create_utc_timestamp DateTime @db.Timestamp(6) - update_user_id String @db.VarChar(32) - update_utc_timestamp DateTime @db.Timestamp(6) + equipment_code String @id(map: "PK_equipmntcd") @db.VarChar(10) + short_description String @db.VarChar(50) + long_description String? @db.VarChar(250) + display_order Int + active_ind Boolean + create_user_id String @db.VarChar(32) + create_utc_timestamp DateTime @db.Timestamp(6) + update_user_id String @db.VarChar(32) + update_utc_timestamp DateTime @db.Timestamp(6) + equipment_equipment_equipment_codeToequipment_code equipment[] @relation("equipment_equipment_codeToequipment_code") } model threat_level_code { @@ -144,35 +145,37 @@ model threat_level_code { } model configuration { - configuration_code String @id(map: "PK_configcode") @db.VarChar(10) - configuration_value String @db.VarChar(250) - long_description String? @db.VarChar(250) + configuration_code String @id(map: "configuration_pk") @db.VarChar(10) + configuration_value String @db.VarChar(250) + long_description String @db.VarChar(250) active_ind Boolean - create_user_id String @db.VarChar(32) - create_utc_timestamp DateTime @db.Timestamp(6) - update_user_id String @db.VarChar(32) - update_utc_timestamp DateTime @db.Timestamp(6) + create_user_id String @db.VarChar(32) + create_utc_timestamp DateTime @db.Timestamp(6) + update_user_id String @db.VarChar(32) + update_utc_timestamp DateTime? @db.Timestamp(6) } /// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments model action { - action_guid String @id(map: "PK_action_guid") @default(dbgenerated("uuid_generate_v4()")) @db.Uuid - case_guid String @db.Uuid - action_type_action_xref_guid String @db.Uuid - actor_guid String @db.Uuid - action_date DateTime @db.Timestamp(6) + action_guid String @id(map: "PK_action_guid") @default(dbgenerated("uuid_generate_v4()")) @db.Uuid + case_guid String @db.Uuid + action_type_action_xref_guid String @db.Uuid + actor_guid String @db.Uuid + action_date DateTime @db.Timestamp(6) active_ind Boolean? - create_user_id String @db.VarChar(32) - create_utc_timestamp DateTime @db.Timestamp(6) - update_user_id String? @db.VarChar(32) - update_utc_timestamp DateTime? @db.Timestamp(6) - case_file case_file @relation(fields: [case_guid], references: [case_file_guid], onDelete: NoAction, onUpdate: NoAction, map: "FK_action__case_guid") + create_user_id String @db.VarChar(32) + create_utc_timestamp DateTime @db.Timestamp(6) + update_user_id String? @db.VarChar(32) + update_utc_timestamp DateTime? @db.Timestamp(6) + equipment_guid String? @db.Uuid + case_file case_file @relation(fields: [case_guid], references: [case_file_guid], onDelete: NoAction, onUpdate: NoAction, map: "FK_action__case_guid") + equipment equipment? @relation(fields: [equipment_guid], references: [equipment_guid], onDelete: NoAction, onUpdate: NoAction, map: "fk_action__equipment_guid") } /// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments model action_code { action_code String @id(map: "PK_action_code") @db.VarChar(10) - short_description String? @db.VarChar(50) + short_description String? @db.VarChar(250) long_description String? @db.VarChar(250) active_ind Boolean? create_user_id String @db.VarChar(32) @@ -313,3 +316,28 @@ model lead_h { operation_executed_at DateTime @default(now()) @db.Timestamp(6) data_after_executed_operation Json? } + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model configuration_h { + h_configuration_guid String @id(map: "PK_h_configuration") @default(dbgenerated("uuid_generate_v4()")) @db.Uuid + target_row_id String @db.VarChar(10) + operation_type String @db.Char(1) + operation_user_id String @default(dbgenerated("CURRENT_USER")) @db.VarChar(32) + operation_executed_at DateTime @default(now()) @db.Timestamp(6) + data_after_executed_operation Json? +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model equipment { + equipment_guid String @id(map: "PK_equipment_guid") @db.Uuid + equipment_code String? @db.VarChar(10) + equipment_location_desc String? @db.VarChar(120) + equipment_geometry_point String? + active_ind Boolean + create_user_id String @db.VarChar(32) + create_utc_timestamp DateTime @db.Timestamp(6) + update_user_id String @db.VarChar(32) + update_utc_timestamp DateTime @db.Timestamp(6) + action action[] + equipment_code_equipment_equipment_codeToequipment_code equipment_code? @relation("equipment_equipment_codeToequipment_code", fields: [equipment_code], references: [equipment_code], onDelete: NoAction, onUpdate: NoAction, map: "fk_equipment__equipment_code") +} diff --git a/backend/src/app.module.ts b/backend/src/app.module.ts index 7bd70940..9277500a 100644 --- a/backend/src/app.module.ts +++ b/backend/src/app.module.ts @@ -23,6 +23,7 @@ import { HWCRAssessmentActionModule } from "./hwcr_assessment_action/hwcr_assess import { CaseFileModule } from "./case_file/case_file.module"; import { InactionJustificationTypeModule } from "./inaction_justification_type/inaction_justification_type.module"; import { DateScalar } from "./common/custom_scalars"; +import { HWCRPreventionActionModule } from "./hwcr_prevention_action/hwcr_prevention_action.module"; @Module({ imports: [ @@ -45,6 +46,7 @@ import { DateScalar } from "./common/custom_scalars"; HwcrOutcomeCodeModule, ConfigurationModule, HWCRAssessmentActionModule, + HWCRPreventionActionModule, CaseFileModule, InactionJustificationTypeModule ], diff --git a/backend/src/auth/jwtauth.guard.ts b/backend/src/auth/jwtauth.guard.ts index 1668b54d..c70a16fe 100644 --- a/backend/src/auth/jwtauth.guard.ts +++ b/backend/src/auth/jwtauth.guard.ts @@ -26,10 +26,6 @@ export class JwtAuthGuard extends AuthGuard('jwt') { context.getClass, ]); - // Log controller/route information before the isPublic check - this.logger.debug(`Executing ${className}.${handler.name}`); - this.logger.debug(`isPublic? ${isPublic}`); - if (isPublic) { return true; } else { diff --git a/backend/src/case_file/case_file.graphql b/backend/src/case_file/case_file.graphql index f4448eb7..f618e53c 100644 --- a/backend/src/case_file/case_file.graphql +++ b/backend/src/case_file/case_file.graphql @@ -4,6 +4,7 @@ type CaseFile { caseIdentifier : String leadIdentifier: String assessmentDetails: Assessment + preventionDetails: Prevention } type Assessment { @@ -54,6 +55,47 @@ input UpdateAssessmentInput { updateUserId: String! } +type Prevention { + actions: [PreventionAction] +} + +type PreventionAction{ + actor: String! + date: Date! + actionCode: String! + shortDescription: String + longDescription: String + activeIndicator: Boolean +} + +input CreatePreventionInput { + leadIdentifier: String + preventionDetails: PreventionDetailsInput! + agencyCode: String! + caseCode: String! + createUserId: String! +} + +input PreventionDetailsInput { + actions: [PreventionActionInput]! +} + +input PreventionActionInput{ + actor: String! + date: Date! + actionCode: String! + activeIndicator: Boolean! +} + +input UpdatePreventionInput { + caseIdentifier: String! + leadIdentifier: String + preventionDetails: PreventionDetailsInput! + agencyCode: String! + caseCode: String! + updateUserId: String! +} + type Query { getCaseFile( caseIdentifier: String!): CaseFile getCaseFileByLeadId( leadIdentifier: String!): CaseFile @@ -62,4 +104,7 @@ type Query { type Mutation { createAssessment(createAssessmentInput: CreateAssessmentInput!): CaseFile! updateAssessment(updateAssessmentInput: UpdateAssessmentInput!): CaseFile! + + createPrevention(createPreventionInput: CreatePreventionInput!): CaseFile! + updatePrevention(updatePreventionInput: UpdatePreventionInput!): CaseFile! } diff --git a/backend/src/case_file/case_file.resolver.ts b/backend/src/case_file/case_file.resolver.ts index 47299c70..7a8da9c4 100644 --- a/backend/src/case_file/case_file.resolver.ts +++ b/backend/src/case_file/case_file.resolver.ts @@ -1,7 +1,7 @@ import { Resolver, Query, Mutation, Args } from '@nestjs/graphql'; import { CaseFileService } from './case_file.service'; -import { CreateAssessmentInput } from './dto/create-case_file.input'; -import { UpdateAssessmentInput } from './dto/update-case_file.input'; +import { CreateAssessmentInput, CreatePreventionInput } from './dto/create-case_file.input'; +import { UpdateAssessmentInput, UpdatePreventionInput } from './dto/update-case_file.input'; import { JwtRoleGuard } from "../auth/jwtrole.guard"; import { UseGuards } from "@nestjs/common"; import { Role } from "../enum/role.enum"; @@ -14,8 +14,14 @@ export class CaseFileResolver { @Mutation('createAssessment') @Roles(Role.COS_OFFICER) - create(@Args('createAssessmentInput') createAssessmentInput: CreateAssessmentInput) { - return this.caseFileService.create(createAssessmentInput); + createAssessment(@Args('createAssessmentInput') createAssessmentInput: CreateAssessmentInput) { + return this.caseFileService.createAssessment(createAssessmentInput); + } + + @Mutation('createPrevention') + @Roles(Role.COS_OFFICER) + createPrevention(@Args('createPreventionInput') createPreventionInput: CreatePreventionInput) { + return this.caseFileService.createPrevention(createPreventionInput); } @Query('getCaseFile') @@ -32,8 +38,14 @@ export class CaseFileResolver { @Mutation('updateAssessment') @Roles(Role.COS_OFFICER) - update(@Args('updateAssessmentInput') updateAssessmentInput: UpdateAssessmentInput) { - return this.caseFileService.update(updateAssessmentInput.caseIdentifier, updateAssessmentInput); + updateAssessment(@Args('updateAssessmentInput') updateAssessmentInput: UpdateAssessmentInput) { + return this.caseFileService.updateAssessment(updateAssessmentInput.caseIdentifier, updateAssessmentInput); + } + + @Mutation('updatePrevention') + @Roles(Role.COS_OFFICER) + updatePrevention(@Args('updatePreventionInput') updatePreventionInput: UpdatePreventionInput) { + return this.caseFileService.updatePrevention(updatePreventionInput.caseIdentifier, updatePreventionInput); } } diff --git a/backend/src/case_file/case_file.service.ts b/backend/src/case_file/case_file.service.ts index 923827cc..94b88a0c 100644 --- a/backend/src/case_file/case_file.service.ts +++ b/backend/src/case_file/case_file.service.ts @@ -1,32 +1,20 @@ import { Injectable } from '@nestjs/common'; -import { CreateAssessmentInput } from './dto/create-case_file.input'; -import { UpdateAssessmentInput } from './dto/update-case_file.input'; +import { CreateAssessmentInput, CreatePreventionInput } from './dto/create-case_file.input'; +import { UpdateAssessmentInput, UpdatePreventionInput } from './dto/update-case_file.input'; import { PrismaService } from "nestjs-prisma"; import { CaseFile } from './entities/case_file.entity'; -import { AssessmentAction } from './entities/assessment-action.entity'; import { GraphQLError } from 'graphql'; @Injectable() export class CaseFileService { constructor(private prisma: PrismaService) { } - async create(createAssessmentInput: CreateAssessmentInput): Promise { - - let actiontypeCode: string = "COMPASSESS"; + async createAssessmentCase(createAssessmentInput: CreateAssessmentInput): Promise + { let caseFileGuid: string; - let caseFileOutput = new CaseFile(); - - try { - - if (createAssessmentInput.leadIdentifier) { - const existingCaseFile = await this.findOneByLeadId(createAssessmentInput.leadIdentifier); - console.log("existingCaseFile", existingCaseFile); - if (existingCaseFile != null && existingCaseFile.caseIdentifier != null) { - throw new Error(`The case ${existingCaseFile.caseIdentifier} assosiated with lead id ${createAssessmentInput.leadIdentifier} already exist. - Please run updateAssessment mutation.`, { - }); - } - } + + try + { await this.prisma.$transaction(async (db) => { let case_file = await db.case_file.create({ @@ -64,7 +52,66 @@ export class CaseFileService { create_utc_timestamp: new Date() } }); + }); + } + catch (exception) { + throw new GraphQLError('Exception occurred. See server log for details', { + }); + } + return caseFileGuid; + } + + async createOtherCase(createInput: CreatePreventionInput): Promise + { + let caseFileGuid: string; + + try + { + await this.prisma.$transaction(async (db) => { + + let case_file = await db.case_file.create({ + data: { + agency_code: { + connect: { + agency_code: createInput.agencyCode + } + }, + create_user_id: createInput.createUserId, + create_utc_timestamp: new Date(), + case_code_case_file_case_codeTocase_code: { + connect: { + case_code: createInput.caseCode + } + }, + } + }); + + caseFileGuid = case_file.case_file_guid; + + await db.lead.create({ + data: { + lead_identifier: createInput.leadIdentifier, + case_identifier: caseFileGuid, + create_user_id: createInput.createUserId, + create_utc_timestamp: new Date() + } + }); + }); + } + catch (exception) { + throw new GraphQLError('Exception occurred. See server log for details', { + }); + } + return caseFileGuid; + } + async createAssessment(createAssessmentInput: CreateAssessmentInput): Promise { + + let actiontypeCode: string = "COMPASSESS"; + let caseFileGuid: string = await this.createAssessmentCase(createAssessmentInput); + let caseFileOutput: CaseFile; + try { + await this.prisma.$transaction(async (db) => { let action_codes_objects = await db.action_type_action_xref.findMany({ where: { action_type_code: actiontypeCode }, select: { action_code: true } @@ -102,24 +149,74 @@ export class CaseFileService { }); } }); - caseFileOutput = await this.findOne(caseFileGuid); } - catch (exception) { - console.log("exception", exception); - throw new GraphQLError('Exception occurred. See server log for details', { + catch (exception) { + throw new GraphQLError('Exception occurred. See server log for details', { + }); + } + return caseFileOutput; + } + + async createPrevention(createPreventionInput: CreatePreventionInput): Promise { + + let actiontypeCode: string = "COSPRV&EDU"; + let caseFileGuid: string = await this.createOtherCase(createPreventionInput); + let caseFileOutput: CaseFile; + try { + await this.prisma.$transaction(async (db) => { + let action_codes_objects = await db.action_type_action_xref.findMany({ + where: { action_type_code: actiontypeCode }, + select: { action_code: true } + }); + let action_codes: Array = []; + for (const action_code_object of action_codes_objects) { + action_codes.push(action_code_object.action_code); + } + for (const action of createPreventionInput.preventionDetails.actions) { + if (action_codes.indexOf(action.actionCode) === -1) { + throw "Some action code values where not passed from the client"; + }; + } + + for (const action of createPreventionInput.preventionDetails.actions) { + let actionTypeActionXref = await db.action_type_action_xref.findFirstOrThrow({ + where: { + action_type_code: actiontypeCode, + action_code: action.actionCode + }, + select: { + action_type_action_xref_guid: true + } + }); + await db.action.create({ + data: { + case_guid: caseFileGuid, + action_type_action_xref_guid: actionTypeActionXref.action_type_action_xref_guid, + actor_guid: action.actor, + action_date: action.date, + active_ind: action.activeIndicator, + create_user_id: createPreventionInput.createUserId, + create_utc_timestamp: new Date + } + }); + } }); + caseFileOutput = await this.findOne(caseFileGuid); } + catch (exception) { + throw new GraphQLError('Exception occurred. See server log for details', { + }); + } return caseFileOutput; } + findAll() { return `This action returns all caseFile`; } async findOne(caseIdentifier: string) { - - let actiontypeCode: string = "COMPASSESS"; let agencyCode: string = "COS" const lead = await this.prisma.lead.findFirst({ @@ -143,14 +240,34 @@ export class CaseFileService { }, }); - const actionCodes = await this.prisma.action_type_action_xref.findMany({ + const assessmentActionCodes = await this.prisma.action_type_action_xref.findMany({ + where: { + action_type_code: 'COMPASSESS', + action_type_action_xref_guid: { in: actionsBase.map((item) => item.action_type_action_xref_guid) }, + }, + select: { + action_code: true, + action_type_action_xref_guid: true, + action_type_code: true, + action_code_action_type_action_xref_action_codeToaction_code: { + select: { + short_description: true, + long_description: true, + active_ind: true + }, + }, + } + }); + + const preventionActionCodes = await this.prisma.action_type_action_xref.findMany({ where: { - action_type_code: actiontypeCode, + action_type_code: 'COSPRV&EDU', action_type_action_xref_guid: { in: actionsBase.map((item) => item.action_type_action_xref_guid) }, }, select: { action_code: true, action_type_action_xref_guid: true, + action_type_code: true, action_code_action_type_action_xref_action_codeToaction_code: { select: { short_description: true, @@ -161,19 +278,38 @@ export class CaseFileService { } }); - const actions: AssessmentAction[] = actionsBase.map((action) => { - let actionData = actionCodes.find((element) => element.action_type_action_xref_guid === action.action_type_action_xref_guid); - return { - actor: action.actor_guid, - date: action.action_date, - actionCode: actionData.action_code, - shortDescription: actionData.action_code_action_type_action_xref_action_codeToaction_code.short_description, - longDescription: actionData.action_code_action_type_action_xref_action_codeToaction_code.long_description, - activeIndicator: action.active_ind, - }; + const assessmentActions = assessmentActionCodes.map((action) => { + let actionData = actionsBase.find((element) => (element.action_type_action_xref_guid === action.action_type_action_xref_guid)); + if(actionData && actionData !== undefined) + { + return { + actor: actionData.actor_guid, + date: actionData.action_date, + actionCode: action.action_code, + shortDescription: action.action_code_action_type_action_xref_action_codeToaction_code.short_description, + longDescription: action.action_code_action_type_action_xref_action_codeToaction_code.long_description, + activeIndicator: actionData.active_ind, + }; + } + }); + + + const preventionActions = preventionActionCodes.map((action) => { + let actionData = actionsBase.find((element) => (element.action_type_action_xref_guid === action.action_type_action_xref_guid)); + if(actionData && actionData !== undefined) + { + return { + actor: actionData.actor_guid, + date: actionData.action_date, + actionCode: action.action_code, + shortDescription: action.action_code_action_type_action_xref_action_codeToaction_code.short_description, + longDescription: action.action_code_action_type_action_xref_action_codeToaction_code.long_description, + activeIndicator: actionData.active_ind, + }; + } }); - const assessment = await this.prisma.case_file.findFirst({ + const caseFile = await this.prisma.case_file.findFirst({ where: { case_file_guid: caseIdentifier }, @@ -195,19 +331,22 @@ export class CaseFileService { }); const case_file: CaseFile = { - caseIdentifier: assessment?.case_file_guid, + caseIdentifier: caseFile?.case_file_guid, leadIdentifier: lead?.lead_identifier, assessmentDetails: { - actionNotRequired: assessment?.action_not_required_ind, - actionJustificationCode: assessment?.inaction_reason_code, - actionJustificationShortDescription: assessment?.inaction_reason_code_case_file_inaction_reason_codeToinaction_reason_code?.short_description, - actionJustificationLongDescription: assessment?.inaction_reason_code_case_file_inaction_reason_codeToinaction_reason_code?.long_description, - actionJustificationActiveIndicator: assessment?.inaction_reason_code_case_file_inaction_reason_codeToinaction_reason_code?.active_ind, - actions: actions + actionNotRequired: caseFile?.action_not_required_ind, + actionJustificationCode: caseFile?.inaction_reason_code, + actionJustificationShortDescription: caseFile?.inaction_reason_code_case_file_inaction_reason_codeToinaction_reason_code?.short_description, + actionJustificationLongDescription: caseFile?.inaction_reason_code_case_file_inaction_reason_codeToinaction_reason_code?.long_description, + actionJustificationActiveIndicator: caseFile?.inaction_reason_code_case_file_inaction_reason_codeToinaction_reason_code?.active_ind, + actions: assessmentActions + }, + preventionDetails: + { + actions: preventionActions } }; - return case_file; } @@ -230,10 +369,10 @@ export class CaseFileService { return caseFileOutput; } - async update(caseIdentifier: string, updateAssessmentInput: UpdateAssessmentInput) { + async updateAssessment(caseIdentifier: string, updateAssessmentInput: UpdateAssessmentInput) { - let actiontypeCode: string = "COMPASSESS"; - let caseFileOutput = new CaseFile(); + let actionTypeCode: string = "COMPASSESS"; + let caseFileOutput: CaseFile; try { await this.prisma.$transaction(async (db) => { @@ -263,44 +402,62 @@ export class CaseFileService { } }); - // "inaction_reason_code" column has foreign key but must accept nulls. - // In Prisma for some reason it is not possible to assign null to a relation field. - // Setting it to "undefined" like in previous statement has no effect. - // The statement below is to update the field from a referenced value to null if nesessary - if (!updateAssessmentInput.assessmentDetails.actionJustificationCode) { - await db.case_file.update({ - where: { case_file_guid: caseIdentifier }, - data: { - inaction_reason_code: null, - } - }); - } - for (const action of updateAssessmentInput.assessmentDetails.actions) { let actionTypeActionXref = await db.action_type_action_xref.findFirstOrThrow({ where: { - action_type_code: actiontypeCode, + action_type_code: actionTypeCode, action_code: action.actionCode }, select: { - action_type_action_xref_guid: true + action_type_action_xref_guid: true, + action_code: true, + action_type_code: true, } }); - - await db.action.updateMany({ + + let actionXref = await db.action.findFirst({ where: { + action_type_action_xref_guid: actionTypeActionXref.action_type_action_xref_guid, case_guid: caseIdentifier, - action_type_action_xref_guid: actionTypeActionXref.action_type_action_xref_guid }, - data: { - actor_guid: action.actor, - action_date: action.date, - active_ind: action.activeIndicator, - update_user_id: updateAssessmentInput.updateUserId, - update_utc_timestamp: new Date + select: { + action_type_action_xref_guid: true, } }); + + if(actionXref) + { + await db.action.updateMany({ + where: { + case_guid: caseIdentifier, + action_type_action_xref_guid: actionTypeActionXref.action_type_action_xref_guid + }, + data: { + actor_guid: action.actor, + action_date: action.date, + active_ind: action.activeIndicator, + update_user_id: updateAssessmentInput.updateUserId, + update_utc_timestamp: new Date + } + }); + } + else + { + await db.action.create({ + data: { + case_guid: caseIdentifier, + action_type_action_xref_guid: actionTypeActionXref.action_type_action_xref_guid, + actor_guid: action.actor, + action_date: action.date, + active_ind: action.activeIndicator, + create_user_id: updateAssessmentInput.updateUserId, + create_utc_timestamp: new Date + } + }); + } }; + + let assessmentCount: number = updateAssessmentInput.assessmentDetails.actions.length; if (assessmentCount === 0) { await db.action.updateMany({ @@ -309,10 +466,89 @@ export class CaseFileService { }); }; }); + + caseFileOutput = await this.findOne(caseIdentifier); + + } + catch (exception) { + throw new GraphQLError('Exception occurred. See server log for details', { + }); + } + return caseFileOutput; + } + + async updatePrevention(caseIdentifier: string, updatePreventionInput: UpdatePreventionInput) { + let actionTypeCode: string = "COSPRV&EDU"; + let caseFileOutput: CaseFile; + + try { + await this.prisma.$transaction(async (db) => { + for (const action of updatePreventionInput.preventionDetails.actions) { + let actionTypeActionXref = await db.action_type_action_xref.findFirstOrThrow({ + where: { + action_type_code: actionTypeCode, + action_code: action.actionCode, + }, + select: { + action_type_action_xref_guid: true, + action_code: true, + action_type_code: true, + + } + }); + + let actionXref = await db.action.findFirst({ + where: { + action_type_action_xref_guid: actionTypeActionXref.action_type_action_xref_guid, + case_guid: caseIdentifier, + }, + select: { + action_type_action_xref_guid: true, + } + }); + + if(actionXref) + { + await db.action.updateMany({ + where: { + case_guid: caseIdentifier, + action_type_action_xref_guid: actionTypeActionXref.action_type_action_xref_guid + }, + data: { + actor_guid: action.actor, + action_date: action.date, + active_ind: action.activeIndicator, + update_user_id: updatePreventionInput.updateUserId, + update_utc_timestamp: new Date + } + }) + } + else + { + await db.action.create({ + data: { + case_guid: caseIdentifier, + action_type_action_xref_guid: actionTypeActionXref.action_type_action_xref_guid, + actor_guid: action.actor, + action_date: action.date, + active_ind: action.activeIndicator, + create_user_id: updatePreventionInput.updateUserId, + create_utc_timestamp: new Date + } + }); + } + }; + let preventionCount: number = updatePreventionInput.preventionDetails.actions.length; + if (preventionCount === 0) { + await db.action.updateMany({ + where: { case_guid: caseIdentifier }, + data: { active_ind: false } + }); + }; + }); caseFileOutput = await this.findOne(caseIdentifier); } catch (exception) { - console.log("exception", exception); throw new GraphQLError('Exception occurred. See server log for details', { }); } diff --git a/backend/src/case_file/dto/create-case_file.input.ts b/backend/src/case_file/dto/create-case_file.input.ts index e1517e1b..4f3d0966 100644 --- a/backend/src/case_file/dto/create-case_file.input.ts +++ b/backend/src/case_file/dto/create-case_file.input.ts @@ -1,4 +1,5 @@ import { AssessmentDetailsInput } from "./assessment-details.input"; +import { PreventionDetailsInput } from "./prevention-details.input"; export class CreateAssessmentInput { leadIdentifier: string; assessmentDetails: AssessmentDetailsInput; @@ -6,3 +7,11 @@ export class CreateAssessmentInput { caseCode: string; createUserId: string; } + +export class CreatePreventionInput { + leadIdentifier: string; + preventionDetails: PreventionDetailsInput; + agencyCode: string; + caseCode: string; + createUserId: string; +} \ No newline at end of file diff --git a/backend/src/case_file/dto/prevention-action.input.ts b/backend/src/case_file/dto/prevention-action.input.ts new file mode 100644 index 00000000..6019dee8 --- /dev/null +++ b/backend/src/case_file/dto/prevention-action.input.ts @@ -0,0 +1,6 @@ +export class PreventionActionInput { + actor: string; + date: Date; + actionCode: string; + activeIndicator: boolean; +} diff --git a/backend/src/case_file/dto/prevention-details.input.ts b/backend/src/case_file/dto/prevention-details.input.ts new file mode 100644 index 00000000..817fc386 --- /dev/null +++ b/backend/src/case_file/dto/prevention-details.input.ts @@ -0,0 +1,5 @@ +import { PreventionActionInput } from "./prevention-action.input" + +export class PreventionDetailsInput { + actions: [PreventionActionInput] +} diff --git a/backend/src/case_file/dto/update-case_file.input.ts b/backend/src/case_file/dto/update-case_file.input.ts index 8e756cec..be41fb57 100644 --- a/backend/src/case_file/dto/update-case_file.input.ts +++ b/backend/src/case_file/dto/update-case_file.input.ts @@ -1,4 +1,5 @@ import { AssessmentDetailsInput } from "./assessment-details.input"; +import { PreventionDetailsInput } from "./prevention-details.input"; export class UpdateAssessmentInput { caseIdentifier: string; @@ -7,4 +8,13 @@ export class UpdateAssessmentInput { agencyCode: string; caseCode: string; updateUserId: string; +} + +export class UpdatePreventionInput { + caseIdentifier: string; + leadIdentifier: string; + preventionDetails: PreventionDetailsInput; + agencyCode: string; + caseCode: string; + updateUserId: string; } \ No newline at end of file diff --git a/backend/src/case_file/entities/assessment.entity.ts b/backend/src/case_file/entities/assessment.entity.ts index 05218ef3..98133357 100644 --- a/backend/src/case_file/entities/assessment.entity.ts +++ b/backend/src/case_file/entities/assessment.entity.ts @@ -1,4 +1,4 @@ -import { AssessmentAction } from "./assessment-action.entity"; +import { Action } from "./case-action.entity"; export class Assessment { actionNotRequired: boolean; @@ -6,6 +6,6 @@ export class Assessment { actionJustificationShortDescription: string; actionJustificationLongDescription: string; actionJustificationActiveIndicator: boolean; - actions: AssessmentAction[] + actions: Action[] } \ No newline at end of file diff --git a/backend/src/case_file/entities/assessment-action.entity.ts b/backend/src/case_file/entities/case-action.entity.ts similarity index 82% rename from backend/src/case_file/entities/assessment-action.entity.ts rename to backend/src/case_file/entities/case-action.entity.ts index 4a376bdf..068b55e9 100644 --- a/backend/src/case_file/entities/assessment-action.entity.ts +++ b/backend/src/case_file/entities/case-action.entity.ts @@ -1,4 +1,4 @@ -export class AssessmentAction { +export class Action { actor: string; date: Date; actionCode: string; diff --git a/backend/src/case_file/entities/case_file.entity.ts b/backend/src/case_file/entities/case_file.entity.ts index 2ab864b6..3693a136 100644 --- a/backend/src/case_file/entities/case_file.entity.ts +++ b/backend/src/case_file/entities/case_file.entity.ts @@ -1,7 +1,9 @@ import { Assessment } from "./assessment.entity"; +import { Prevention } from "./prevention.entity"; export class CaseFile { caseIdentifier: string; leadIdentifier: string; assessmentDetails: Assessment; + preventionDetails: Prevention; } diff --git a/backend/src/case_file/entities/prevention.entity.ts b/backend/src/case_file/entities/prevention.entity.ts new file mode 100644 index 00000000..9a58312d --- /dev/null +++ b/backend/src/case_file/entities/prevention.entity.ts @@ -0,0 +1,5 @@ +import { Action } from "./case-action.entity"; + +export class Prevention { + actions: Action[] +} diff --git a/backend/src/hwcr_assessment_action/hwcr_assessment_action.service.ts b/backend/src/hwcr_assessment_action/hwcr_assessment_action.service.ts index 4340b101..1414ee5f 100644 --- a/backend/src/hwcr_assessment_action/hwcr_assessment_action.service.ts +++ b/backend/src/hwcr_assessment_action/hwcr_assessment_action.service.ts @@ -9,7 +9,7 @@ export class HWCRAssessmentActionService { async find(actionTypeCode?: string) { const dataContext = this.prisma.action_type_action_xref; let queryResult = null; - + actionTypeCode = "COMPASSESS"; //send from frontend later? if (actionTypeCode) { queryResult = await dataContext.findMany({ where: { diff --git a/backend/src/hwcr_prevention_action/entities/hwcr_prevention_action.entity.ts b/backend/src/hwcr_prevention_action/entities/hwcr_prevention_action.entity.ts new file mode 100644 index 00000000..95f9a024 --- /dev/null +++ b/backend/src/hwcr_prevention_action/entities/hwcr_prevention_action.entity.ts @@ -0,0 +1,9 @@ +export class HWCRPreventionAction { + actionTypeCode: string + actionCode: string + displayOrder: number + activeIndicator: boolean + shortDescription: string + longDescription: string +} + diff --git a/backend/src/hwcr_prevention_action/hwcr_prevention_action.graphql b/backend/src/hwcr_prevention_action/hwcr_prevention_action.graphql new file mode 100644 index 00000000..a8e723bd --- /dev/null +++ b/backend/src/hwcr_prevention_action/hwcr_prevention_action.graphql @@ -0,0 +1,12 @@ +type HWCRPreventionAction { + actionTypeCode: String! + actionCode: String! + displayOrder: Int + activeIndicator: Boolean + shortDescription: String! + longDescription: String! +} + +type Query { + HWCRPreventionActions (actionTypeCode: String): [HWCRPreventionAction]! +} diff --git a/backend/src/hwcr_prevention_action/hwcr_prevention_action.module.ts b/backend/src/hwcr_prevention_action/hwcr_prevention_action.module.ts new file mode 100644 index 00000000..046c7afd --- /dev/null +++ b/backend/src/hwcr_prevention_action/hwcr_prevention_action.module.ts @@ -0,0 +1,10 @@ +import { Module } from '@nestjs/common'; +import { PrismaModule } from 'nestjs-prisma'; +import { HWCRPreventionActionService } from './hwcr_prevention_action.service'; +import { HWCRPreventionActionResolver } from './hwcr_prevention_action.resolver'; + +@Module({ + imports: [PrismaModule], + providers: [HWCRPreventionActionResolver, HWCRPreventionActionService], +}) +export class HWCRPreventionActionModule { } diff --git a/backend/src/hwcr_prevention_action/hwcr_prevention_action.resolver.spec.ts b/backend/src/hwcr_prevention_action/hwcr_prevention_action.resolver.spec.ts new file mode 100644 index 00000000..b762c582 --- /dev/null +++ b/backend/src/hwcr_prevention_action/hwcr_prevention_action.resolver.spec.ts @@ -0,0 +1,21 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { PrismaModule } from 'nestjs-prisma'; +import { HWCRPreventionActionResolver } from './hwcr_prevention_action.resolver'; +import { HWCRPreventionActionService } from './hwcr_prevention_action.service'; + +describe('ActionTypeActionXrefResolver', () => { + let resolver: HWCRPreventionActionResolver; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + imports: [PrismaModule], + providers: [HWCRPreventionActionResolver, HWCRPreventionActionService], + }).compile(); + + resolver = module.get(HWCRPreventionActionService); + }); + + it('should be defined', () => { + expect(resolver).toBeDefined(); + }); +}); diff --git a/backend/src/hwcr_prevention_action/hwcr_prevention_action.resolver.ts b/backend/src/hwcr_prevention_action/hwcr_prevention_action.resolver.ts new file mode 100644 index 00000000..df9068a2 --- /dev/null +++ b/backend/src/hwcr_prevention_action/hwcr_prevention_action.resolver.ts @@ -0,0 +1,19 @@ +import { Resolver, Query, Args } from '@nestjs/graphql'; +import { JwtRoleGuard } from "../auth/jwtrole.guard"; +import { UseGuards } from "@nestjs/common"; +import { Role } from "../enum/role.enum"; +import { Roles } from "../auth/decorators/roles.decorator"; +import { HWCRPreventionActionService } from "./hwcr_prevention_action.service" + +@UseGuards(JwtRoleGuard) +@Resolver('HWCRPreventionAction') +export class HWCRPreventionActionResolver { + constructor(private readonly HWCRPreventionActionService: HWCRPreventionActionService) { } + + @Query('HWCRPreventionActions') + @Roles(Role.COS_OFFICER) + find(@Args('actionTypeCode') actionTypeCode?: string) { + return this.HWCRPreventionActionService.find(actionTypeCode); + } + +} diff --git a/backend/src/hwcr_prevention_action/hwcr_prevention_action.service.spec.ts b/backend/src/hwcr_prevention_action/hwcr_prevention_action.service.spec.ts new file mode 100644 index 00000000..3eedf2a8 --- /dev/null +++ b/backend/src/hwcr_prevention_action/hwcr_prevention_action.service.spec.ts @@ -0,0 +1,20 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { PrismaModule } from 'nestjs-prisma'; +import { HWCRPreventionActionService } from './hwcr_prevention_action.service'; + +describe('HWCRPreventionActionService', () => { + let service: HWCRPreventionActionService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + imports: [PrismaModule], + providers: [HWCRPreventionActionService], + }).compile(); + + service = module.get(HWCRPreventionActionService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/backend/src/hwcr_prevention_action/hwcr_prevention_action.service.ts b/backend/src/hwcr_prevention_action/hwcr_prevention_action.service.ts new file mode 100644 index 00000000..4ef6b0c9 --- /dev/null +++ b/backend/src/hwcr_prevention_action/hwcr_prevention_action.service.ts @@ -0,0 +1,67 @@ +import { Injectable } from '@nestjs/common'; +import { PrismaService } from "nestjs-prisma"; +import { HWCRPreventionAction } from './entities/hwcr_prevention_action.entity'; + +@Injectable() +export class HWCRPreventionActionService { + constructor(private prisma: PrismaService) { } + + async find(actionTypeCode?: string) { + const dataContext = this.prisma.action_type_action_xref; + let queryResult = null; + actionTypeCode = "COSPRV&EDU"; //send from frontend later? + if (actionTypeCode) { + queryResult = await dataContext.findMany({ + where: { + action_type_code: actionTypeCode + }, + select: { + action_type_code: true, + action_code: true, + display_order: true, + active_ind: true, + action_code_action_type_action_xref_action_codeToaction_code: { + select: { + short_description: true, + long_description: true, + } + } + }, + orderBy: { + display_order: 'asc', + } + }) + } + else { + queryResult = await dataContext.findMany({ + select: { + action_type_code: true, + action_code: true, + display_order: true, + active_ind: true, + action_code_action_type_action_xref_action_codeToaction_code: { + select: { + short_description: true, + long_description: true, + } + } + } + }) + } + let actionCodes: Array = []; + + queryResult.forEach((record) => { + actionCodes.push( + Object.assign(new HWCRPreventionAction(), { + actionTypeCode: record.action_type_code, + actionCode: record.action_code, + displayOrder: record.display_order, + activeIndicator: record.active_ind, + shortDescription: record.action_code_action_type_action_xref_action_codeToaction_code.short_description, + longDescription: record.action_code_action_type_action_xref_action_codeToaction_code.long_description + })); + }); + + return actionCodes; + } +} diff --git a/docker-compose.yml b/docker-compose.yml index a271860e..bbcb238e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -17,7 +17,7 @@ x-postgres-vars: &postgres-vars services: database: - image: postgres:15 + image: postgis/postgis:15-3.3 container_name: cm-database environment: <<: *postgres-vars diff --git a/migrations/sql/R__0.15.0__CE-356_seed_data.sql b/migrations/sql/R__0.15.0__CE-356_seed_data.sql index d6c81a67..eaa1a155 100644 --- a/migrations/sql/R__0.15.0__CE-356_seed_data.sql +++ b/migrations/sql/R__0.15.0__CE-356_seed_data.sql @@ -1,7 +1,8 @@ insert into case_management.action_type_code (action_type_code, short_description, long_description, active_ind, create_user_id, create_utc_timestamp) values - ('COMPASSESS', 'Complaint Assessment', 'Complaint Assessment', 'Y', CURRENT_USER, CURRENT_TIMESTAMP) + ('COMPASSESS', 'Complaint Assessment', 'Complaint Assessment', 'Y', CURRENT_USER, CURRENT_TIMESTAMP), + ('COSPRV&EDU', 'Prevention and Education', 'Prevention and Education', 'Y', CURRENT_USER, CURRENT_TIMESTAMP) on conflict do nothing; insert into case_management.action_code @@ -10,7 +11,12 @@ values ('ASSESSRISK', 'Assessed public safety risk', 'Assessed public safety risk', 'Y', CURRENT_USER, CURRENT_TIMESTAMP), ('ASSESSHLTH', 'Assessed health as per animal welfare guidelines', 'Assessed health as per animal welfare guidelines', 'Y', CURRENT_USER, CURRENT_TIMESTAMP), ('ASSESSHIST', 'Assessed known conflict history', 'Assessed known conflict history', 'Y', CURRENT_USER, CURRENT_TIMESTAMP), - ('CNFRMIDENT', 'Confirmed identification of offending animal(s)', 'Confirmed identification of offending animal(s)', 'Y', CURRENT_USER, CURRENT_TIMESTAMP) + ('CNFRMIDENT', 'Confirmed identification of offending animal(s)', 'Confirmed identification of offending animal(s)', 'Y', CURRENT_USER, CURRENT_TIMESTAMP), + ('PROVSFTYIN', 'Provided safety information to the public', 'Provided safety information to the public', 'Y', CURRENT_USER, CURRENT_TIMESTAMP), + ('PROVAMHSIN', 'Provided attractant management and husbandry information to the public', 'Provided attractant management and husbandry information to the public', 'Y', CURRENT_USER, CURRENT_TIMESTAMP), + ('CDCTMEDREL', 'Conducted media release to educate the community', 'Conducted media release to educate the community', 'Y', CURRENT_USER, CURRENT_TIMESTAMP), + ('CNTCTGROUP', 'Contacted WildSafeBC or local interest group to deliver education to the public', 'Contacted WildSafeBC or local interest group to deliver education to the public', 'Y', CURRENT_USER, CURRENT_TIMESTAMP), + ('CNTCTBYLAW', 'Contacted bylaw to assist with managing attractants', 'Contacted bylaw to assist with managing attractants', 'Y', CURRENT_USER, CURRENT_TIMESTAMP) on conflict do nothing; insert into case_management.action_type_action_xref @@ -19,7 +25,12 @@ values ('COMPASSESS', 'ASSESSRISK', 1, 'Y', CURRENT_USER, CURRENT_TIMESTAMP), ('COMPASSESS', 'ASSESSHLTH', 2, 'Y', CURRENT_USER, CURRENT_TIMESTAMP), ('COMPASSESS', 'ASSESSHIST', 3, 'Y', CURRENT_USER, CURRENT_TIMESTAMP), - ('COMPASSESS', 'CNFRMIDENT', 4, 'Y', CURRENT_USER, CURRENT_TIMESTAMP) + ('COMPASSESS', 'CNFRMIDENT', 4, 'Y', CURRENT_USER, CURRENT_TIMESTAMP), + ('COSPRV&EDU', 'PROVSFTYIN', 1, 'Y', CURRENT_USER, CURRENT_TIMESTAMP), + ('COSPRV&EDU', 'PROVAMHSIN', 2, 'Y', CURRENT_USER, CURRENT_TIMESTAMP), + ('COSPRV&EDU', 'CDCTMEDREL', 3, 'Y', CURRENT_USER, CURRENT_TIMESTAMP), + ('COSPRV&EDU', 'CNTCTGROUP', 4, 'Y', CURRENT_USER, CURRENT_TIMESTAMP), + ('COSPRV&EDU', 'CNTCTBYLAW', 5, 'Y', CURRENT_USER, CURRENT_TIMESTAMP) on conflict do nothing; insert into case_management.case_code @@ -40,3 +51,23 @@ values ('NOPUBSFTYC', 'COS', 'No public safety concern', 'No public safety concern', 'Y', CURRENT_USER, CURRENT_TIMESTAMP), ('OTHOPRPRTY', 'COS', 'Other operational priorities', 'Other operational priorities', 'Y', CURRENT_USER, CURRENT_TIMESTAMP) on conflict do nothing; + +insert into case_management.action_type_code + (action_type_code, short_description, long_description, active_ind, create_user_id, create_utc_timestamp) +values + ('EQUIPMENT', 'Equipment', 'Equipment', 'Y', CURRENT_USER, CURRENT_TIMESTAMP) +on conflict do nothing; + +insert into case_management.action_code + (action_code, short_description, long_description, active_ind, create_user_id, create_utc_timestamp) +values + ('SETEQUIPMT', 'Equipment set by an officer', 'Equipment set by an officer', 'Y', CURRENT_USER, CURRENT_TIMESTAMP), + ('REMEQUIPMT', 'Equipment removed by an officer', 'Equipment removed by an officer', 'Y', CURRENT_USER, CURRENT_TIMESTAMP) +on conflict do nothing; + +insert into case_management.action_type_action_xref + (action_type_code, action_code, display_order, active_ind, create_user_id, create_utc_timestamp) +values + ('EQUIPMENT', 'SETEQUIPMT', 1, 'Y', CURRENT_USER, CURRENT_TIMESTAMP), + ('EQUIPMENT', 'REMEQUIPMT', 2, 'Y', CURRENT_USER, CURRENT_TIMESTAMP) +on conflict do nothing; \ No newline at end of file diff --git a/migrations/sql/R__0.16.1__CE-365_new_seed_data.sql b/migrations/sql/R__0.16.1__CE-365_new_seed_data.sql new file mode 100644 index 00000000..3a34d01a --- /dev/null +++ b/migrations/sql/R__0.16.1__CE-365_new_seed_data.sql @@ -0,0 +1,23 @@ +insert into case_management.action_code + (action_code, short_description, long_description, active_ind, create_user_id, create_utc_timestamp) +values + ('CNTCTBIOVT', 'Contacted biologist and/or veterinarian', 'Contacted biologist and/or veterinarian', 'Y', CURRENT_USER, CURRENT_TIMESTAMP), + ('DIRLOWLACT', 'Directed livestock owner to or explained sections 2, 26(2) and 75 of the Wildlife Act', 'Directed livestock owner to or explained sections 2, 26(2) and 75 of the Wildlife Act', 'Y', CURRENT_USER, CURRENT_TIMESTAMP), + ('CONTACTLPP', 'Contacted the Livestock Protection Program ("LPP") (cattle and sheep only)', 'Contacted the Livestock Protection Program ("LPP") (cattle and sheep only)', 'Y', CURRENT_USER, CURRENT_TIMESTAMP) +on conflict do nothing; + +UPDATE case_management.action_type_action_xref +SET display_order = 6 WHERE action_code = 'CNTCTBYLAW'; +UPDATE case_management.action_type_action_xref +SET display_order = 5 WHERE action_code = 'CNTCTGROUP'; + +insert into case_management.action_type_action_xref + (action_type_code, action_code, display_order, active_ind, create_user_id, create_utc_timestamp) +values + ('COSPRV&EDU', 'CNTCTBIOVT', 4, 'Y', CURRENT_USER, CURRENT_TIMESTAMP), + ('COSPRV&EDU', 'DIRLOWLACT', 7, 'Y', CURRENT_USER, CURRENT_TIMESTAMP), + ('COSPRV&EDU', 'CONTACTLPP', 8, 'Y', CURRENT_USER, CURRENT_TIMESTAMP) +on conflict do nothing; + +UPDATE case_management.configuration +SET configuration_value = 2 WHERE configuration_code = 'CDTABLEVER'; \ No newline at end of file diff --git a/migrations/sql/V1.16.1__CE-357.sql b/migrations/sql/V1.16.1__CE-357.sql new file mode 100644 index 00000000..f2fc3209 --- /dev/null +++ b/migrations/sql/V1.16.1__CE-357.sql @@ -0,0 +1,35 @@ +-- +-- CREATE TABLE equipment +-- +CREATE TABLE + case_management.equipment ( + equipment_guid uuid, + equipment_code varchar(10), + equipment_location_desc varchar(120), + equipment_geometry_point text, + active_ind bool NOT NULL, + create_user_id varchar(32) NOT NULL, + create_utc_timestamp timestamp NOT NULL, + update_user_id varchar(32) NOT NULL, + update_utc_timestamp timestamp NOT NULL, + CONSTRAINT "PK_equipment_guid" PRIMARY KEY (equipment_guid) + ); + +-- case_management.equipment foreign keys +ALTER TABLE case_management.equipment ADD CONSTRAINT FK_equipment__equipment_code FOREIGN KEY (equipment_code) REFERENCES case_management.equipment_code(equipment_code); + +ALTER TABLE action ADD COLUMN equipment_guid uuid; + +ALTER TABLE case_management.action ADD CONSTRAINT FK_action__equipment_guid FOREIGN KEY (equipment_guid) REFERENCES case_management.equipment(equipment_guid); + +comment on table case_management.equipment is 'Represents a piece of physical equipment that has been deployed in support of the case. Contains information about where and when the equipment was deployed.'; +comment on column case_management.equipment.equipment_guid is 'System generated unique key for a piece of equipment. This key should never be exposed to users via any system utilizing the tables.'; +comment on column case_management.equipment.equipment_code is 'A human readable code used to identify a piece of equipment'; +comment on column case_management.equipment.equipment_location_desc is 'Free form text describing the location of the equipment. Usually (but not always) an address.'; +comment on column case_management.equipment.equipment_geometry_point is 'The closest approximation to where the equipment is deployed. Stored as a geometric point using the EPSG:3005 Projected Coordinate System (BC Albers)'; +comment on column case_management.equipment.active_ind is 'A boolean indicator to determine if the equipment record is active and should be displayed in the application.'; +comment on column case_management.equipment.create_user_id is 'The id of the user that created the equipment record.'; +comment on column case_management.equipment.create_utc_timestamp is 'The timestamp when the equipment record was created. The timestamp is stored in UTC with no Offset.'; +comment on column case_management.equipment.update_user_id is 'The id of the user that updated the equipment record.'; +comment on column case_management.equipment.update_utc_timestamp is 'The timestamp when the equipment record was updated. The timestamp is stored in UTC with no Offset.'; +comment on column case_management.action.equipment_guid is 'System generated unique key for a piece of equipment. This key should never be exposed to users via any system utilizing the tables.'; \ No newline at end of file diff --git a/migrations/sql/V1.16.2__CE-365.sql b/migrations/sql/V1.16.2__CE-365.sql new file mode 100644 index 00000000..70e5d8df --- /dev/null +++ b/migrations/sql/V1.16.2__CE-365.sql @@ -0,0 +1,2 @@ +ALTER TABLE case_management.action_code + ALTER COLUMN short_description TYPE VARCHAR(250); \ No newline at end of file