Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
__pycache__/
*.pyc
.coverage
*.egg-info/
dist/
build/
.pytest_cache/
1 change: 1 addition & 0 deletions bankweb/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""BankWeb API - Python implementation based on OpenAPI 3.0 specification."""
24 changes: 24 additions & 0 deletions bankweb/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""Data models for the BankWeb API."""

from bankweb.models.user import UserModel, NewImageModel, AccountBalanceResp, AdminUserInfoResp
from bankweb.models.transaction import (
TransactionDBModel,
TransactionResp,
TransactionRespDataTableResp,
AdminUserInfoRespDataTableResp,
)
from bankweb.models.store import StoreItem, BuyProductReq, PurchaseHistoryItemResp

__all__ = [
"UserModel",
"NewImageModel",
"AccountBalanceResp",
"AdminUserInfoResp",
"TransactionDBModel",
"TransactionResp",
"TransactionRespDataTableResp",
"AdminUserInfoRespDataTableResp",
"StoreItem",
"BuyProductReq",
"PurchaseHistoryItemResp",
]
113 changes: 113 additions & 0 deletions bankweb/models/store.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
"""Store-related data models."""

from __future__ import annotations

from dataclasses import dataclass
from datetime import datetime
from typing import Optional


@dataclass
class StoreItem:
"""Represents an item available in the store."""

id: int = 0
name: Optional[str] = None
description: Optional[str] = None
price: float = 0.0
installments: int = 0

def to_dict(self) -> dict:
return {
"id": self.id,
"name": self.name,
"description": self.description,
"price": self.price,
"installments": self.installments,
}

@classmethod
def from_dict(cls, data: dict) -> StoreItem:
return cls(
id=data.get("id", 0),
name=data.get("name"),
description=data.get("description"),
price=data.get("price", 0.0),
installments=data.get("installments", 0),
)

@property
def installment_amount(self) -> float:
if self.installments <= 0:
return self.price
return round(self.price / self.installments, 2)


@dataclass
class BuyProductReq:
"""Request model for purchasing a product."""

id: int = 0
quantity: int = 0
price: float = 0.0

def to_dict(self) -> dict:
return {
"id": self.id,
"quantity": self.quantity,
"price": self.price,
}

@classmethod
def from_dict(cls, data: dict) -> BuyProductReq:
return cls(
id=data.get("id", 0),
quantity=data.get("quantity", 0),
price=data.get("price", 0.0),
)

@property
def total_cost(self) -> float:
return round(self.price * self.quantity, 2)


@dataclass
class PurchaseHistoryItemResp:
"""Response model for purchase history items."""

purchase_time: Optional[datetime] = None
name: Optional[str] = None
description: Optional[str] = None
quantity: int = 0
price: float = 0.0
user_name: Optional[str] = None

def to_dict(self) -> dict:
return {
"purchaseTime": (
self.purchase_time.isoformat() if self.purchase_time else None
),
"name": self.name,
"description": self.description,
"quantity": self.quantity,
"price": self.price,
"userName": self.user_name,
}

@classmethod
def from_dict(cls, data: dict) -> PurchaseHistoryItemResp:
pt = data.get("purchaseTime")
if isinstance(pt, str):
pt = datetime.fromisoformat(pt)
return cls(
purchase_time=pt,
name=data.get("name"),
description=data.get("description"),
quantity=data.get("quantity", 0),
price=data.get("price", 0.0),
user_name=data.get("userName"),
)

@property
def total_cost(self) -> float:
return round(self.price * self.quantity, 2)
168 changes: 168 additions & 0 deletions bankweb/models/transaction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
"""Transaction-related data models."""

from __future__ import annotations

from dataclasses import dataclass
from datetime import datetime
from typing import List, Optional


@dataclass
class TransactionDBModel:
"""Database model for a transaction."""

id: int = 0
sender_id: Optional[str] = None
receiver_id: Optional[str] = None
transaction_date_time: Optional[datetime] = None
reason: Optional[str] = None
amount: float = 0.0
reference: Optional[str] = None

def to_dict(self) -> dict:
return {
"id": self.id,
"senderId": self.sender_id,
"receiverId": self.receiver_id,
"transactionDateTime": (
self.transaction_date_time.isoformat()
if self.transaction_date_time
else None
),
"reason": self.reason,
"amount": self.amount,
"reference": self.reference,
}

@classmethod
def from_dict(cls, data: dict) -> TransactionDBModel:
dt = data.get("transactionDateTime")
if isinstance(dt, str):
dt = datetime.fromisoformat(dt)
return cls(
id=data.get("id", 0),
sender_id=data.get("senderId"),
receiver_id=data.get("receiverId"),
transaction_date_time=dt,
reason=data.get("reason"),
amount=data.get("amount", 0.0),
reference=data.get("reference"),
)


@dataclass
class TransactionResp:
"""Response model for transaction data."""

id: int = 0
sender_id: Optional[str] = None
receiver_id: Optional[str] = None
date_time: Optional[str] = None
reason: Optional[str] = None
amount: float = 0.0
reference: Optional[str] = None
sender_name: Optional[str] = None
sender_surname: Optional[str] = None
receiver_name: Optional[str] = None
receiver_surname: Optional[str] = None

def to_dict(self) -> dict:
return {
"id": self.id,
"senderId": self.sender_id,
"receiverId": self.receiver_id,
"dateTime": self.date_time,
"reason": self.reason,
"amount": self.amount,
"reference": self.reference,
"senderName": self.sender_name,
"senderSurname": self.sender_surname,
"receiverName": self.receiver_name,
"receiverSurname": self.receiver_surname,
}

@classmethod
def from_dict(cls, data: dict) -> TransactionResp:
return cls(
id=data.get("id", 0),
sender_id=data.get("senderId"),
receiver_id=data.get("receiverId"),
date_time=data.get("dateTime"),
reason=data.get("reason"),
amount=data.get("amount", 0.0),
reference=data.get("reference"),
sender_name=data.get("senderName"),
sender_surname=data.get("senderSurname"),
receiver_name=data.get("receiverName"),
receiver_surname=data.get("receiverSurname"),
)

@property
def sender_full_name(self) -> str:
parts = [p for p in (self.sender_name, self.sender_surname) if p]
return " ".join(parts)

@property
def receiver_full_name(self) -> str:
parts = [p for p in (self.receiver_name, self.receiver_surname) if p]
return " ".join(parts)


@dataclass
class TransactionRespDataTableResp:
"""Paginated response for transaction listings."""

records_total: int = 0
records_filtered: int = 0
data: Optional[List[TransactionResp]] = None

def to_dict(self) -> dict:
return {
"recordsTotal": self.records_total,
"recordsFiltered": self.records_filtered,
"data": [t.to_dict() for t in self.data] if self.data else None,
}

@classmethod
def from_dict(cls, data: dict) -> TransactionRespDataTableResp:
items = data.get("data")
parsed_items = (
[TransactionResp.from_dict(i) for i in items] if items else None
)
return cls(
records_total=data.get("recordsTotal", 0),
records_filtered=data.get("recordsFiltered", 0),
data=parsed_items,
)


@dataclass
class AdminUserInfoRespDataTableResp:
"""Paginated response for admin user info listings."""

records_total: int = 0
records_filtered: int = 0
data: Optional[list] = None

def to_dict(self) -> dict:
from bankweb.models.user import AdminUserInfoResp

return {
"recordsTotal": self.records_total,
"recordsFiltered": self.records_filtered,
"data": [u.to_dict() for u in self.data] if self.data else None,
}

@classmethod
def from_dict(cls, data: dict) -> AdminUserInfoRespDataTableResp:
from bankweb.models.user import AdminUserInfoResp

items = data.get("data")
parsed_items = (
[AdminUserInfoResp.from_dict(i) for i in items] if items else None
)
return cls(
records_total=data.get("recordsTotal", 0),
records_filtered=data.get("recordsFiltered", 0),
data=parsed_items,
)
Loading