From 732ff634fa0ee02070bd8fdf9df7021c3e993bed Mon Sep 17 00:00:00 2001 From: maziggy Date: Fri, 20 Feb 2026 08:26:23 +0100 Subject: [PATCH] fix: resolve printer model server-side for "Any Model" queue items (#435) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous fix passed target_model from the frontend, but this relied on printer.model being set on the client. When a printer was added without selecting a model (the field is optional), the frontend sent no target_model parameter, causing the OR logic to be bypassed entirely — the widget only queried printer_id=X and missed unassigned model-based items. The backend now looks up the printer's model from the database when target_model isn't provided by the client, ensuring "Clear Plate & Start Next" appears for model-based queue jobs regardless of how the printer was configured. --- CHANGELOG.md | 2 +- backend/app/api/routes/print_queue.py | 35 ++++++++++++++++++--------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 248ddb8e6..9423d8b9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to Bambuddy will be documented in this file. ## [0.2.1b2] - Unreleased ### Fixed -- **Queue Stuck on "Busy" for "Any Model" Jobs** ([#435](https://github.com/maziggy/bambuddy/issues/435)) — When a print was queued with "Any [Model]" (e.g., "Any P1S"), it was created with `printer_id=NULL` and `target_model="P1S"`. After the assigned printer finished, the queue widget queried only for items matching `printer_id=X`, missing the next pending model-based item (`printer_id IS NULL`). With no next item found, the "Clear Plate & Start Next" button never appeared, leaving the scheduler stuck reporting "Busy". The queue API now accepts an optional `target_model` parameter; when combined with `printer_id`, it uses OR logic to also return unassigned items whose `target_model` matches the printer's model. The frontend passes the printer's model through to this query. +- **Queue Stuck on "Busy" for "Any Model" Jobs** ([#435](https://github.com/maziggy/bambuddy/issues/435)) — When a print was queued with "Any [Model]" (e.g., "Any P1S"), it was created with `printer_id=NULL` and `target_model="P1S"`. After the assigned printer finished, the queue widget queried only for items matching `printer_id=X`, missing the next pending model-based item (`printer_id IS NULL`). With no next item found, the "Clear Plate & Start Next" button never appeared, leaving the scheduler stuck reporting "Busy". The queue API now accepts an optional `target_model` parameter; when combined with `printer_id`, it uses OR logic to also return unassigned items whose `target_model` matches the printer's model. The frontend passes the printer's model through to this query. Additionally, the backend now resolves the printer's model server-side from the database when the frontend doesn't provide `target_model` (e.g., when the printer was added without selecting a model), ensuring the OR logic works regardless of whether the client knows the printer's model. ### New Features - **Include Beta Updates Setting** — New toggle in Settings → Updates to opt in to beta/prerelease update notifications. Default: off (stable only). The update checker now fetches `/releases` instead of `/releases/latest` and filters by `parse_version()` prerelease detection (not GitHub's `prerelease` flag, which may not be set correctly). Users on the Docker `latest` tag will no longer see notifications for beta releases they can't install. diff --git a/backend/app/api/routes/print_queue.py b/backend/app/api/routes/print_queue.py index 37ec5fd34..636e58759 100644 --- a/backend/app/api/routes/print_queue.py +++ b/backend/app/api/routes/print_queue.py @@ -270,19 +270,30 @@ async def list_queue( if printer_id == -1: # Special value: filter for unassigned items query = query.where(PrintQueueItem.printer_id.is_(None)) - elif target_model: - # Include both printer-specific items AND model-based (unassigned) items - query = query.where( - or_( - PrintQueueItem.printer_id == printer_id, - and_( - PrintQueueItem.printer_id.is_(None), - func.lower(PrintQueueItem.target_model) == target_model.lower(), - ), - ) - ) else: - query = query.where(PrintQueueItem.printer_id == printer_id) + # Resolve effective model: prefer explicit param, fall back to printer's DB model. + # This ensures model-based "Any X" items are returned even when the frontend + # doesn't send target_model (e.g. printer.model is NULL on the client side). + effective_model = target_model + if not effective_model: + printer_row = ( + await db.execute(select(Printer.model).where(Printer.id == printer_id)) + ).scalar_one_or_none() + effective_model = printer_row + + if effective_model: + # Include both printer-specific items AND model-based (unassigned) items + query = query.where( + or_( + PrintQueueItem.printer_id == printer_id, + and_( + PrintQueueItem.printer_id.is_(None), + func.lower(PrintQueueItem.target_model) == effective_model.lower(), + ), + ) + ) + else: + query = query.where(PrintQueueItem.printer_id == printer_id) elif target_model: query = query.where(func.lower(PrintQueueItem.target_model) == target_model.lower()) if status: