Files
bakery-ia/services/tenant/app/models/tenants.py
2025-09-30 21:58:10 +02:00

121 lines
4.8 KiB
Python

# services/tenant/app/models/tenants.py - FIXED VERSION
"""
Tenant models for bakery management - FIXED
Removed cross-service User relationship to eliminate circular dependencies
"""
from sqlalchemy import Column, String, Boolean, DateTime, Float, ForeignKey, Text, Integer, JSON
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import relationship
from datetime import datetime, timezone
import uuid
from shared.database.base import Base
class Tenant(Base):
"""Tenant/Bakery model"""
__tablename__ = "tenants"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
name = Column(String(200), nullable=False)
subdomain = Column(String(100), unique=True)
business_type = Column(String(100), default="bakery")
business_model = Column(String(100), default="individual_bakery") # individual_bakery, central_baker_satellite, retail_bakery, hybrid_bakery
# Location info
address = Column(Text, nullable=False)
city = Column(String(100), default="Madrid")
postal_code = Column(String(10), nullable=False)
latitude = Column(Float)
longitude = Column(Float)
# Contact info
phone = Column(String(20))
email = Column(String(255))
# Status
is_active = Column(Boolean, default=True)
subscription_tier = Column(String(50), default="starter")
# ML status
ml_model_trained = Column(Boolean, default=False)
last_training_date = Column(DateTime(timezone=True))
# Ownership (user_id without FK - cross-service reference)
owner_id = Column(UUID(as_uuid=True), nullable=False, index=True)
# Timestamps
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
updated_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc))
# Relationships - only within tenant service
members = relationship("TenantMember", back_populates="tenant", cascade="all, delete-orphan")
# REMOVED: users relationship - no cross-service SQLAlchemy relationships
def __repr__(self):
return f"<Tenant(id={self.id}, name={self.name})>"
class TenantMember(Base):
"""Tenant membership model for team access"""
__tablename__ = "tenant_members"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
tenant_id = Column(UUID(as_uuid=True), ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False)
user_id = Column(UUID(as_uuid=True), nullable=False, index=True) # No FK - cross-service reference
# Role and permissions specific to this tenant
role = Column(String(50), default="member") # owner, admin, member, viewer
permissions = Column(Text) # JSON string of permissions
# Status
is_active = Column(Boolean, default=True)
invited_by = Column(UUID(as_uuid=True)) # No FK - cross-service reference
invited_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
joined_at = Column(DateTime(timezone=True))
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
# Relationships - only within tenant service
tenant = relationship("Tenant", back_populates="members")
# REMOVED: user relationship - no cross-service SQLAlchemy relationships
def __repr__(self):
return f"<TenantMember(tenant_id={self.tenant_id}, user_id={self.user_id}, role={self.role})>"
# Additional models for subscriptions, plans, etc.
class Subscription(Base):
"""Subscription model for tenant billing"""
__tablename__ = "subscriptions"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
tenant_id = Column(UUID(as_uuid=True), ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False)
plan = Column(String(50), default="starter") # starter, professional, enterprise
status = Column(String(50), default="active") # active, suspended, cancelled
# Billing
monthly_price = Column(Float, default=0.0)
billing_cycle = Column(String(20), default="monthly") # monthly, yearly
next_billing_date = Column(DateTime(timezone=True))
trial_ends_at = Column(DateTime(timezone=True))
# Limits
max_users = Column(Integer, default=5)
max_locations = Column(Integer, default=1)
max_products = Column(Integer, default=50)
# Features - Store plan features as JSON
features = Column(JSON)
# Timestamps
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
updated_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc))
# Relationships
tenant = relationship("Tenant")
def __repr__(self):
return f"<Subscription(tenant_id={self.tenant_id}, plan={self.plan}, status={self.status})>"