Initial commit

This commit is contained in:
Azeez Muibi
2025-03-20 13:35:44 +01:00
commit af9a6148a1
48 changed files with 2451 additions and 0 deletions
+459
View File
@@ -0,0 +1,459 @@
"""
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 __init__(self):
self.type_field = None
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