from sqlalchemy import Column, Integer, String, Float, Boolean, ForeignKey, DateTime, Text from sqlalchemy.orm import relationship from datetime import datetime from sqlalchemy import Index from database import Base # ========================= # USER # ========================= class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True, index=True) name = Column(String, nullable=True) phone = Column(String, unique=True, nullable=False) email = Column(String, unique=True) # 🔥 ADD THESE TWO NEW COLUMNS dob = Column(String, nullable=True) gender = Column(String, nullable=True) created_at = Column(DateTime, default=datetime.utcnow) frontend_ip = Column(String, nullable=True) backend_ip = Column(String, nullable=True) orders = relationship("Order", back_populates="user") # 🔥 NEW RELATION addresses = relationship("UserAddress", back_populates="user") class UserAddress(Base): __tablename__ = "user_addresses" id = Column(Integer, primary_key=True, index=True) user_id = Column(Integer, ForeignKey("users.id"), index=True) flat = Column(String) building = Column(String) landmark = Column(String) lat = Column(Float) lng = Column(Float) address_type = Column(String) # HOME / WORK / OTHER is_default = Column(Boolean, default=False) created_at = Column(DateTime, default=datetime.utcnow) frontend_ip = Column(String, nullable=True) backend_ip = Column(String, nullable=True) user = relationship("User", back_populates="addresses") # ========================= # VENDOR (Kitchen) # ========================= class Vendor(Base): __tablename__ = "vendors" id = Column(Integer, primary_key=True, index=True) name = Column(String, nullable=False) # 🔥 FULL ADDRESS (structured) flat = Column(String) building = Column(String) landmark = Column(String) location = Column(String) # full readable address lat = Column(Float, nullable=False) lng = Column(Float, nullable=False) radius = Column(Float, default=2) email = Column(String, unique=True) password = Column(String) is_active = Column(Boolean, default=True) is_open = Column(Boolean, default=False) created_at = Column(DateTime, default=datetime.utcnow) frontend_ip = Column(String, nullable=True) backend_ip = Column(String, nullable=True) city = Column(String) zone = Column(String) zonal_admin_id = Column(Integer, ForeignKey("admins.id")) menus = relationship("VendorMenu", back_populates="vendor") # ========================= # MENU ITEMS (Admin Controlled) # ========================= class MenuItem(Base): __tablename__ = "menu_items" id = Column(Integer, primary_key=True, index=True) name = Column(String, nullable=False) category = Column(String) description = Column(Text) # 🔥 NEW vendor_price = Column(Float, nullable=False) selling_price = Column(Float, nullable=False) image_url = Column(String, nullable=True) is_deleted = Column(Boolean, default=False) created_at = Column(DateTime, default=datetime.utcnow) vendors = relationship("VendorMenu", back_populates="menu_item") # ========================= # VENDOR MENU (Availability) # ========================= class VendorMenu(Base): __tablename__ = "vendor_menu" id = Column(Integer, primary_key=True, index=True) vendor_id = Column(Integer, ForeignKey("vendors.id"), index=True) menu_item_id = Column(Integer, ForeignKey("menu_items.id"), index=True) is_available = Column(Boolean, default=True) vendor = relationship("Vendor", back_populates="menus") menu_item = relationship("MenuItem", back_populates="vendors") # ========================= # ORDER # ========================= class Order(Base): __tablename__ = "orders" id = Column(Integer, primary_key=True, index=True) batch_id = Column(Integer, ForeignKey("batches.id"), nullable=True, index=True) zonal_admin_id = Column(Integer, ForeignKey("admins.id"), index=True) # ✅ ADD admin = relationship("Admin") user_id = Column(Integer, ForeignKey("users.id"), index=True) user_lat = Column(Float) user_lng = Column(Float) # 🔥 ORDER ADDRESS SNAPSHOT address_flat = Column(String, nullable=True) address_building = Column(String, nullable=True) address_landmark = Column(String, nullable=True) address_type = Column(String, nullable=True) address_lat = Column(Float, nullable=True) address_lng = Column(Float, nullable=True) total_amount = Column(Float, nullable=False) gst = Column(Float, nullable=False) final_amount = Column(Float, nullable=False) status = Column(String, default="PLACED", index=True) reject_reason = Column(String, nullable=True) # 🔥 ADD THIS payment_status = Column(String, default="PENDING") delivery = relationship("Delivery", back_populates="order", uselist=False) created_at = Column(DateTime, default=datetime.utcnow) frontend_ip = Column(String, nullable=True) backend_ip = Column(String, nullable=True) user = relationship("User", back_populates="orders") items = relationship("OrderItem", back_populates="order") batch = relationship("Batch", back_populates="orders") cancel_reason = Column(Text, nullable=True) cancelled_by = Column(String, nullable=True) cancelled_at = Column(DateTime, nullable=True) # ========================= # ORDER ITEMS (Snapshot) # ========================= class OrderItem(Base): __tablename__ = "order_items" id = Column(Integer, primary_key=True, index=True) order_id = Column(Integer, ForeignKey("orders.id"), index=True) menu_item_id = Column(Integer, ForeignKey("menu_items.id"), index=True) vendor_id = Column(Integer, index=True) quantity = Column(Integer, nullable=False) name = Column(String) vendor_price = Column(Float, nullable=False) selling_price = Column(Float, nullable=False) status = Column(String, default="PREPARING") order = relationship("Order", back_populates="items") # ✅ MUST BE INSIDE CLASS __table_args__ = ( Index("idx_order_vendor", "order_id", "vendor_id"), ) # ========================= # DELIVERY # ========================= class Delivery(Base): __tablename__ = "deliveries" id = Column(Integer, primary_key=True, index=True) order_id = Column(Integer, ForeignKey("orders.id"), index=True) delivery_boy_id = Column(Integer, ForeignKey("delivery_boys.id"), index=True) status = Column(String, default="ASSIGNED") # Payment handling payment_method = Column(String) # COD / QR payment_amount = Column(Float) # ✅ store actual paid amount payment_proof = Column(Text) # image URL / text note created_at = Column(DateTime, default=datetime.utcnow) frontend_ip = Column(String, nullable=True) backend_ip = Column(String, nullable=True) delivery_boy = relationship("DeliveryBoy") order = relationship("Order", back_populates="delivery") class Batch(Base): __tablename__ = "batches" id = Column(Integer, primary_key=True, index=True) zonal_admin_id = Column(Integer, ForeignKey("admins.id"), index=True) # ✅ ADD status = Column(String, default="CREATED", index=True) # CREATED / ASSIGNED / PICKED_UP / OUT_FOR_DELIVERY / DELIVERED # CREATED / ASSIGNED / PICKED / COMPLETED created_at = Column(DateTime, default=datetime.utcnow) delivery_boy_id = Column(Integer, ForeignKey("delivery_boys.id"), nullable=True) orders = relationship("Order", back_populates="batch") # ✅ FIX HERE delivery_boy = relationship( "DeliveryBoy", back_populates="batches", foreign_keys=[delivery_boy_id] ) # ========================= # ADMIN (City + Zonal) # ========================= class Admin(Base): __tablename__ = "admins" id = Column(Integer, primary_key=True, index=True) name = Column(String, nullable=False) email = Column(String, unique=True, nullable=False) password = Column(String, nullable=False) role = Column(String, nullable=False) # CITY_ADMIN / ZONAL_ADMIN city = Column(String, nullable=True) zone = Column(String, nullable=True) created_at = Column(DateTime, default=datetime.utcnow) frontend_ip = Column(String, nullable=True) backend_ip = Column(String, nullable=True) class DeliveryBoy(Base): __tablename__ = "delivery_boys" id = Column(Integer, primary_key=True, index=True) name = Column(String, nullable=False) email = Column(String, unique=True, nullable=False) phone = Column(String, nullable=False) password = Column(String, nullable=False) city = Column(String) zone = Column(String) zonal_admin_id = Column(Integer, ForeignKey("admins.id")) is_active = Column(Boolean, default=True) # 🔥 NEW: STATUS SYSTEM status = Column(String, default="OFFLINE", index=True) # OFFLINE / IDLE / ASSIGNED / PICKED_UP / OUT_FOR_DELIVERY # 🔥 NEW: ASSIGNMENT TRACKING (VERY IMPORTANT) current_batch_id = Column(Integer, nullable=True) current_order_id = Column(Integer, nullable=True) # 🔥 NEW: LIVE LOCATION (for admin tracking later) lat = Column(Float, nullable=True) lng = Column(Float, nullable=True) created_at = Column(DateTime, default=datetime.utcnow) frontend_ip = Column(String, nullable=True) backend_ip = Column(String, nullable=True) # ✅ ADD THIS (CRITICAL FIX) batches = relationship( "Batch", back_populates="delivery_boy", foreign_keys="Batch.delivery_boy_id" ) from sqlalchemy import Column, Integer, String, Text, DateTime, Boolean from datetime import datetime class NotificationToken(Base): __tablename__ = "notification_tokens" id = Column( Integer, primary_key=True, index=True ) user_id = Column( Integer, nullable=False, index=True ) role = Column( String, nullable=False ) token = Column( Text, unique=True, nullable=False ) # ✅ DEVICE INFO device_name = Column(String) platform = Column(String) browser = Column(String) # ✅ ACTIVE / LOGOUT SUPPORT is_active = Column( Boolean, default=True ) created_at = Column( DateTime, default=datetime.utcnow ) updated_at = Column( DateTime, default=datetime.utcnow, onupdate=datetime.utcnow ) # ========================= # REVIEWS # ========================= class Review(Base): __tablename__ = "reviews" id = Column(Integer, primary_key=True, index=True) user_id = Column(Integer, ForeignKey("users.id"), index=True) order_id = Column(Integer, ForeignKey("orders.id"), unique=True, index=True) # One review per order zonal_admin_id = Column(Integer, ForeignKey("admins.id"), index=True) rating = Column(Integer, nullable=False) # 1 to 5 stars comment = Column(Text, nullable=True) # Optional written review created_at = Column(DateTime, default=datetime.utcnow) # Relationships user = relationship("User") order = relationship("Order") zonal_admin = relationship("Admin") # ========================= # SUPPORT TICKETS # ========================= class SupportTicket(Base): __tablename__ = "support_tickets" id = Column(Integer, primary_key=True, index=True) user_id = Column(Integer, ForeignKey("users.id")) user_name = Column(String, nullable=False) mobile_number = Column(String, nullable=False) message = Column(Text, nullable=False) status = Column(String, default="OPEN") # OPEN / CLOSED / IN_PROGRESS created_at = Column(DateTime, default=datetime.utcnow) frontend_ip = Column(String, nullable=True) backend_ip = Column(String, nullable=True) user = relationship("User")