mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-05-09 05:35:30 +02:00
[PR #1063] [MERGED] feat(inventory): unified Spoolman inventory UI + Storage Location + AMS deep-link + SpoolBuddy NFC write support #1152
Labels
No labels
A1
automated
automated
bug
bug
Closed due to inactivity
contrib
dependencies
dependencies
duplicate
enhancement
feedback
hold
invalid
Notes
P1S
pull-request
security
security
ThumbsUp
user-report
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/bambuddy#1152
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/maziggy/bambuddy/pull/1063
Author: @netscout2001
Created: 4/21/2026
Status: ✅ Merged
Merged: 4/24/2026
Merged by: @maziggy
Base:
dev← Head:feature/spoolman-inventory-ui📝 Commits (10+)
afbb1f9feat(inventory): replace Spoolman iframe with internal inventory UI87875besecurity: harden Spoolman inventory proxy endpoints2d59d78security: harden Spoolman inventory helpers and input validationf2fb707feat(inventory): add editable Storage Location field to spoolsc30384ffeat(inventory): deep-link from AMS slot hover card to internal inventoryea55790perf(inventory): fetch deep-link spool by ID instead of waiting for full list479506cfix(inventory): prevent wrong-endpoint 404 and avoid redundant API call on deep-link301caf4fix(inventory): hide usage history widget in Spoolman mode3144887fix(security): guard Infinity/NaN price and invalid deep-link spool IDsdae3f78feat(spoolbuddy): Spoolman-aware NFC tag lookup and weight sync📊 Changes
47 files changed (+7248 additions, -343 deletions)
View changed files
📝
CHANGELOG.md(+15 -2)➕
backend/app/api/routes/_spoolman_helpers.py(+222 -0)📝
backend/app/api/routes/spoolbuddy.py(+372 -75)➕
backend/app/api/routes/spoolman_inventory.py(+531 -0)📝
backend/app/core/auth.py(+44 -2)📝
backend/app/core/database.py(+10 -0)📝
backend/app/main.py(+2 -0)📝
backend/app/models/spool.py(+3 -1)📝
backend/app/models/spoolbuddy_device.py(+1 -0)📝
backend/app/schemas/spool.py(+5 -3)📝
backend/app/schemas/spoolbuddy.py(+47 -31)📝
backend/app/services/opentag3d.py(+65 -23)📝
backend/app/services/spoolbuddy_ssh.py(+88 -22)📝
backend/app/services/spoolman.py(+321 -5)📝
backend/app/services/spoolman_tracking.py(+10 -2)➕
backend/tests/integration/test_auth_apikey_rbac.py(+160 -0)📝
backend/tests/integration/test_spoolbuddy.py(+1099 -2)➕
backend/tests/integration/test_spoolman_inventory_api.py(+1524 -0)📝
backend/tests/unit/services/test_spoolman_service.py(+48 -1)📝
backend/tests/unit/services/test_spoolman_tracking.py(+7 -3)...and 27 more files
📄 Description
Description
This PR integrates Spoolman more deeply into Bambuddy so users never have to leave the app to manage their filament, regardless of which inventory backend is active.
Unified Inventory UI for Spoolman mode
When Spoolman is enabled, the Bambuddy inventory page proxies all spool data through a new backend API (/spoolman/inventory/*). Create, edit, archive, delete and bulk-create spools — all from the same table/card UI as the internal inventory. The frontend is fully inventory-backend-agnostic.
Storage Location field
A new "Storage Location" text field on every spool (e.g. "Shelf A, Box 3"). In internal inventory mode it is stored locally. In Spoolman mode it maps bidirectionally to Spoolman's native location field — reads on load, writes back on save, and can be explicitly cleared.
"Open in Inventory" deep-link from AMS slot hover card
The hover card shown when hovering over an AMS slot now contains an "Open in Inventory" button (for both Spoolman-linked and internally-assigned spools). Clicking navigates to /inventory?spool=, which immediately opens the edit modal for that exact spool. Falls back to a targeted single-spool fetch if the spool list is not yet cached.
SpoolBuddy NFC write support for Spoolman spools (bonus — not part of the original FR)
SpoolBuddy devices can now write OpenTag3D NDEF tags for Spoolman-managed spools, not just local DB spools. The nfc/write-tag endpoint falls back to Spoolman when a spool is not found locally and encodes the tag via a new encode_opentag3d_from_mapped() path. After a successful write, nfc/write-result stores the tag UID back into Spoolman's extra.tag field. Spoolman spools are also fully discoverable via NFC scan (nfc/tag-scanned) and weight sync (scale/update-spool-weight) uses Spoolman's own filament.spool_weight as core weight instead of a hardcoded 250 g fallback.
Related Issue
Fixes https://github.com/maziggy/bambuddy/issues/1038
Documentation
Type of Change
Changes Made
/spoolman/inventory/*proxy API (list, get, create, bulk-create, update, delete, archive, restore, weight sync)SpoolBuddyInventoryPage— replaced Spoolman iframe with full internal inventory UI in Spoolman modeInventoryPage—?spool=<id>deep-link support and "Open in Inventory" button on AMS slot hover cardSpoolFormModal/AdditionalSection— new Storage Location field, bidirectional Spoolmanlocationsync_spoolman_helpers.py—_map_spoolman_spool(),_safe_float(),_safe_int(),_safe_optional_float()opentag3d.py—encode_opentag3d_from_mapped()for dict-based NDEF encoding without ORM objectspoolbuddy.py— Spoolman-awarenfc/tag-scanned,nfc/write-tag,nfc/write-result,scale/update-spool-weightspool_id ≤ 0guard, SSRF scheme check, uint16/byte overflow clamps,max_lengthon tag fields,removeprefixinstead oflstripfor color hexScreenshots
see Issue FR
Testing
Unit: 952 passed
Integration: 1004 passed
Frontend: 1447/1447 passed
Bandit security scan: 0 Medium/High findings
I have tested this on my local machine
Checklist
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.