TorbatYar/backend/services/delivery/app/models/pricing.py
Mortezakoohjani 72077908f1 feat(delivery): deploy backend phases 10.2-10.8 through settlement
Ship fleet, availability, pricing, dispatch, routing, tracking, and settlement on delivery-service 0.10.8.0 with migrations and phase tests green.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-27 21:01:23 +03:30

109 lines
3.6 KiB
Python

"""Pricing, capabilities & bundles — Phase 10.4."""
from __future__ import annotations
import uuid
from decimal import Decimal
from sqlalchemy import Index, Numeric, String, Text, UniqueConstraint
from sqlalchemy.orm import Mapped, mapped_column
from sqlalchemy.types import JSON
from app.core.database import Base
from app.models.base import (
ActorAuditMixin,
OptimisticLockMixin,
SoftDeleteMixin,
TenantMixin,
TimestampMixin,
UUIDPrimaryKeyMixin,
)
from app.models.types import (
CapabilityBundleStatus,
CapabilityStatus,
GUID,
PricingRuleStatus,
)
class PricingRule(
Base,
UUIDPrimaryKeyMixin,
TenantMixin,
TimestampMixin,
SoftDeleteMixin,
ActorAuditMixin,
OptimisticLockMixin,
):
__tablename__ = "pricing_rules"
organization_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
code: Mapped[str] = mapped_column(String(50), nullable=False)
name: Mapped[str] = mapped_column(String(255), nullable=False)
status: Mapped[PricingRuleStatus] = mapped_column(
default=PricingRuleStatus.DRAFT, nullable=False
)
base_amount: Mapped[Decimal] = mapped_column(Numeric(18, 4), nullable=False)
currency_code: Mapped[str] = mapped_column(String(3), nullable=False, default="IRR")
rule_config: Mapped[dict | None] = mapped_column(JSON, nullable=True)
metadata_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)
__table_args__ = (
UniqueConstraint("tenant_id", "code", name="uq_pricing_rules_tenant_code"),
Index("ix_pricing_rules_tenant_status", "tenant_id", "status"),
Index("ix_pricing_rules_tenant_deleted", "tenant_id", "is_deleted"),
)
class CapabilityDefinition(
Base,
UUIDPrimaryKeyMixin,
TenantMixin,
TimestampMixin,
SoftDeleteMixin,
ActorAuditMixin,
OptimisticLockMixin,
):
__tablename__ = "capability_definitions"
code: Mapped[str] = mapped_column(String(50), nullable=False)
name: Mapped[str] = mapped_column(String(255), nullable=False)
description: Mapped[str | None] = mapped_column(Text, nullable=True)
status: Mapped[CapabilityStatus] = mapped_column(
default=CapabilityStatus.ACTIVE, nullable=False
)
metadata_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)
__table_args__ = (
UniqueConstraint(
"tenant_id", "code", name="uq_capability_definitions_tenant_code"
),
Index("ix_capability_definitions_tenant_deleted", "tenant_id", "is_deleted"),
)
class CapabilityBundle(
Base,
UUIDPrimaryKeyMixin,
TenantMixin,
TimestampMixin,
SoftDeleteMixin,
ActorAuditMixin,
OptimisticLockMixin,
):
__tablename__ = "capability_bundles"
code: Mapped[str] = mapped_column(String(50), nullable=False)
name: Mapped[str] = mapped_column(String(255), nullable=False)
status: Mapped[CapabilityBundleStatus] = mapped_column(
default=CapabilityBundleStatus.DRAFT, nullable=False
)
capability_codes: Mapped[list | None] = mapped_column(JSON, nullable=True)
pricing_rule_id: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True)
metadata_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)
__table_args__ = (
UniqueConstraint("tenant_id", "code", name="uq_capability_bundles_tenant_code"),
Index("ix_capability_bundles_tenant_status", "tenant_id", "status"),
Index("ix_capability_bundles_tenant_deleted", "tenant_id", "is_deleted"),
)