5119ca775b
Backend: - Add GET /classifications/results endpoint with project/level/keyword filters - Add column relationship to ClassificationResult model - Fix test data generator to fetch column IDs from DB after bulk insert Frontend: - Fix request.ts interceptor to return full response body (keep total/pagination) - Fix all pages to use res.data instead of res - Add getClassificationResults API in classification.ts - Implement fetchData in Classification.vue with proper filtering and pagination - Fix same res.data issue in Category.vue, Metadata.vue, Project.vue, DataSource.vue, Dashboard.vue, Task.vue
116 lines
4.7 KiB
Python
116 lines
4.7 KiB
Python
from datetime import datetime
|
|
from sqlalchemy import Column, Integer, String, Text, ForeignKey, DateTime, Float, Enum as SAEnum
|
|
from sqlalchemy.orm import relationship
|
|
import enum
|
|
|
|
from app.core.database import Base
|
|
|
|
|
|
class ProjectStatus(str, enum.Enum):
|
|
CREATED = "created"
|
|
SCANNING = "scanning"
|
|
ASSIGNING = "assigning"
|
|
LABELING = "labeling"
|
|
REVIEWING = "reviewing"
|
|
ACCEPTING = "accepting"
|
|
PUBLISHED = "published"
|
|
|
|
|
|
class TaskStatus(str, enum.Enum):
|
|
PENDING = "pending"
|
|
IN_PROGRESS = "in_progress"
|
|
COMPLETED = "completed"
|
|
REJECTED = "rejected"
|
|
|
|
|
|
class ResultStatus(str, enum.Enum):
|
|
AUTO = "auto"
|
|
MANUAL = "manual"
|
|
REVIEWED = "reviewed"
|
|
PUBLISHED = "published"
|
|
CONFLICT = "conflict"
|
|
|
|
|
|
class ClassificationProject(Base):
|
|
__tablename__ = "classification_project"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
name = Column(String(200), nullable=False)
|
|
template_id = Column(Integer, ForeignKey("classification_template.id"))
|
|
description = Column(Text)
|
|
status = Column(String(20), default=ProjectStatus.CREATED.value)
|
|
target_source_ids = Column(Text) # comma separated source ids
|
|
target_database_ids = Column(Text)
|
|
target_table_ids = Column(Text)
|
|
planned_start = Column(DateTime)
|
|
planned_end = Column(DateTime)
|
|
created_by = Column(Integer, ForeignKey("sys_user.id"), nullable=False)
|
|
created_at = Column(DateTime, default=datetime.utcnow)
|
|
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
|
|
|
tasks = relationship("ClassificationTask", back_populates="project", cascade="all, delete-orphan")
|
|
results = relationship("ClassificationResult", back_populates="project", cascade="all, delete-orphan")
|
|
|
|
|
|
class ClassificationTask(Base):
|
|
__tablename__ = "classification_task"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
project_id = Column(Integer, ForeignKey("classification_project.id"), nullable=False)
|
|
name = Column(String(200))
|
|
assigner_id = Column(Integer, ForeignKey("sys_user.id"))
|
|
assignee_id = Column(Integer, ForeignKey("sys_user.id"))
|
|
target_type = Column(String(20), default="table") # table, column, file
|
|
target_ids = Column(Text) # comma separated ids
|
|
status = Column(String(20), default=TaskStatus.PENDING.value)
|
|
deadline = Column(DateTime)
|
|
completed_at = Column(DateTime)
|
|
created_at = Column(DateTime, default=datetime.utcnow)
|
|
|
|
project = relationship("ClassificationProject", back_populates="tasks")
|
|
assigner = relationship("User", foreign_keys=[assigner_id])
|
|
assignee = relationship("User", foreign_keys=[assignee_id])
|
|
|
|
|
|
class ClassificationResult(Base):
|
|
__tablename__ = "classification_result"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
project_id = Column(Integer, ForeignKey("classification_project.id"), nullable=False)
|
|
column_id = Column(Integer, ForeignKey("meta_column.id"), nullable=True)
|
|
file_id = Column(Integer, ForeignKey("unstructured_file.id"), nullable=True)
|
|
category_id = Column(Integer, ForeignKey("category.id"))
|
|
level_id = Column(Integer, ForeignKey("data_level.id"))
|
|
source = Column(String(20), default="auto") # auto, manual, ml
|
|
confidence = Column(Float, default=0.0) # 0-1
|
|
labeler_id = Column(Integer, ForeignKey("sys_user.id"))
|
|
reviewer_id = Column(Integer, ForeignKey("sys_user.id"))
|
|
status = Column(String(20), default=ResultStatus.AUTO.value)
|
|
label_time = Column(DateTime)
|
|
review_time = Column(DateTime)
|
|
created_at = Column(DateTime, default=datetime.utcnow)
|
|
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
|
|
|
project = relationship("ClassificationProject", back_populates="results")
|
|
column = relationship("DataColumn")
|
|
category = relationship("Category")
|
|
level = relationship("DataLevel")
|
|
|
|
|
|
class ClassificationChange(Base):
|
|
__tablename__ = "classification_change"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
result_id = Column(Integer, ForeignKey("classification_result.id"), nullable=False)
|
|
change_type = Column(String(20), nullable=False) # category, level, both
|
|
old_category_id = Column(Integer, ForeignKey("category.id"))
|
|
new_category_id = Column(Integer, ForeignKey("category.id"))
|
|
old_level_id = Column(Integer, ForeignKey("data_level.id"))
|
|
new_level_id = Column(Integer, ForeignKey("data_level.id"))
|
|
reason = Column(Text)
|
|
applicant_id = Column(Integer, ForeignKey("sys_user.id"))
|
|
approver_id = Column(Integer, ForeignKey("sys_user.id"))
|
|
approval_status = Column(String(20), default="pending") # pending, approved, rejected
|
|
approval_comment = Column(Text)
|
|
created_at = Column(DateTime, default=datetime.utcnow)
|