456 lines
11 KiB
Python
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 |