Skip to content

Instantly share code, notes, and snippets.

@Konyuka
Last active November 28, 2025 06:23
Show Gist options
  • Select an option

  • Save Konyuka/a640c3008d34a3ae081ace0500d91d71 to your computer and use it in GitHub Desktop.

Select an option

Save Konyuka/a640c3008d34a3ae081ace0500d91d71 to your computer and use it in GitHub Desktop.
Risk Rating Service - Complete Architecture

Risk Rating Service - Complete Architecture

System Architecture Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                           RISK RATING SERVICE                            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                          PRESENTATION LAYER                              β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  API Controllers:                                                        β”‚
β”‚  β€’ RiskRatingController        β†’ Main risk calculation endpoints        β”‚
β”‚  β€’ RiskConfigController        β†’ Configuration management               β”‚
β”‚  β€’ RiskExportController        β†’ Data export & reporting                β”‚
β”‚                                                                          β”‚
β”‚  UI Components:                                                          β”‚
β”‚  β€’ Risk Dashboard Widget       β†’ Summary statistics                     β”‚
β”‚  β€’ Account Risk Profile View   β†’ Detailed risk breakdown                β”‚
β”‚  β€’ Risk History Timeline       β†’ Audit trail                            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                    ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                          SERVICE LAYER                                   β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Core Services:                                                          β”‚
β”‚  β€’ RiskRatingService           β†’ Main orchestrator                      β”‚
β”‚  β€’ RiskExportService           β†’ Data export & reporting                β”‚
β”‚                                                                          β”‚
β”‚  Calculators (Strategy Pattern):                                        β”‚
β”‚  β€’ PartyRiskCalculator         β†’ Customer type risk (Sheet 2)           β”‚
β”‚  β€’ CountryRiskCalculator       β†’ Geographic risk (Sheet 5)              β”‚
β”‚  β€’ IndustryRiskCalculator      β†’ Industry/business risk (Sheet 6)       β”‚
β”‚  β€’ ProductRiskCalculator       β†’ Product risk (Sheets 7-14)             β”‚
β”‚  β€’ SecondaryRiskCalculator     β†’ PEP, sanctions, adverse media          β”‚
β”‚                                                                          β”‚
β”‚  Helper Services:                                                        β”‚
β”‚  β€’ RiskClassifier              β†’ Risk class determination               β”‚
β”‚  β€’ RiskRatingHelper            β†’ Utility functions                      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                    ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                          DATA LAYER                                      β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Core Models:                                                            β”‚
β”‚  β€’ CustomerRiskProfile         β†’ Main risk rating record                β”‚
β”‚  β€’ ProfileIndicator            β†’ Individual risk indicators             β”‚
β”‚  β€’ RiskAssessmentHistory       β†’ Audit trail                            β”‚
β”‚                                                                          β”‚
β”‚  Configuration Models:                                                   β”‚
β”‚  β€’ RiskCountryClassification   β†’ Country risk matrix (A/B/C/D)          β”‚
β”‚  β€’ RiskIndustry                β†’ Industry risk matrix                   β”‚
β”‚  β€’ RiskProduct                 β†’ Product risk matrix                    β”‚
β”‚  β€’ RiskProductIndustryScore    β†’ Product-industry combinations          β”‚
β”‚                                                                          β”‚
β”‚  Screening Models:                                                       β”‚
β”‚  β€’ PepScreeningResult          β†’ PEP status tracking                    β”‚
β”‚  β€’ AdverseMediaScreening       β†’ Media monitoring                       β”‚
β”‚  β€’ SanctionsScreening          β†’ Sanctions list checks                  β”‚
β”‚  β€’ StrSarReport                β†’ STR/SAR filings                        β”‚
β”‚                                                                          β”‚
β”‚  Supporting Models:                                                      β”‚
β”‚  β€’ CustomerProductHolding      β†’ Product ownership                      β”‚
β”‚  β€’ RelatedPartyRisk            β†’ Beneficiaries, associates              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                    ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                          INTEGRATION LAYER                               β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Events & Listeners:                                                     β”‚
β”‚  β€’ RiskRatingCalculated Event  β†’ Triggered on calculation               β”‚
β”‚  β€’ NotifyHighRiskAccount       β†’ AML notifications                      β”‚
β”‚  β€’ LogRiskRatingCalculation    β†’ Audit logging                          β”‚
β”‚                                                                          β”‚
β”‚  Observers:                                                              β”‚
β”‚  β€’ AccountObserver             β†’ Auto-recalculate on changes            β”‚
β”‚                                                                          β”‚
β”‚  Background Jobs:                                                        β”‚
β”‚  β€’ BatchRiskRatingJob          β†’ Bulk calculations                      β”‚
β”‚  β€’ RecalculateRiskRatingJob    β†’ Single recalculation                   β”‚
β”‚                                                                          β”‚
β”‚  Console Commands:                                                       β”‚
β”‚  β€’ ReviewRiskRatings           β†’ Scheduled review checker               β”‚
β”‚                                                                          β”‚
β”‚  Notifications:                                                          β”‚
β”‚  β€’ HighRiskAccountCreated      β†’ New high-risk alerts                   β”‚
β”‚  β€’ RiskReviewDue               β†’ Review reminders                       β”‚
β”‚  β€’ RiskClassChanged            β†’ Risk change alerts                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Risk Calculation Flow

Account Creation/Update
        ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 1. RiskRatingService::calculateRiskRating()                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 2. PRIMARY RISK CALCULATION (Profile Indicators)             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚   a) PartyRiskCalculator                                      β”‚
β”‚      β†’ Customer Type (Individual/Institutional/Trust)         β”‚
β”‚      β†’ Score: 0-2                                             β”‚
β”‚                                                               β”‚
β”‚   b) CountryRiskCalculator                                    β”‚
β”‚      β†’ Country Classification (A/B/C/D)                       β”‚
β”‚      β†’ Score: 0-5                                             β”‚
β”‚                                                               β”‚
β”‚   c) IndustryRiskCalculator                                   β”‚
β”‚      β†’ Industry Base Score                                    β”‚
β”‚      β†’ Risk Indicators (Import/Export, Cash, etc.)            β”‚
β”‚      β†’ Score: 0-5                                             β”‚
β”‚                                                               β”‚
β”‚   d) ProductRiskCalculator                                    β”‚
β”‚      β†’ Product Base Score                                     β”‚
β”‚      β†’ Contribution Thresholds                                β”‚
β”‚      β†’ Product-Industry Matrix                                β”‚
β”‚      β†’ Score: 0.5-2                                           β”‚
β”‚                                                               β”‚
β”‚   e) Distribution Risk (from PartyRiskCalculator)             β”‚
β”‚      β†’ Face-to-face vs Non-face-to-face                       β”‚
β”‚      β†’ Score: 0-1                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        ↓
    Total Primary Score = Sum of all components
        ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 3. SECONDARY RISK CALCULATION (Risk Indicators)              β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚   a) PEP Status Check                                         β”‚
β”‚      β†’ FPEP = Default to High Risk (5)                        β”‚
β”‚      β†’ DPEP + Adverse Media = Default to High Risk            β”‚
β”‚                                                               β”‚
β”‚   b) Customer Conduct                                         β”‚
β”‚      β†’ STR/SAR Reports                                        β”‚
β”‚      β†’ Score: 0-3                                             β”‚
β”‚                                                               β”‚
β”‚   c) Adverse Media                                            β”‚
β”‚      β†’ Financial Crime Related                                β”‚
β”‚      β†’ Score: 0-3                                             β”‚
β”‚                                                               β”‚
β”‚   d) Sanctions Screening                                      β”‚
β”‚      β†’ UNSC/OFAC/EU Lists                                     β”‚
β”‚      β†’ Score: 0 or ESCALATE                                   β”‚
β”‚                                                               β”‚
β”‚   e) Related Parties                                          β”‚
β”‚      β†’ Beneficiaries Risk                                     β”‚
β”‚      β†’ Score: Variable                                        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        ↓
    Total Secondary Score = Sum of indicators
        ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 4. RISK CLASSIFICATION                                        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚   Total Score = Primary Score + Secondary Score               β”‚
β”‚                                                               β”‚
β”‚   Risk Classes:                                               β”‚
β”‚   β€’ Score 7+      = High Risk (Enhanced DD)                   β”‚
β”‚   β€’ Score 6-6.9   = High Risk (Enhanced DD)                   β”‚
β”‚   β€’ Score 5-5.9   = High Risk (Enhanced DD)                   β”‚
β”‚   β€’ Score 4-4.9   = Medium+ Risk (Enhanced Light DD)          β”‚
β”‚   β€’ Score 3-3.9   = Medium Risk (Standard DD)                 β”‚
β”‚   β€’ Score 2-2.9   = Low Risk (Simplified DD)                  β”‚
β”‚                                                               β”‚
β”‚   Special Rules:                                              β”‚
β”‚   β€’ FPEP β†’ Minimum score 5 (High Risk)                        β”‚
β”‚   β€’ DPEP + Adverse Media β†’ Minimum score 5                    β”‚
β”‚   β€’ Sanctions Hit β†’ ESCALATE to AML Office                    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 5. SAVE & NOTIFY                                              β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚   a) Save CustomerRiskProfile                                 β”‚
β”‚   b) Create ProfileIndicators                                 β”‚
β”‚   c) Log RiskAssessmentHistory                                β”‚
β”‚   d) Fire RiskRatingCalculated Event                          β”‚
β”‚   e) Send Notifications (if High Risk)                        β”‚
β”‚   f) Set Next Review Date                                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Data Model Relationships

Account (Existing Model)
    β”œβ”€β”€ hasOne: currentRiskProfile (CustomerRiskProfile)
    β”œβ”€β”€ hasMany: riskProfiles (CustomerRiskProfile - historical)
    β”œβ”€β”€ hasMany: productHoldings (CustomerProductHolding)
    β”œβ”€β”€ hasMany: pepScreenings (PepScreeningResult)
    β”œβ”€β”€ hasMany: adverseMediaScreenings (AdverseMediaScreening)
    β”œβ”€β”€ hasMany: sanctionsScreenings (SanctionsScreening)
    └── hasMany: strSarReports (StrSarReport)

CustomerRiskProfile
    β”œβ”€β”€ belongsTo: account (Account)
    β”œβ”€β”€ belongsTo: industry (RiskIndustry)
    β”œβ”€β”€ hasMany: profileIndicators (ProfileIndicator)
    β”œβ”€β”€ hasMany: relatedParties (RelatedPartyRisk)
    └── hasMany: assessmentHistory (RiskAssessmentHistory)

RiskProduct
    β”œβ”€β”€ hasMany: productHoldings (CustomerProductHolding)
    └── belongsToMany: industries (RiskIndustry) β†’ through RiskProductIndustryScore

RiskIndustry
    β”œβ”€β”€ hasMany: customerProfiles (CustomerRiskProfile)
    └── belongsToMany: products (RiskProduct) β†’ through RiskProductIndustryScore

Risk Score Matrix (Quick Reference)

Profile Indicators (Primary Risk)

Component Sheet(s) Min Score Max Score Notes
Party Risk 2 0 2 Customer type
Country Risk 5 0 5 A=0, B=1, C=3, D=5
Distribution Risk 2 0 1 Face-to-face vs remote
Industry Risk 6 0 5 Base + indicators
Product Risk 7-14 0.5 2 Very Low to High
Total Primary 0.5 15

Secondary Indicators (Additional Risk)

Indicator Score Action
FPEP N/A Default total to 5 minimum
DPEP + Adverse Media N/A Default total to 5 minimum
STR/SAR (2+ in 12m) +2 Add to total
STR maintained +3 Add to total
Adverse Media +3 Add to total
Sanctions List N/A ESCALATE - No dealings

Risk Classification

Total Score Risk Class Due Diligence AML Approval Review Period
7.0+ High Enhanced Required 6 months
6.0-6.9 High Enhanced Required 6 months
5.0-5.9 High Enhanced Required 6 months
4.0-4.9 Medium+ Enhanced Light Not Required 12 months
3.0-3.9 Medium Standard Not Required 12 months
2.0-2.9 Low Simplified Not Required 24 months

File Structure

app/
β”œβ”€β”€ Console/
β”‚   └── Commands/
β”‚       └── ReviewRiskRatings.php
β”œβ”€β”€ Events/
β”‚   └── RiskRatingCalculated.php
β”œβ”€β”€ Helpers/
β”‚   └── RiskRatingHelper.php
β”œβ”€β”€ Http/
β”‚   └── Controllers/
β”‚       β”œβ”€β”€ RiskRatingController.php
β”‚       β”œβ”€β”€ RiskConfigController.php
β”‚       └── RiskExportController.php
β”œβ”€β”€ Jobs/
β”‚   β”œβ”€β”€ BatchRiskRatingJob.php
β”‚   └── RecalculateRiskRatingJob.php
β”œβ”€β”€ Listeners/
β”‚   β”œβ”€β”€ NotifyHighRiskAccount.php
β”‚   └── LogRiskRatingCalculation.php
β”œβ”€β”€ Notifications/
β”‚   β”œβ”€β”€ HighRiskAccountCreated.php
β”‚   β”œβ”€β”€ RiskReviewDue.php
β”‚   └── RiskClassChanged.php
β”œβ”€β”€ Observers/
β”‚   └── AccountObserver.php
β”œβ”€β”€ Providers/
β”‚   └── RiskRatingServiceProvider.php
β”œβ”€β”€ RiskRating/                          ← Models namespace
β”‚   β”œβ”€β”€ AdverseMediaScreening.php
β”‚   β”œβ”€β”€ CustomerProductHolding.php
β”‚   β”œβ”€β”€ CustomerRiskProfile.php
β”‚   β”œβ”€β”€ PepScreeningResult.php
β”‚   β”œβ”€β”€ ProfileIndicator.php
β”‚   β”œβ”€β”€ RelatedPartyRisk.php
β”‚   β”œβ”€β”€ RiskAssessmentHistory.php
β”‚   β”œβ”€β”€ RiskCountryClassification.php
β”‚   β”œβ”€β”€ RiskIndustry.php
β”‚   β”œβ”€β”€ RiskProduct.php
β”‚   β”œβ”€β”€ RiskProductIndustryScore.php
β”‚   β”œβ”€β”€ SanctionsScreening.php
β”‚   └── StrSarReport.php
└── Services/
    └── RiskRating/
        β”œβ”€β”€ Calculators/
        β”‚   β”œβ”€β”€ CountryRiskCalculator.php
        β”‚   β”œβ”€β”€ IndustryRiskCalculator.php
        β”‚   β”œβ”€β”€ PartyRiskCalculator.php
        β”‚   β”œβ”€β”€ ProductRiskCalculator.php
        β”‚   └── SecondaryRiskCalculator.php
        β”œβ”€β”€ RiskClassifier.php
        β”œβ”€β”€ RiskExportService.php
        └── RiskRatingService.php

database/
β”œβ”€β”€ migrations/
β”‚   β”œβ”€β”€ 2024_01_01_000001_create_customer_risk_profiles_table.php
β”‚   β”œβ”€β”€ 2024_01_01_000002_create_profile_indicators_table.php
β”‚   β”œβ”€β”€ 2024_01_01_000003_create_risk_assessment_history_table.php
β”‚   β”œβ”€β”€ 2024_01_01_000004_create_risk_country_classifications_table.php
β”‚   β”œβ”€β”€ 2024_01_01_000005_create_risk_industries_table.php
β”‚   β”œβ”€β”€ 2024_01_01_000006_create_risk_products_table.php
β”‚   β”œβ”€β”€ 2024_01_01_000007_create_risk_product_industry_scores_table.php
β”‚   β”œβ”€β”€ 2024_01_01_000008_create_customer_product_holdings_table.php
β”‚   β”œβ”€β”€ 2024_01_01_000009_create_related_party_risks_table.php
β”‚   β”œβ”€β”€ 2024_01_01_000010_create_pep_screening_results_table.php
β”‚   β”œβ”€β”€ 2024_01_01_000011_create_adverse_media_screenings_table.php
β”‚   β”œβ”€β”€ 2024_01_01_000012_create_sanctions_screenings_table.php
β”‚   └── 2024_01_01_000013_create_str_sar_reports_table.php
└── seeds/
    β”œβ”€β”€ RiskCountryClassificationsSeeder.php
    β”œβ”€β”€ RiskIndustriesSeeder.php
    └── RiskProductsSeeder.php

resources/
└── views/
    └── risk-rating/
        β”œβ”€β”€ widgets/
        β”‚   └── summary.blade.php
        └── partials/
            └── risk-profile.blade.php

routes/
└── api.php                              ← API routes defined here

API Endpoints Quick Reference

Calculate & Manage Risk

POST   /api/risk-rating/calculate              Calculate new risk rating
POST   /api/risk-rating/{id}/recalculate       Recalculate existing
POST   /api/risk-rating/batch-calculate        Bulk calculation
GET    /api/risk-rating/{id}                   Get current rating
GET    /api/risk-rating/{id}/history           Get rating history
POST   /api/risk-rating/{id}/approve           Approve high-risk account

Query & Reports

GET    /api/risk-rating/review-required        Accounts needing review
GET    /api/risk-rating/high-risk              High-risk accounts
GET    /api/risk-rating/statistics             Dashboard statistics
POST   /api/risk-rating/export/csv             Export to CSV
GET    /api/risk-rating/export/report          Generate report

Configuration

GET    /api/risk-rating/config/countries       List countries
PUT    /api/risk-rating/config/countries/{id}  Update country
GET    /api/risk-rating/config/industries      List industries
POST   /api/risk-rating/config/industries      Create industry
GET    /api/risk-rating/config/products        List products
POST   /api/risk-rating/config/products        Create product
GET    /api/risk-rating/config/product-industry-matrix  Get matrix
POST   /api/risk-rating/config/product-industry-matrix  Update matrix

Environment Variables

# Queue Configuration
QUEUE_CONNECTION=database

# Mail Configuration (for notifications)
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=your_username
MAIL_PASSWORD=your_password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=aml@yourcompany.com
MAIL_FROM_NAME="${APP_NAME} AML"

# Risk Rating Specific
RISK_RATING_HIGH_APPROVAL_REQUIRED=true
RISK_RATING_AUTO_RECALCULATE=true
RISK_RATING_NOTIFICATION_ENABLED=true

Key Business Rules

1. Country Classification

  • Country A: FATF members (except USA) = 0 points
  • Country B: Non-FATF + USA = 1 point
  • Country C: FATF Grey List = 3 points
  • Country D: FATF Black List = 5 points

2. Product Contribution Limits

  • Very Low products have thresholds:
    • Monthly: ≀ R4,000
    • Annual: ≀ R48,000
    • Lump Sum: ≀ R200,000
  • Exceeding limits upgrades to Medium

3. PEP Rules

  • FPEP: Automatically High Risk (min score 5)
  • DPEP: High Risk only if adverse media present
  • RCA: Ordinary/related to FPEP treated as high risk

4. Sanctions List

  • Any hit on UNSC/OFAC/EU sanctions = IMMEDIATE ESCALATION
  • No business relationship allowed
  • Must be reviewed by AML Compliance Officer

5. STR/SAR Reporting

  • 2+ STR/SAR in 12 months = Non-discretionary +2 points
  • Relationship maintained after STR = +3 points

6. Review Periods

  • High Risk: 6 months
  • Medium+ Risk: 12 months
  • Medium Risk: 12 months
  • Low Risk: 24 months

Security Considerations

Data Protection

  • All risk data is sensitive - ensure proper access controls
  • Audit trail maintained in risk_assessment_history
  • PII encryption recommended for production

Access Control

// Recommended permissions
'risk_rating.calculate'     => ['admin', 'compliance'],
'risk_rating.approve'       => ['aml_officer'],
'risk_rating.view'          => ['admin', 'compliance', 'relationship_manager'],
'risk_rating.export'        => ['admin', 'compliance'],
'risk_rating.config.manage' => ['admin'],

Audit Logging

  • All risk calculations logged
  • All approvals/rejections logged
  • Configuration changes tracked
  • Access to high-risk profiles logged

Performance Optimization

Caching Strategy

// Cache country classifications (rarely change)
Cache::remember('risk_countries', 86400, function() {
    return RiskCountryClassification::all();
});

// Cache industry matrix (rarely change)
Cache::remember('risk_industries', 86400, function() {
    return RiskIndustry::all();
});

Database Indexing

-- Already defined in migrations
CREATE INDEX idx_account_id ON customer_risk_profiles(account_id);
CREATE INDEX idx_is_current ON customer_risk_profiles(is_current);
CREATE INDEX idx_risk_class ON customer_risk_profiles(risk_class);
CREATE INDEX idx_review_date ON customer_risk_profiles(next_review_date);

Queue Processing

# Process risk calculations in background
php artisan queue:work --queue=risk_rating,default --tries=3

Monitoring & Alerts

Health Checks

// Check for overdue reviews
$overdue = CustomerRiskProfile::current()
    ->whereDate('next_review_date', '<', now())
    ->count();

// Check for pending AML approvals
$pendingApprovals = CustomerRiskProfile::current()
    ->where('requires_aml_approval', true)
    ->count();

// Check average calculation time
$avgTime = RiskAssessmentHistory::where('created_at', '>=', now()->subDay())
    ->avg('calculation_time_ms');

Key Metrics

  • Total risk profiles
  • Distribution by risk class
  • Pending AML approvals
  • Overdue reviews
  • Average risk score trend
  • Calculation performance

Compliance Checklist

  • All 13 database tables created
  • Country classifications seeded (update regularly per FATF)
  • Industry classifications configured
  • Product classifications configured
  • Product-industry matrix populated
  • PEP screening integration active
  • Sanctions screening integration active
  • Adverse media monitoring configured
  • Notification system tested
  • Review schedule automated
  • Audit trail verified
  • User permissions configured
  • Documentation completed
  • Training materials prepared
  • Go-live approval obtained

Support & Maintenance

Regular Maintenance Tasks

Monthly:

  • Review and update country classifications (check FATF updates)
  • Review high-risk accounts
  • Check for overdue reviews

Quarterly:

  • Audit risk calculation accuracy
  • Review and update industry risk indicators
  • Update product classifications if new products launched

Annually:

  • Full review of risk framework alignment
  • Update risk matrices based on regulatory changes
  • System performance review

Troubleshooting Guide

Issue: Risk score seems incorrect Solution:

  1. Check risk_assessment_history for calculation details
  2. Review profile_indicators for breakdown
  3. Verify configuration data (countries, industries, products)

Issue: Notifications not sending Solution:

  1. Check queue worker is running
  2. Verify mail configuration
  3. Check notification logs

Issue: Reviews not triggering Solution:

  1. Verify cron is running php artisan schedule:run
  2. Check next_review_date values
  3. Review command logs

Version History

v1.0.0 - Initial Implementation

  • All 13 tables implemented
  • Core calculation engine
  • API endpoints
  • Notification system
  • Export functionality

Document Version: 1.0
Last Updated: 2024-01-01
Author: Development Team
Classification: Internal Use Only


---
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment