424 lines
26 KiB
Python
424 lines
26 KiB
Python
from __future__ import annotations
|
|
|
|
import uuid
|
|
from datetime import datetime
|
|
|
|
from geoalchemy2 import Geometry
|
|
from sqlalchemy import CheckConstraint, DateTime, ForeignKey, Float, Index, JSON, String, Text, UniqueConstraint, func, text
|
|
from sqlalchemy.sql.sqltypes import Integer
|
|
from sqlalchemy.dialects.postgresql import UUID
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
from app.db.base import Base
|
|
|
|
|
|
class Project(Base):
|
|
__tablename__ = "projects"
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
name: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
description: Mapped[str | None] = mapped_column(Text, nullable=True)
|
|
region: Mapped[str] = mapped_column(String(120), default="Belgium and Belgian North Sea")
|
|
status: Mapped[str] = mapped_column(String(32), default="active")
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
|
|
|
|
areas: Mapped[list["Area"]] = relationship("Area", back_populates="project", cascade="all, delete-orphan")
|
|
datasets: Mapped[list["Dataset"]] = relationship("Dataset", back_populates="project", cascade="all, delete-orphan")
|
|
|
|
|
|
class Area(Base):
|
|
__tablename__ = "areas"
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
project_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("projects.id", ondelete="CASCADE"), nullable=False)
|
|
name: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
geometry: Mapped[str] = mapped_column(Geometry("MultiPolygon", srid=4326), nullable=False)
|
|
original_crs: Mapped[str | None] = mapped_column(String(64), nullable=True)
|
|
area_m2: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
bbox: Mapped[str | None] = mapped_column(Geometry("Polygon", srid=4326), nullable=True)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
|
|
project: Mapped[Project] = relationship("Project", back_populates="areas")
|
|
|
|
|
|
class Dataset(Base):
|
|
__tablename__ = "datasets"
|
|
__table_args__ = (
|
|
CheckConstraint(
|
|
"valid_to IS NULL OR valid_from IS NULL OR valid_to >= valid_from",
|
|
name="ck_datasets_temporal_valid_range",
|
|
),
|
|
Index(
|
|
"ix_datasets_project_temporal_series_observed",
|
|
"project_id",
|
|
"temporal_series_key",
|
|
"observed_at",
|
|
),
|
|
)
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
project_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("projects.id", ondelete="CASCADE"), nullable=False)
|
|
area_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("areas.id", ondelete="SET NULL"), nullable=True)
|
|
name: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
dataset_type: Mapped[str] = mapped_column(String(64), nullable=False)
|
|
source: Mapped[str] = mapped_column(String(120), nullable=False)
|
|
storage_path: Mapped[str | None] = mapped_column(String(500), nullable=True)
|
|
original_filename: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
|
stored_filename: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
|
content_type: Mapped[str | None] = mapped_column(String(120), nullable=True)
|
|
size_bytes: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
|
checksum_sha256: Mapped[str | None] = mapped_column(String(64), nullable=True)
|
|
derived_from_dataset_id: Mapped[uuid.UUID | None] = mapped_column(
|
|
UUID(as_uuid=True),
|
|
ForeignKey("datasets.id", ondelete="SET NULL"),
|
|
nullable=True,
|
|
)
|
|
crs: Mapped[str | None] = mapped_column(String(64), nullable=True)
|
|
bounds_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)
|
|
resolution_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)
|
|
bands_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)
|
|
metadata_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)
|
|
dataset_role: Mapped[str] = mapped_column(String(32), nullable=False, default="source", server_default="source")
|
|
source_name: Mapped[str | None] = mapped_column(String(120), nullable=True)
|
|
reference_layer_name: Mapped[str | None] = mapped_column(String(120), nullable=True)
|
|
source_metadata: Mapped[dict | None] = mapped_column(JSON, nullable=True)
|
|
provenance_metadata: Mapped[dict | None] = mapped_column(JSON, nullable=True)
|
|
imported_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
temporal_series_key: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
|
observed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
|
valid_from: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
|
valid_to: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
|
temporal_granularity: Mapped[str | None] = mapped_column(String(32), nullable=True)
|
|
source_version: Mapped[str | None] = mapped_column(String(120), nullable=True)
|
|
status: Mapped[str] = mapped_column(String(32), default="uploaded")
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
|
|
|
|
project: Mapped[Project] = relationship("Project", back_populates="datasets")
|
|
versions: Mapped[list["DatasetVersion"]] = relationship(
|
|
"DatasetVersion",
|
|
back_populates="dataset",
|
|
cascade="all, delete-orphan",
|
|
)
|
|
vector_features: Mapped[list["VectorFeature"]] = relationship(
|
|
"VectorFeature",
|
|
back_populates="dataset",
|
|
cascade="all, delete-orphan",
|
|
)
|
|
|
|
|
|
class DatasetVersion(Base):
|
|
__tablename__ = "dataset_versions"
|
|
__table_args__ = (
|
|
CheckConstraint(
|
|
"valid_to IS NULL OR valid_from IS NULL OR valid_to >= valid_from",
|
|
name="ck_dataset_versions_temporal_valid_range",
|
|
),
|
|
Index("ix_dataset_versions_dataset_version", "dataset_id", "version", unique=True),
|
|
)
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
dataset_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("datasets.id", ondelete="CASCADE"), nullable=False)
|
|
version: Mapped[int] = mapped_column(Integer, default=1)
|
|
storage_path: Mapped[str | None] = mapped_column(String(500), nullable=True)
|
|
source_version: Mapped[str | None] = mapped_column(String(120), nullable=True)
|
|
observed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
|
valid_from: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
|
valid_to: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
|
checksum_sha256: Mapped[str | None] = mapped_column(String(64), nullable=True)
|
|
source_metadata: Mapped[dict | None] = mapped_column(JSON, nullable=True)
|
|
provenance_metadata: Mapped[dict | None] = mapped_column(JSON, nullable=True)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
|
|
dataset: Mapped[Dataset] = relationship("Dataset", back_populates="versions")
|
|
|
|
|
|
class VectorFeature(Base):
|
|
__tablename__ = "vector_features"
|
|
__table_args__ = (
|
|
Index("ix_vector_features_dataset_id", "dataset_id"),
|
|
Index("ix_vector_features_geometry", "geometry", postgresql_using="gist"),
|
|
Index("ix_vector_features_dataset_source_feature", "dataset_id", "source_feature_id"),
|
|
Index(
|
|
"ix_vector_features_dataset_municipality",
|
|
"dataset_id",
|
|
text("(properties_json ->> 'municipality')"),
|
|
),
|
|
)
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
dataset_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("datasets.id", ondelete="CASCADE"), nullable=False)
|
|
feature_class: Mapped[str | None] = mapped_column(String(120), nullable=True)
|
|
source_feature_id: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
|
properties_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)
|
|
geometry: Mapped[str] = mapped_column(Geometry("Geometry", srid=4326, spatial_index=False), nullable=False)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
|
|
dataset: Mapped[Dataset] = relationship("Dataset", back_populates="vector_features")
|
|
|
|
|
|
class AnalysisRun(Base):
|
|
__tablename__ = "analysis_runs"
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
project_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("projects.id", ondelete="CASCADE"), nullable=False)
|
|
area_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("areas.id", ondelete="SET NULL"), nullable=True)
|
|
dataset_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("datasets.id", ondelete="SET NULL"), nullable=True)
|
|
job_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("jobs.id", ondelete="SET NULL"), nullable=True)
|
|
analysis_type: Mapped[str] = mapped_column(String(64), nullable=False)
|
|
status: Mapped[str] = mapped_column(String(32), nullable=False)
|
|
model_name: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
|
model_version: Mapped[str | None] = mapped_column(String(120), nullable=True)
|
|
parameters_json: Mapped[dict] = mapped_column(JSON, nullable=False)
|
|
result_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
started_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
|
finished_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
|
error_message: Mapped[str | None] = mapped_column(Text, nullable=True)
|
|
|
|
|
|
class Detection(Base):
|
|
__tablename__ = "detections"
|
|
__table_args__ = (
|
|
Index("ix_detections_project_id", "project_id"),
|
|
Index("ix_detections_dataset_id", "dataset_id"),
|
|
Index("ix_detections_analysis_run_id", "analysis_run_id"),
|
|
Index("ix_detections_class_name", "class_name"),
|
|
Index("ix_detections_geometry", "geometry", postgresql_using="gist"),
|
|
)
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
project_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("projects.id", ondelete="CASCADE"), nullable=False)
|
|
dataset_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("datasets.id", ondelete="SET NULL"), nullable=True)
|
|
analysis_run_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("analysis_runs.id", ondelete="SET NULL"), nullable=True)
|
|
job_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("jobs.id", ondelete="SET NULL"), nullable=True)
|
|
model_name: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
model_version: Mapped[str | None] = mapped_column(String(120), nullable=True)
|
|
class_name: Mapped[str] = mapped_column(String(120), nullable=False)
|
|
confidence: Mapped[float] = mapped_column(Float, nullable=False)
|
|
geometry: Mapped[str] = mapped_column(Geometry("Geometry", srid=4326, spatial_index=False), nullable=False)
|
|
bbox_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)
|
|
source_tile_path: Mapped[str | None] = mapped_column(String(500), nullable=True)
|
|
properties_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
|
|
|
|
class Segmentation(Base):
|
|
__tablename__ = "segmentations"
|
|
__table_args__ = (
|
|
Index("ix_segmentations_project_id", "project_id"),
|
|
Index("ix_segmentations_dataset_id", "dataset_id"),
|
|
Index("ix_segmentations_analysis_run_id", "analysis_run_id"),
|
|
Index("ix_segmentations_job_id", "job_id"),
|
|
Index("ix_segmentations_class_name", "class_name"),
|
|
Index("ix_segmentations_geometry", "geometry", postgresql_using="gist"),
|
|
)
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
project_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("projects.id", ondelete="CASCADE"), nullable=False)
|
|
dataset_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("datasets.id", ondelete="SET NULL"), nullable=True)
|
|
job_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("jobs.id", ondelete="SET NULL"), nullable=True)
|
|
analysis_run_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("analysis_runs.id", ondelete="SET NULL"), nullable=True)
|
|
model_name: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
model_version: Mapped[str | None] = mapped_column(String(120), nullable=True)
|
|
class_name: Mapped[str] = mapped_column(String(120), nullable=False)
|
|
confidence: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
geometry: Mapped[str] = mapped_column(Geometry("MultiPolygon", srid=4326, spatial_index=False), nullable=False)
|
|
bbox_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)
|
|
area_m2: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
mask_path: Mapped[str | None] = mapped_column(Text, nullable=True)
|
|
source_tile_path: Mapped[str | None] = mapped_column(String(500), nullable=True)
|
|
tile_index: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
|
properties_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)
|
|
provenance_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
|
|
|
|
class QualityCheck(Base):
|
|
__tablename__ = "quality_checks"
|
|
__table_args__ = (
|
|
Index("ix_quality_checks_project_id", "project_id"),
|
|
Index("ix_quality_checks_reference_dataset_id", "reference_dataset_id"),
|
|
Index("ix_quality_checks_candidate_dataset_id", "candidate_dataset_id"),
|
|
Index("ix_quality_checks_analysis_run_id", "analysis_run_id"),
|
|
)
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
project_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("projects.id", ondelete="CASCADE"), nullable=False)
|
|
job_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("jobs.id", ondelete="SET NULL"), nullable=True)
|
|
analysis_run_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("analysis_runs.id", ondelete="SET NULL"), nullable=True)
|
|
candidate_dataset_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("datasets.id", ondelete="SET NULL"), nullable=True)
|
|
reference_dataset_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("datasets.id", ondelete="CASCADE"), nullable=False)
|
|
check_type: Mapped[str] = mapped_column(String(120), nullable=False)
|
|
status: Mapped[str] = mapped_column(String(32), nullable=False)
|
|
score: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
parameters_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)
|
|
findings_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
completed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
|
|
|
|
|
class Metric(Base):
|
|
__tablename__ = "metrics"
|
|
__table_args__ = (
|
|
Index("ix_metrics_quality_check_id", "quality_check_id"),
|
|
Index("ix_metrics_analysis_run_id", "analysis_run_id"),
|
|
)
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
quality_check_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("quality_checks.id", ondelete="CASCADE"), nullable=True)
|
|
analysis_run_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("analysis_runs.id", ondelete="SET NULL"), nullable=True)
|
|
metric_key: Mapped[str] = mapped_column(String(120), nullable=False)
|
|
metric_value: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
metric_unit: Mapped[str | None] = mapped_column(String(64), nullable=True)
|
|
label: Mapped[str | None] = mapped_column(String(120), nullable=True)
|
|
metadata_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
|
|
|
|
class DetectionReview(Base):
|
|
__tablename__ = "detection_reviews"
|
|
__table_args__ = (
|
|
CheckConstraint(
|
|
"evidence_role IN ('false_positive', 'false_negative')",
|
|
name="ck_detection_reviews_evidence_role",
|
|
),
|
|
CheckConstraint(
|
|
"decision IN ('confirmed_model_false_positive', 'confirmed_model_false_negative', "
|
|
"'reference_gap_or_change', 'qa_alignment_mismatch', "
|
|
"'imagery_obscured_or_uncertain', 'uncertain', 'unreviewed')",
|
|
name="ck_detection_reviews_decision",
|
|
),
|
|
UniqueConstraint(
|
|
"quality_check_id",
|
|
"evidence_role",
|
|
"evidence_feature_id",
|
|
name="uq_detection_reviews_evidence",
|
|
),
|
|
Index("ix_detection_reviews_project_id", "project_id"),
|
|
Index("ix_detection_reviews_quality_check_id", "quality_check_id"),
|
|
Index("ix_detection_reviews_analysis_run_id", "analysis_run_id"),
|
|
Index("ix_detection_reviews_decision", "decision"),
|
|
)
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
project_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("projects.id", ondelete="CASCADE"), nullable=False)
|
|
quality_check_id: Mapped[uuid.UUID] = mapped_column(
|
|
UUID(as_uuid=True),
|
|
ForeignKey("quality_checks.id", ondelete="CASCADE"),
|
|
nullable=False,
|
|
)
|
|
analysis_run_id: Mapped[uuid.UUID | None] = mapped_column(
|
|
UUID(as_uuid=True),
|
|
ForeignKey("analysis_runs.id", ondelete="SET NULL"),
|
|
nullable=True,
|
|
)
|
|
evidence_role: Mapped[str] = mapped_column(String(32), nullable=False)
|
|
evidence_feature_id: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
detection_id: Mapped[uuid.UUID | None] = mapped_column(
|
|
UUID(as_uuid=True),
|
|
ForeignKey("detections.id", ondelete="SET NULL"),
|
|
nullable=True,
|
|
)
|
|
reference_feature_id: Mapped[uuid.UUID | None] = mapped_column(
|
|
UUID(as_uuid=True),
|
|
ForeignKey("vector_features.id", ondelete="SET NULL"),
|
|
nullable=True,
|
|
)
|
|
decision: Mapped[str] = mapped_column(String(64), nullable=False, default="unreviewed", server_default="unreviewed")
|
|
notes: Mapped[str | None] = mapped_column(Text, nullable=True)
|
|
reviewed_by: Mapped[str] = mapped_column(String(120), nullable=False, default="operator", server_default="operator")
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
|
|
|
|
|
|
class Export(Base):
|
|
__tablename__ = "exports"
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
project_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("projects.id", ondelete="CASCADE"), nullable=False)
|
|
analysis_run_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("analysis_runs.id", ondelete="SET NULL"), nullable=True)
|
|
export_type: Mapped[str] = mapped_column(String(64), nullable=False)
|
|
storage_path: Mapped[str] = mapped_column(String(500), nullable=False)
|
|
metadata_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
|
|
|
|
class Job(Base):
|
|
__tablename__ = "jobs"
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
job_type: Mapped[str] = mapped_column(String(128), nullable=False)
|
|
status: Mapped[str] = mapped_column(String(32), nullable=False, default="queued")
|
|
project_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("projects.id", ondelete="CASCADE"), nullable=False)
|
|
dataset_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("datasets.id", ondelete="SET NULL"), nullable=True)
|
|
input_dataset_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("datasets.id", ondelete="SET NULL"), nullable=True)
|
|
output_dataset_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("datasets.id", ondelete="SET NULL"), nullable=True)
|
|
parameters_json: Mapped[dict] = mapped_column(JSON, nullable=False, default=dict)
|
|
result_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)
|
|
error_message: Mapped[str | None] = mapped_column(Text, nullable=True)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
started_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
|
finished_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
|
|
|
|
|
class AoiOperation(Base):
|
|
__tablename__ = "aoi_operations"
|
|
__table_args__ = (
|
|
CheckConstraint(
|
|
"status IN ('queued', 'running', 'partial', 'success', 'failed', 'cancelled')",
|
|
name="ck_aoi_operations_status",
|
|
),
|
|
Index("ix_aoi_operations_project_status", "project_id", "status"),
|
|
Index("ix_aoi_operations_geometry", "geometry", postgresql_using="gist"),
|
|
)
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
project_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("projects.id", ondelete="CASCADE"), nullable=False)
|
|
area_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("areas.id", ondelete="SET NULL"), nullable=True)
|
|
parent_job_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("jobs.id", ondelete="SET NULL"), nullable=True)
|
|
operation_type: Mapped[str] = mapped_column(String(128), nullable=False)
|
|
status: Mapped[str] = mapped_column(String(32), nullable=False, default="queued")
|
|
geometry: Mapped[str] = mapped_column(Geometry("MultiPolygon", srid=4326, spatial_index=False), nullable=False)
|
|
request_json: Mapped[dict] = mapped_column(JSON, nullable=False, default=dict)
|
|
plan_json: Mapped[dict] = mapped_column(JSON, nullable=False, default=dict)
|
|
result_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)
|
|
error_message: Mapped[str | None] = mapped_column(Text, nullable=True)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
started_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
|
finished_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
|
updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
|
|
|
|
|
|
class AoiOperationPartition(Base):
|
|
__tablename__ = "aoi_operation_partitions"
|
|
__table_args__ = (
|
|
CheckConstraint(
|
|
"status IN ('queued', 'running', 'success', 'failed', 'skipped')",
|
|
name="ck_aoi_operation_partitions_status",
|
|
),
|
|
UniqueConstraint("operation_id", "partition_key", name="uq_aoi_operation_partition_key"),
|
|
Index("ix_aoi_operation_partitions_operation_status", "operation_id", "status"),
|
|
Index("ix_aoi_operation_partitions_geometry", "geometry", postgresql_using="gist"),
|
|
)
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
operation_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("aoi_operations.id", ondelete="CASCADE"), nullable=False)
|
|
child_job_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("jobs.id", ondelete="SET NULL"), nullable=True)
|
|
partition_key: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
provider_key: Mapped[str] = mapped_column(String(120), nullable=False)
|
|
product_key: Mapped[str] = mapped_column(String(120), nullable=False)
|
|
ordinal: Mapped[int] = mapped_column(Integer, nullable=False)
|
|
status: Mapped[str] = mapped_column(String(32), nullable=False, default="queued")
|
|
geometry: Mapped[str] = mapped_column(Geometry("MultiPolygon", srid=4326, spatial_index=False), nullable=False)
|
|
attempt_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
|
|
max_attempts: Mapped[int] = mapped_column(Integer, nullable=False, default=3)
|
|
checkpoint_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)
|
|
result_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)
|
|
error_message: Mapped[str | None] = mapped_column(Text, nullable=True)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
started_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
|
finished_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
|
updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
|