Wire nested nav pages for phases 5.1-5.11 to real list/create endpoints, fix COA import connectivity via same-origin proxy, and add operational migration. Co-authored-by: Cursor <cursoragent@cursor.com>
64 lines
2.9 KiB
Python
64 lines
2.9 KiB
Python
"""Phase ops — lightweight business documents for Sales/Purchase/Inventory UI."""
|
|
from __future__ import annotations
|
|
|
|
import uuid
|
|
from datetime import date
|
|
from decimal import Decimal
|
|
|
|
from sqlalchemy import Boolean, Date, Index, Numeric, String, Text, UniqueConstraint
|
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
|
|
from app.core.database import Base
|
|
from app.models.base import TenantMixin, TimestampMixin, UUIDPrimaryKeyMixin
|
|
from app.models.types import GUID
|
|
|
|
|
|
class BusinessDocument(Base, UUIDPrimaryKeyMixin, TenantMixin, TimestampMixin):
|
|
"""Generic operational document used by Sales / Purchase / Inventory screens."""
|
|
|
|
__tablename__ = "business_documents"
|
|
|
|
module: Mapped[str] = mapped_column(String(40), nullable=False)
|
|
doc_type: Mapped[str] = mapped_column(String(50), nullable=False)
|
|
number: Mapped[str] = mapped_column(String(50), nullable=False)
|
|
doc_date: Mapped[date] = mapped_column(Date, nullable=False)
|
|
party_name: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
|
party_id: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True)
|
|
amount: Mapped[Decimal] = mapped_column(Numeric(18, 4), default=Decimal("0"), nullable=False)
|
|
status: Mapped[str] = mapped_column(String(30), default="draft", nullable=False)
|
|
description: Mapped[str | None] = mapped_column(Text, nullable=True)
|
|
meta_json: Mapped[str | None] = mapped_column(Text, nullable=True)
|
|
|
|
__table_args__ = (
|
|
UniqueConstraint("tenant_id", "module", "number", name="uq_biz_doc_tenant_module_number"),
|
|
Index("ix_biz_doc_tenant_module_type", "tenant_id", "module", "doc_type"),
|
|
)
|
|
|
|
|
|
class InventoryItem(Base, UUIDPrimaryKeyMixin, TenantMixin, TimestampMixin):
|
|
__tablename__ = "inventory_items"
|
|
|
|
code: Mapped[str] = mapped_column(String(50), nullable=False)
|
|
name: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
item_type: Mapped[str] = mapped_column(String(30), default="goods", nullable=False)
|
|
unit: Mapped[str] = mapped_column(String(30), default="عدد", nullable=False)
|
|
quantity_on_hand: Mapped[Decimal] = mapped_column(Numeric(18, 4), default=Decimal("0"), nullable=False)
|
|
unit_cost: Mapped[Decimal] = mapped_column(Numeric(18, 4), default=Decimal("0"), nullable=False)
|
|
is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
|
|
|
|
__table_args__ = (
|
|
UniqueConstraint("tenant_id", "code", name="uq_inventory_item_tenant_code"),
|
|
)
|
|
|
|
|
|
class Warehouse(Base, UUIDPrimaryKeyMixin, TenantMixin, TimestampMixin):
|
|
__tablename__ = "warehouses"
|
|
|
|
code: Mapped[str] = mapped_column(String(50), nullable=False)
|
|
name: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
|
|
|
|
__table_args__ = (
|
|
UniqueConstraint("tenant_id", "code", name="uq_warehouse_tenant_code"),
|
|
)
|