Files
bambuddy/backend/app/models/__init__.py
T
maziggy 71a06f3638 Add batch orders with a quantity per plate (#342)
Printing a multi-plate file in different quantities per plate meant
queueing each plate separately and tracking the counts by hand: one
shared Quantity field cannot say "plate 1 once, plate 2 twice, plate 3
three times". Each selected plate now carries its own quantity, and the
submission becomes an order on a new Batches tab.

The point is the distinction the old flat batch could not express.
print_batch_plates stores how many runs of each plate were wanted,
separately from what was queued, so a run that fails, is cancelled or is
skipped does not satisfy a target -- the order goes on saying it owes a
print instead of quietly under-delivering. Queue remaining re-queues
exactly what is missing, for the whole order or one plate, by cloning
the most recent item for that plate: that inherits the printer or model
target, AMS mapping, filament overrides and print options along with the
validation they already passed, rather than re-serialising twenty fields
through a template that would drift from the model the first time
someone adds a column. Clones append to the end of the relevant
printer's queue and take the same advisory lock the add-to-queue route
does; positions are per-printer sequences, not global.

Cost is measured, not estimated. print_log_entries gains queue_item_id,
set where the queue item is already in scope, so each run's material and
energy are attributed through the item that produced them -- an
unrelated reprint of the same archive never lands in an order's total,
and a multi-plate order gets each plate's own cost rather than the whole
file's via the plate-scoped estimate from #2614. Before any run has
completed there is no honest figure, so cost reads as unknown instead of
a fabricated 0.00.

The Batches tab wires up GET /queue/batches, which has been unreferenced
since the batch MVP shipped, along with six locale keys that were
translated and never used. It is a separate tab because an order
outlives the queue that produced it: once its runs finish they leave the
active queue, so Queue and History each hold half the picture.

completed was not a reachable status before now, so every batch created
since April is still marked active however long ago its last print
finished -- 73 of them on the development install. A startup pass closes
out the finished ones: those whose runs all completed become completed,
and groupings whose items were all cancelled become cancelled, which is
what they are. Not applied to orders, which state their intent
independently of their runs and still owe the work. Only batches with
nothing queued or printing are considered, and repeating the pass also
catches an order whose last run landed while the process was down.
Batches with neither items nor targets are no longer listed at all --
empty shells left when a grouping's items went with their source
archive.

Dispatch applies the same source-file gates as POST /queue/. It creates
queue items, so without them it would be a weaker door to the same
outcome; the archive and library-file checks move into shared helpers
so a third route cannot drift from them.
2026-08-04 11:11:36 +02:00

94 lines
3.5 KiB
Python

from backend.app.models.ams_history import AMSSensorHistory
from backend.app.models.ams_label import AmsLabel
from backend.app.models.api_key import APIKey
from backend.app.models.archive import PrintArchive
from backend.app.models.auth_ephemeral import AuthEphemeralToken, AuthRateLimitEvent
from backend.app.models.color_catalog import ColorCatalogEntry
from backend.app.models.filament import Filament
from backend.app.models.github_backup import GitHubBackupConfig, GitHubBackupLog
from backend.app.models.group import Group, user_groups
from backend.app.models.kprofile_note import KProfileNote
from backend.app.models.library import FileVariantGroup, LibraryFile, LibraryFolder
from backend.app.models.local_preset import LocalPreset
from backend.app.models.location import Location
from backend.app.models.long_lived_token import LongLivedToken
from backend.app.models.maintenance import MaintenanceHistory, MaintenanceType, PrinterMaintenance
from backend.app.models.notification import NotificationLog
from backend.app.models.notification_template import NotificationTemplate
from backend.app.models.oidc_provider import OIDCProvider, UserOIDCLink
from backend.app.models.orca_base_cache import OrcaBaseProfile
from backend.app.models.pending_upload import PendingUpload
from backend.app.models.pipeline_run import PipelineJob, PipelineRun
from backend.app.models.print_batch import PrintBatch, PrintBatchPlate
from backend.app.models.printer import Printer
from backend.app.models.printer_sensor_history import PrinterSensorHistory
from backend.app.models.project import Project
from backend.app.models.settings import Settings
from backend.app.models.slicer_pipeline import SlicerPipeline
from backend.app.models.smart_plug import SmartPlug
from backend.app.models.smart_plug_energy_snapshot import SmartPlugEnergySnapshot
from backend.app.models.sponsor_toast_state import SponsorToastState
from backend.app.models.spool import Spool
from backend.app.models.spool_assignment import SpoolAssignment
from backend.app.models.spool_catalog import SpoolCatalogEntry
from backend.app.models.spool_k_profile import SpoolKProfile
from backend.app.models.spool_usage_history import SpoolUsageHistory
from backend.app.models.spoolbuddy_device import SpoolBuddyDevice
from backend.app.models.user import User
from backend.app.models.user_email_pref import UserEmailPreference
from backend.app.models.user_otp_code import UserOTPCode
from backend.app.models.user_totp import UserTOTP
__all__ = [
"Printer",
"PrintArchive",
"Filament",
"Settings",
"SmartPlug",
"SmartPlugEnergySnapshot",
"MaintenanceType",
"PrinterMaintenance",
"MaintenanceHistory",
"KProfileNote",
"NotificationTemplate",
"NotificationLog",
"Project",
"APIKey",
"AMSSensorHistory",
"PrinterSensorHistory",
"AmsLabel",
"PendingUpload",
"PrintBatch",
"PrintBatchPlate",
"LibraryFolder",
"LibraryFile",
"FileVariantGroup",
"Location",
"User",
"Group",
"user_groups",
"GitHubBackupConfig",
"GitHubBackupLog",
"LocalPreset",
"OIDCProvider",
"UserOIDCLink",
"OrcaBaseProfile",
"PipelineJob",
"PipelineRun",
"SlicerPipeline",
"Spool",
"SpoolKProfile",
"SpoolAssignment",
"SpoolCatalogEntry",
"SpoolUsageHistory",
"ColorCatalogEntry",
"SpoolBuddyDevice",
"SponsorToastState",
"UserEmailPreference",
"UserOTPCode",
"UserTOTP",
"AuthEphemeralToken",
"AuthRateLimitEvent",
"LongLivedToken",
]