75 lines
2.3 KiB
Python
75 lines
2.3 KiB
Python
import uuid
|
|
|
|
from decimal import Decimal
|
|
from typing import TYPE_CHECKING
|
|
|
|
from sqlalchemy import (
|
|
ColumnElement,
|
|
ForeignKey,
|
|
Numeric,
|
|
UniqueConstraint,
|
|
Uuid,
|
|
type_coerce,
|
|
)
|
|
from sqlalchemy.ext.hybrid import hybrid_property
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
from ..db.base_class import reg
|
|
|
|
|
|
if TYPE_CHECKING:
|
|
from .batch import Batch
|
|
from .voucher import Voucher
|
|
|
|
|
|
@reg.mapped_as_dataclass(unsafe_hash=True)
|
|
class Inventory:
|
|
__tablename__ = "inventories"
|
|
__table_args__ = (UniqueConstraint("voucher_id", "batch_id"),)
|
|
id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, insert_default=uuid.uuid4)
|
|
voucher_id: Mapped[uuid.UUID] = mapped_column(
|
|
Uuid,
|
|
ForeignKey("vouchers.id"),
|
|
nullable=False,
|
|
index=True,
|
|
)
|
|
batch_id: Mapped[uuid.UUID] = mapped_column(Uuid, ForeignKey("batches.id"), nullable=False)
|
|
quantity: Mapped[Decimal] = mapped_column(Numeric(precision=15, scale=2), nullable=False)
|
|
rate: Mapped[Decimal] = mapped_column(Numeric(precision=15, scale=2), nullable=False)
|
|
tax: Mapped[Decimal] = mapped_column(Numeric(precision=15, scale=5), nullable=False)
|
|
discount: Mapped[Decimal] = mapped_column(Numeric(precision=15, scale=5), nullable=False)
|
|
|
|
voucher: Mapped["Voucher"] = relationship("Voucher", back_populates="inventories")
|
|
batch: Mapped["Batch"] = relationship("Batch", back_populates="inventories")
|
|
|
|
def __init__(
|
|
self,
|
|
quantity: Decimal,
|
|
rate: Decimal,
|
|
tax: Decimal,
|
|
discount: Decimal,
|
|
batch: "Batch",
|
|
voucher_id: uuid.UUID | None = None,
|
|
id_: uuid.UUID | None = None,
|
|
) -> None:
|
|
self.batch = batch
|
|
self.quantity = quantity
|
|
self.rate = rate
|
|
self.tax = tax
|
|
self.discount = discount
|
|
if id_ is not None:
|
|
self.id = id_
|
|
if voucher_id is not None:
|
|
self.voucher_id = voucher_id
|
|
|
|
@hybrid_property
|
|
def amount(self) -> Decimal:
|
|
return self.quantity * self.rate * (1 + self.tax) * (1 - self.discount)
|
|
|
|
@amount.inplace.expression
|
|
@classmethod
|
|
def _amount_expression(cls) -> ColumnElement[Decimal]:
|
|
return type_coerce(
|
|
cls.quantity * cls.rate * (1 + cls.tax) * (1 - cls.discount), Numeric(precision=15, scale=2)
|
|
).label("amount")
|