feat: extract workflow material services phase 3

This commit is contained in:
2026-04-07 09:22:24 +02:00
parent e3cda1c9f7
commit 8f8d2e68b7
5 changed files with 324 additions and 99 deletions
@@ -16,7 +16,9 @@ from app.domains.orders.models import Order, OrderLine, OrderStatus
from app.domains.products.models import CadFile, Product
from app.domains.rendering.models import OutputType, RenderTemplate
from app.domains.rendering.workflow_runtime_services import (
auto_populate_materials_for_cad,
prepare_order_line_render_context,
resolve_order_line_material_map,
resolve_order_line_template_context,
)
@@ -216,3 +218,150 @@ def test_resolve_order_line_template_context_uses_exact_template_and_override(sy
"InnerRing": "HARTOMAT_OVERRIDE",
"OuterRing": "HARTOMAT_OVERRIDE",
}
def test_resolve_order_line_material_map_disables_materials_when_template_blocks_replacement(
sync_session,
tmp_path,
monkeypatch,
):
from app.config import settings
monkeypatch.setattr(settings, "upload_dir", str(tmp_path / "uploads"))
line = _seed_order_line_graph(sync_session, tmp_path)
template = RenderTemplate(
id=uuid.uuid4(),
name="Lighting Only",
category_key="bearings",
blend_file_path="/templates/lighting-only.blend",
original_filename="lighting-only.blend",
target_collection="Product",
material_replace_enabled=False,
lighting_only=True,
is_active=True,
)
result = resolve_order_line_material_map(
line,
line.product.cad_file,
line.product.cad_part_materials,
material_library="/libraries/materials.blend",
template=template,
)
assert result.use_materials is False
assert result.material_map is None
assert result.override_material is None
def test_resolve_order_line_material_map_prefers_line_override_over_output_override(
sync_session,
tmp_path,
monkeypatch,
):
from app.config import settings
monkeypatch.setattr(settings, "upload_dir", str(tmp_path / "uploads"))
line = _seed_order_line_graph(sync_session, tmp_path)
line.material_override = "LINE_OVERRIDE"
line.output_type.material_override = "OUTPUT_OVERRIDE"
sync_session.commit()
result = resolve_order_line_material_map(
line,
line.product.cad_file,
line.product.cad_part_materials,
material_library="/libraries/materials.blend",
template=None,
)
assert result.override_material == "LINE_OVERRIDE"
assert result.use_materials is True
assert result.material_map == {
"InnerRing": "LINE_OVERRIDE",
"OuterRing": "LINE_OVERRIDE",
}
def test_auto_populate_materials_for_cad_updates_only_blank_products_and_queues_once(sync_session, tmp_path):
line = _seed_order_line_graph(sync_session, tmp_path)
cad_file = line.product.cad_file
assert cad_file is not None
line.product.components = [
{"part_name": "InnerRing", "material": "Steel"},
{"part_name": "OuterRing", "material": "Rubber"},
]
line.product.cad_part_materials = []
second_product = Product(
id=uuid.uuid4(),
pim_id="P-2000",
name="Bearing B",
category_key="bearings",
cad_file_id=cad_file.id,
cad_file=cad_file,
components=[
{"part_name": "InnerRing", "material": "Brass"},
{"part_name": "OuterRing", "material": "Copper"},
],
cad_part_materials=[{"part_name": "InnerRing", "material": "Existing"}],
)
sync_session.add(second_product)
sync_session.commit()
queued: list[tuple[str, dict[str, str]]] = []
result = auto_populate_materials_for_cad(
sync_session,
str(cad_file.id),
enqueue_thumbnail=lambda current_cad_file_id, part_colors: queued.append(
(current_cad_file_id, part_colors)
),
)
sync_session.refresh(line.product)
sync_session.refresh(second_product)
assert result.updated_product_ids == [str(line.product.id)]
assert result.queued_thumbnail_regeneration is True
assert result.part_colors == {"InnerRing": "Steel", "OuterRing": "Rubber"}
assert queued == [(str(cad_file.id), {"InnerRing": "Steel", "OuterRing": "Rubber"})]
assert line.product.cad_part_materials == [
{"part_name": "InnerRing", "material": "Steel"},
{"part_name": "OuterRing", "material": "Rubber"},
]
assert second_product.cad_part_materials == [{"part_name": "InnerRing", "material": "Existing"}]
def test_auto_populate_materials_for_cad_skips_when_materials_already_present(sync_session, tmp_path):
line = _seed_order_line_graph(sync_session, tmp_path)
cad_file = line.product.cad_file
assert cad_file is not None
line.product.components = [
{"part_name": "InnerRing", "material": "Steel"},
{"part_name": "OuterRing", "material": "Rubber"},
]
sync_session.commit()
queued: list[tuple[str, dict[str, str]]] = []
result = auto_populate_materials_for_cad(
sync_session,
str(cad_file.id),
enqueue_thumbnail=lambda current_cad_file_id, part_colors: queued.append(
(current_cad_file_id, part_colors)
),
)
sync_session.refresh(line.product)
assert result.updated_product_ids == []
assert result.queued_thumbnail_regeneration is False
assert result.part_colors is None
assert queued == []
assert line.product.cad_part_materials == [
{"part_name": "InnerRing", "material": "Steel raw"},
{"part_name": "OuterRing", "material": "Steel raw"},
]