Lease Policy Engine

100% Database-Configurable Policy System

v2.0 Lease Module

Lease Processing Policy Engine

A 100% database-configurable policy engine where rules, conditions, operators, and actions are all stored in database tables. Nothing is hard-coded — add new policies without changing any PHP code.

100% Database-Driven

All rules stored in DB tables

Flexible Conditions

16+ operators, AND/OR logic

Approval Integration

Uses existing ApprovalEngine

Cumulative Execution

ALL matching policies run

How It Works

Policy Evaluation Process

1

Lease Processing Created

User submits a new lease application

2

Load Applicable Policies

Based on scope: Global → Region → Branch → Customer Type

3

Evaluate Each Policy's Conditions

Check if lease data matches configured rules

4

Execute ALL Matching Actions

Cumulative: every matched policy's actions run

5

Trigger Approvals if Needed

Uses existing ApprovalEngine for multi-level approval

flowchart TD
    A[📄 New Lease] --> B{Load Policies}
    B --> C[Policy 1]
    B --> D[Policy 2]
    B --> E[Policy N]
    
    C --> F{Conditions Met?}
    D --> G{Conditions Met?}
    E --> H{Conditions Met?}
    
    F -->|Yes| I[Execute Actions]
    G -->|Yes| J[Execute Actions]
    H -->|Yes| K[Execute Actions]
    
    F -->|No| L[Skip]
    G -->|No| L
    H -->|No| L
    
    I --> M{Any Approval
Required?} J --> M K --> M L --> M M -->|Yes| N[PENDING_APPROVAL] M -->|No| O[ACTIVE] style A fill:#7c3aed,stroke:#a78bfa style N fill:#f59e0b,stroke:#fbbf24 style O fill:#10b981,stroke:#34d399

Complete Enum Reference

All valid enum values for the policy engine. Use these exact values when configuring policies in the database.

ScopeType

Defines where a policy applies (with inheritance)

lease_policy_scopes.scope_type
GLOBAL

Applies to all branches across the organization

scope_value: NULL

REGION

Applies to all branches within a specific region

scope_value: "Punjab", "Sindh"

BRANCH

Applies to a specific branch only

scope_value: "Lahore", "Karachi"

CUSTOMER_TYPE

Applies based on customer category

scope_value: "SALARIED", "VIP"

Inheritance: Policies are loaded in order: GLOBAL → REGION → BRANCH → CUSTOMER_TYPE. All applicable policies execute.

ConditionOperator

How to compare field values against thresholds

lease_policy_conditions.operator
Operator Symbol Description Value Format Example
Equality Operators
EQUALS = Exact match Single value "SALARIED"
NOT_EQUALS Not equal to Single value "BLACKLISTED"
Comparison Operators
GREATER_THAN > Value greater than threshold NUMBER "200000"
LESS_THAN < Value less than threshold NUMBER "500"
GREATER_OR_EQUAL Value >= threshold NUMBER "100000"
LESS_OR_EQUAL Value <= threshold NUMBER "24"
Range Operators
BETWEEN min ≤ x ≤ max Value within range (inclusive) JSON object {"min": 100000, "max": 500000}
NOT_BETWEEN x < min OR x > max Value outside range JSON object {"min": 0, "max": 50000}
List Operators
IN Value exists in list JSON array ["electronics", "furniture"]
NOT_IN Value not in list JSON array ["blacklisted", "rejected"]
String Operators
CONTAINS *x* String contains substring STRING "premium"
NOT_CONTAINS !*x* String does not contain STRING "test"
STARTS_WITH x* String starts with prefix STRING "VIP-"
ENDS_WITH *x String ends with suffix STRING "-GOLD"
Null Check Operators
IS_NULL = NULL Field is null or empty N/A
IS_NOT_NULL ≠ NULL Field has a value N/A

ValueType

Data type of the condition value for proper parsing

lease_policy_conditions.value_type
NUMBER

Integers, decimals

"200000", "0.15"

STRING

Text values

"SALARIED", "VIP"

DATE

ISO date format

"2026-01-01"

BOOLEAN

True/False

"true", "false"

LIST

JSON arrays

["a", "b"]

ActionType

What happens when policy conditions are met

lease_policy_actions.action_type
REQUIRE_APPROVAL

Triggers approval workflow via the existing ApprovalEngine

action_config: {
  "approval_setup_id": 5,           // References approval_setups.id
  "notification_type": "LEASE_HIGHVALUE_CREATE"  // Base type, system appends _APPROVAL/_APPROVED/_REJECTED
}
BLOCK

Completely blocks the lease processing with an error

action_config: {
  "reason": "Customer is blacklisted",
  "error_code": "BLK_BLACKLIST_001"
}
ADD_FEE

Adds additional fees to the lease (fixed amount or percentage)

action_config: {
  "fee_type": "risk_premium",       // or "verification_fee", "processing_fee"
  "amount": 5000,                   // Fixed amount (PKR)
  "percent": null,                  // OR percentage of total
  "description": "High-risk customer premium"
}
NOTIFY

Sends notifications to specified users/roles

action_config: {
  "recipients": ["branch_manager", "risk_officer", "compliance"],
  "template": "high_value_lease_notification",
  "channels": ["email", "in_app"]
}
MODIFY_TERMS

Automatically modifies lease terms based on policy

action_config: {
  "increase_advance_percent": 10,   // Add 10% to required advance
  "reduce_max_tenure": 6,           // Reduce max tenure by 6 months
  "increase_interest_rate": 0.5     // Add 0.5% to interest rate
}

LogicGroup

How multiple conditions are combined

lease_policy_conditions.logic_group
AND All conditions must be TRUE
-- Both must be true to trigger policy
total_amount > 200000 AND item_count > 5

-- Evaluation: TRUE AND TRUE = TRUE
--             TRUE AND FALSE = FALSE

Use AND when you want ALL conditions to be satisfied.

OR At least one condition must be TRUE
-- Either triggers the policy
total_amount > 500000 OR customer_type = 'NEW'

-- Evaluation: TRUE OR FALSE = TRUE
--             FALSE OR TRUE = TRUE

Use OR when ANY condition being true should trigger.

Complex Condition Grouping (group_order)

-- Group 1 (AND): High amount AND many items
-- Group 2 (OR): OR customer is new

(total_amount > 200000 AND item_count > 3) OR (customer_type = 'NEW')

-- Database records:
INSERT INTO lease_policy_conditions (policy_id, field_name, operator, value, logic_group, group_order) VALUES
(1, 'total_amount', 'GREATER_THAN', '200000', 'AND', 1),  -- Group 1
(1, 'item_count', 'GREATER_THAN', '3', 'AND', 1),        -- Group 1
(1, 'customer_type', 'EQUALS', 'NEW', 'OR', 2);          -- Group 2 (OR with Group 1)

CustomerType

Valid values for customer_type field and CUSTOMER_TYPE scope

SALARIED

Fixed salary employees

SELF_EMPLOYED

Freelancers, contractors

BUSINESS

Business owners

PENSIONER

Retired with pension

GOVERNMENT

Govt employees

CORPORATE

B2B corporate clients

VIP

Premium customers

NEW

First-time customers

ItemCategory

Valid values for item_categories field (use with IN operator)

electronics
furniture
appliances
mobile
computer
solar
generator
vehicle
machinery
other

NotificationType (Base Values)

Base notification types stored in policy config. System appends _APPROVAL/_APPROVED/_REJECTED

Pattern: {OPERATION}_{POLICY}_{ACTION}

Store only the base type. ApprovalEngine appends status suffix automatically.

LEASE_HIGHVALUE_CREATE

High value lease creation

→ _APPROVAL
→ _APPROVED
→ _REJECTED
LEASE_MULTIITEM_CREATE

Multiple items lease

→ _APPROVAL
→ _APPROVED
→ _REJECTED
LEASE_HIGHRISK_CREATE

High risk customer

→ _APPROVAL
→ _APPROVED
→ _REJECTED
LEASE_NEWCUSTOMER_CREATE

New customer verification

→ _APPROVAL
→ _APPROVED
→ _REJECTED
LEASE_LONGTERM_CREATE

Long duration lease

→ _APPROVAL
→ _APPROVED
→ _REJECTED
LEASE_BRANCH_CREATE

Branch-specific policy

→ _APPROVAL
→ _APPROVED
→ _REJECTED

Database Schema

erDiagram
    lease_policies {
        bigint id PK "1"
        string policy_name "High Risk Auto Lease"
        string policy_code UK "AUTO-HIGH-RISK-001"
        text description "Requires additional approval for customers with credit score below 650"
        boolean is_active "true"
        int priority "10"
        timestamp effective_from "2024-01-01"
        timestamp effective_to "2025-12-31"
        bigint created_by FK "100"
        timestamp created_at "2024-01-15 09:30:00"
        timestamp updated_at "2024-06-20 14:15:00"
    }

    lease_policy_scopes {
        bigint id PK "101"
        bigint policy_id FK "1"
        string scope_type "REGION"
        string scope_value "US-WEST"
    }

    lease_policy_scopes {
        bigint id PK "102"
        bigint policy_id FK "1"
        string scope_type "CUSTOMER_TYPE"
        string scope_value "NEW_CUSTOMER"
    }

    lease_policy_conditions {
        bigint id PK "201"
        bigint policy_id FK "1"
        string field_name "credit_score"
        string operator "LESS_THAN"
        text value "650"
        string value_type "NUMBER"
        string logic_group "AND"
        int group_order "1"
    }

    lease_policy_conditions {
        bigint id PK "202"
        bigint policy_id FK "1"
        string field_name "vehicle_value"
        string operator "GREATER_THAN"
        text value "50000"
        string value_type "NUMBER"
        string logic_group "AND"
        int group_order "2"
    }

    lease_policy_conditions {
        bigint id PK "203"
        bigint policy_id FK "1"
        string field_name "employment_status"
        string operator "EQUALS"
        text value "SELF_EMPLOYED"
        string value_type "STRING"
        string logic_group "OR"
        int group_order "1"
    }

    lease_policy_actions {
        bigint id PK "301"
        bigint policy_id FK "1"
        string action_type "REQUIRE_APPROVAL"
        json action_config "{ approver_level: 'SENIOR_MANAGER', timeout_hours: 48 }"
    }

    lease_policy_actions {
        bigint id PK "302"
        bigint policy_id FK "1"
        string action_type "ADD_FEE"
        json action_config "{ fee_code: 'RISK_PREMIUM', amount: 500, currency: 'USD' }"
    }

    lease_policy_evaluations {
        bigint id PK "10001"
        bigint lease_processing_id FK "5001"
        bigint policy_id FK "1"
        boolean condition_met "true"
        json evaluation_details "{ matched_conditions: ['credit_score', 'vehicle_value'] }"
        string result_action "REQUIRE_APPROVAL"
        timestamp evaluated_at "2024-02-15 10:23:45"
    }

    approval_setups {
        bigint id PK "401"
        string model_type "LEASE_APPLICATION"
        string action "RISK_POLICY_APPROVAL"
        boolean is_active "true"
    }

    lease_policies ||--o{ lease_policy_scopes : has
    lease_policies ||--o{ lease_policy_conditions : has
    lease_policies ||--o{ lease_policy_actions : has
    lease_policies ||--o{ lease_policy_evaluations : logs
    lease_policy_actions }o--|| approval_setups : references
                    

Table Definitions

lease_policies

Master policy definitions

CREATE TABLE lease_policies (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    policy_name VARCHAR(255) NOT NULL,
    policy_code VARCHAR(100) UNIQUE NOT NULL,
    description TEXT,
    is_active BOOLEAN DEFAULT TRUE,
    priority INT DEFAULT 0,  -- Higher = first
    effective_from TIMESTAMP NULL,
    effective_to TIMESTAMP NULL,
    created_by BIGINT REFERENCES users(id),
    created_at TIMESTAMP,
    updated_at TIMESTAMP
);

lease_policy_scopes

Where policies apply

CREATE TABLE lease_policy_scopes (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    policy_id BIGINT REFERENCES lease_policies(id),
    scope_type ENUM('GLOBAL','REGION','BRANCH','CUSTOMER_TYPE'),
    scope_value VARCHAR(255) NULL,
    UNIQUE(policy_id, scope_type, scope_value)
);

-- Examples:
-- GLOBAL, NULL         → All branches
-- REGION, 'Punjab'     → Punjab region
-- BRANCH, 'Lahore'     → Lahore only
-- CUSTOMER_TYPE, 'VIP' → VIP customers

lease_policy_conditions

Configurable rules

CREATE TABLE lease_policy_conditions (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    policy_id BIGINT REFERENCES lease_policies(id),
    field_name VARCHAR(100) NOT NULL,
    operator ENUM(
        'EQUALS','NOT_EQUALS',
        'GREATER_THAN','LESS_THAN',
        'GREATER_OR_EQUAL','LESS_OR_EQUAL',
        'BETWEEN','NOT_BETWEEN',
        'IN','NOT_IN',
        'CONTAINS','NOT_CONTAINS',
        'STARTS_WITH','ENDS_WITH',
        'IS_NULL','IS_NOT_NULL'
    ) NOT NULL,
    value TEXT NOT NULL,
    value_type ENUM('NUMBER','STRING','DATE','BOOLEAN','LIST'),
    logic_group ENUM('AND','OR') DEFAULT 'AND',
    group_order INT DEFAULT 0
);

lease_policy_actions

What happens when conditions match

CREATE TABLE lease_policy_actions (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    policy_id BIGINT REFERENCES lease_policies(id),
    action_type ENUM(
        'REQUIRE_APPROVAL',
        'BLOCK',
        'ADD_FEE',
        'NOTIFY',
        'MODIFY_TERMS'
    ) NOT NULL,
    action_config JSON NOT NULL
);

-- action_config examples shown in ActionType enum above

Detailed Execution Flow

sequenceDiagram
    autonumber
    actor User
    participant LW as Livewire
    participant SVC as LeaseService
    participant PE as PolicyEngine
    participant DB as Database
    participant AE as ApprovalEngine

    User->>LW: Submit Lease
    LW->>SVC: create(leaseData)
    
    SVC->>DB: INSERT LeaseProcessing (DRAFT)
    DB-->>SVC: lease_id
    
    SVC->>PE: evaluate(lease)
    activate PE
    
    PE->>DB: SELECT policies WHERE scope matches
    DB-->>PE: policies[]
    
    loop Each Policy (by priority)
        PE->>DB: SELECT conditions WHERE policy_id
        DB-->>PE: conditions[]
        
        PE->>PE: evaluateConditions(lease, conditions)
        
        alt Conditions Match
            PE->>DB: SELECT actions WHERE policy_id
            DB-->>PE: actions[]
            
            loop Each Action
                alt REQUIRE_APPROVAL
                    PE->>AE: createRequest(setup_id, lease_id)
                else ADD_FEE
                    PE->>SVC: addFee(lease, config)
                else MODIFY_TERMS
                    PE->>SVC: modifyTerms(lease, config)
                else NOTIFY
                    PE->>PE: queueNotification(config)
                end
            end
            
            PE->>DB: INSERT evaluation (MET)
        else No Match
            PE->>DB: INSERT evaluation (SKIPPED)
        end
    end
    
    PE-->>SVC: {approvals_needed, fees_added, terms_modified}
    deactivate PE
    
    alt approvals_needed
        SVC->>DB: UPDATE status = PENDING_APPROVAL
    else
        SVC->>DB: UPDATE status = ACTIVE
    end
    
    SVC-->>LW: Result
    LW-->>User: Show Status
                    

Approval Engine Integration

Uses Existing ApprovalEngine

The Policy Engine doesn't create a new approval system. It uses the existing ApprovalEngineService with ApprovalSetup and ApprovalRequest tables.

flowchart LR
    subgraph Policy["Policy Engine"]
        P["Policy: HVL_APPROVAL"]
        C["Condition: amount > 200K"]
        A["Action: REQUIRE_APPROVAL
approval_setup_id: 5"] end subgraph Approval["Existing ApprovalEngine"] AS["ApprovalSetup (ID: 5)
model_type: LeaseProcessing"] ASS["ApprovalSetupSteps
1. Branch Manager
2. Regional Director"] AR["ApprovalRequest
status: PENDING"] end subgraph Lease["LeaseProcessing"] LP["Status: PENDING_APPROVAL"] end P --> C C -->|Match| A A -->|Creates| AR AS --> ASS AS --> AR AR --> LP style Policy fill:#1a1a3e,stroke:#8b5cf6 style Approval fill:#1a3a2e,stroke:#10b981

Policy Action Config:

{
  "approval_setup_id": 5,
  "notification_type": "LEASE_HIGHVALUE_CREATE"  // Base type only
}

PolicyEngine Code:

if ($action->type === 'REQUIRE_APPROVAL') {
    $this->approvalEngine->createRequest(
        $config->approval_setup_id,
        $config->notification_type, // LEASE_HIGHVALUE_CREATE
        $leaseProcessing->id
    );
}

Notification Type Pattern

Standard Naming Convention

{OPERATION}_{POLICY}_{ACTION}_{STATUS}

All notification types in the ERP follow this naming convention. This ensures consistency across modules. The Policy Engine stores the base type (without status), and the ApprovalEngine appends the status suffix automatically.

OPERATION

Module/Entity

LEASE
POLICY

Policy type (optional)

HIGHVALUE
ACTION

CRUD operation

CREATE
STATUS

Auto-appended

_APPROVAL

How Notifications Are Generated

flowchart LR
    subgraph Policy["Policy Action Config"]
        B["notification_type:
LEASE_HIGHVALUE_CREATE"] end subgraph System["ApprovalEngine Appends"] S1["+ _APPROVAL"] S2["+ _APPROVED"] S3["+ _REJECTED"] end subgraph Final["Final Notification Keys"] F1["LEASE_HIGHVALUE_CREATE_APPROVAL
→ Sent to approvers"] F2["LEASE_HIGHVALUE_CREATE_APPROVED
→ Sent to initiator"] F3["LEASE_HIGHVALUE_CREATE_REJECTED
→ Sent to initiator"] end B --> S1 --> F1 B --> S2 --> F2 B --> S3 --> F3 style Policy fill:#1a1a3e,stroke:#8b5cf6 style System fill:#2a1a1a,stroke:#f43f5e style Final fill:#1a2e1a,stroke:#10b981

Complete Lease Notification Types

Full Notification Type Trigger Recipient Policy Context
LEASE_HIGHVALUE_CREATE_APPROVAL Policy match (>200K) Next Approver High Value
LEASE_HIGHVALUE_CREATE_APPROVED Final approval Salesperson High Value
LEASE_HIGHVALUE_CREATE_REJECTED Rejection Salesperson High Value
LEASE_NEWCUSTOMER_CREATE_APPROVAL First-time customer Next Approver New Customer
LEASE_NEWCUSTOMER_CREATE_APPROVED Verified & approved Salesperson New Customer
LEASE_NEWCUSTOMER_CREATE_REJECTED Verification failed Salesperson New Customer
LEASE_HIGHRISK_CREATE_APPROVAL Low credit score Risk Officer High Risk
LEASE_HIGHRISK_CREATE_APPROVED Risk accepted Salesperson High Risk
LEASE_HIGHRISK_CREATE_REJECTED Risk declined Salesperson High Risk

config/approvals.php - Lease Policy Entries

return [
    // ─────────────────────────────────────────────
    // HIGH VALUE LEASE NOTIFICATIONS
    // ─────────────────────────────────────────────
    'LEASE_HIGHVALUE_CREATE_APPROVAL' => [
        'title' => 'High Value Lease - Approval Required',
        'action_url' => '/approvals/{id}',
        'message' => '{causer} submitted high value lease #{display} (PKR {amount}) for approval',
        'type' => 'LEASE_HIGHVALUE_CREATE_APPROVAL',
    ],
    'LEASE_HIGHVALUE_CREATE_APPROVED' => [
        'title' => 'High Value Lease - Approved',
        'action_url' => '/leases/{id}',
        'message' => 'Your high value lease #{display} has been approved by {approver}',
        'type' => 'LEASE_HIGHVALUE_CREATE_APPROVED',
    ],
    'LEASE_HIGHVALUE_CREATE_REJECTED' => [
        'title' => 'High Value Lease - Rejected',
        'action_url' => '/leases/{id}',
        'message' => 'Your high value lease #{display} was rejected. Reason: {remarks}',
        'type' => 'LEASE_HIGHVALUE_CREATE_REJECTED',
    ],

    // ─────────────────────────────────────────────
    // NEW CUSTOMER LEASE NOTIFICATIONS
    // ─────────────────────────────────────────────
    'LEASE_NEWCUSTOMER_CREATE_APPROVAL' => [
        'title' => 'New Customer Lease - Verification Required',
        'action_url' => '/approvals/{id}',
        'message' => '{causer} submitted first-time customer lease #{display} for verification',
        'type' => 'LEASE_NEWCUSTOMER_CREATE_APPROVAL',
    ],
    'LEASE_NEWCUSTOMER_CREATE_APPROVED' => [
        'title' => 'New Customer Lease - Verified',
        'action_url' => '/leases/{id}',
        'message' => 'New customer lease #{display} verified and approved',
        'type' => 'LEASE_NEWCUSTOMER_CREATE_APPROVED',
    ],
    'LEASE_NEWCUSTOMER_CREATE_REJECTED' => [
        'title' => 'New Customer Lease - Rejected',
        'action_url' => '/leases/{id}',
        'message' => 'New customer lease #{display} rejected. Reason: {remarks}',
        'type' => 'LEASE_NEWCUSTOMER_CREATE_REJECTED',
    ],

    // ... more policy notification types
];

Notification Flow Sequence

sequenceDiagram
    autonumber
    participant S as Salesperson
    participant PE as PolicyEngine
    participant AE as ApprovalEngine
    participant NS as NotificationService
    participant M as Manager

    S->>PE: Submit Lease (350K)
    PE->>PE: Evaluate: High Value Policy Matched
    PE->>AE: createRequest(setup_id, "LEASE_HIGHVALUE_CREATE", lease_id)
    
    AE->>AE: Append "_APPROVAL" suffix
    AE->>NS: send("LEASE_HIGHVALUE_CREATE_APPROVAL", manager_id)
    NS->>M: 📧 "High Value Lease - Approval Required"
    
    alt Manager Approves
        M->>AE: approve(request_id)
        AE->>AE: Append "_APPROVED" suffix
        AE->>NS: send("LEASE_HIGHVALUE_CREATE_APPROVED", salesperson_id)
        NS->>S: 📧 "High Value Lease - Approved"
    else Manager Rejects
        M->>AE: reject(request_id, remarks)
        AE->>AE: Append "_REJECTED" suffix  
        AE->>NS: send("LEASE_HIGHVALUE_CREATE_REJECTED", salesperson_id)
        NS->>S: 📧 "High Value Lease - Rejected"
    end
                        
Key Point

The Policy Engine only stores the base notification type (e.g., LEASE_HIGHVALUE_CREATE). The ApprovalEngine automatically appends the status suffix (_APPROVAL, _APPROVED, or _REJECTED) based on the workflow action.

Live Scenarios

1 High-Value Lease: PKR 350,000

LEASE DATA

total_amount:350,000
item_count:3
customer_type:SALARIED
credit_score:720
previous_leases:2
branch:Lahore

POLICY EVALUATION

HVL_APPROVAL 350K > 200K
MULTI_ITEM 3 ≤ 5
NEW_CUST prev=2 ≠ 0

ACTIONS EXECUTED

REQUIRE_APPROVAL

→ Branch Manager approval

Final Status:

PENDING_APPROVAL

2 High-Risk: Multiple Policies Triggered

LEASE DATA

total_amount:450,000
item_count:7
customer_type:NEW
credit_score:420
categories:electronics

4 POLICIES MATCHED

HVL_APPROVAL
MULTI_ITEM
HIGH_RISK
NEW_CUST

CUMULATIVE ACTIONS

REQUIRE_APPROVAL x4
ADD_FEE PKR 2,500
MODIFY_TERMS +10% advance
NOTIFY Risk Team

Cumulative Execution: ALL 4 policies run. Customer must get 4 separate approvals, pays extra fee, and advance requirement increases.

Sample Database Records

-- =============================================
-- POLICY 1: High Value Lease Approval
-- =============================================

INSERT INTO lease_policies 
    (policy_name, policy_code, description, is_active, priority) 
VALUES 
    ('High Value Lease', 'HVL_APPROVAL', 'Approval for leases > 200K', TRUE, 100);

INSERT INTO lease_policy_scopes (policy_id, scope_type, scope_value) 
VALUES (1, 'GLOBAL', NULL);

INSERT INTO lease_policy_conditions 
    (policy_id, field_name, operator, value, value_type, logic_group) 
VALUES 
    (1, 'total_amount', 'GREATER_THAN', '200000', 'NUMBER', 'AND');

INSERT INTO lease_policy_actions (policy_id, action_type, action_config) 
VALUES (1, 'REQUIRE_APPROVAL', '{"approval_setup_id": 5, "notification_type": "LEASE_HIGHVALUE_CREATE"}');


-- =============================================
-- POLICY 2: Multi-Item Review (items > 5)
-- =============================================

INSERT INTO lease_policies 
    (policy_name, policy_code, description, is_active, priority) 
VALUES 
    ('Multi-Item Review', 'MULTI_ITEM', 'Review for 5+ items', TRUE, 90);

INSERT INTO lease_policy_scopes (policy_id, scope_type, scope_value) 
VALUES (2, 'GLOBAL', NULL);

INSERT INTO lease_policy_conditions 
    (policy_id, field_name, operator, value, value_type, logic_group) 
VALUES 
    (2, 'item_count', 'GREATER_THAN', '5', 'NUMBER', 'AND');

INSERT INTO lease_policy_actions (policy_id, action_type, action_config) 
VALUES (2, 'REQUIRE_APPROVAL', '{"approval_setup_id": 6, "notification_type": "LEASE_MULTIITEM_CREATE"}');


-- =============================================
-- POLICY 3: High Risk (low credit + high amount)
-- =============================================

INSERT INTO lease_policies 
    (policy_name, policy_code, description, is_active, priority) 
VALUES 
    ('High Risk Customer', 'HIGH_RISK', 'Low credit + high value', TRUE, 110);

INSERT INTO lease_policy_scopes (policy_id, scope_type, scope_value) 
VALUES (3, 'GLOBAL', NULL);

-- Two conditions with AND logic
INSERT INTO lease_policy_conditions 
    (policy_id, field_name, operator, value, value_type, logic_group, group_order) 
VALUES 
    (3, 'customer_credit_score', 'LESS_THAN', '500', 'NUMBER', 'AND', 1),
    (3, 'total_amount', 'GREATER_THAN', '100000', 'NUMBER', 'AND', 1);

-- Multiple actions
INSERT INTO lease_policy_actions (policy_id, action_type, action_config) 
VALUES 
    (3, 'REQUIRE_APPROVAL', '{"approval_setup_id": 7, "notification_type": "LEASE_HIGHRISK_CREATE"}'),
    (3, 'MODIFY_TERMS', '{"increase_advance_percent": 10}'),
    (3, 'NOTIFY', '{"recipients": ["risk_officer"], "template": "high_risk_alert"}');


-- =============================================
-- POLICY 4: Branch-Specific (Karachi Electronics)
-- =============================================

INSERT INTO lease_policies 
    (policy_name, policy_code, description, is_active, priority) 
VALUES 
    ('Karachi Electronics', 'KHI_ELECTRONICS', 'Karachi branch electronics policy', TRUE, 80);

-- Branch-specific scope
INSERT INTO lease_policy_scopes (policy_id, scope_type, scope_value) 
VALUES (4, 'BRANCH', 'Karachi');

-- Using IN operator for categories
INSERT INTO lease_policy_conditions 
    (policy_id, field_name, operator, value, value_type, logic_group, group_order) 
VALUES 
    (4, 'item_categories', 'IN', '["electronics", "mobile", "computer"]', 'LIST', 'AND', 1),
    (4, 'total_amount', 'GREATER_THAN', '150000', 'NUMBER', 'AND', 1);

INSERT INTO lease_policy_actions (policy_id, action_type, action_config) 
VALUES (4, 'REQUIRE_APPROVAL', '{"approval_setup_id": 8, "notification_type": "LEASE_BRANCH_CREATE"}');

Evaluable Fields

These field names can be used in lease_policy_conditions.field_name

Financial

  • total_amount - Total lease value
  • advance_amount - Advance payment
  • monthly_installment - EMI
  • processing_fee - Fees
  • total_payable - With interest

Item-Related

  • item_count - Number of items
  • item_categories - Category list
  • item_total_value - Items price
  • has_electronics - Boolean

Customer

  • customer_credit_score - Score
  • customer_type - See enum
  • customer_income - Monthly
  • customer_previous_leases - Count
  • customer_status - Active/Blacklisted

Lease Terms

  • duration_months - Tenure
  • interest_rate - Rate %
  • advance_percent - Advance %
  • plan_type - Plan code

Historical

  • customer_default_count - Defaults
  • customer_on_time_payments - %
  • customer_total_leased - Lifetime

Context

  • branch_code - Current branch
  • region_code - Current region
  • processing_date - Date
  • created_by_role - User role

Implementation Roadmap

1

Phase 1: Database Schema

  • □ Create migrations for all 5 tables
  • □ Create Eloquent models with relationships
  • □ Add database seeders with sample policies
2

Phase 2: PolicyEngine Core

  • □ Create PolicyEngineService class
  • □ Implement ConditionEvaluator with all 16 operators
  • □ Implement ActionExecutor for all 5 action types
  • □ Implement scope-based policy loading
3

Phase 3: Integration

  • □ Integrate with existing ApprovalEngineService
  • □ Update LeaseProcessingService to call PolicyEngine
  • □ Create notification templates
4

Phase 4: Testing

  • □ Unit tests for ConditionEvaluator
  • □ Integration tests for PolicyEngine
  • □ Feature tests for complete flows