Skip to content

Credit Rules

Context

This document describes the business rules for credit evaluation in our banking system.

Simple Evaluation

The basic rule checks whether the client's balance exceeds the requested amount.

Contract

evaluate_credit

Evaluate whether the client can obtain a credit for the requested amount. The rule is simple: the client's balance must exceed the requested amount.

Inputs
ParameterTypeDefault
client_idstr
amountfloat
Output
returnbool

Source Code

def evaluate_credit(client_id: str, amount: float) -> bool:
    """Evaluate whether the client can obtain a credit for the requested amount.

    The rule is simple: the client's balance must exceed the requested amount.
    """
    try:
        result = CheckClientBalance().call(client_id)
    except ServiceError:
        return False
    return result.balance > amount

External Service

class CheckClientBalance(ExternalService):
    """Call to the Core Banking API (Blackbox)."""

    component_name = "CoreBanking"

    def execute(self, client_id: str) -> ClientBalance:
        pass  # type: ignore[return-value]

    def mock(self, client_id: str) -> MockResponse:
        return MockResponse(data=ClientBalance(
            balance=1500.0,
            currency="USD",
            account_status="active",
        ))

    def mock_error(self, client_id: str) -> MockErrorResponse:
        return MockErrorResponse(
            error_code="CLIENT_NOT_FOUND",
            error_message="The specified client was not found.",
            http_code=404,
        )

Execution Flow

Try it Live

Playground — evaluate_credit

Evaluate whether the client can obtain a credit for the requested amount. The rule is simple: the client's balance must exceed the requested amount.

View source code
def evaluate_credit(client_id: str, amount: float) -> bool:
    """Evaluate whether the client can obtain a credit for the requested amount.

    The rule is simple: the client's balance must exceed the requested amount.
    """
    try:
        result = CheckClientBalance().call(client_id)
    except ServiceError:
        return False
    return result.balance > amount
Mock configuration
Test cases
  • No test cases saved yet.

Advanced Evaluation

The advanced rule combines balance and credit score.

Contract

evaluate_credit_advanced

Advanced evaluation combining balance and credit score. Returns a structured CreditDecision with the decision and details.

Inputs
ParameterTypeDefault
client_idstr
amountfloat
score_thresholdint600
Output
returnCreditDecision
CreditDecision Full credit evaluation result.
ParameterTypeDefault
approved *bool
balance *float
scoreint | NoneNone
incidentsint | NoneNone
reasonslist[str][]

Source Code

def evaluate_credit_advanced(client_id: str, amount: float, score_threshold: int = 600) -> CreditDecision:
    """Advanced evaluation combining balance and credit score.

    Returns a structured CreditDecision with the decision and details.
    """
    result = CheckClientBalance().call(client_id)

    if result.balance > amount:
        history = CheckCreditHistory().call(client_id)
        score_ok = history.score >= score_threshold
        incidents_ok = history.incidents == 0
        reasons = [
            r for r in [
                "Credit score too low" if not score_ok else None,
                "Incidents detected" if not incidents_ok else None,
            ]
            if r
        ]
        return CreditDecision(
            approved=score_ok and incidents_ok,
            balance=result.balance,
            score=history.score,
            incidents=history.incidents,
            reasons=reasons,
        )
    else:
        return CreditDecision(
            approved=False,
            balance=result.balance,
            reasons=["Insufficient balance"],
        )

Execution Flow

Sequence diagram — evaluate_credit_advanced

sequenceDiagram
    participant evaluate_credit_advanced
    participant CheckClientBalance as CoreBanking / CheckClientBalance
    participant CheckCreditHistory as CoreBanking / CheckCreditHistory
    evaluate_credit_advanced->>+CheckClientBalance: client_id
    CheckClientBalance-->>-evaluate_credit_advanced: response
    alt result.balance > amount
        evaluate_credit_advanced->>+CheckCreditHistory: client_id
        CheckCreditHistory-->>-evaluate_credit_advanced: response
    else
    end

Try it Live

Playground — evaluate_credit_advanced

Advanced evaluation combining balance and credit score. Returns a structured CreditDecision with the decision and details.

View source code
def evaluate_credit_advanced(client_id: str, amount: float, score_threshold: int = 600) -> CreditDecision:
    """Advanced evaluation combining balance and credit score.

    Returns a structured CreditDecision with the decision and details.
    """
    result = CheckClientBalance().call(client_id)

    if result.balance > amount:
        history = CheckCreditHistory().call(client_id)
        score_ok = history.score >= score_threshold
        incidents_ok = history.incidents == 0
        reasons = [
            r for r in [
                "Credit score too low" if not score_ok else None,
                "Incidents detected" if not incidents_ok else None,
            ]
            if r
        ]
        return CreditDecision(
            approved=score_ok and incidents_ok,
            balance=result.balance,
            score=history.score,
            incidents=history.incidents,
            reasons=reasons,
        )
    else:
        return CreditDecision(
            approved=False,
            balance=result.balance,
            reasons=["Insufficient balance"],
        )
Mock configuration
Test cases
  • No test cases saved yet.

Typed Evaluation (with Pydantic/Dataclass models)

This version uses structured types for inputs and outputs. The contract table below lets you unfold each type to see its internal structure.

Contract

evaluate_credit_typed

Evaluate a credit request using structured types. Accepts a CreditRequest and returns a FullCreditDecision with full details. The contract table will show the structure of both types.

Inputs
ParameterTypeDefault
requestCreditRequest
CreditRequest A structured credit evaluation request.
ParameterTypeDefault
client_id *str
amount *float
score_thresholdint600
include_historyboolTrue
Output
returnFullCreditDecision
FullCreditDecision The full credit evaluation result.
ParameterTypeDefault
approved *bool
balance *float
historyCreditHistory | NoneNone
reasonslist[str][]

Data Models

class CreditRequest(BaseModel):
    """A structured credit evaluation request."""

    client_id: str
    amount: float
    score_threshold: int = 600
    include_history: bool = True

Source Code

def evaluate_credit_typed(request: CreditRequest) -> FullCreditDecision:
    """Evaluate a credit request using structured types.

    Accepts a CreditRequest and returns a FullCreditDecision with full details.
    The contract table will show the structure of both types.
    """
    try:
        result = CheckClientBalance().call(request.client_id)
    except ServiceError:
        return FullCreditDecision(
            approved=False,
            balance=0.0,
            reasons=["Unable to verify balance"],
        )

    if result.balance <= request.amount:
        return FullCreditDecision(
            approved=False,
            balance=result.balance,
            reasons=["Insufficient balance"],
        )

    if not request.include_history:
        return FullCreditDecision(approved=True, balance=result.balance)

    history = CheckCreditHistory().call(request.client_id)

    score_ok = history.score >= request.score_threshold
    incidents_ok = history.incidents == 0

    reasons = [
        r for r in [
            "Credit score too low" if not score_ok else None,
            "Incidents detected" if not incidents_ok else None,
        ]
        if r
    ]

    return FullCreditDecision(
        approved=score_ok and incidents_ok,
        balance=result.balance,
        history=history,
        reasons=reasons if reasons else [],
    )

Try it Live

Playground — evaluate_credit_typed

Evaluate a credit request using structured types. Accepts a CreditRequest and returns a FullCreditDecision with full details. The contract table will show the structure of both types.

View source code
def evaluate_credit_typed(request: CreditRequest) -> FullCreditDecision:
    """Evaluate a credit request using structured types.

    Accepts a CreditRequest and returns a FullCreditDecision with full details.
    The contract table will show the structure of both types.
    """
    try:
        result = CheckClientBalance().call(request.client_id)
    except ServiceError:
        return FullCreditDecision(
            approved=False,
            balance=0.0,
            reasons=["Unable to verify balance"],
        )

    if result.balance <= request.amount:
        return FullCreditDecision(
            approved=False,
            balance=result.balance,
            reasons=["Insufficient balance"],
        )

    if not request.include_history:
        return FullCreditDecision(approved=True, balance=result.balance)

    history = CheckCreditHistory().call(request.client_id)

    score_ok = history.score >= request.score_threshold
    incidents_ok = history.incidents == 0

    reasons = [
        r for r in [
            "Credit score too low" if not score_ok else None,
            "Incidents detected" if not incidents_ok else None,
        ]
        if r
    ]

    return FullCreditDecision(
        approved=score_ok and incidents_ok,
        balance=result.balance,
        history=history,
        reasons=reasons if reasons else [],
    )
Mock configuration
Test cases
  • No test cases saved yet.