Files
2025-03-22 17:11:46 +01:00

456 lines
11 KiB
Python

"""
Data models for request and response validation.
"""
from dataclasses import dataclass, field, asdict
from typing import List, Dict, Any, Optional, TypeVar, Type, cast
from datetime import datetime
import json
T = TypeVar('T', bound='BaseModel')
class BaseModel:
"""Base model with serialization capabilities."""
def to_dict(self) -> Dict[str, Any]:
"""Convert model to dictionary."""
result = {k: v for k, v in asdict(self).items() if v is not None}
# Handle special case for type_field
if hasattr(self, 'type_field') and self.type_field is not None:
result['$type'] = self.type_field
del result['type_field']
return result
def to_json(self) -> str:
"""Convert model to JSON string."""
return json.dumps(self.to_dict())
@classmethod
def from_dict(cls: Type[T], data: Dict[str, Any]) -> T:
"""Create model instance from dictionary."""
# Handle special case for $type field
if '$type' in data:
data_copy = data.copy()
data_copy['type_field'] = data_copy.pop('$type')
data = data_copy
return cls(**{k: v for k, v in data.items() if k in cls.__annotations__})
@dataclass
class EligibilityCheckRequest(BaseModel):
"""Model for eligibility check request."""
type_field: str # This will be mapped to $type in JSON
transactionId: str
countryCode: str
customerId: str
accountId: str
lienAmount: float
channel: str
msisdn: Optional[str] = None
@dataclass
class EligibleOffer(BaseModel):
"""Model for eligible offer."""
minamount: float
maxamount: float
productId: int
offerid: int
Tenor: int
@dataclass
class EligibilityCheckResponse(BaseModel):
"""Model for eligibility check response."""
customerId: str
transactionId: str
eligibleOffers: List[Dict[str, Any]]
resultCode: str
resultDescription: str
msisdn: Optional[str] = None
@dataclass
class SelectOffersRequest(BaseModel):
"""Model for select offers request."""
requestId: str
transactionId: str
customerId: str
accountId: str
msisdn: str
requestedAmount: float
productid: str
channel: str
@dataclass
class Offer(BaseModel):
"""Model for offer details."""
offerId: str
productId: str
amount: float
upfrontPayment: float
interestRate: float
Interest: float
ManagementRate: float
ManagementFee: float
InsuranceRate: float
InsuranceFee: float
VATRate: float
VATamount: float
recommendedRepaymentDates: List[str]
installmentAmount: float
totalRepaymentAmount: float
@dataclass
class SelectOffersResponse(BaseModel):
"""Model for select offers response."""
requestId: str
transactionId: str
customerId: str
accountId: str
offers: List[Dict[str, Any]]
resultCode: str
resultDescription: str
outstandingDebtAmount: Optional[float] = 0
@dataclass
class ProvideLoanRequest(BaseModel):
"""Model for provide loan request."""
type_field: str # This will be mapped to $type in JSON
requestId: str
transactionId: str
customerId: str
accountId: str
productId: str
lienAmount: float
requestedAmount: float
collectionType: int
loanType: int
channel: str
msisdn: Optional[str] = None
@dataclass
class ProvideLoanResponse(BaseModel):
"""Model for provide loan response."""
requestId: str
transactionId: str
customerId: str
accountId: str
resultCode: str
resultDescription: str
msisdn: Optional[str] = None
@dataclass
class LoanInformationRequest(BaseModel):
"""Model for loan information request."""
type_field: str # This will be mapped to $type in JSON
transactionId: str
customerId: str
channel: str
msisdn: Optional[str] = None
@dataclass
class Loan(BaseModel):
"""Model for loan details."""
debtId: str
loanDate: str
dueDate: str
currentLoanAmount: float
initialLoanAmount: float
defaultFee: float
continiousFee: float
productId: str
@dataclass
class LoanInformationResponse(BaseModel):
"""Model for loan information response."""
customerId: str
loans: List[Dict[str, Any]]
resultCode: str
resultDescription: str
totalDebtAmount: Optional[float] = None
@dataclass
class RepaymentRequest(BaseModel):
"""Model for repayment request."""
type_field: str # This will be mapped to $type in JSON
transactionId: str
customerId: str
debtId: str
productId: str
channel: str
msisdn: Optional[str] = None
@dataclass
class RepaymentResponse(BaseModel):
"""Model for repayment response."""
customerId: str
productId: str
debtId: str
resultCode: str
resultDescription: str
@dataclass
class CustomerConsentRequest(BaseModel):
"""Model for customer consent request."""
type_field: str # This will be mapped to $type in JSON
transactionId: str
customerId: str
accountId: str
requestTime: str
consentType: str
channel: str
@dataclass
class CustomerConsentResponse(BaseModel):
"""Model for customer consent response."""
resultCode: str
resultDescription: str
@dataclass
class NotificationCallbackRequest(BaseModel):
"""Model for notification callback request."""
fbnTransactionId: str
transactionId: str
customerId: str
accountId: str
debtId: str
transactionType: str
amountProvided: float
amountCollected: float
responseCode: str
responseDescription: str
@dataclass
class NotificationCallbackResponse(BaseModel):
"""Model for notification callback response."""
resultCode: str
resultDescription: str
@dataclass
class RACCheckRequest(BaseModel):
"""Model for RAC check request."""
transactionId: str
fbnTransactionId: str
customerId: str
accountId: str
RAC_Array: List[str]
@dataclass
class RACResponse(BaseModel):
"""Model for RAC response details."""
SalaryAccount: Optional[str] = None
BVN: Optional[str] = None
BVNAttachedtoAccount: Optional[str] = None
CRMS: Optional[str] = None
CRC: Optional[str] = None
AccountStatus: Optional[str] = None
Lien: Optional[str] = None
NoBounchedCheck: Optional[str] = None
Whitelist: Optional[str] = None
NoPastDueSalaryLoan: Optional[str] = None
NoPastDueOtherLoan: Optional[str] = None
@dataclass
class RACCheckResponse(BaseModel):
"""Model for RAC check response."""
RACResponse: Dict[str, Any]
resultCode: str
resultDescription: str
@dataclass
class DisbursementRequest(BaseModel):
"""Model for disbursement request."""
requestId: str
debtId: str
transactionId: str
customerId: str
accountId: str
productId: str
provideAmount: float
countryId: str
collectAmountInterest: Optional[float] = None
collectAmountMgtFee: Optional[float] = None
collectAmountInsurance: Optional[float] = None
collectAmountVAT: Optional[float] = None
comment: Optional[str] = None
@dataclass
class DisbursementResponse(BaseModel):
"""Model for disbursement response."""
requestId: str
debtId: str
transactionId: str
customerId: str
accountId: str
productId: str
provideAmount: float
resultCode: str
resultDescription: str
collectAmountInterest: Optional[float] = None
collectAmountMgtFee: Optional[float] = None
collectAmountInsurance: Optional[float] = None
collectAmountVAT: Optional[float] = None
@dataclass
class CollectLoanRequest(BaseModel):
"""Model for collect loan request."""
transactionId: str
fbnTransactionId: str
debtId: str
customerId: str
accountId: str
productId: str
collectAmount: float
collectionMethod: int
lienAmount: float
countryId: str
penalCharge: Optional[float] = 0.0
comment: Optional[str] = None
@dataclass
class CollectLoanResponse(BaseModel):
"""Model for collect loan response."""
transactionId: str
debtId: str
customerId: str
accountId: str
productId: str
collectAmount: float
lienAmount: float
resultCode: str
resultDescription: str
penalCharge: Optional[float] = 0.0
@dataclass
class TransactionCheckRequest(BaseModel):
"""Model for transaction check request."""
counter: str
TransactionId: str
requestID: str
customerId: str
accountId: str
countryId: str
transactionType: str
@dataclass
class TransactionCheckResponse(BaseModel):
"""Model for transaction check response."""
type_field: str # This will be mapped to $type in JSON
nativeId: str
customerId: str
accountId: str
providedAmount: float
collectedAmount: float
resultCode: str
resultDescription: str
@dataclass
class PenalChargeRequest(BaseModel):
"""Model for penal charge request."""
transactionId: str
fbnTransactionId: str
debtId: str
customerId: str
accountId: str
penalCharge: float
lienAmount: float
countryId: str
comment: Optional[str] = None
@dataclass
class PenalChargeResponse(BaseModel):
"""Model for penal charge response."""
resultCode: str
resultDescription: str
@dataclass
class RevokeEnableConsentRequest(BaseModel):
"""Model for revoke/enable consent request."""
transactionId: str
fbnTransactionId: str
customerId: str
accountId: str
processTime: str
consentType: str
countryId: str
comment: Optional[str] = None
@dataclass
class RevokeEnableConsentResponse(BaseModel):
"""Model for revoke/enable consent response."""
type_field: str # This will be mapped to $type in JSON
customerId: str
accountId: str
resultCode: str
resultDescription: str
@dataclass
class ValidateTokenRequest(BaseModel):
"""Model for validate token request."""
RequestId: str
UserId: str
CountryId: str
TokenCode: str
@dataclass
class ValidateTokenResponse(BaseModel):
"""Model for validate token response."""
Authenticated: bool
AuthenticatedMessage: str
ResponseCode: str
ResponseMessage: str
RequestId: str
@dataclass
class LienCheckRequest(BaseModel):
"""Model for lien check request."""
transactionId: str
customerId: str
accountId: str
countryId: str
@dataclass
class LienCheckResponse(BaseModel):
"""Model for lien check response."""
lienAmount: float
resultCode: str
resultDescription: str
@dataclass
class NewTransactionCheckRequest(BaseModel):
"""Model for new transaction check request."""
transactionId: str
debtId: str
transactionType: str
fbnTransactionId: str
origTransactionId: str
customerId: str
@dataclass
class TransactionData(BaseModel):
"""Model for transaction data."""
transactionId: str
providedAmount: float
collectedAmount: float
resultCode: str
resultDescription: str
@dataclass
class NewTransactionCheckResponse(BaseModel):
"""Model for new transaction check response."""
transactionId: str
data: Dict[str, Any]
resultCode: str
resultDescription: str
@dataclass
class SMSRequest(BaseModel):
"""Model for SMS request."""
text: str
dest: str
unicode: bool
@dataclass
class SMSResponse(BaseModel):
"""Model for SMS response."""
data: str
statusCode: int
IsSuccessful: bool
errorMessage: Optional[str] = None