107 lines
2.5 KiB
Python
107 lines
2.5 KiB
Python
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
from typing import Any, Dict, Optional
|
||
|
|
|
||
|
|
from sqlalchemy.exc import IntegrityError
|
||
|
|
from sqlalchemy.orm import Session
|
||
|
|
|
||
|
|
from adapters.db.models.account import Account
|
||
|
|
|
||
|
|
|
||
|
|
def account_to_dict(obj: Account) -> Dict[str, Any]:
|
||
|
|
return {
|
||
|
|
"id": obj.id,
|
||
|
|
"name": obj.name,
|
||
|
|
"code": obj.code,
|
||
|
|
"account_type": obj.account_type,
|
||
|
|
"parent_id": obj.parent_id,
|
||
|
|
"business_id": obj.business_id,
|
||
|
|
"created_at": obj.created_at,
|
||
|
|
"updated_at": obj.updated_at,
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
def _validate_parent(db: Session, parent_id: Optional[int], business_id: Optional[int]) -> Optional[int]:
|
||
|
|
if parent_id is None:
|
||
|
|
return None
|
||
|
|
parent = db.get(Account, parent_id)
|
||
|
|
if not parent:
|
||
|
|
raise ValueError("PARENT_NOT_FOUND")
|
||
|
|
# والد باید عمومی یا متعلق به همان کسبوکار باشد
|
||
|
|
if parent.business_id is not None and parent.business_id != business_id:
|
||
|
|
raise ValueError("INVALID_PARENT_BUSINESS")
|
||
|
|
return parent.id
|
||
|
|
|
||
|
|
|
||
|
|
def create_account(
|
||
|
|
db: Session,
|
||
|
|
*,
|
||
|
|
name: str,
|
||
|
|
code: str,
|
||
|
|
account_type: str,
|
||
|
|
business_id: Optional[int],
|
||
|
|
parent_id: Optional[int] = None,
|
||
|
|
) -> Dict[str, Any]:
|
||
|
|
parent_id = _validate_parent(db, parent_id, business_id)
|
||
|
|
obj = Account(
|
||
|
|
name=name,
|
||
|
|
code=code,
|
||
|
|
account_type=account_type,
|
||
|
|
business_id=business_id,
|
||
|
|
parent_id=parent_id,
|
||
|
|
)
|
||
|
|
db.add(obj)
|
||
|
|
try:
|
||
|
|
db.commit()
|
||
|
|
except IntegrityError as e:
|
||
|
|
db.rollback()
|
||
|
|
raise ValueError("ACCOUNT_CODE_NOT_UNIQUE") from e
|
||
|
|
db.refresh(obj)
|
||
|
|
return account_to_dict(obj)
|
||
|
|
|
||
|
|
|
||
|
|
def update_account(
|
||
|
|
db: Session,
|
||
|
|
account_id: int,
|
||
|
|
*,
|
||
|
|
name: Optional[str] = None,
|
||
|
|
code: Optional[str] = None,
|
||
|
|
account_type: Optional[str] = None,
|
||
|
|
parent_id: Optional[int] = None,
|
||
|
|
) -> Optional[Dict[str, Any]]:
|
||
|
|
obj = db.get(Account, account_id)
|
||
|
|
if not obj:
|
||
|
|
return None
|
||
|
|
if parent_id is not None:
|
||
|
|
parent_id = _validate_parent(db, parent_id, obj.business_id)
|
||
|
|
if name is not None:
|
||
|
|
obj.name = name
|
||
|
|
if code is not None:
|
||
|
|
obj.code = code
|
||
|
|
if account_type is not None:
|
||
|
|
obj.account_type = account_type
|
||
|
|
obj.parent_id = parent_id if parent_id is not None else obj.parent_id
|
||
|
|
try:
|
||
|
|
db.commit()
|
||
|
|
except IntegrityError as e:
|
||
|
|
db.rollback()
|
||
|
|
raise ValueError("ACCOUNT_CODE_NOT_UNIQUE") from e
|
||
|
|
db.refresh(obj)
|
||
|
|
return account_to_dict(obj)
|
||
|
|
|
||
|
|
|
||
|
|
def delete_account(db: Session, account_id: int) -> bool:
|
||
|
|
obj = db.get(Account, account_id)
|
||
|
|
if not obj:
|
||
|
|
return False
|
||
|
|
db.delete(obj)
|
||
|
|
db.commit()
|
||
|
|
return True
|
||
|
|
|
||
|
|
|
||
|
|
def get_account(db: Session, account_id: int) -> Optional[Dict[str, Any]]:
|
||
|
|
obj = db.get(Account, account_id)
|
||
|
|
return account_to_dict(obj) if obj else None
|
||
|
|
|
||
|
|
|