feat: implement complete CMT backend with API endpoints and test suite
- Add 7 core API endpoints: users, transactions, partners, products, inventory, payments, credit - Implement role-based authentication (admin/write/read-only access) - Add comprehensive database models with proper relationships - Include full test coverage for all endpoints and business logic - Set up Alembic migrations and Docker configuration - Configure FastAPI app with CORS and database integration
This commit is contained in:
+184
-15
@@ -2,40 +2,209 @@
|
||||
Custom validation schema
|
||||
"""
|
||||
from sqlmodel import SQLModel
|
||||
from app.schemas.base import UserRole, PartnerType, PaymentMethod
|
||||
from typing import Optional
|
||||
from datetime import datetime, date
|
||||
from .base import TransactionType, TransactionStatus
|
||||
|
||||
|
||||
class ClientCreate(SQLModel):
|
||||
######################################################
|
||||
# Users
|
||||
class UserCreate(SQLModel):
|
||||
username: str
|
||||
password: str
|
||||
role: UserRole = UserRole.READ_ONLY
|
||||
|
||||
|
||||
class UserUpdate(SQLModel):
|
||||
username: Optional[str] = None
|
||||
password: Optional[str] = None
|
||||
role: Optional[UserRole] = None
|
||||
|
||||
|
||||
class UserLogin(SQLModel):
|
||||
username: str
|
||||
password: str
|
||||
|
||||
|
||||
class UserResponse(SQLModel):
|
||||
id: Optional[int] = None
|
||||
username: str
|
||||
role: UserRole
|
||||
|
||||
|
||||
class Token(SQLModel):
|
||||
access_token: str
|
||||
token_type: str
|
||||
expires_in: int
|
||||
user: UserResponse
|
||||
|
||||
|
||||
class TokenData(SQLModel):
|
||||
username: Optional[str] = None
|
||||
user_id: Optional[int] = None
|
||||
role: Optional[UserRole] = None
|
||||
|
||||
|
||||
##################################################
|
||||
# Transactions
|
||||
class TransactionBase(SQLModel):
|
||||
partner_id: int
|
||||
transcation_type: TransactionType = TransactionType.SALE
|
||||
transaction_status: TransactionStatus = TransactionStatus.UNPAID
|
||||
total_amount: int
|
||||
|
||||
class TransactionCreate(TransactionBase):
|
||||
pass
|
||||
|
||||
class TransactionUpdate(SQLModel):
|
||||
partner_id: Optional[int] = None
|
||||
transcation_type: Optional[TransactionType] = None
|
||||
transaction_status: Optional[TransactionStatus] = None
|
||||
total_amount: Optional[int] = None
|
||||
|
||||
class TransactionResponse(TransactionBase):
|
||||
id: int
|
||||
created_by: int
|
||||
updated_by: int
|
||||
created_on: datetime
|
||||
updated_on: datetime
|
||||
|
||||
|
||||
##################################################
|
||||
# Partners
|
||||
class PartnerBase(SQLModel):
|
||||
tin_number: int
|
||||
names: str
|
||||
phone_number: str
|
||||
|
||||
|
||||
class ClientUpdate(SQLModel):
|
||||
tin_number: Optional[int] = None
|
||||
names: Optional[str] = None
|
||||
type: PartnerType = PartnerType.CLIENT
|
||||
phone_number: Optional[str] = None
|
||||
|
||||
class PartnerCreate(PartnerBase):
|
||||
pass
|
||||
|
||||
class SupplierCreate(SQLModel):
|
||||
tin_number: int
|
||||
names: str
|
||||
phone_number: str
|
||||
|
||||
|
||||
class SupplierUpdate(ClientUpdate):
|
||||
class PartnerUpdate(SQLModel):
|
||||
tin_number: Optional[int] = None
|
||||
names: Optional[str] = None
|
||||
type: Optional[PartnerType] = None
|
||||
phone_number: Optional[str] = None
|
||||
|
||||
class PartnerResponse(PartnerBase):
|
||||
id: int
|
||||
|
||||
class ProductCreate(SQLModel):
|
||||
|
||||
##################################################
|
||||
# Products
|
||||
class ProductBase(SQLModel):
|
||||
product_code: str
|
||||
product_name: str
|
||||
purchase_price: int
|
||||
selling_price: int
|
||||
|
||||
class ProductCreate(ProductBase):
|
||||
pass
|
||||
|
||||
class ProductUpdate(SQLModel):
|
||||
product_code: Optional[str] = None
|
||||
product_name: Optional[str] = None
|
||||
purchase_price: Optional[int] = None
|
||||
selling_price: Optional[int] = None
|
||||
|
||||
class ProductResponse(ProductBase):
|
||||
id: int
|
||||
date_modified: datetime
|
||||
|
||||
|
||||
##################################################
|
||||
# Transaction Details
|
||||
class TransactionDetailsBase(SQLModel):
|
||||
partner_id: int
|
||||
product_id: int
|
||||
qty: int
|
||||
selling_price: int
|
||||
total_value: int
|
||||
|
||||
class TransactionDetailsCreate(TransactionDetailsBase):
|
||||
pass
|
||||
|
||||
class TransactionDetailsUpdate(SQLModel):
|
||||
partner_id: Optional[int] = None
|
||||
product_id: Optional[int] = None
|
||||
qty: Optional[int] = None
|
||||
selling_price: Optional[int] = None
|
||||
total_value: Optional[int] = None
|
||||
|
||||
class TransactionDetailsResponse(TransactionDetailsBase):
|
||||
id: int
|
||||
created_by: int
|
||||
updated_by: int
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
|
||||
##################################################
|
||||
# Payments
|
||||
class PaymentBase(SQLModel):
|
||||
transaction_id: int
|
||||
payment_method: PaymentMethod = PaymentMethod.CASH
|
||||
paid_amount: int
|
||||
payment_date: date
|
||||
|
||||
class PaymentCreate(PaymentBase):
|
||||
pass
|
||||
|
||||
class PaymentUpdate(SQLModel):
|
||||
transaction_id: Optional[int] = None
|
||||
payment_method: Optional[PaymentMethod] = None
|
||||
paid_amount: Optional[int] = None
|
||||
payment_date: Optional[date] = None
|
||||
|
||||
class PaymentResponse(PaymentBase):
|
||||
id: int
|
||||
created_by: int
|
||||
updated_by: int
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
|
||||
##################################################
|
||||
# Credit
|
||||
class CreditBase(SQLModel):
|
||||
partner_id: int
|
||||
transaction_id: int
|
||||
credit_amount: int
|
||||
credit_limit: int
|
||||
balance: int
|
||||
|
||||
class CreditCreate(CreditBase):
|
||||
pass
|
||||
|
||||
class CreditUpdate(SQLModel):
|
||||
partner_id: Optional[int] = None
|
||||
transaction_id: Optional[int] = None
|
||||
credit_amount: Optional[int] = None
|
||||
credit_limit: Optional[int] = None
|
||||
balance: Optional[int] = None
|
||||
|
||||
class CreditResponse(CreditBase):
|
||||
id: int
|
||||
created_by: int
|
||||
updated_by: int
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
|
||||
##################################################
|
||||
# Inventory
|
||||
class InventoryBase(SQLModel):
|
||||
product_id: int
|
||||
total_qty: int
|
||||
|
||||
class InventoryCreate(InventoryBase):
|
||||
pass
|
||||
|
||||
class InventoryUpdate(SQLModel):
|
||||
product_id: Optional[int] = None
|
||||
total_qty: Optional[int] = None
|
||||
|
||||
class InventoryResponse(InventoryBase):
|
||||
id: int
|
||||
|
||||
Reference in New Issue
Block a user