# Merchant Risk Module This document provides a comprehensive overview of the Merchant Risk module, designed for both technical developers and non-technical stakeholders (Product Managers, Risk Analysts, etc.). --- ## 1. Non-Technical Overview (For Product Managers & Business) The **Merchant Risk Module** is the core automated engine used to evaluate the health and performance of CreditFair's loan portfolio across various merchant partners. Instead of manually running multiple Excel sheets or Jupyter notebooks, this module takes raw data dumps (Master Data, Lender Data, Adjustments, etc.) and automatically churns them through 5 distinct analytical stages. ### The 5 Core Processes: 1. **Gross Risk (Before Adjustment)**: Merges all raw loan data with the latest lender information to calculate raw, unadjusted risk metrics (e.g., Principal Outstanding, Total Overdue, NPA). 2. **After Adjustment**: Compares the raw data against previous month's metrics and known manual adjustments to refine the numbers, giving a more accurate "true" risk picture. 3. **Consolidated MIS**: Aggregates the adjusted data across different Fintech partners to provide a high-level summary dashboard, outputting a polished Excel file with embedded performance charts. 4. **Portfolio Cuts**: Slices and dices the portfolio based on specific dimensions (like Jify state, Jify score, or Non-Jify partners) to help identify concentrated areas of risk. 5. **Static Pool / Vintage Analysis**: Tracks how specific "cohorts" (loans disbursed in the same month) perform over time. This helps predict future defaults based on historical aging curves. --- ## 2. Technical Developer Guide ### Directory Structure All core business logic scripts for these 5 processes are stored within the `src/application/use_cases/merchant_risk/` directory. ```text src/application/use_cases/merchant_risk/ │ ├── process_gross_risk.py # 1. Stage 1: Before Adjustment calculations ├── process_after_adjustment.py # 2. Stage 2: After Adjustment calculations ├── process_consolidated_mis.py # 3. Stage 3: High-level aggregation & Excel generation ├── process_portfolio_cuts.py # 4. Stage 4: Jify & Non-Jify segmentation └── process_static_pool.py # 5. Stage 5: Numba-optimized vintage curve calculations ``` *Note: Shared calculation logic (like NPA bucketing) is abstracted into `src/application/services/merchant_risk/risk_engine.py`.* ### How it Works (Data Flow) The API route (`routes.py`) acts as the orchestrator. It receives the raw CSV/Excel files from the frontend and passes them to these Use Cases sequentially. **The output of one script often feeds directly into the next.** For instance, the CSV output generated by `ProcessGrossRiskUseCase` is immediately fed as an input parameter to `ProcessAfterAdjustmentUseCase`. All methods are wrapped in a `@with_cloudwatch_logging` decorator (found in `src/core/logger.py`), which ensures any `pandas` errors or key faults are instantly streamed to AWS CloudWatch with full tracebacks. --- ## 3. Process Visualization / Flowchart The following diagram illustrates how the raw input files flow through the 5 scripts to generate the final ZIP bundle. ```mermaid flowchart TD %% Inputs M[Master Data] L[Lender Data] A[Adjustments Data] P[Previous Month Data] F[Fintech Sheet] J[Jify State/Score] %% Scripts S1(1. Gross Risk\n'process_gross_risk.py') S2(2. After Adjustment\n'process_after_adjustment.py') S3(3. Consolidated MIS\n'process_consolidated_mis.py') S4(4. Portfolio Cuts\n'process_portfolio_cuts.py') S5(5. Static Pool\n'process_static_pool.py') %% Outputs O1[(Before Adj CSV)] O2[(After Adj CSV)] O3[(MIS Excel + Charts)] O4[(Cuts CSVs)] O5[(Vintage CSVs)] Z{ZIP Bundle Generator} %% Flow M & L & A --> S1 S1 -->|Generates| O1 O1 --> Z O1 & A & P & L --> S2 S2 -->|Generates| O2 O2 --> Z O2 & F --> S3 S3 -->|Generates| O3 O3 --> Z O2 & F & J --> S4 S4 -->|Generates| O4 O4 --> Z O2 & F --> S5 S5 -->|Generates| O5 O5 --> Z Z -->|Creates one-time EC2 link| EMAIL[Sent to User via SES Email] ``` ## 4. Key Developer Tips 1. **Pandas Memory Management**: Because these files can be hundreds of megabytes in size, try to only read the specific columns you need using `usecols` when using `pd.read_csv()`. 2. **Numba**: The `process_static_pool.py` heavily utilizes Numba `@njit` decorators for the vintage loop. If you modify the vintage logic, be aware that Numba requires strictly typed structures (e.g., standard Python loops and numpy arrays, avoiding direct pandas manipulation inside the decorated function).