Skip to content

Commit

Permalink
feat: CE-1002 Allow CEEB users to capture authorization number (#84)
Browse files Browse the repository at this point in the history
Co-authored-by: Mike Sears <[email protected]>
Co-authored-by: afwilcox <[email protected]>
  • Loading branch information
3 people authored Sep 13, 2024
1 parent 409efa4 commit 644ce13
Show file tree
Hide file tree
Showing 15 changed files with 567 additions and 12 deletions.
66 changes: 55 additions & 11 deletions backend/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -270,23 +270,25 @@ model case_code {

/// 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 case_file {
case_file_guid String @id(map: "PK_case_file_guid") @default(dbgenerated("uuid_generate_v4()")) @db.Uuid
case_code String @db.VarChar(10)
owned_by_agency_code String @db.VarChar(10)
inaction_reason_code String? @db.VarChar(10)
case_file_guid String @id(map: "PK_case_file_guid") @default(dbgenerated("uuid_generate_v4()")) @db.Uuid
case_code String @db.VarChar(10)
owned_by_agency_code String @db.VarChar(10)
inaction_reason_code String? @db.VarChar(10)
action_not_required_ind Boolean?
note_text String?
review_required_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)
action action[]
case_code_case_file_case_codeTocase_code case_code @relation("case_file_case_codeTocase_code", fields: [case_code], references: [case_code], onDelete: NoAction, onUpdate: NoAction, map: "FK_case_file__case_code")
inaction_reason_code_case_file_inaction_reason_codeToinaction_reason_code inaction_reason_code? @relation("case_file_inaction_reason_codeToinaction_reason_code", fields: [inaction_reason_code], references: [inaction_reason_code], onDelete: NoAction, onUpdate: NoAction, map: "FK_case_file__inaction_reason_code")
agency_code agency_code @relation(fields: [owned_by_agency_code], references: [agency_code], onDelete: NoAction, onUpdate: NoAction, map: "FK_case_file__owned_by_agency_code")
authorization_permit authorization_permit[]
case_code_case_file_case_codeTocase_code case_code @relation("case_file_case_codeTocase_code", fields: [case_code], references: [case_code], onDelete: NoAction, onUpdate: NoAction, map: "FK_case_file__case_code")
inaction_reason_code_case_file_inaction_reason_codeToinaction_reason_code inaction_reason_code? @relation("case_file_inaction_reason_codeToinaction_reason_code", fields: [inaction_reason_code], references: [inaction_reason_code], onDelete: NoAction, onUpdate: NoAction, map: "FK_case_file__inaction_reason_code")
agency_code agency_code @relation(fields: [owned_by_agency_code], references: [agency_code], onDelete: NoAction, onUpdate: NoAction, map: "FK_case_file__owned_by_agency_code")
decision decision[]
lead lead[]
site site[]
wildlife wildlife[]
}

Expand Down Expand Up @@ -570,3 +572,45 @@ model sector_code {
update_utc_timestamp DateTime @db.Timestamp(6)
schedule_sector_xref_schedule_sector_xref_sector_codeTosector_code schedule_sector_xref[] @relation("schedule_sector_xref_sector_codeTosector_code")
}

model authorization_permit {
authorization_permit_guid String @id(map: "PK_authorization_permit_guid") @default(dbgenerated("uuid_generate_v4()")) @db.Uuid
case_file_guid String @db.Uuid
authorization_permit_id String @db.VarChar(50)
active_ind Boolean? @default(true)
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_file_guid], references: [case_file_guid], onDelete: NoAction, onUpdate: NoAction, map: "fk_authorization_permit__case_file_guid")
}

model authorization_permit_h {
h_authorization_permit_guid String @id(map: "PK_h_authorization_permit") @default(dbgenerated("uuid_generate_v4()")) @db.Uuid
target_row_id String @db.Uuid
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?
}

model site {
site_guid String @id(map: "PK_site_guid") @default(dbgenerated("uuid_generate_v4()")) @db.Uuid
case_file_guid String @db.Uuid
site_id String @db.VarChar(50)
active_ind Boolean? @default(true)
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_file_guid], references: [case_file_guid], onDelete: NoAction, onUpdate: NoAction, map: "fk_site__case_file_guid")
}

model site_h {
h_site_guid String @id(map: "PK_h_site") @default(dbgenerated("uuid_generate_v4()")) @db.Uuid
target_row_id String @db.Uuid
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?
}
21 changes: 21 additions & 0 deletions backend/src/case_file/case_file.resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import { DeleteWildlifeInput } from "./dto/wildlife/delete-wildlife-input";
import { UpdateWildlifeInput } from "./dto/wildlife/update-wildlife-input";
import { CreateDecisionInput } from "./dto/ceeb/decision/create-decsion-input";
import { UpdateDecisionInput } from "./dto/ceeb/decision/update-decsion-input";
import { CreateAuthorizationOutcomeInput } from "./dto/ceeb/authorization-outcome/create-authorization-outcome-input";
import { UpdateAuthorizationOutcomeInput } from "./dto/ceeb/authorization-outcome/update-authorization-outcome-input";
import { DeleteAuthorizationOutcomeInput } from "./dto/ceeb/authorization-outcome/delete-authorization-outcome-input";

@UseGuards(JwtRoleGuard)
@Resolver("CaseFile")
Expand Down Expand Up @@ -135,4 +138,22 @@ export class CaseFileResolver {
updateDecision(@Args("input") input: UpdateDecisionInput) {
return this.caseFileService.updateDecision(input);
}

@Mutation("createAuthorizationOutcome")
@Roles(Role.CEEB)
createAuthorizationOutcome(@Args("input") input: CreateAuthorizationOutcomeInput) {
return this.caseFileService.createAuthorizationOutcome(input);
}

@Mutation("updateAuthorizationOutcome")
@Roles(Role.CEEB)
updateAuthorizationOutcome(@Args("input") input: UpdateAuthorizationOutcomeInput) {
return this.caseFileService.updateAuthorizationOutcome(input);
}

@Mutation("deleteAuthorizationOutcome")
@Roles(Role.CEEB)
deleteAuthorizationOutcome(@Args("input") input: DeleteAuthorizationOutcomeInput) {
return this.caseFileService.deleteAuthorizationOutcome(input);
}
}
256 changes: 256 additions & 0 deletions backend/src/case_file/case_file.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ import { DecisionInput } from "./dto/ceeb/decision/decision-input";
import { randomUUID } from "crypto";
import { Decision } from "./entities/decision-entity";
import { UpdateDecisionInput } from "./dto/ceeb/decision/update-decsion-input";
import { CreateAuthorizationOutcomeInput } from "./dto/ceeb/authorization-outcome/create-authorization-outcome-input";
import { AuthorizationOutcomeSearchResults } from "./dto/ceeb/authorization-outcome/authorization-outcome-search-results";
import { AuthorizationOutcome } from "./entities/authorization-outcome.entity";
import { UpdateAuthorizationOutcomeInput } from "./dto/ceeb/authorization-outcome/update-authorization-outcome-input";
import { DeleteAuthorizationOutcomeInput } from "./dto/ceeb/authorization-outcome/delete-authorization-outcome-input";

@Injectable()
export class CaseFileService {
Expand Down Expand Up @@ -309,6 +314,24 @@ export class CaseFileService {
},
},
},
authorization_permit: {
where: {
active_ind: true,
},
select: {
authorization_permit_guid: true,
authorization_permit_id: true,
},
},
site: {
where: {
active_ind: true,
},
select: {
site_guid: true,
site_id: true,
},
},
},
});

Expand Down Expand Up @@ -404,6 +427,10 @@ export class CaseFileService {
caseFile.decision = record;
}

//-- add the authorization if there's either authorized_permit or site
//-- but there can be only one
caseFile.authorization = this._getAuthorizationOutcome(queryResult as AuthorizationOutcomeSearchResults);

return caseFile;
};

Expand Down Expand Up @@ -2777,6 +2804,235 @@ export class CaseFileService {
}
};

//--
//-- authorization outcome
//--
private _addAuthorizationOutcome = async (
db: Omit<
PrismaClient<Prisma.PrismaClientOptions, never, DefaultArgs>,
"$connect" | "$disconnect" | "$on" | "$transaction" | "$use" | "$extends"
>,
caseId: string,
type: "permit" | "site",
value: string,
userId: string,
): Promise<any> => {
try {
let record: any = {
case_file_guid: caseId,
create_user_id: userId,
update_user_id: userId,
create_utc_timestamp: new Date(),
update_utc_timestamp: new Date(),
};

if (type === "permit") {
record = { ...record, authorization_permit_id: value };

const result = await db.authorization_permit.create({
data: record,
});

return result?.authorization_permit_guid;
} else {
record = { ...record, site_id: value };

const result = await db.site.create({
data: record,
});

return result.site_guid;
}
} catch (exception) {
let { message } = exception;
this.logger.error(
`Unable to create new ${type === "permit" ? "authorization_permit" : "site"} record: `,
message,
);
throw new GraphQLError("Exception occurred. See server log for details", exception);
}
};

private _removeAuthorizationOutcome = async (
db: Omit<
PrismaClient<Prisma.PrismaClientOptions, never, DefaultArgs>,
"$connect" | "$disconnect" | "$on" | "$transaction" | "$use" | "$extends"
>,
id: string,
type: "permit" | "site",
userId: string,
current: Date,
): Promise<any> => {
const softDeleteFragment = { active_ind: false, update_user_id: userId, update_utc_timestamp: current };

try {
if (type === "permit") {
const result = await db.authorization_permit.update({
where: { authorization_permit_guid: id },
data: softDeleteFragment,
});
} else {
const result = await db.site.update({
where: { site_guid: id },
data: softDeleteFragment,
});
}
} catch (exception) {
let { message } = exception;
this.logger.error(
`Unable to create new ${type === "permit" ? "authorization_permit" : "site"} record: `,
message,
);
throw new GraphQLError("Exception occurred. See server log for details", exception);
}
};

private _updateAuthorizationOutcome = async (
db: Omit<
PrismaClient<Prisma.PrismaClientOptions, never, DefaultArgs>,
"$connect" | "$disconnect" | "$on" | "$transaction" | "$use" | "$extends"
>,
id: string,
type: "permit" | "site",
value: string,
userId: string,
current: Date,
): Promise<any> => {
const record = {
update_user_id: userId,
update_utc_timestamp: current,
...(type === "permit" && { authorization_permit_id: value }),
...(type === "site" && { site_id: value }),
};

try {
if (type === "permit") {
const result = await db.authorization_permit.update({
where: { authorization_permit_guid: id },
data: record,
});
} else {
const result = await db.site.update({
where: { site_guid: id },
data: record,
});
}
} catch (exception) {
let { message } = exception;
this.logger.error(
`Unable to update existing ${type === "permit" ? "authorization_permit" : "site"} record: `,
message,
);
throw new GraphQLError("Exception occurred. See server log for details", exception);
}
};

private _getAuthorizationOutcome = (query: AuthorizationOutcomeSearchResults): AuthorizationOutcome => {
const { authorization_permit: permit, site } = query;

if (permit.length !== 0) {
return { id: permit[0].authorization_permit_guid, type: "permit", value: permit[0].authorization_permit_id };
}

if (site.length !== 0) {
return { id: site[0].site_guid, type: "site", value: site[0].site_id };
}

return null;
};

createAuthorizationOutcome = async (model: CreateAuthorizationOutcomeInput): Promise<CaseFile> => {
let caseFileId = "";

try {
let result: CaseFile;

await this.prisma.$transaction(async (db) => {
const { leadIdentifier, createUserId, input } = model;

const caseFile = await this.findOneByLeadId(leadIdentifier);

if (caseFile && caseFile?.caseIdentifier) {
caseFileId = caseFile.caseIdentifier;
} else {
const caseInput: CreateCaseInput = { ...model };
caseFileId = await this.createCase(db, caseInput);
}

//-- create a new authorized_permit or site record depending on the type
//-- of authorization is provided
const { type, value } = input;

const outcome = await this._addAuthorizationOutcome(db, caseFileId, type, value, createUserId);
});

return await this.findOne(caseFileId);
} catch (error) {
console.log("exception: unable to create authorization outcome ", error);
throw new GraphQLError("Exception occurred. See server log for details", {});
}
};

updateAuthorizationOutcome = async (model: UpdateAuthorizationOutcomeInput): Promise<CaseFile> => {
const { caseIdentifier, updateUserId, input } = model;
const timestamp = new Date();

try {
let result: CaseFile;

await this.prisma.$transaction(async (db) => {
//-- get the current case file and compare the current
//-- authorization outcome to the submited outcome if the
//-- outcome is a different type, remove the old outcome
//-- and add a new one or update the type if the same
const caseFile = await this.findOne(caseIdentifier);
const { authorization: current } = caseFile;

const { type, value } = input;
if (current.type === type) {
await this._updateAuthorizationOutcome(db, current.id, type, value, updateUserId, timestamp);
} else {
await this._removeAuthorizationOutcome(db, current.id, current.type, updateUserId, timestamp);

if (current.type === "permit") {
await this._addAuthorizationOutcome(db, caseIdentifier, type, value, updateUserId);
} else {
await this._addAuthorizationOutcome(db, caseIdentifier, type, value, updateUserId);
}
}
});

return await this.findOne(caseIdentifier);
} catch (error) {
console.log("exception: unable to create authorization outcome ", error);
throw new GraphQLError("Exception occurred. See server log for details", {});
}
};

deleteAuthorizationOutcome = async (model: DeleteAuthorizationOutcomeInput): Promise<CaseFile> => {
const { caseIdentifier, updateUserId, id } = model;
const timestamp = new Date();

try {
await this.prisma.$transaction(async (db) => {
const caseFile = await this.findOne(caseIdentifier);

if (caseFile) {
const {
authorization: { type },
} = caseFile;

await this._removeAuthorizationOutcome(db, id, type, updateUserId, timestamp);
}
});

return await this.findOne(caseIdentifier);
} catch (error) {
console.log("exception: unable to delete authorization outcome ", error);
throw new GraphQLError("Exception occurred. See server log for details", {});
}
};

//--
//-- not implemented
//--
Expand Down
Loading

0 comments on commit 644ce13

Please sign in to comment.