Phase 1: FastAPI backend with async job model
- backend/app: FastAPI API wrapping the CAD skill modules - upload -> job -> poll -> model / BOM / artifacts -> geometry query - SQLite via SQLModel (Model, Job, BomRow, QueryLog) - ThreadPoolExecutor worker, serialized, with live stage updates - docker-compose.yml: dev server (mounts source, --reload) on :8000 - api-test.sh: end-to-end live validation script - requirements.txt: add fastapi, uvicorn, python-multipart, sqlmodel - external_diagram.py: port active-area detection OCC.Core -> OCP - .gitignore, PHASE1.md Validated live: MR16 round-trip passes (28 BOM rows, 12 artifacts, bounding-box query, xlsx download; active-area detection working). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
"""SQLModel tables: Model, Job, BomRow, QueryLog."""
|
||||
from datetime import datetime, timezone
|
||||
from typing import Optional
|
||||
|
||||
from sqlmodel import Field, SQLModel
|
||||
|
||||
|
||||
def utcnow() -> datetime:
|
||||
return datetime.now(timezone.utc)
|
||||
|
||||
|
||||
class Model(SQLModel, table=True):
|
||||
"""One uploaded STEP file and its extracted metadata."""
|
||||
id: Optional[int] = Field(default=None, primary_key=True)
|
||||
name: str
|
||||
original_filename: str
|
||||
stem: str
|
||||
backend: Optional[str] = None # "build123d" | "freecad"
|
||||
face_count: Optional[int] = None
|
||||
part_count: Optional[int] = None
|
||||
bbox_x_mm: Optional[float] = None
|
||||
bbox_y_mm: Optional[float] = None
|
||||
bbox_z_mm: Optional[float] = None
|
||||
has_chinese: bool = False
|
||||
created_at: datetime = Field(default_factory=utcnow)
|
||||
|
||||
|
||||
class Job(SQLModel, table=True):
|
||||
"""A processing run for a model. Status: pending|running|done|error."""
|
||||
id: Optional[int] = Field(default=None, primary_key=True)
|
||||
model_id: int = Field(foreign_key="model.id", index=True)
|
||||
status: str = Field(default="pending", index=True)
|
||||
stage: Optional[str] = None # current pipeline stage
|
||||
error: Optional[str] = None
|
||||
artifacts: Optional[str] = None # JSON list of relative filenames
|
||||
options: Optional[str] = None # JSON of the request options
|
||||
created_at: datetime = Field(default_factory=utcnow)
|
||||
started_at: Optional[datetime] = None
|
||||
finished_at: Optional[datetime] = None
|
||||
|
||||
|
||||
class BomRow(SQLModel, table=True):
|
||||
"""One BOM line for a model."""
|
||||
id: Optional[int] = Field(default=None, primary_key=True)
|
||||
model_id: int = Field(foreign_key="model.id", index=True)
|
||||
part_number: Optional[str] = None
|
||||
part_name_original: Optional[str] = None
|
||||
part_name_english: Optional[str] = None
|
||||
quantity: Optional[int] = None
|
||||
level: Optional[int] = None
|
||||
parent: Optional[str] = None
|
||||
bbox_x_mm: Optional[float] = None
|
||||
bbox_y_mm: Optional[float] = None
|
||||
bbox_z_mm: Optional[float] = None
|
||||
notes: Optional[str] = None
|
||||
|
||||
|
||||
class QueryLog(SQLModel, table=True):
|
||||
"""A natural-language geometry query and its result."""
|
||||
id: Optional[int] = Field(default=None, primary_key=True)
|
||||
model_id: int = Field(foreign_key="model.id", index=True)
|
||||
query: str
|
||||
result: Optional[str] = None
|
||||
created_at: datetime = Field(default_factory=utcnow)
|
||||
Reference in New Issue
Block a user