Files
bambuddy/backend/app
maziggy dde724f83c Repair no-3MF archives' photos and their silent filament writes (#1820)
Two faults behind the same kind of print: one that arrives without a
    retrievable 3MF, which on an H2S is any job started from the printer's
    own internal library.

    Such an archive has no file_path, and Path("").parent is Path("."), so
    every site that derived the archive's folder from it landed on the data
    directory itself. The finish-photo capture spotted that and wrote to
    <archive_dir>/<id>/photos instead. Nothing else did. The photo was
    written in one place and looked for in another: reads 404'd, deletes
    dropped the name and left the file, and the notification attachment
    never found the image. Hand-uploaded photos worked only because upload
    and read agreed with each other rather than with the capture. Give the
    question one owner in utils/archive_paths and have all four sites ask
    it. Lookups check the old shared location too, so photos already
    uploaded there stay reachable; uploads now go where captures go.

    Separately, the remain%-delta fallback that stands in for a missing 3MF
    can charge nothing for several reasons, and did so without a word. The
    AMS reading is coarse and, on the reporter's printer, noisy: it rises
    mid-print, swings five points over a job, sits at 100% through a
    36-minute print on a fresh spool, and goes negative on a nearly empty
    one -- which the start-of-print gate rejects, dropping the only slot
    that was printing. Two of their prints went uncounted for two different
    reasons and both read as "no spools updated", which is also what a print
    with nothing to charge prints. Name the slot and the two readings in
    each case, on the Spoolman path and on the internal-inventory path,
    which has carried the same gates since #1119.

    The Spoolman path also had no notion of which slots the print used, so a
    spool swapped into an idle slot mid-print reads as consumption and is
    billed to whoever that slot is assigned to -- the fault #1269 fixed for
    the internal tracker, still open here, and likeliest on exactly the
    prints this fallback serves, where nothing else narrows the field. Use
    the same three pieces of evidence it does: the print's mapping, its
    mid-print tray changes, and the tray it started on. The last needs
    storing, because the internal tracker's row is deleted before this runs
    and a screen-started print has no mapping to fall back on -- hence a new
    nullable column, and no backfill, since a row from before it existed has
    nothing to say. Where no evidence exists at all, every slot is still
    considered.

    Both paths also treated tray_now == 255 as naming a slot. It does not:
    it is the field's initial value, the fallback for an unparseable
    reading, and what it reports with nothing loaded. Mapped as a tray id it
    becomes (255, 1), so as the only evidence it excluded every real slot
    and charged nothing at all -- this issue's own bug, arriving by a new
    route. On the internal path that is live today; on the Spoolman path it
    would have shipped with the guard above. The external holder reports 254
    when it is genuinely in use.

    The arithmetic is untouched: at one percent per step this cannot resolve
    a small print, and pretending otherwise would be worse than saying so.
2026-08-15 15:01:42 +02:00
..
…
…
2026-08-15 14:40:37 +02:00
…