-
Notifications
You must be signed in to change notification settings - Fork 222
Feature/implement risk rule ( WIP ) BAL-2445 #2528
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from 2 commits
05d6dac
f72c12b
c27a411
e7e1066
a0d8f96
3c2c215
2b51595
62b007f
ad7fa9c
1d56a23
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
-- CreateEnum | ||
CREATE TYPE "IndicatorRiskLevel" AS ENUM ('positive', 'moderate', 'critical'); | ||
|
||
-- CreateEnum | ||
CREATE TYPE "RuleEngine" AS ENUM ('Ballerine', 'JsonLogic'); | ||
|
||
-- CreateTable | ||
CREATE TABLE "WorkflowDefinitionRiskRulePolicy" ( | ||
"id" TEXT NOT NULL, | ||
"workflowDefinitionId" TEXT NOT NULL, | ||
"riskRulesPolicyId" TEXT NOT NULL, | ||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
"updatedAt" TIMESTAMP(3) NOT NULL, | ||
|
||
CONSTRAINT "WorkflowDefinitionRiskRulePolicy_pkey" PRIMARY KEY ("id") | ||
); | ||
|
||
-- CreateTable | ||
CREATE TABLE "RiskRulesPolicy" ( | ||
"id" TEXT NOT NULL, | ||
"projectId" TEXT NOT NULL, | ||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
"updatedAt" TIMESTAMP(3) NOT NULL, | ||
|
||
CONSTRAINT "RiskRulesPolicy_pkey" PRIMARY KEY ("id") | ||
); | ||
|
||
-- CreateTable | ||
CREATE TABLE "RiskRuleSet" ( | ||
"id" TEXT NOT NULL, | ||
"riskRulePolicyId" TEXT NOT NULL, | ||
"domain" TEXT NOT NULL, | ||
"indicator" TEXT NOT NULL, | ||
"riskLevel" "IndicatorRiskLevel" NOT NULL, | ||
"baseRiskScore" INTEGER NOT NULL, | ||
"additionalRiskScore" INTEGER NOT NULL, | ||
"minRiskScore" INTEGER, | ||
"maxRiskScore" INTEGER, | ||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
"updatedAt" TIMESTAMP(3) NOT NULL, | ||
|
||
CONSTRAINT "RiskRuleSet_pkey" PRIMARY KEY ("id") | ||
); | ||
|
||
-- CreateTable | ||
CREATE TABLE "Rule" ( | ||
"id" TEXT NOT NULL, | ||
"riskRuleSetId" TEXT NOT NULL, | ||
"key" TEXT NOT NULL, | ||
"operator" TEXT NOT NULL, | ||
"comparisonValue" JSONB NOT NULL, | ||
"engine" "RuleEngine" NOT NULL, | ||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
"updatedAt" TIMESTAMP(3) NOT NULL, | ||
"riskRuleSetRiskRulePolicyId" TEXT, | ||
|
||
CONSTRAINT "Rule_pkey" PRIMARY KEY ("id") | ||
); | ||
|
||
-- CreateIndex | ||
CREATE UNIQUE INDEX "WorkflowDefinitionRiskRulePolicy_workflowDefinitionId_key" ON "WorkflowDefinitionRiskRulePolicy"("workflowDefinitionId"); | ||
|
||
-- CreateIndex | ||
CREATE INDEX "WorkflowDefinitionRiskRulePolicy_workflowDefinitionId_idx" ON "WorkflowDefinitionRiskRulePolicy"("workflowDefinitionId"); | ||
|
||
-- CreateIndex | ||
CREATE INDEX "WorkflowDefinitionRiskRulePolicy_riskRulesPolicyId_idx" ON "WorkflowDefinitionRiskRulePolicy"("riskRulesPolicyId"); | ||
|
||
-- CreateIndex | ||
CREATE UNIQUE INDEX "WorkflowDefinitionRiskRulePolicy_workflowDefinitionId_riskR_key" ON "WorkflowDefinitionRiskRulePolicy"("workflowDefinitionId", "riskRulesPolicyId"); | ||
|
||
-- CreateIndex | ||
CREATE INDEX "RiskRulesPolicy_projectId_idx" ON "RiskRulesPolicy"("projectId"); | ||
|
||
-- CreateIndex | ||
CREATE INDEX "RiskRuleSet_riskRulePolicyId_idx" ON "RiskRuleSet"("riskRulePolicyId"); | ||
|
||
-- CreateIndex | ||
CREATE UNIQUE INDEX "RiskRuleSet_id_riskRulePolicyId_key" ON "RiskRuleSet"("id", "riskRulePolicyId"); | ||
|
||
-- AddForeignKey | ||
ALTER TABLE "WorkflowDefinitionRiskRulePolicy" ADD CONSTRAINT "WorkflowDefinitionRiskRulePolicy_riskRulesPolicyId_fkey" FOREIGN KEY ("riskRulesPolicyId") REFERENCES "RiskRulesPolicy"("id") ON DELETE RESTRICT ON UPDATE CASCADE; | ||
|
||
-- AddForeignKey | ||
ALTER TABLE "WorkflowDefinitionRiskRulePolicy" ADD CONSTRAINT "WorkflowDefinitionRiskRulePolicy_workflowDefinitionId_fkey" FOREIGN KEY ("workflowDefinitionId") REFERENCES "WorkflowDefinition"("id") ON DELETE RESTRICT ON UPDATE CASCADE; | ||
|
||
-- AddForeignKey | ||
ALTER TABLE "RiskRulesPolicy" ADD CONSTRAINT "RiskRulesPolicy_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE RESTRICT ON UPDATE CASCADE; | ||
|
||
-- AddForeignKey | ||
ALTER TABLE "RiskRuleSet" ADD CONSTRAINT "RiskRuleSet_riskRulePolicyId_fkey" FOREIGN KEY ("riskRulePolicyId") REFERENCES "RiskRulesPolicy"("id") ON DELETE RESTRICT ON UPDATE CASCADE; | ||
|
||
-- AddForeignKey | ||
ALTER TABLE "Rule" ADD CONSTRAINT "Rule_riskRuleSetId_fkey" FOREIGN KEY ("riskRuleSetId") REFERENCES "RiskRuleSet"("id") ON DELETE RESTRICT ON UPDATE CASCADE; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -188,12 +188,13 @@ model WorkflowDefinition { | |
persistStates Json? | ||
submitStates Json? | ||
|
||
createdAt DateTime @default(now()) | ||
updatedAt DateTime @updatedAt | ||
createdBy String @default("SYSTEM") | ||
project Project? @relation(fields: [projectId], references: [id]) | ||
workflowRuntimeData WorkflowRuntimeData[] | ||
uiDefinitions UiDefinition[] | ||
createdAt DateTime @default(now()) | ||
updatedAt DateTime @updatedAt | ||
createdBy String @default("SYSTEM") | ||
project Project? @relation(fields: [projectId], references: [id]) | ||
workflowRuntimeData WorkflowRuntimeData[] | ||
uiDefinitions UiDefinition[] | ||
workflowDefinitionRiskRulePolicy WorkflowDefinitionRiskRulePolicy? | ||
|
||
@@unique([name, version, projectId, definitionType]) | ||
@@index([projectId, name, definitionType]) | ||
|
@@ -370,6 +371,7 @@ model Project { | |
SalesforceIntegration SalesforceIntegration? | ||
workflowDefinitions WorkflowDefinition[] | ||
uiDefinitions UiDefinition[] | ||
riskRulesPolicies RiskRulesPolicy[] | ||
WorkflowRuntimeDataToken WorkflowRuntimeDataToken[] | ||
TransactionRecord TransactionRecord[] | ||
AlertDefinition AlertDefinition[] | ||
|
@@ -806,6 +808,12 @@ enum RiskCategory { | |
high | ||
} | ||
|
||
enum IndicatorRiskLevel { | ||
positive | ||
moderate | ||
critical | ||
} | ||
|
||
enum ComplianceStatus { | ||
compliant | ||
non_compliant | ||
|
@@ -855,6 +863,11 @@ enum BusinessReportStatus { | |
completed | ||
} | ||
|
||
enum RuleEngine { | ||
Ballerine | ||
JsonLogic | ||
} | ||
|
||
model BusinessReport { | ||
id String @id @default(cuid()) | ||
type BusinessReportType | ||
|
@@ -878,3 +891,72 @@ model BusinessReport { | |
@@index([riskScore]) | ||
@@index([type]) | ||
} | ||
|
||
model WorkflowDefinitionRiskRulePolicy { | ||
id String @id @default(cuid()) | ||
workflowDefinitionId String @unique | ||
riskRulesPolicyId String | ||
riskRulesPolicy RiskRulesPolicy @relation(fields: [riskRulesPolicyId], references: [id]) | ||
workflowDefinition WorkflowDefinition @relation(fields: [workflowDefinitionId], references: [id]) | ||
|
||
createdAt DateTime @default(now()) | ||
updatedAt DateTime @updatedAt | ||
|
||
@@unique([workflowDefinitionId, riskRulesPolicyId]) | ||
@@index([workflowDefinitionId]) | ||
@@index([riskRulesPolicyId]) | ||
} | ||
|
||
model RiskRulesPolicy { | ||
id String @id @default(cuid()) | ||
projectId String | ||
|
||
riskRuleSets RiskRuleSet[] | ||
workflowDefinitionRiskRulePolicies WorkflowDefinitionRiskRulePolicy[] | ||
project Project @relation(fields: [projectId], references: [id]) | ||
|
||
createdAt DateTime @default(now()) | ||
updatedAt DateTime @updatedAt | ||
|
||
@@index([projectId]) | ||
} | ||
|
||
model RiskRuleSet { | ||
id String @id @default(cuid()) | ||
riskRulePolicyId String | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. name There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. operator |
||
|
||
domain String | ||
indicator String | ||
riskLevel IndicatorRiskLevel | ||
|
||
baseRiskScore Int | ||
additionalRiskScore Int | ||
minRiskScore Int? | ||
maxRiskScore Int? | ||
|
||
riskRulePolicy RiskRulesPolicy @relation(fields: [riskRulePolicyId], references: [id]) | ||
rules Rule[] | ||
|
||
createdAt DateTime @default(now()) | ||
updatedAt DateTime @updatedAt | ||
|
||
@@unique([id, riskRulePolicyId]) | ||
@@index([riskRulePolicyId]) | ||
} | ||
|
||
model Rule { | ||
id String @id @default(cuid()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. name |
||
riskRuleSetId String | ||
|
||
key String | ||
operator String | ||
comparisonValue Json | ||
engine RuleEngine | ||
|
||
riskRuleSet RiskRuleSet @relation(fields: [riskRuleSetId], references: [id]) | ||
|
||
createdAt DateTime @default(now()) | ||
updatedAt DateTime @updatedAt | ||
|
||
riskRuleSetRiskRulePolicyId String? | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { Type } from '@sinclair/typebox'; | ||
|
||
export const TypeStringEnum = <T extends string[]>(values: [...T], description?: string) => | ||
Type.Unsafe<T[number]>({ | ||
type: 'string', | ||
enum: values, | ||
description, | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { Module } from '@nestjs/common'; | ||
import { AppLoggerModule } from '@/common/app-logger/app-logger.module'; | ||
import { RiskRulePolicyService } from '@/risk-rules/risk-rule-policy/risk-rule-policy.service'; | ||
import { RiskRulePolicyRepository } from '@/risk-rules/risk-rule-policy/risk-rule-policy.repository'; | ||
import { PrismaModule } from '@/prisma/prisma.module'; | ||
import { RiskRuleSetModule } from '@/risk-rules/risk-rule-set/risk-rule-set.module'; | ||
|
||
@Module({ | ||
imports: [AppLoggerModule, PrismaModule, RiskRuleSetModule], | ||
providers: [RiskRulePolicyService, RiskRulePolicyRepository], | ||
exports: [RiskRulePolicyService], | ||
}) | ||
export class RiskRulePolicyModule {} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,52 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { Injectable } from '@nestjs/common'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { PrismaService } from '@/prisma/prisma.service'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { Prisma } from '@prisma/client'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { ProjectScopeService } from '@/project/project-scope.service'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { TProjectIds } from '@/types'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@Injectable() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export class RiskRulePolicyRepository { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
constructor( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private readonly prisma: PrismaService, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private readonly scopeService: ProjectScopeService, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) {} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
async createRiskRulePolicy( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
projectId: string, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
createArgs: Prisma.RiskRulesPolicyCreateArgs['data'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return this.prisma.riskRulesPolicy.create({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
data: createArgs, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
async findRiskRulePolicyById(id: string, projectIds: TProjectIds) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return this.prisma.riskRulesPolicy.findUnique({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
where: { id }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider scoping the query to specific projects. The method currently retrieves a risk rule policy by ID without considering the project scope. It might be beneficial to include a filter by - where: { id },
+ where: { id, projectId: { in: projectIds } }, Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
async findRiskRulePolicyByWorkflowDefinitionId( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
workflowDefinitionId: string, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
projectIds: TProjectIds, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return this.prisma.riskRulesPolicy.findFirstOrThrow({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
where: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
workflowDefinitionRiskRulePolicies: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
some: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
workflowDefinitionId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
select: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
riskRuleSets: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add project scoping to the query. The method fetches data based on the workflow definition ID but does not scope the query to specific projects, which might lead to unauthorized data access. - where: {
+ where: {
+ projectId: { in: projectIds },
workflowDefinitionRiskRulePolicies: {
some: {
workflowDefinitionId,
},
},
+ }, Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
async findRiskRulePolicyByProjectId(projectId: string) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return this.prisma.riskRulesPolicy.findFirst({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
where: { projectId }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { Injectable } from '@nestjs/common'; | ||
import { RiskRulePolicyRepository } from './risk-rule-policy.repository'; | ||
|
||
@Injectable() | ||
export class RiskRulePolicyService { | ||
constructor(private readonly riskRuleSetRepository: RiskRulePolicyRepository) {} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well-structured service class for risk rule policy management. The Consider adding service methods. Currently, the service class does not contain any methods. Depending on the requirements, you might want to add methods to handle specific business logic related to risk rule policies. Would you like me to help draft some of the service methods based on typical CRUD operations? |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { Module } from '@nestjs/common'; | ||
import { AppLoggerModule } from '@/common/app-logger/app-logger.module'; | ||
import { PrismaModule } from '@/prisma/prisma.module'; | ||
import { RiskRuleSetService } from '@/risk-rules/risk-rule-set/risk-rule-set.service'; | ||
import { RiskRuleSetRepository } from '@/risk-rules/risk-rule-set/risk-rule-set.repository'; | ||
|
||
@Module({ | ||
imports: [AppLoggerModule, PrismaModule], | ||
providers: [RiskRuleSetService, RiskRuleSetRepository], | ||
exports: [RiskRuleSetService], | ||
}) | ||
export class RiskRuleSetModule {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
low