{
  "rejected": {
    "key": "rejected",
    "description": [
      "If the application is ever aborted or rejected, then case has failed, else passed",
      "If the field is not checked, then the rule is to be skipped"
    ],
    "value": {
      "source": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.status_logs.status",
            "primaryColumn": "application_id",
            "dbCondition": [
              "where status in ('rejected', 'aborted')",
              "order by created_at",
              "limit 1"
            ]
          }
        }
      ],
      "against": [
        {
          "type": "list",
          "details": {
            "value": [
              "rejected",
              "aborted"
            ],
            "condition": "notInList"
          }
        }
      ],
      "message": "Application was aborted or rejected in the past"
    },
    "priority": 1
  },
  "max_net_loan_amount": {
    "key": "max_net_loan_amount",
    "description": [
      "If the application’s loan amount <= Max loan amount, then the rule has passed, else fail",
      "Eg. If the requested loan amount is 500000 and the max loan amount is 250000, then it has failed this rule"
    ],
    "value": {
      "source": [
        {
          "type": "key"
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf..net_loan_amount",
            "dbRaw": "select (ca.loan_amount - ec.upfront_from_customer) as net_loan_amount from consumer_application ca inner join emi_calculation ec on ca.id = ec.application_id where ca.id = {sys.input.identifier}",
            "condition": "lessThanEqual"
          }
        }
      ],
      "message": "Requested net loan amount does not match the grade criteria"
    },
    "priority": 2
  },
  "min_net_loan_amount": {
    "key": "min_net_loan_amount",
    "description": [
      "If the application’s loan amount >= Min loan amount, then the rule has passed, else fail",
      "Eg. If the requested loan amount is 5000 and the min loan amount is 25000, then it has failed this rule"
    ],
    "value": {
      "source": [
        {
          "type": "key"
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf..net_loan_amount",
            "dbRaw": "select (ca.loan_amount - ec.upfront_from_customer) as net_loan_amount from consumer_application ca inner join emi_calculation ec on ca.id = ec.application_id where ca.id = {sys.input.identifier}",
            "condition": "greaterThanEqual"
          }
        }
      ],
      "message": "Requested net loan amount does not match the grade criteria"
    },
    "priority": 2
  },
  "max_net_tenure": {
    "key": "max_net_tenure",
    "description": [
      "If the application’s net tenure <= net tenure field, then the rule has passed, else failed"
    ],
    "value": {
      "source": [
        {
          "type": "key"
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.emi_calculation.remaining_emi",
            "primaryColumn": "application_id",
            "dbCondition": [
              "order by created_at desc",
              "limit 1"
            ],
            "condition": "lessThanEqual"
          }
        }
      ],
      "message": "Requested max net tenure does not match the grade criteria"
    },
    "priority": 3
  },
  "min_net_tenure": {
    "key": "min_net_tenure",
    "description": [
      "If the application’s net tenure >= net tenure field, then the rule has passed, else failed"
    ],
    "value": {
      "source": [
        {
          "type": "key"
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.emi_calculation.remaining_emi",
            "primaryColumn": "application_id",
            "dbCondition": [
              "order by created_at desc",
              "limit 1"
            ],
            "condition": "greaterThanEqual"
          }
        }
      ],
      "message": "Requested min net tenure does not match the grade criteria"
    },
    "priority": 3
  },
  "score": {
    "key": "score",
    "value": {
      "source": [
        {
          "type": "key"
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.credit_report.Score",
            "primaryColumn": "application_id",
            "dbCondition": [
              "where applicant_type = 1"
            ],
            "condition": "greaterThanEqual"
          }
        }
      ],
      "message": "Applicant score does not match the grade criteria"
    },
    "priority": 4
  },
  "thin_file": {
    "key": "thin_file_score",
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf..score_result",
            "dbRaw": "SELECT CASE WHEN EXISTS (SELECT 1 FROM credit_report WHERE application_id = {sys.input.identifier} AND applicant_type = 1 AND (score >= -1 AND score <= 10 OR score > {sys.input.score})) THEN 1 ELSE 0 END AS score_result;",
            "condition": "equal"
          }
        }
      ],
      "message": "Applicant does not satisfy the thin file criteria"
    },
    "priority": 4
  },
  "cf_foir": {
    "key": "cf_foir",
    "description": [
      "If the application’s CF FOIR > max CF FOIR, then the rule has failed, else pass"
    ],
    "value": {
      "source": [
        {
          "type": "key"
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.credit_report.cfFoir",
            "primaryColumn": "application_id",
            "condition": "lessThanEqual"
          }
        }
      ],
      "message": "Applicant's CF FOIR does not match the grade criteria"
    },
    "priority": 4
  },
  "foir": {
    "key": "foir",
    "description": [
      "If the application’s FOIR > max FOIR, then the rule has failed, else pass"
    ],
    "value": {
      "source": [
        {
          "type": "key"
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.credit_report.FoirIncludingCFEMI",
            "primaryColumn": "application_id",
            "condition": "lessThanEqual"
          }
        }
      ],
      "message": "Applicant's FOIR does not match the grade criteria"
    },
    "priority": 4
  },
  "monthly_income": {
    "key": "monthly_income",
    "description": [
      "If the application’s monthly income >= Monthly Income, then the rule has passed, else failed"
    ],
    "value": {
      "source": [
        {
          "type": "key"
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.consumer_application.monthly_income",
            "primaryColumn": "id",
            "condition": "greaterThanEqual"
          }
        }
      ],
      "message": "Applicants monthly income does not match the grade criteria"
    }
  },
  "age": {
    "key": "age",
    "description": [
      "If the application’s age >= Min Age, then pass else fail",
      "If the value is null, then the rule is to be skipped"
    ],
    "value": {
      "source": [
        {
          "type": "key"
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.consumer_application.dob",
            "primaryColumn": "id",
            "condition": "greaterThanEqual",
            "function": {
              "call": "dateDiffInYear(var1, var2)",
              "arg": [
                "db.dob",
                "fun.getCurrentDate"
              ]
            }
          }
        }
      ],
      "message": "Applicant age does not match the grade criteria"
    },
    "priority": 4
  },
  "age_salaried": {
    "key": "age_salaried",
    "description": [
      "If the application’s age >= Min Age & age <= Max range, then pass else rejected",
      "If the value is null, then the rule is to be skipped"
    ],
    "value": {
      "source": [
        {
          "type": "key"
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.consumer_application.dob",
            "dbRaw": "select ca.dob from consumer_application ca where id = {sys.input.identifier}",
            "primaryColumn": "id",
            "condition": "inBetween",
            "function": {
              "call": "dateDiffInYear(var1, var2)",
              "arg": [
                "db.dob",
                "fun.getCurrentDate"
              ]
            }
          }
        }
      ],
      "message": "Age for salaried employment does not match the grade criteria"
    },
    "priority": 4
  },
  "age_self_employed": {
    "key": "age_self_employed",
    "description": [
      "If the application’s age >= Min Age & age <= Max range, then pass else rejected",
      "If the value is null, then the rule is to be skipped"
    ],
    "value": {
      "source": [
        {
          "type": "key"
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.consumer_application.dob",
            "dbRaw": "select ca.dob from consumer_application ca where id = {sys.input.identifier}",
            "primaryColumn": "id",
            "condition": "inBetween",
            "function": {
              "call": "dateDiffInYear(var1, var2)",
              "arg": [
                "db.dob",
                "fun.getCurrentDate"
              ]
            }
          }
        }
      ],
      "message": "Age for self employment does not match the grade criteria"
    },
    "priority": 4
  },
  "ageAtLastEMI": {
    "key": "ageAtLastEMI",
    "description": [
      "Calculate the date difference between last EMI date and the DoB",
      "If this age is > input, then fail, else pass",
      "If the field is blank, then the rule is to be skipped"
    ],
    "value": {
      "source": [
        {
          "type": "key"
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.consumer_application.dob",
            "dbRaw": "select ca.dob, date(DATE_ADD(emi_calculation.emi_date, INTERVAL emi_calculation.remaining_emi month)) as last_emi_date from consumer_application as ca left join consumer_application_element cae on ca.id = cae.application_id left join emi_calculation on emi_calculation.application_id = cae.application_id where ca.id = {sys.input.identifier} limit sys.input.identifier1",
            "condition": "lessThanEqual",
            "function": {
              "call": "dateDiffInYear(var1, var2)",
              "arg": [
                "db.dob",
                "db.last_emi_date"
              ]
            }
          }
        }
      ],
      "message": "Applicant's age at the end of tenure does not match the grade criteria"
    },
    "priority": 4
  },
  "employee_status": {
    "key": "employee_status",
    "description": [
      "If the application’s employment is present in the selected dropdown, then the rule is passed else failed",
      "If none are selected in the dropdown, then this rule is to be skipped"
    ],
    "value": {
      "source": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.consumer_application.employee_status",
            "primaryColumn": "id"
          },
          "optional": 1
        }
      ],
      "against": [
        {
          "type": "key",
          "details": {
            "condition": "inList"
          }
        }
      ],
      "message": "Employee's current status does not match the grade criteria"
    },
    "priority": 4
  },
  "solar_financing_for": {
    "key": "solar_financing_for",
    "description": [
      "If the application’s type of customer is present in the selected dropdown, then the rule is passed else failed",
      "If none are selected in the dropdown, then this rule is to be skipped"
    ],
    "value": {
      "source": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.consumer_application_element.type_of_customer",
            "primaryColumn": "application_id"
          },
          "optional": 1
        }
      ],
      "against": [
        {
          "type": "key",
          "details": {
            "condition": "inList"
          }
        }
      ],
      "message": "Solar financing for does not match the grade criteria"
    },
    "priority": 4
  },
  "solar_power_type": {
    "key": "solar_power_type",
    "description": [
      "If the application’s solar power type is present in the selected dropdown, then the rule is passed else failed",
      "If none are selected in the dropdown, then this rule is to be skipped"
    ],
    "value": {
      "source": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.consumer_application_element.solar_power_type",
            "primaryColumn": "application_id"
          },
          "optional": 1
        }
      ],
      "against": [
        {
          "type": "key",
          "details": {
            "condition": "inList"
          }
        }
      ],
      "message": "Solar power type does not match the grade criteria"
    },
    "priority": 4
  },
  "kw_capping": {
    "key": "kw_capping",
    "description": [
      "If the inverter kw installation and the loan amount does not match, then fail"
    ],
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf..comparison_result",
            "dbRaw": "SELECT CASE WHEN mav.max_approved_value IS NULL THEN 1 WHEN ca.approved_amount IS NULL THEN 1 WHEN ca.approved_amount > mav.max_approved_value THEN 0 ELSE 1 END AS comparison_result FROM consumer_application_element cae INNER JOIN consumer_application ca ON ca.id = cae.application_id LEFT JOIN kw_installation_records mav ON mav.KW = cae.inverter_KW_installation WHERE ca.id = {sys.input.identifier}",
            "condition": "equal"
          }
        }
      ],
      "message": "KW capping does not match the grade criteria"
    }
  },
  "check_duplicates": {
    "key": "check_duplicates",
    "description": [
      "If the application’s PAN card / Mobile Number / Email ID is present previously then the case has failed, else passed",
      "If the field is not checked, then the rule is to be skipped"
    ],
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf..checker",
            "dbRaw": "SELECT CASE WHEN identifier_details.email IS NOT NULL AND identifier_details.mobile_number IS NOT NULL AND identifier_details.pan_card IS NOT NULL THEN MAX(CASE WHEN email_match.email IS NULL AND mobile_number_match.mobile_number IS NULL AND pan_match.pan_card IS NULL THEN 1 ELSE 0 END) ELSE 0 END AS checker FROM (SELECT id,email,mobile_number,pan_card FROM consumer_application WHERE id = {sys.input.identifier}) AS identifier_details LEFT JOIN (SELECT ca.email FROM consumer_application ca JOIN merchant m ON ca.merchant_id = m.id WHERE ca.id != {sys.input.identifier} AND DATEDIFF(CURDATE(), ca.created_at) <= 90 AND ca.is_deleted IS NULL AND m.status != 'bre') AS email_match ON email_match.email = identifier_details.email LEFT JOIN (SELECT ca.mobile_number FROM consumer_application ca JOIN merchant m ON ca.merchant_id = m.id WHERE ca.id != {sys.input.identifier} AND DATEDIFF(CURDATE(), ca.created_at) <= 90 AND ca.is_deleted IS NULL AND m.status != 'bre') AS mobile_number_match ON mobile_number_match.mobile_number = identifier_details.mobile_number LEFT JOIN (SELECT ca.pan_card FROM consumer_application ca JOIN merchant m ON ca.merchant_id = m.id WHERE ca.id != {sys.input.identifier} AND DATEDIFF(CURDATE(), ca.created_at) <= 90 AND ca.is_deleted IS NULL AND m.status != 'bre') AS pan_match ON pan_match.pan_card = identifier_details.pan_card;",
            "condition": "equal"
          }
        }
      ],
      "message": "Repeat applicant"
    },
    "priority": 4
  },
  "guarantor": {
    "key": "guarantor",
    "description": [
      "If the application has zero loans, then pass",
      "If the application has at least 1 non-guarantor loan then pass else fail",
      "If the field is not checked, then the rule is to be skipped"
    ],
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf..decision",
            "dbRaw": "select max(case when foir.OwnershipType is null or foir.OwnershipType!='Guarantor' then 1 else 0 end) as decision from (select id from consumer_application where consumer_application.id ={sys.input.identifier}) consumer_application left join (select foir.application_id , foir.OwnershipType from foir where deleted_at is null AND foir.accounttype!='Credit Fair EMI' and foir.applicant_type = {sys.input.applicant_type}) foir on foir.application_id = consumer_application.id",
            "condition": "equal"
          }
        }
      ],
      "message": "Applicant has a tradeline as a Guarantor"
    },
    "priority": 4
  },
  "caseType": {
    "key": "caseType",
    "description": [
      "If any of the mentioned values are present in the DPD of the tradeline then fail, else pass",
      "If the field is blank, then the rule is to be skipped",
      "Eg. Inputs -> PWOS,SET"
    ],
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.null.null",
            "dbRaw": "SELECT JSON_ARRAYAGG(JSON_OBJECT('dpd', foir.dpd)) AS foir_data FROM foir WHERE application_id = {sys.input.identifier} and foir.applicant_type = {sys.input.applicant_type}",
            "primaryColumn": "application_id",
            "function": {
              "call": "case_type_check(var1, var2)",
              "arg": [
                "sys.input.case_type",
                "db.foir_data"
              ]
            },
            "condition": "equal"
          }
        }
      ],
      "message": "DPD case type does not match the grade criteria"
    },
    "priority": 1
  },
  "dpd_count_above_zero": {
    "key": "dpd",
    "fallback": {
      "rule": "dpd_check_equifax"
    },
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "value": "CAIS_Account_DETAILS",
            "config_accessors": "bureau",
            "function": {
              "call": "dpd_check_experian(var1, var2, var3)",
              "arg": [
                "sys.input.dpd_years_above_0",
                "sys.input.dpd_count_above_0",
                "s3.CAIS_Account_DETAILS"
              ]
            },
            "condition": "equal"
          }
        }
      ],
      "message": "DPD count does not match the grade criteria"
    },
    "priority": 4
  },
  "dpd_years_above_zero": {
    "key": "dpd",
    "fallback": {
      "rule": "dpd_check_equifax"
    },
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "value": "CAIS_Account_DETAILS",
            "config_accessors": "bureau",
            "function": {
              "call": "dpd_check_experian(var1, var2, var3)",
              "arg": [
                "sys.input.dpd_years_above_0",
                "sys.input.dpd_count_above_0",
                "s3.CAIS_Account_DETAILS"
              ]
            },
            "condition": "equal"
          }
        }
      ],
      "message": "DPD count does not match the grade criteria"
    },
    "priority": 4
  },
  "dpd_check_equifax": {
    "key": "dpd_check_equifax",
    "fallback": true,
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "value": "sch:Account",
            "config_accessors": "bureau",
            "function": {
              "call": "dpd_check_equifax(var1, var2, var3)",
              "arg": [
                "sys.input.dpd_years_above_0",
                "sys.input.dpd_count_above_0",
                "s3.sch:Account"
              ]
            },
            "condition": "equal"
          }
        }
      ],
      "message": "DPD count does not match the grade criteria"
    },
    "priority": 4
  },
  "past_dues": {
    "key": "past_dues",
    "description": [
      "If total past due amount >= input, then fail else pass",
      "If the field is blank, then the rule is to be skipped"
    ],
    "value": {
      "source": [
        {
          "type": "key"
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.credit_report.TotalPastDue",
            "primaryColumn": "application_id",
            "condition": "lessThanEqual"
          },
          "optional": 1
        }
      ],
      "message": "Past due count does not not match the grade criteria"
    },
    "priority": 1
  },
  "pre_dpd_count": {
    "key": "pre_dpd_count",
    "description": [
      "3 Inputs:",
      [
        "Year (Numeric)",
        "Keywords (Characters)",
        "Count (Numeric)"
      ],
      "Logic:",
      [
        "Extract all the tradelines opened in last [Year]",
        "For each tradeline sum the number of times DPD is not part of [Keywords]",
        "If this sum >= count, then fail else pass",
        "If all the above fields are blank then skip"
      ]
    ],
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.null.null",
            "dbRaw": "select JSON_ARRAYAGG(JSON_OBJECT('DateOpened', DATE_FORMAT(foir.DateOpened, '%Y-%m-%d'), 'created_at', DATE_FORMAT(foir.created_at, '%Y-%m-%d'), 'dpd', foir.dpd)) as foir_data from foir where application_id = {sys.input.identifier} and foir.applicant_type = {sys.input.applicant_type}",
            "primaryColumn": "application_id",
            "function": {
              "call": "pre_dpd_check(var1, var2, var3, var4)",
              "arg": [
                "sys.input.pre_dpd_count",
                "sys.input.pre_dpd_years",
                "sys.input.pre_dpd_keywords",
                "db.foir_data"
              ]
            },
            "condition": "equal"
          }
        }
      ],
      "message": "Pre DPD count (within a certain period) does not not match the grade criteria"
    },
    "priority": 1
  },
  "pre_dpd_years": {
    "key": "pre_dpd_check",
    "description": [
      "3 Inputs:",
      [
        "Year (Numeric)",
        "Keywords (Characters)",
        "Count (Numeric)"
      ],
      "Logic:",
      [
        "Extract all the tradelines opened in last [Year]",
        "For each tradeline sum the number of times DPD is not part of [Keywords]",
        "If this sum >= count, then fail else pass",
        "If all the above fields are blank then skip"
      ]
    ],
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.null.null",
            "dbRaw": "select JSON_ARRAYAGG(JSON_OBJECT('DateOpened', DATE_FORMAT(foir.DateOpened, '%Y-%m-%d'), 'created_at', DATE_FORMAT(foir.created_at, '%Y-%m-%d'), 'dpd', foir.dpd)) as foir_data from foir where application_id = {sys.input.identifier} and foir.applicant_type = {sys.input.applicant_type}",
            "primaryColumn": "application_id",
            "function": {
              "call": "pre_dpd_check(var1, var2, var3, var4)",
              "arg": [
                "sys.input.pre_dpd_count",
                "sys.input.pre_dpd_years",
                "sys.input.pre_dpd_keywords",
                "db.foir_data"
              ]
            },
            "condition": "equal"
          }
        }
      ],
      "message": "Pre DPD count (within a certain period) does not not match the grade criteria"
    },
    "priority": 1
  },
  "pre_dpd_keywords": {
    "key": "pre_dpd_keywords",
    "description": [
      "3 Inputs:",
      [
        "Year (Numeric)",
        "Keywords (Characters)",
        "Count (Numeric)"
      ],
      "Logic:",
      [
        "Extract all the tradelines opened in last [Year]",
        "For each tradeline sum the number of times DPD is not part of [Keywords]",
        "If this sum >= count, then fail else pass",
        "If all the above fields are blank then skip"
      ]
    ],
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.null.null",
            "dbRaw": "select JSON_ARRAYAGG(JSON_OBJECT('DateOpened', DATE_FORMAT(foir.DateOpened, '%Y-%m-%d'), 'created_at', DATE_FORMAT(foir.created_at, '%Y-%m-%d'), 'dpd', foir.dpd)) as foir_data from foir where application_id = {sys.input.identifier} and foir.applicant_type = {sys.input.applicant_type}",
            "primaryColumn": "application_id",
            "function": {
              "call": "pre_dpd_check(var1, var2, var3, var4)",
              "arg": [
                "sys.input.pre_dpd_count",
                "sys.input.pre_dpd_years",
                "sys.input.pre_dpd_keywords",
                "db.foir_data"
              ]
            },
            "condition": "equal"
          }
        }
      ],
      "message": "Pre DPD count (within a certain period) does not not match the grade criteria"
    },
    "priority": 1
  },
  "post_dpd_count": {
    "key": "post_dpd_count",
    "description": [
      "3 Inputs:",
      [
        "Year (Numeric)",
        "Keywords (Characters)",
        "Count (Numeric)"
      ],
      "Logic:",
      [
        "Extract all the tradelines opened before [Year]",
        "For each tradeline sum the number of times DPD is not part of [Keywords]",
        "If this sum >= count, then fail else pass",
        "If all the above fields are blank then skip"
      ]
    ],
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.null.null",
            "dbRaw": "select JSON_ARRAYAGG(JSON_OBJECT('DateOpened', DATE_FORMAT(foir.DateOpened, '%Y-%m-%d'), 'created_at', DATE_FORMAT(foir.created_at, '%Y-%m-%d'), 'dpd', foir.dpd)) as foir_data from foir where application_id = {sys.input.identifier} and foir.applicant_type = {sys.input.applicant_type}",
            "primaryColumn": "application_id",
            "function": {
              "call": "post_dpd_check(var1, var2, var3, var4)",
              "arg": [
                "sys.input.post_dpd_count",
                "sys.input.post_dpd_year",
                "sys.input.post_dpd_keywords",
                "db.foir_data"
              ]
            },
            "condition": "equal"
          }
        }
      ],
      "message": "Post DPD count (above a certain period) does not not match the grade criteria"
    },
    "priority": 1
  },
  "post_dpd_year": {
    "key": "post_dpd_year",
    "description": [
      "3 Inputs:",
      [
        "Year (Numeric)",
        "Keywords (Characters)",
        "Count (Numeric)"
      ],
      "Logic:",
      [
        "Extract all the tradelines opened before [Year]",
        "For each tradeline sum the number of times DPD is not part of [Keywords]",
        "If this sum >= count, then fail else pass",
        "If all the above fields are blank then skip"
      ]
    ],
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.null.null",
            "dbRaw": "select JSON_ARRAYAGG(JSON_OBJECT('DateOpened', DATE_FORMAT(foir.DateOpened, '%Y-%m-%d'), 'created_at', DATE_FORMAT(foir.created_at, '%Y-%m-%d'), 'dpd', foir.dpd)) as foir_data from foir where application_id = {sys.input.identifier} and foir.applicant_type = {sys.input.applicant_type}",
            "primaryColumn": "application_id",
            "function": {
              "call": "post_dpd_check(var1, var2, var3, var4)",
              "arg": [
                "sys.input.post_dpd_count",
                "sys.input.post_dpd_year",
                "sys.input.post_dpd_keywords",
                "db.foir_data"
              ]
            },
            "condition": "equal"
          }
        }
      ],
      "message": "Post DPD count (above a certain period) does not not match the grade criteria"
    },
    "priority": 1
  },
  "post_dpd_keywords": {
    "key": "post_dpd_keywords",
    "description": [
      "3 Inputs:",
      [
        "Year (Numeric)",
        "Keywords (Characters)",
        "Count (Numeric)"
      ],
      "Logic:",
      [
        "Extract all the tradelines opened before [Year]",
        "For each tradeline sum the number of times DPD is not part of [Keywords]",
        "If this sum >= count, then fail else pass",
        "If all the above fields are blank then skip"
      ]
    ],
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.null.null",
            "dbRaw": "select JSON_ARRAYAGG(JSON_OBJECT('DateOpened', DATE_FORMAT(foir.DateOpened, '%Y-%m-%d'), 'created_at', DATE_FORMAT(foir.created_at, '%Y-%m-%d'), 'dpd', foir.dpd)) as foir_data from foir where application_id = {sys.input.identifier} and foir.applicant_type = {sys.input.applicant_type}",
            "primaryColumn": "application_id",
            "function": {
              "call": "post_dpd_check(var1, var2, var3, var4)",
              "arg": [
                "sys.input.post_dpd_count",
                "sys.input.post_dpd_year",
                "sys.input.post_dpd_keywords",
                "db.foir_data"
              ]
            },
            "condition": "equal"
          }
        }
      ],
      "message": "Post DPD count (above a certain period) does not not match the grade criteria"
    },
    "priority": 1
  },
  "track_record": {
    "key": "track_record",
    "fallback": {
      "rule": "track_record_equifax"
    },
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "value": [
              "CAIS_Account_DETAILS",
              "ReportDate"
            ],
            "config_accessors": "bureau",
            "function": {
              "call": "check_track_record(var1, var2, var3, var4, var5, var6, var7)",
              "arg": [
                "s3.ReportDate",
                "sys.input.net_loan_amount",
                "sys.config.experian_ownership",
                "s3.CAIS_Account_DETAILS",
                "sys.input.track_record",
                "sys.input.bureau_type",
                "sys.config.account_type"
              ]
            },
            "condition": "equal"
          }
        }
      ],
      "message": "Applicant's track record does not match the grade criteria"
    },
    "priority": 4
  },
  "track_record_equifax": {
    "key": "track_record_equifax",
    "fallback": true,
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "value": [
              "sch:Account",
              "sch:Date"
            ],
            "config_accessors": "bureau",
            "function": {
              "call": "check_track_record(var1, var2, var3, var4, var5, var6, var7)",
              "arg": [
                "s3.ReportDate",
                "sys.input.net_loan_amount",
                "sys.config.experian_ownership",
                "s3.sch:Account",
                "sys.input.track_record",
                "sys.input.bureau_type",
                "sys.config.account_type"
              ]
            },
            "condition": "equal"
          }
        }
      ],
      "message": "Applicant's track record does not match the grade criteria"
    },
    "priority": 4
  },
  "average_balance": {
    "key": "average_balance",
    "value": {
      "source": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.emi_calculation.emi",
            "primaryColumn": "application_id",
            "dbSelect": [
              "2*emi"
            ],
            "dbCondition": [
              "order by created_at desc",
              "limit 1"
            ]
          }
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.finbit_datas.average_balance",
            "primaryColumn": "application_id",
            "condition": "greaterThanEqual"
          }
        }
      ]
    },
    "priority": 4
  },
  "negative_area": {
    "key": "negative_area",
    "description": [
      "If application’s current address / application's permanent address / co-application’s address is part of the level 1 negative area list, then fail else pass",
      "If the field is not checked, then the rule is to be skipped"
    ],
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf..checker",
            "dbRaw": "SELECT CASE WHEN ca.current_address_pincode IS NOT NULL AND loc_curr.pincode IS NOT NULL THEN 0 WHEN cae.installation_address_pincode IS NOT NULL AND loc_inst.pincode IS NOT NULL THEN 0 ELSE 1 END AS checker FROM consumer_application ca JOIN consumer_application_element cae ON ca.id = cae.application_id LEFT JOIN locations loc_curr ON loc_curr.pincode COLLATE utf8mb4_unicode_ci = ca.current_address_pincode COLLATE utf8mb4_unicode_ci LEFT JOIN locations loc_inst ON loc_inst.pincode COLLATE utf8mb4_unicode_ci = cae.installation_address_pincode COLLATE utf8mb4_unicode_ci WHERE ca.id = {sys.input.identifier} LIMIT 1;",
            "condition": "equal"
          }
        }
      ],
      "message": "Applicant's address is considered in negative area"
    },
    "priority": 4
  },
  "co_applicant_negative_area": {
    "key": "co_applicant_negative_area",
    "description": [
      "If application’s current address co_applicant address is part of the level 1 negative area list, then fail else pass",
      "If the field is not checked, then the rule is to be skipped"
    ],
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf..checker",
            "dbRaw": "SELECT CASE WHEN ca.co_applicant_address_pincode IS NOT NULL AND loc_co.pincode IS NOT NULL THEN 0 ELSE 1 END AS checker FROM consumer_application ca LEFT JOIN locations loc_co ON loc_co.pincode COLLATE utf8mb4_unicode_ci = ca.co_applicant_address_pincode COLLATE utf8mb4_unicode_ci WHERE ca.id = {sys.input.identifier} LIMIT 1;",
            "condition": "equal"
          }
        }
      ],
      "message": "co-applicant's address is considered in negative area"
    },
    "priority": 4
  },
  "bureau_surrogate": {
    "key": "bureau_surrogate",
    "fallback": {
      "rule": "surrogate_check_equifax"
    },
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "value": [
              "CAIS_Account_DETAILS",
              "ReportDate"
            ],
            "config_accessors": "bureau",
            "function": {
              "call": "check_surrogate_rule(var1, var2, var3, var4, var5, var6, var7)",
              "arg": [
                "sys.input.net_loan_amount",
                "s3.ReportDate",
                "sys.input.bureau_surrogate",
                "s3.CAIS_Account_DETAILS",
                "sys.config.experian_ownership",
                "sys.config.account_type",
                "sys.input.bureau_type"
              ]
            },
            "condition": "equal"
          }
        }
      ],
      "message": "Surrogate policy check failed"
    },
    "priority": 4
  },
  "surrogate_check_equifax": {
    "key": "surrogate_check_equifax",
    "fallback": true,
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "value": [
              "sch:Account",
              "sch:Date"
            ],
            "config_accessors": "bureau",
            "function": {
              "call": "check_surrogate_rule(var1, var2, var3, var4, var5, var6, var7)",
              "arg": [
                "sys.input.net_loan_amount",
                "s3.sch:Date",
                "sys.input.bureau_surrogate",
                "s3.sch:Account",
                "sys.config.experian_ownership",
                "sys.config.account_type",
                "sys.input.bureau_type"
              ]
            },
            "condition": "equal"
          }
        }
      ],
      "message": "Surrogate policy check failed"
    },
    "priority": 4
  },
  "accountType": {
    "key": "accountType",
    "description": [
      "If >= 3 open gold loans are present then fail, else pass",
      "If the field is not checked, then the rule is to be skipped"
    ],
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.null.null",
            "dbRaw": "SELECT JSON_ARRAYAGG(JSON_OBJECT('AccountType', foir.AccountType,'DateClosed', case when foir.DateClosed is null then '-' else foir.DateClosed end)) AS foir_data FROM foir WHERE application_id = {sys.input.identifier} AND foir.AccountType = 'Gold Loan' AND foir.applicant_type = {sys.input.applicant_type} limit 1",
            "function": {
              "call": "account_type_check(var1, var2, var3)",
              "arg": [
                "db.foir_data"
              ]
            },
            "condition": "equal"
          }
        }
      ],
      "message": "Gold Loan tradeline count does not match the grade criteria"
    },
    "priority": 4
  },
  "no_owned_house": {
    "key": "no_owned_house",
    "description": [
      "If current address is not present OR",
      "Else If current address is present but isn’t",
      [
        "OWNED",
        "PARENTS HOUSE",
        "Self Owned",
        "Parent Owned"
      ],
      "Then fail, else pass",
      "If the field is not checked, then the rule is to be skipped"
    ],
    "value": {
      "source": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.consumer_application.current_address_status",
            "primaryColumn": "id"
          }
        }
      ],
      "against": [
        {
          "type": "list",
          "details": {
            "value": [
              "OWNED",
              "PARENTS HOUSE",
              "Self Owned",
              "Parent Owned"
            ],
            "condition": "inList"
          }
        }
      ],
      "message": "No house is owned to match the grade criteria"
    },
    "priority": 1
  },
  "zero_downpayment": {
    "key": "zero_downpayment",
    "description": [
      "If EMI is not generated, then mention reason as “EMI not generated” and fail",
      "Else if EMI is generated and upfront from customer is <= 0, then fail as “zero downpayment”",
      "Else Pass",
      "If the field is not checked, then the rule is to be skipped"
    ],
    "value": {
      "source": [
        {
          "type": "key"
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.emi_calculation.upfront_from_customer",
            "primaryColumn": "application_id",
            "dbCondition": [
              "order by created_at desc",
              "limit 1"
            ],
            "condition": "greaterThan"
          }
        }
      ],
      "message": "No down-payment amount present to match the grade criteria"
    },
    "priority": 1
  },
  "fetch_gst": {
    "key": "fetch_gst",
    "description": [
      "If GST verification is checked then if both of the below conditions is true:",
      [
        "If applicant’s employment type is 'business', 'self employed - business', 'self employed - professional'",
        "GST authStatus is ‘Inactive’"
      ],
      "Then the case has failed, else passed",
      "If the field is not checked, then the rule is to be skipped"
    ],
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf..active_status",
            "dbRaw": "select case when consumer_application.employee_status in ('business', 'self employed - business', 'self employed - professional') then (case when data is not null then (case when json_unquote(json_extract(data, '$.result[0].authStatus')) ='Inactive' then 0 else 1 end)else 0 end) else 1 end as active_status from (select * from consumer_application where consumer_application.id = {sys.input.identifier}) consumer_application left join (select * from (select *, row_number() over(partition by application_id order by created_at desc) row_no from gst_pan_data where deleted_at is null) gst_pan_data where row_no = 1) gst_pan_data on gst_pan_data.application_id = consumer_application.id",
            "condition": "equal"
          }
        }
      ],
      "message": "GST verification failed"
    },
    "priority": 4
  },
  "term_loan_amount_paid": {
    "key": "term_loan_amount_paid",
    "description": [
      "Loan period is > 0 Years",
      "Loan is either ['Auto Loan', 'Housing Loan', 'Personal Loan', 'Consumer Loan', 'Education Loan', 'Loan to Professional', 'Two-wheeler Loan', 'Commercial Vehicle Loan', 'Used Car Loan', 'Business Loan-Priority Sector-Small Business', 'Business Loan - Priority Sector- Agriculture', 'Business Loan - Priority Sector- Others', 'Business Non-Funded Credit Facility', 'Business Non-Funded Credit Facility - Priority', 'Staff Loan']",
      "The loan should be active/open",
      "Extract the maximum of  Amount Paid ",
      "If the max(Amount Paid) > requested loan amount * [amount paid], then pass else fail",
      "If the input in the field is not present, then the rule is to be skipped"
    ],
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.null.null",
            "dbRaw": "SELECT IF (credit_report.Score < 10, 1, 0) as is_thin_file , JSON_ARRAYAGG( JSON_OBJECT( 'DateOpened', case when DATE_FORMAT(foir.DateOpened, '%Y-%m-%d') is null then '-' else DATE_FORMAT(foir.DateOpened, '%Y-%m-%d') end , 'DateClosed', case when DATE_FORMAT(foir.DateClosed , '%Y-%m-%d') is null then '-' else DATE_FORMAT(foir.DateClosed, '%Y-%m-%d') end , 'dpd', foir.dpd, 'Balance', foir.Balance , 'ApprovedAmount', foir.ApprovedAmount , 'AccountType', REPLACE(REPLACE(foir.AccountType, ']', ''), '[', '') ) ) AS foir_data FROM credit_report inner join (select * from foir where deleted_at is null) foir on foir.application_id = credit_report.application_id WHERE credit_report.application_id = {sys.input.identifier} AND credit_report.applicant_type = {sys.input.applicant_type} AND credit_report.deleted_at is null",
            "primaryColumn": "application_id",
            "function": {
              "call": "is_term_loan(var1, var2, var3, var4)",
              "arg": [
                "db.foir_data",
                "db.is_thin_file",
                "sys.config.term_loans",
                "fun.getCurrentDate",
                "sys.input.term_loan_amount_paid_percentage",
                "sys.input.loan_amount"
              ]
            },
            "condition": "equal"
          }
        }
      ],
      "message": "Due amount for old and open unsecure loans does not match the grade criteria"
    },
    "priority": 1
  },
  "is_pincode_approved": {
    "key": "is_pincode_approved",
    "description": [
      "Both the condition is true: If current address pincode is part of the approved pincode list and If permanent address pincode is past of the approved pincode list Then the case has passed, else failed"
    ],
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf..checker",
            "dbRaw": "SELECT CASE WHEN current_check.pin_codes IS NOT NULL AND install_check.pin_codes IS NOT NULL THEN 1 ELSE 0 END AS checker FROM consumer_application LEFT JOIN approved_pin_codes current_check ON current_check.pin_codes = consumer_application.current_address_pincode AND current_check.deleted_at IS NULL LEFT JOIN consumer_application_element cae ON cae.application_id = consumer_application.id LEFT JOIN approved_pin_codes install_check ON install_check.pin_codes = cae.installation_address_pincode AND install_check.deleted_at IS NULL WHERE consumer_application.id = {sys.input.identifier} LIMIT 1",
            "condition": "equal"
          }
        }
      ],
      "message": "Applicant's address pincode is not approved"
    },
    "priority": 4
  },
  "co-applicant_is_pincode_approved": {
    "key": "applicant_is_pincode_approved",
    "description": [
      "Both the condition is true: If current address pincode is part of the approved pincode list and If permanent address pincode is past of the approved pincode list Then the case has passed, else failed"
    ],
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf..checker",
            "dbRaw": "SELECT CASE WHEN co_app_check.pin_codes IS NOT NULL THEN 1 ELSE 0 END AS checker FROM consumer_application LEFT JOIN approved_pin_codes co_app_check ON co_app_check.pin_codes = consumer_application.co_applicant_address_pincode AND co_app_check.deleted_at IS NULL WHERE consumer_application.id = {sys.input.identifier} LIMIT 1;",
            "condition": "equal"
          }
        }
      ],
      "message": "Applicant's address pincode is not approved"
    },
    "priority": 4
  },
  "bank_validation": {
    "key": "bank_validation",
    "description": [
      "Both the condition is true: If current address pincode is part of the approved pincode list and If permanent address pincode is past of the approved pincode list Then the case has passed, else failed"
    ],
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.null.null",
            "dbRaw": "SELECT consumer_application.id AS application_id, consumer_application.name, CASE WHEN JSON_VALID(karza_response) and karza_response like '%bankResponse%' THEN JSON_UNQUOTE(JSON_EXTRACT(karza_response, '$.result.bankResponse')) ELSE '' END AS transaction_status, CASE WHEN JSON_VALID(karza_response) and karza_response like '%accountName%' THEN JSON_UNQUOTE(JSON_EXTRACT(karza_response, '$.result.accountName')) ELSE '' END AS account_name FROM bank LEFT JOIN consumer_application ON consumer_application.id = bank.application_id WHERE application_id = {sys.input.identifier} ORDER BY bank.created_at DESC LIMIT 1;",
            "primaryColumn": "application_id",
            "function": {
              "call": "bank_validation_check(var1, var2, var3, var4)",
              "arg": [
                "sys.input.bank_validation",
                "db.transaction_status",
                "db.name",
                "db.account_name"
              ]
            },
            "condition": "equal"
          }
        }
      ],
      "message": "Bank details not present in the application"
    },
    "priority": 4
  },
  "e_bill_fuzzy_match": {
    "key": "e_bill_fuzzy_match",
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.consumer_application_files.ebill_name_verify",
            "primaryColumn": "consumer_application_id",
            "dbCondition": [
              "where file_type in ('electricity_bill_validation_report', 'electricity_bill') and ebill_name_verify is not null",
              "order by created_at desc",
              "limit 1"
            ],
            "condition": "greaterThanEqual",
            "function": {
              "call": "check_ebill_name_match(var1, var2)",
              "arg": [
                "db.ebill_name_verify",
                "sys.input.e_bill_fuzzy_match"
              ]
            }
          }
        }
      ],
      "message": "Electricity bill validation name match does not match grade criteria"
    }
  },
  "epf_verification": {
    "key": "epf_verification",
    "description": [
      "If EPF verification is checked then in the EPF-report check if any of the below conditions is true:",
      [
        "isEmployed is false",
        "uanNameMatch is false",
        "employerName doesn’t match the name mentioned in our application"
      ],
      "Then the application has failed, else pass",
      "If the field is not checked then the rule is to be skipped"
    ],
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.employment_verification.data",
            "primaryColumn": "application_id",
            "function": {
              "call": "is_employment_verification(var1)",
              "arg": [
                "db.data"
              ]
            },
            "condition": "equal"
          }
        }
      ],
      "message": "epf employment verification failed - epf"
    },
    "priority": 4
  },
  "credit_card_amount_paid": {
    "key": "credit_card_amount_paid",
    "description": [
      "Extract all the open credit cards",
      "Calculate Amount Paid",
      "Identify the maximum Amount Paid",
      "If the max(Amount Paid) > requested loan amount * [amount paid], then pass else fail",
      "If the input in the field is not present, then the rule is to be skipped"
    ],
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 1
          }
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.null.null",
            "dbRaw": "SELECT ca.loan_amount,JSON_ARRAYAGG(JSON_OBJECT('AccountType', foir.AccountType ,'ApprovedAmount', foir.ApprovedAmount ,'Balance', foir.Balance ,'DateClosed', case when foir.DateClosed is null then '-' else foir.DateClosed end ,'InstallmentAmount', foir.InstallmentAmount)) AS foir_data FROM consumer_application AS ca INNER JOIN foir ON foir.application_id = ca.id WHERE ca.id = {sys.input.identifier} AND foir.AccountType = 'Credit Card' and foir.applicant_type = {sys.input.applicant_type}",
            "function": {
              "call": "credit_card_check(var1, var2, var3)",
              "arg": [
                "sys.input.credit_card_percentage",
                "db.foir_data",
                "db.loan_amount"
              ]
            },
            "condition": "equal"
          }
        }
      ],
      "message": "Credit Card tradeline due amount does not match the grade criteria"
    },
    "priority": 4
  },
  "dpd_rules": {
      "key": "dpd_rules",
      "fallback": {
          "rule": "dpd_rules_equifax"
      },
      "value": {
          "source": [
              {
                  "type": "text",
                  "details": {
                      "value": 0
                  }
              }
          ],
          "against": [
              {
                  "type": "s3",
                  "details": {
                      "value": "CAIS_Account_DETAILS",
                      "config_accessors": "bureau",
                      "function": {
                          "call": "dpd_reject_rule(var1, var2, var3, var4, var5)",
                          "arg": [
                              "sys.input.dpd_rules",
                              "s3.CAIS_Account_DETAILS",
                              "sys.input.bureau_type",
                              "sys.config.experian_ownership",
                              "sys.config.account_type"
                          ]
                      },
                      "condition": "equal"
                  }
              }
          ],
          "message": "DPD rules does not match as per grade criteria"
      },
      "priority": 2
  },
  "dpd_rules_equifax": {
      "key": "dpd_rules_equifax",
      "fallback": true,
      "value": {
          "source": [
              {
                  "type": "text",
                  "details": {
                      "value": 0
                  }
              }
          ],
          "against": [
              {
                  "type": "s3",
                  "details": {
                      "value": "sch:Account",
                      "config_accessors": "bureau",
                      "function": {
                          "call": "dpd_reject_rule(var1, var2, var3, var4, var5)",
                          "arg": [
                              "sys.input.dpd_rules",
                              "s3.sch:Account",
                              "sys.input.bureau_type",
                              "sys.config.experian_ownership",
                              "sys.config.account_type"
                          ]
                      },
                      "condition": "equal"
                  }
              }
          ],
          "message": "DPD rules does not match as per grade criteria"
      },
      "priority": 2
  },
  "keyword_rules": {
    "key": "keyword_rules",
    "fallback": {
      "rule": "keyword_rules_equifax"
    },
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 0
          }
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "value": "CAIS_Account_DETAILS",
            "config_accessors": "bureau",
            "function": {
              "call": "keyword_reject_rule(var1, var2, var3, var4, var5)",
              "arg": [
                "sys.input.keyword_rules",
                "s3.CAIS_Account_DETAILS",
                "sys.input.bureau_type",
                "sys.config.experian_ownership",
                "sys.config.account_type"
              ]
            },
            "condition": "equal"
          }
        }
      ],
      "message": "Keyword rule does not match grade criteria"
    },
    "priority": 2
  },
  "keyword_rules_equifax": {
    "key": "keyword_rules_equifax",
    "fallback": true,
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 0
          }
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "value": "sch:Account",
            "config_accessors": "bureau",
            "function": {
              "call": "keyword_reject_rule(var1, var2, var3, var4, var5)",
              "arg": [
                "sys.input.keyword_rules",
                "s3.sch:Account",
                "sys.input.bureau_type",
                "sys.config.experian_ownership",
                "sys.config.account_type"
              ]
            },
            "condition": "equal"
          }
        }
      ],
      "message": "DPD rules does not match as per grade criteria"
    },
    "priority": 2
  },
  "account_status_rules": {
    "key": "account_status_rules",
    "fallback": {
      "rule": "account_status_rules_equifax"
    },
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 0
          }
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "value": "CAIS_Account_DETAILS",
            "config_accessors": "bureau",
            "function": {
              "call": "check_account_status(var1, var2, var3, var4, var5, var6)",
              "arg": [
                "sys.input.account_status_rules",
                "s3.CAIS_Account_DETAILS",
                "sys.config.experian_ownership",
                "sys.input.bureau_type",
                "sys.config.account_status_mappings",
                "sys.config.account_status"
              ]
            },
            "condition": "equal"
          }
        }
      ],
      "message": "Account status rules does not match grade criteria"
    },
    "priority": 2
  },
  "account_status_rules_equifax": {
    "key": "account_status_rules_equifax",
    "fallback": true,
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 0
          }
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "value": "sch:Account",
            "config_accessors": "bureau",
            "function": {
              "call": "check_account_status(var1, var2, var3, var4, var5, var6)",
              "arg": [
                "sys.input.account_status_rules",
                "s3.sch:Account",
                "sys.config.experian_ownership",
                "sys.input.bureau_type",
                "sys.config.account_status_mappings",
                "sys.config.account_status"
              ]
            },
            "condition": "equal"
          }
        }
      ],
      "message": "Account status rules does not match grade criteria"
    },
    "priority": 2
  },
  "principal_written_off_rules": {
    "key": "principal_written_off_rules",
    "fallback": {
      "rule": "principal_written_off_rules_equifax"
    },
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 0
          }
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "value": "CAIS_Account_DETAILS",
            "config_accessors": "bureau",
            "function": {
              "call": "check_principal_write_off(var1, var2, var3, var4)",
              "arg": [
                "sys.input.principal_written_off_rules",
                "s3.CAIS_Account_DETAILS",
                "sys.input.bureau_type",
                "sys.config.experian_ownership"
              ]
            },
            "condition": "equal"
          }
        }
      ],
      "message": "Principal written off rules does not match grade criteria"
    },
    "priority": 2
  },
  "principal_written_off_rules_equifax": {
    "key": "principal_written_off_rules_equifax",
    "fallback": true,
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 0
          }
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "value": "sch:Account",
            "config_accessors": "bureau",
            "function": {
              "call": "check_principal_write_off(var1, var2, var3, var4)",
              "arg": [
                "sys.input.principal_written_off_rules",
                "s3.sch:Account",
                "sys.input.bureau_type",
                "sys.config.experian_ownership"
              ]
            },
            "condition": "equal"
          }
        }
      ],
      "message": "Principal written off rules does not match grade criteria"
    },
    "priority": 2
  },
  "past_dues_rules": {
    "key": "past_dues_rules",
    "fallback": {
      "rule":"past_dues_rules_equifax"
    },
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 0
          }
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "value": "CAIS_Account_DETAILS",
            "config_accessors": "bureau",
            "function": {
              "call": "check_total_past_dues(var1, var2, var3, var4, var5)",
              "arg": [
                "sys.input.past_dues_rules",
                "s3.CAIS_Account_DETAILS",
                "sys.input.bureau_type",
                "sys.config.experian_ownership",
                "sys.config.account_type"
              ]
            },
            "condition": "equal"
          }
        }
      ],
      "message": "Past dues rules does not match grade criteria"
    },
    "priority": 2
  },
  "past_dues_rules_equifax": {
    "key": "past_dues_rules_equifax",
    "fallback": true,
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 0
          }
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "value": "sch:Account",
            "config_accessors": "bureau",
            "function": {
              "call": "check_total_past_dues(var1, var2, var3, var4, var5)",
              "arg": [
                "sys.input.past_dues_rules",
                "s3.sch:Account",
                "sys.input.bureau_type",
                "sys.config.experian_ownership",
                "sys.config.account_type"
              ]
            },
            "condition": "equal"
          }
        }
      ],
      "message": "Past dues rules does not match grade criteria"
    },
    "priority": 2
  },
  "rejection_total_past_dues": {
    "key": "total_past_dues",
    "fallback": {
      "rule":"rejection_total_past_dues_equifax"
    },
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 0
          }
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "value": "CAIS_Account_DETAILS",
            "config_accessors": "bureau",
            "function": {
              "call": "check_total_past_dues(var1, var2, var3, var4, var5)",
              "arg": [
                "sys.input.total_past_dues_rules",
                "s3.CAIS_Account_DETAILS",
                "sys.input.bureau_type",
                "sys.config.experian_ownership",
                "sys.config.account_type"
              ]
            },
            "condition": "equal"
          }
        }
      ]
    },
    "priority": 2
  },
  "rejection_total_past_dues_equifax": {
    "key": "rejection_total_past_dues_equifax",
    "fallback": true,
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 0
          }
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "value": "sch:Account",
            "config_accessors": "bureau",
            "function": {
              "call": "check_total_past_dues(var1, var2, var3, var4, var5)",
              "arg": [
                "sys.input.total_past_dues_rules",
                "s3.sch:Account",
                "sys.input.bureau_type",
                "sys.config.experian_ownership",
                "sys.config.account_type"
              ]
            },
            "condition": "equal"
          }
        }
      ]
    },
    "priority": 2
  },
  "rejection_nach_bounce": {
    "key": "nach_bounce",
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 0
          }
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "config_accessors": "pirimid",
            "function": {
              "call": "check_bounce_number(var1, var2)",
              "arg": [
                "s3.analytics",
                "sys.input.nach_bounce_rule"
              ]
            },
            "condition": "equal"
          }
        }
      ]
    },
    "priority": 2
  },
  "rejection_principal_written_off_amount": {
    "key": "principal_write_off_amount",
    "fallback": {
      "rule": "rejection_principal_written_off_amount_equifax"
    },
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 0
          }
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "value": "CAIS_Account_DETAILS",
            "config_accessors": "bureau",
            "function": {
              "call": "check_principal_write_off(var1, var2, var3, var4)",
              "arg": [
                "sys.input.principal_write_off_rules",
                "s3.CAIS_Account_DETAILS",
                "sys.input.bureau_type",
                "sys.config.experian_ownership"
              ]
            },
            "condition": "equal"
          }
        }
      ]
    },
    "priority": 2
  },
  "rejection_principal_written_off_amount_equifax": {
    "key": "rejection_principal_written_off_amount_equifax",
    "fallback": true,
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 0
          }
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "value": "sch:Account",
            "config_accessors": "bureau",
            "function": {
              "call": "check_principal_write_off(var1, var2, var3, var4)",
              "arg": [
                "sys.input.principal_write_off_rules",
                "s3.sch:Account",
                "sys.input.bureau_type",
                "sys.config.experian_ownership"
              ]
            },
            "condition": "equal"
          }
        }
      ]
    },
    "priority": 2
  },
  "rejection_account_status": {
    "key": "account_status_rejection_rules",
    "fallback": {
      "rule": "rejection_account_status_equifax"
    },
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 0
          }
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "value": "CAIS_Account_DETAILS",
            "config_accessors": "bureau",
            "function": {
              "call": "check_account_status(var1, var2, var3, var4, var5, var6)",
              "arg": [
                "sys.input.account_status_rejection_rules",
                "s3.CAIS_Account_DETAILS",
                "sys.config.experian_ownership",
                "sys.input.bureau_type",
                "sys.config.account_status_mappings",
                "sys.config.account_status"
              ]
            },
            "condition": "equal"
          }
        }
      ]
    },
    "priority": 2
  },
  "rejection_account_status_equifax": {
    "key": "rejection_account_status_equifax",
    "fallback": true,
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 0
          }
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "value": "sch:Account",
            "config_accessors": "bureau",
            "function": {
              "call": "check_account_status(var1, var2, var3, var4, var5, var6)",
              "arg": [
                "sys.input.account_status_rejection_rules",
                "s3.sch:Account",
                "sys.config.experian_ownership",
                "sys.input.bureau_type",
                "sys.config.account_status_mappings",
                "sys.config.account_status"
              ]
            },
            "condition": "equal"
          }
        }
      ]
    },
    "priority": 2
  },
  "rejection_keyword": {
    "key": "keyword_experian_rejection",
    "fallback": {
      "rule": "rejection_keyword_equifax"
    },
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 0
          }
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "value": "CAIS_Account_DETAILS",
            "config_accessors": "bureau",
            "function": {
              "call": "keyword_reject_rule(var1, var2, var3, var4, var5, var6)",
              "arg": [
                "sys.input.keyword_rejection_rules",
                "s3.CAIS_Account_DETAILS",
                "sys.input.bureau_type",
                "sys.config.experian_ownership",
                "sys.config.account_type",
                false
              ]
            },
            "condition": "equal"
          }
        }
      ]
    },
    "priority": 2
  },
  "rejection_keyword_equifax": {
    "key": "rejection_keyword_equifax",
    "fallback": true,
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 0
          }
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "value": "sch:Account",
            "config_accessors": "bureau",
            "function": {
              "call": "keyword_reject_rule(var1, var2, var3, var4, var5, var6)",
              "arg": [
                "sys.input.keyword_rejection_rules",
                "s3.sch:Account",
                "sys.input.bureau_type",
                "sys.config.experian_ownership",
                "sys.config.account_type",
                false
              ]
            },
            "condition": "equal"
          }
        }
      ]
    },
    "priority": 2
  },
  "rejection_dpd": {
    "key": "dpd_rejection_rules",
    "fallback": {
      "rule": "rejection_dpd_equifax"
    },
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 0
          }
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "value": "CAIS_Account_DETAILS",
            "config_accessors": "bureau",
            "function": {
              "call": "dpd_reject_rule(var1, var2, var3, var4, var5, var6)",
              "arg": [
                "sys.input.dpd_rejection_rules",
                "s3.CAIS_Account_DETAILS",
                "sys.input.bureau_type",
                "sys.config.experian_ownership",
                "sys.config.account_type",
                false
              ]
            },
            "condition": "equal"
          }
        }
      ]
    },
    "priority": 2
  },
  "rejection_dpd_equifax": {
    "key": "rejection_dpd_equifax",
    "fallback": true,
    "value": {
      "source": [
        {
          "type": "text",
          "details": {
            "value": 0
          }
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "value": "sch:Account",
            "config_accessors": "bureau",
            "function": {
              "call": "dpd_reject_rule(var1, var2, var3, var4, var5, var6)",
              "arg": [
                "sys.input.dpd_rejection_rules",
                "s3.sch:Account",
                "sys.input.bureau_type",
                "sys.config.experian_ownership",
                "sys.config.account_type",
                false
              ]
            },
            "condition": "equal"
          }
        }
      ]
    },
    "priority": 2
  },
  "rejection_monthly_income": {
    "key": "monthly_income",
    "description": [
      "If the application’s monthly income >= Monthly Income, then the rule has passed, else rejected"
    ],
    "value": {
      "source": [
        {
          "type": "key"
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.consumer_application.monthly_income",
            "primaryColumn": "id",
            "condition": "greaterThanEqual"
          }
        }
      ]
    },
    "priority": 2
  },
  "co_applicant_rejection_monthly_income": {
    "key": "monthly_income",
    "description": [
      "If the co-applicant's monthly income >= Monthly Income, then the rule has passed, else rejected"
    ],
    "value": {
      "source": [
        {
          "type": "key"
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.consumer_application.co_applicant_monthly_income",
            "primaryColumn": "id",
            "condition": "greaterThanEqual"
          }
        }
      ]
    },
    "priority": 2
  },
  "rejection_age": {
    "key": "age_range",
    "description": [
      "If the application’s age >= Min Age & age <= Max range, then pass else rejected",
      "If the value is null, then the rule is to be skipped"
    ],
    "value": {
      "source": [
        {
          "type": "key"
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.consumer_application.dob",
            "primaryColumn": "id",
            "condition": "inBetween",
            "function": {
              "call": "dateDiffInYear(var1, var2)",
              "arg": [
                "db.dob",
                "fun.getCurrentDate"
              ]
            }
          }
        }
      ]
    },
    "priority": 4
  },
  "co_applicant_rejection_age": {
    "key": "age_range",
    "description": [
      "If the co_applicant's age >= Min Age & age <= Max range, then pass else rejected",
      "If the value is null, then the rule is to be skipped"
    ],
    "value": {
      "source": [
        {
          "type": "key"
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.consumer_application.co_applicant_dob",
            "primaryColumn": "id",
            "condition": "inBetween",
            "function": {
              "call": "dateDiffInYear(var1, var2)",
              "arg": [
                "db.co_applicant_dob",
                "fun.getCurrentDate"
              ]
            }
          }
        }
      ]
    },
    "priority": 4
  },
  "rejection_score": {
    "description": [
      "If the application’s score >= Min Score and score <= Max Score, then rejected else pass"
    ],
    "key": "credit_score_range",
    "value": {
      "source": [
        {
          "type": "key"
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.credit_report.Score",
            "primaryColumn": "application_id",
            "dbCondition": [
              "where applicant_type = 1"
            ],
            "condition": "notInBetween"
          }
        }
      ]
    },
    "priority": 4
  },
  "co_applicant_rejection_score": {
    "description": [
      "If the co-applicant's score >= Min Score and score <= Max Score, then rejected else pass"
    ],
    "key": "credit_score_range",
    "value": {
      "source": [
        {
          "type": "key"
        }
      ],
      "against": [
        {
          "type": "db",
          "details": {
            "value": "sourceFile.cf.credit_report.Score",
            "primaryColumn": "application_id",
            "dbCondition": [
              "where applicant_type = 2"
            ],
            "condition": "notInBetween"
          }
        }
      ]
    },
    "priority": 4
  },
  "min_banking_months": {
    "key": "min_banking_months",
    "description": [
      "Checks if the bank statement has enough history",
      "Pass if Actual Months >= Configured Months"
    ],
    "value": {
      "source": [
        {
          "type": "key"
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "config_accessors": "pirimid", 
            "value": "analytics",
            "function": {
              "call": "get_banking_month_count(var1)",
              "arg": [
                "s3.analytics"
              ]
            },
            "condition": "greaterThanEqual"
          }
        }
      ],
      "message": "Insufficient banking history duration"
    },
    "priority": 3
  },
  "name_match_threshold_pct": {
    "key": "name_match_threshold_pct",
    "description": [
      "Fuzzy matches Applicant Name vs Bank Account Name",
      "Pass if Match Score >= Configured Threshold"
    ],
    "value": {
      "source": [
        {
          "type": "key"
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "config_accessors": "pirimid",
            "value": "analytics",
            "function": {
              "call": "get_name_match_score(var1, var2)",
              "arg": [
                "s3.analytics",
                "sys.input.applicant_name"
              ]
            },
            "condition": "greaterThanEqual"
          }
        }
      ],
      "message": "Bank account name does not match applicant name"
    },
    "priority": 2
  },
  "emi_bounce_rule": {
    "key": "emi_bounce_rule",
    "description": [
      "Counts EMI bounces in the last X months",
      "Pass if Actual Bounces <= Configured Limit"
    ],
    "value": {
      "source": [
        {
          "type": "key"
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "config_accessors": "pirimid",
            "value": "analytics",
            "function": {
              "call": "get_recent_bounce_count(var1, var2)",
              "arg": [
                "s3.analytics",
                "sys.input.emi_bounce_lookback_months"
              ]
            },
            "condition": "lessThanEqual"
          }
        }
      ],
      "message": "Too many recent EMI bounces"
    },
    "priority": 1
  },
  "speculative_txn_cap_pct": {
    "key": "speculative_txn_cap_pct",
    "description": [
      "Calculates speculative spend as % of income",
      "Pass if Actual % <= Configured Cap"
    ],
    "value": {
      "source": [
        {
          "type": "key"
        }
      ],
      "against": [
        {
          "type": "s3",
          "details": {
            "config_accessors": "pirimid",
            "value": "analytics",
            "function": {
              "call": "get_speculative_spend_percentage(var1, var2)",
              "arg": [
                "s3.analytics",
                "sys.input.declared_monthly_income"
              ]
            },
            "condition": "lessThanEqual"
          }
        }
      ],
      "message": "Speculative transaction volume exceeds allowed limit"
    },
    "priority": 2
  }
}