feat: per-order-line material override — override materials for individual renders
- Add `material_override` nullable column on OrderLine (DB migration)
- Line override takes priority over OutputType override
- PATCH /orders/{id}/lines/{id} endpoint to update material_override
- Inline dropdown on each order line in the OrderDetail page
- Amber background when override is active
- Same output type, different material per line — no need to create a new output type
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -96,6 +96,7 @@ def _build_line_out(line: OrderLine) -> OrderLineOut:
|
||||
render_log=line.render_log if hasattr(line, 'render_log') else None,
|
||||
render_started_at=line.render_started_at if hasattr(line, 'render_started_at') else None,
|
||||
render_completed_at=line.render_completed_at if hasattr(line, 'render_completed_at') else None,
|
||||
material_override=getattr(line, 'material_override', None),
|
||||
notes=line.notes,
|
||||
created_at=line.created_at,
|
||||
updated_at=line.updated_at,
|
||||
@@ -1096,6 +1097,42 @@ async def dispatch_single_line_render(
|
||||
return {"dispatched": True, "line_id": str(line.id)}
|
||||
|
||||
|
||||
class PatchLineBody(BaseModel):
|
||||
material_override: str | None = None
|
||||
|
||||
|
||||
@router.patch("/{order_id}/lines/{line_id}")
|
||||
async def patch_order_line(
|
||||
order_id: uuid.UUID,
|
||||
line_id: uuid.UUID,
|
||||
body: PatchLineBody,
|
||||
user: User = Depends(require_admin_or_pm),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
"""Update fields on an order line (admin/PM only)."""
|
||||
result = await db.execute(select(Order).where(Order.id == order_id))
|
||||
order = result.scalar_one_or_none()
|
||||
if not order:
|
||||
raise HTTPException(404, detail="Order not found")
|
||||
|
||||
line_result = await db.execute(
|
||||
select(OrderLine).where(OrderLine.id == line_id, OrderLine.order_id == order_id)
|
||||
)
|
||||
line = line_result.scalar_one_or_none()
|
||||
if not line:
|
||||
raise HTTPException(404, detail="Order line not found")
|
||||
|
||||
data = body.model_dump(exclude_unset=True)
|
||||
from sqlalchemy import update as sql_update
|
||||
if data:
|
||||
await db.execute(
|
||||
sql_update(OrderLine).where(OrderLine.id == line.id).values(**data)
|
||||
)
|
||||
await db.commit()
|
||||
|
||||
return {"updated": True, "line_id": str(line.id)}
|
||||
|
||||
|
||||
class RejectLineBody(BaseModel):
|
||||
reason: str = ""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user