Files
HartOMat/backend/app/services/order_status_service.py
T
2026-03-05 22:12:38 +01:00

87 lines
2.8 KiB
Python

"""Service to auto-advance order status when all renders complete."""
import logging
from datetime import datetime
from sqlalchemy import create_engine, select, update as sql_update
from sqlalchemy.orm import Session
from app.models.order import Order, OrderStatus
from app.models.order_line import OrderLine
logger = logging.getLogger(__name__)
def check_order_completion(order_id: str) -> bool:
"""If all renderable lines are done, auto-advance order to completed.
Called from Celery tasks (sync context).
Returns True if the order was advanced to completed.
"""
from app.config import settings as app_settings
sync_url = app_settings.database_url.replace("+asyncpg", "")
engine = create_engine(sync_url)
try:
with Session(engine) as session:
# Get all lines that have an output type (i.e. renderable)
lines = session.execute(
select(OrderLine).where(
OrderLine.order_id == order_id,
OrderLine.output_type_id.isnot(None),
)
).scalars().all()
if not lines:
return False
# Check if all renderable lines are in a terminal state
all_terminal = all(
line.render_status in ("completed", "failed", "cancelled")
for line in lines
)
if not all_terminal:
return False
# Check order is still in processing state
order = session.execute(
select(Order).where(Order.id == order_id)
).scalar_one_or_none()
if order is None or order.status != OrderStatus.processing:
return False
# Auto-advance to completed
now = datetime.utcnow()
session.execute(
sql_update(Order)
.where(Order.id == order_id)
.values(
status=OrderStatus.completed,
completed_at=now,
updated_at=now,
)
)
session.commit()
logger.info(f"Order {order_id} auto-advanced to completed (all {len(lines)} lines done)")
# Notify order creator
try:
from app.services.notification_service import emit_notification_sync
emit_notification_sync(
actor_user_id=None,
target_user_id=str(order.created_by),
action="order.completed",
entity_type="order",
entity_id=str(order_id),
details={"order_number": order.order_number},
)
except Exception:
logger.exception("Failed to emit order.completed notification")
return True
finally:
engine.dispose()