brewman/brewman/brewman/models/account_base.py

128 lines
4.5 KiB
Python

import uuid
from typing import TYPE_CHECKING
from sqlalchemy import Boolean, ForeignKey, Integer, Unicode, Uuid, func, select
from sqlalchemy.orm import Mapped, Session, mapped_column, relationship
from ..db.base_class import reg
from ..schemas.account import AccountLink
from .account_type import AccountType
if TYPE_CHECKING:
from .cost_centre import CostCentre
from .journal import Journal
from .product import Product
from .rate_contract import RateContract
@reg.mapped_as_dataclass(unsafe_hash=True)
class AccountBase:
__tablename__ = "accounts"
id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, insert_default=uuid.uuid4)
code: Mapped[int] = mapped_column(Integer, nullable=False)
name: Mapped[str] = mapped_column(Unicode, unique=True, nullable=False)
type_id: Mapped[int] = mapped_column("type", Integer, ForeignKey("account_types.id"), nullable=False)
account_type: Mapped[str] = mapped_column(Unicode, nullable=False)
is_starred: Mapped[bool] = mapped_column(Boolean, nullable=False)
is_active: Mapped[bool] = mapped_column(Boolean, nullable=False)
is_reconcilable: Mapped[bool] = mapped_column(Boolean, nullable=False)
cost_centre_id: Mapped[uuid.UUID] = mapped_column(
Uuid,
ForeignKey("cost_centres.id"),
nullable=False,
)
is_fixture: Mapped[bool] = mapped_column(Boolean, nullable=False)
__mapper_args__ = {"polymorphic_on": account_type}
type_: Mapped[AccountType] = relationship("AccountType", back_populates="accounts")
journals: Mapped[list["Journal"]] = relationship("Journal", back_populates="account")
cost_centre: Mapped["CostCentre"] = relationship("CostCentre", back_populates="accounts")
products: Mapped[list["Product"]] = relationship("Product", back_populates="account")
rate_contracts: Mapped[list["RateContract"]] = relationship("RateContract", back_populates="vendor")
def __init__(
self,
name: str,
type_id: int,
is_starred: bool,
is_active: bool,
is_reconcilable: bool,
cost_centre_id: uuid.UUID,
code: int | None = None,
id_: uuid.UUID | None = None,
is_fixture: bool = False,
) -> None:
if code is not None:
self.code = code
self.name = name
self.type_id = type_id
self.is_starred = is_starred
self.is_active = is_active
self.is_reconcilable = is_reconcilable
self.cost_centre_id = cost_centre_id
if id_ is not None:
self.id = id_
self.is_fixture = is_fixture
def can_delete(self, advanced_delete: bool) -> tuple[bool, str]:
if self.is_fixture:
return False, f"{self.name} is a fixture and cannot be edited or deleted."
if self.is_active:
return False, "Account is active"
if len(self.journals) > 0 and not advanced_delete:
return False, "Account has journal entries"
return True, ""
@classmethod
def get_code(cls, type_: int, db: Session) -> int:
code: int = db.execute(
select(func.coalesce(func.max(AccountBase.code), 0) + 1).where(AccountBase.type_id == type_)
).scalar_one()
return code
@classmethod
def all_purchases(cls) -> uuid.UUID:
return uuid.UUID("240dd899-c413-854c-a7eb-67a29d154490")
@classmethod
def cash_in_hand(cls) -> AccountLink:
return AccountLink(id_=uuid.UUID("ed2341bb-80b8-9649-90db-f9aaca183bb3"), name="Cash in Hand")
@classmethod
def local_purchase(cls) -> AccountLink:
return AccountLink(id_=uuid.UUID("d2b75912-505f-2548-9093-466dfff6a0f9"), name="Local Purchase")
@classmethod
def salary_acc(cls) -> AccountLink:
return AccountLink(id_=uuid.UUID("5c2b54d0-c174-004d-a0d5-92cdaadcefa7"), name="Staff Salary")
@classmethod
def salary_id(cls) -> uuid.UUID:
return uuid.UUID("5c2b54d0-c174-004d-a0d5-92cdaadcefa7")
@classmethod
def incentive(cls) -> AccountLink:
return AccountLink(id_=uuid.UUID("b7eff754-e8ba-e047-ab06-9132c15c7640"), name="Incentives")
@classmethod
def incentive_id(cls) -> uuid.UUID:
return uuid.UUID("b7eff754-e8ba-e047-ab06-9132c15c7640")
@classmethod
def esi_pf_expense(cls) -> uuid.UUID:
return uuid.UUID("d2a1a286-e900-764b-a1a5-9f4b00dbb940")
@classmethod
def esi_pf_payable(cls) -> uuid.UUID:
return uuid.UUID("42277912-cc18-854b-b134-9f4b00dba419")
@classmethod
def suspense(cls) -> uuid.UUID:
return uuid.UUID("3854e317-6f3b-5142-ab26-9c44d4cddd08")