Initial commit — multi-tenant filtering, port constraints, chart bbox
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,52 @@
|
||||
"""
|
||||
Organization models: Port, Company, BuoyOwnership
|
||||
Used for multi-client access control and per-port default views.
|
||||
"""
|
||||
from sqlalchemy import Column, String, Float, Boolean, DateTime, Text
|
||||
from sqlalchemy.sql import func
|
||||
from database import Base
|
||||
|
||||
|
||||
class Port(Base):
|
||||
"""Geographic port / region served by this deployment."""
|
||||
__tablename__ = "ports"
|
||||
|
||||
id = Column(String, primary_key=True)
|
||||
name = Column(String, nullable=False)
|
||||
country = Column(String, default="Colombia")
|
||||
center_lat = Column(Float, nullable=True)
|
||||
center_lon = Column(Float, nullable=True)
|
||||
default_zoom = Column(Float, default=12.0)
|
||||
chart_name = Column(String, nullable=True) # folder under charts/, e.g. "BAHÍA_DE_CARTAGENA"
|
||||
activo = Column(Boolean, default=True)
|
||||
creado_en = Column(DateTime, server_default=func.now())
|
||||
|
||||
|
||||
class Company(Base):
|
||||
"""Buoy-owner company (client). Belongs to a home port."""
|
||||
__tablename__ = "companies"
|
||||
|
||||
id = Column(String, primary_key=True)
|
||||
name = Column(String, nullable=False)
|
||||
port_id = Column(String, nullable=True) # FK → ports.id
|
||||
contact_email = Column(String, nullable=True)
|
||||
contact_phone = Column(String, nullable=True)
|
||||
activa = Column(Boolean, default=True)
|
||||
notas = Column(Text, nullable=True)
|
||||
creado_en = Column(DateTime, server_default=func.now())
|
||||
|
||||
|
||||
class BuoyOwnership(Base):
|
||||
"""
|
||||
Which company owns (and monitors) a given Aid/MMSI.
|
||||
A company user can see AIS/ATON real-time data only for buoys
|
||||
listed in this table under their company_id.
|
||||
"""
|
||||
__tablename__ = "buoy_ownership"
|
||||
|
||||
id = Column(String, primary_key=True)
|
||||
company_id = Column(String, nullable=False) # FK → companies.id
|
||||
aid_id = Column(String, nullable=True) # FK → aids.id (nullable if aid not yet in DB)
|
||||
mmsi = Column(String, nullable=True) # direct MMSI reference
|
||||
notas = Column(Text, nullable=True)
|
||||
creado_en = Column(DateTime, server_default=func.now())
|
||||
@@ -4,9 +4,10 @@ from database import Base
|
||||
import enum
|
||||
|
||||
class Role(str, enum.Enum):
|
||||
SUPERADMIN = "SUPERADMIN"
|
||||
ADMIN = "ADMIN"
|
||||
USER = "USER"
|
||||
SUPERADMIN = "SUPERADMIN"
|
||||
ADMIN = "ADMIN"
|
||||
CLIENT_ADMIN = "CLIENT_ADMIN" # company-scoped: can start/stop recordings for own aids
|
||||
USER = "USER" # company-scoped: read-only
|
||||
|
||||
class User(Base):
|
||||
__tablename__ = "users"
|
||||
@@ -17,6 +18,7 @@ class User(Base):
|
||||
email = Column(String, unique=True, nullable=True)
|
||||
hashed_pw = Column(String, nullable=False)
|
||||
role = Column(String, default="USER")
|
||||
company_id = Column(String, nullable=True)
|
||||
activo = Column(Boolean, default=True)
|
||||
creado_en = Column(DateTime, server_default=func.now())
|
||||
ultimo_login = Column(DateTime, nullable=True)
|
||||
|
||||
@@ -2,6 +2,7 @@ from sqlalchemy import Column, String, Float, DateTime, Boolean, Integer
|
||||
from sqlalchemy.sql import func
|
||||
from database import Base
|
||||
|
||||
|
||||
class Vessel(Base):
|
||||
__tablename__ = "vessels"
|
||||
|
||||
@@ -44,5 +45,18 @@ class RecordingEvent(Base):
|
||||
inicio = Column(DateTime, nullable=False)
|
||||
fin = Column(DateTime, nullable=True)
|
||||
distancia_min_m = Column(Float, nullable=True)
|
||||
trigger = Column(String) # PROXIMIDAD | PROYECCION
|
||||
trigger = Column(String) # PROXIMIDAD | PROYECCION | MANUAL
|
||||
cerrado = Column(Boolean, default=False)
|
||||
|
||||
|
||||
class AtonTrack(Base):
|
||||
"""Continuous position history for AIS AtoN (Type 21) devices."""
|
||||
__tablename__ = "aton_tracks"
|
||||
|
||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||
mmsi = Column(String, nullable=False, index=True)
|
||||
timestamp = Column(DateTime, server_default=func.now(), index=True)
|
||||
lat = Column(Float, nullable=False)
|
||||
lon = Column(Float, nullable=False)
|
||||
voltage_v = Column(Float, nullable=True)
|
||||
off_position = Column(Boolean, nullable=True)
|
||||
|
||||
Reference in New Issue
Block a user