382a18fd02
Backend:
- Phase I: notification_configs router (GET/PUT/{event}/{channel}/POST reset)
war bereits in notifications.py — add-alias endpoint in uploads.py ergänzt
- OutputType schema: workflow_definition_id + workflow_name fields;
PATCH unterstützt Workflow-Zuweisung; _enrich_workflow_names() batch query
- Dispatch-Integration: orders.py dispatch_renders() → dispatch_render_with_workflow()
mit Legacy-Fallback; neues Logging
- uploads.py: POST /validations/{id}/add-alias für Material-Lücken
Pipeline:
- step_processor.py: extract_mesh_edge_data() via OCC — berechnet Dihedralwinkel
aller Kanten, liefert suggested_smooth_angle + sharp_edge_midpoints
Integriert in extract_cad_metadata() und process_cad_file()
- domains/rendering/tasks.py: apply_asset_library_materials_task (K3),
export_gltf_for_order_line_task → Blender export_gltf.py (K4),
export_blend_for_order_line_task → export_blend.py fix (K5)
- render-worker/scripts/still_render.py: _mark_sharp_and_seams() mit
OCC midpoint KD-tree matching + UV-Seam-Markierung
- render-worker/scripts/blender_render.py: identische Funktion + mesh_attributes parsing
Frontend:
- Layout.tsx: Upload-Link in Sidebar (alle User); Asset Libraries Link (admin/PM)
- App.tsx: /asset-libraries Route
- AssetLibrary.tsx: neue Seite (Upload, Catalog-Anzeige, Refresh, Toggle, Delete)
- OutputTypeTable.tsx: Workflow-Dropdown + Legacy/Workflow Badge
- ProductDetail.tsx: Geometry-Karte (Volumen, Surface, BBox, Sharp-Winkel)
- api/outputTypes.ts + api/products.ts: neue Felder
- api/imports.ts: ImportValidation API
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
143 lines
3.5 KiB
Python
143 lines
3.5 KiB
Python
import uuid
|
|
from datetime import datetime
|
|
from pydantic import BaseModel
|
|
|
|
|
|
class OutputTypeCreate(BaseModel):
|
|
name: str
|
|
description: str | None = None
|
|
renderer: str = "threejs"
|
|
render_settings: dict = {}
|
|
output_format: str = "png"
|
|
sort_order: int = 0
|
|
is_active: bool = True
|
|
compatible_categories: list[str] = []
|
|
render_backend: str = "auto"
|
|
is_animation: bool = False
|
|
transparent_bg: bool = False
|
|
pricing_tier_id: int | None = None
|
|
cycles_device: str | None = None
|
|
|
|
|
|
class OutputTypePatch(BaseModel):
|
|
name: str | None = None
|
|
description: str | None = None
|
|
renderer: str | None = None
|
|
render_settings: dict | None = None
|
|
output_format: str | None = None
|
|
sort_order: int | None = None
|
|
is_active: bool | None = None
|
|
compatible_categories: list[str] | None = None
|
|
render_backend: str | None = None
|
|
is_animation: bool | None = None
|
|
transparent_bg: bool | None = None
|
|
pricing_tier_id: int | None = None
|
|
cycles_device: str | None = None
|
|
workflow_definition_id: uuid.UUID | None = None
|
|
|
|
|
|
class OutputTypeOut(BaseModel):
|
|
id: uuid.UUID
|
|
name: str
|
|
description: str | None
|
|
renderer: str
|
|
render_settings: dict
|
|
output_format: str
|
|
sort_order: int
|
|
compatible_categories: list[str]
|
|
render_backend: str
|
|
is_animation: bool
|
|
transparent_bg: bool
|
|
cycles_device: str | None = None
|
|
pricing_tier_id: int | None = None
|
|
pricing_tier_name: str | None = None
|
|
price_per_item: float | None = None
|
|
workflow_definition_id: uuid.UUID | None = None
|
|
workflow_name: str | None = None
|
|
is_active: bool
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
|
|
model_config = {"from_attributes": True}
|
|
|
|
|
|
class RenderPositionCreate(BaseModel):
|
|
name: str
|
|
rotation_x: float = 0.0
|
|
rotation_y: float = 0.0
|
|
rotation_z: float = 0.0
|
|
is_default: bool = False
|
|
sort_order: int = 0
|
|
|
|
|
|
class RenderPositionPatch(BaseModel):
|
|
name: str | None = None
|
|
rotation_x: float | None = None
|
|
rotation_y: float | None = None
|
|
rotation_z: float | None = None
|
|
is_default: bool | None = None
|
|
sort_order: int | None = None
|
|
|
|
|
|
class RenderPositionOut(BaseModel):
|
|
id: uuid.UUID
|
|
product_id: uuid.UUID
|
|
name: str
|
|
rotation_x: float
|
|
rotation_y: float
|
|
rotation_z: float
|
|
is_default: bool
|
|
sort_order: int
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
|
|
model_config = {"from_attributes": True}
|
|
|
|
|
|
class WorkflowDefinitionCreate(BaseModel):
|
|
name: str
|
|
output_type_id: uuid.UUID | None = None
|
|
config: dict
|
|
is_active: bool = True
|
|
|
|
|
|
class WorkflowDefinitionUpdate(BaseModel):
|
|
name: str | None = None
|
|
config: dict | None = None
|
|
is_active: bool | None = None
|
|
|
|
|
|
class WorkflowDefinitionOut(BaseModel):
|
|
id: uuid.UUID
|
|
name: str
|
|
output_type_id: uuid.UUID | None
|
|
config: dict
|
|
is_active: bool
|
|
created_at: datetime
|
|
model_config = {"from_attributes": True}
|
|
|
|
|
|
class WorkflowNodeResultOut(BaseModel):
|
|
id: uuid.UUID
|
|
node_name: str
|
|
status: str
|
|
output: dict | None
|
|
log: str | None
|
|
duration_s: float | None
|
|
created_at: datetime
|
|
model_config = {"from_attributes": True}
|
|
|
|
|
|
class WorkflowRunOut(BaseModel):
|
|
id: uuid.UUID
|
|
workflow_def_id: uuid.UUID | None
|
|
order_line_id: uuid.UUID | None
|
|
celery_task_id: str | None
|
|
status: str
|
|
started_at: datetime | None
|
|
completed_at: datetime | None
|
|
error_message: str | None
|
|
created_at: datetime
|
|
node_results: list[WorkflowNodeResultOut] = []
|
|
model_config = {"from_attributes": True}
|