Files
HartOMat/backend/app/domains/products/schemas.py
T
Hartmut 409fb92899 feat(P2): USD Foundation — canonical part identity + material overrides
M1 — USD exporter:
- render-worker/scripts/export_step_to_usd.py (631 lines)
  Full XCAF traversal, one UsdGeom.Mesh per leaf part,
  schaeffler:partKey on every prim, index-space sharpEdgeVertexPairs
- render-worker/Dockerfile: usd-core>=24.11 installed (USD 0.26.3)

M2 — usd_master MediaAsset + pipeline auto-chain:
- migrations 060 (usd_master enum), 061 (3 JSONB columns),
  062 (rename tessellation settings keys)
- generate_usd_master_task: runs export_step_to_usd.py, upserts
  usd_master MediaAsset, writes resolved_material_assignments to CadFile
- Auto-chained from generate_gltf_geometry_task after every GLB export
- step_tasks.py shim re-exports generate_usd_master_task

M3 — scene-manifest API:
- part_key_service.py: build_scene_manifest(), generate_part_key(),
  four-layer material priority resolution with provenance
- SceneManifest / PartEntry Pydantic models in products/schemas.py
- GET /api/cad/{id}/scene-manifest endpoint (graceful fallback to
  parsed_objects when USD not yet generated)
- POST /api/cad/{id}/generate-usd-master endpoint
- frontend/src/api/sceneManifest.ts: fetchSceneManifest(),
  triggerUsdMasterGeneration()

M4 — manual-material-overrides API:
- GET/PUT /api/cad/{id}/manual-material-overrides endpoints
- CadFile.manual_material_overrides JSONB column (migration 061)
- getManualOverrides() / saveManualOverrides() in cad.ts

M5 — ThreeDViewer partKey integration:
- export_step_to_gltf.py injects partKeyMap into GLB extras
- ThreeDViewer: partKeyMap extraction, resolvePartKey(), effectiveMaterials
  merges legacy partMaterials + new manualOverrides (server-side persistence)
- MaterialPanel: dual-path save (partKey vs legacy), provenance badge,
  reconciliation panel for unmatched/unassigned parts

Also:
- Admin.tsx: generate-missing-usd-masters + canonical scenes bulk actions
- ProductDetail.tsx: usd_master row in asset table
- vite-env.d.ts: fix ImportMeta.env TypeScript error
- GPUProbeResult: add timestamp/devices/render_time_s fields

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 13:11:09 +01:00

91 lines
2.5 KiB
Python

import uuid
from datetime import datetime
from typing import Literal
from pydantic import BaseModel
from app.domains.rendering.schemas import RenderPositionOut
class ProductCreate(BaseModel):
pim_id: str
name: str | None = None
category_key: str | None = None
ebene1: str | None = None
ebene2: str | None = None
baureihe: str | None = None
produkt_baureihe: str | None = None
lagertyp: str | None = None
name_cad_modell: str | None = None
gewuenschte_bildnummer: str | None = None
medias_rendering: bool | None = None
components: list[dict] = []
cad_part_materials: list[dict] = []
notes: str | None = None
is_active: bool = True
source_excel: str | None = None
class ProductPatch(BaseModel):
name: str | None = None
category_key: str | None = None
ebene1: str | None = None
ebene2: str | None = None
baureihe: str | None = None
produkt_baureihe: str | None = None
lagertyp: str | None = None
name_cad_modell: str | None = None
gewuenschte_bildnummer: str | None = None
medias_rendering: bool | None = None
components: list[dict] | None = None
cad_part_materials: list[dict] | None = None
notes: str | None = None
is_active: bool | None = None
class ProductOut(BaseModel):
id: uuid.UUID
pim_id: str
name: str | None
category_key: str | None
ebene1: str | None
ebene2: str | None
baureihe: str | None
produkt_baureihe: str | None
lagertyp: str | None
name_cad_modell: str | None
gewuenschte_bildnummer: str | None
medias_rendering: bool | None
components: list[dict]
cad_part_materials: list[dict]
cad_file_id: uuid.UUID | None
thumbnail_url: str | None = None
render_image_url: str | None = None
processing_status: str | None = None
cad_parsed_objects: list[str] | None = None
cad_mesh_attributes: dict | None = None
arbeitspaket: str | None = None
cad_render_log: dict | None = None
notes: str | None
is_active: bool
source_excel: str | None
render_positions: list[RenderPositionOut] = []
created_at: datetime
updated_at: datetime
model_config = {"from_attributes": True}
class PartEntry(BaseModel):
part_key: str
source_name: str
prim_path: str | None = None
effective_material: str | None
assignment_provenance: Literal["manual", "auto", "source", "default"]
is_unassigned: bool
class SceneManifest(BaseModel):
cad_file_id: str
parts: list[PartEntry]
unmatched_source_rows: list[str]
unassigned_parts: list[str]