printedparts stage 14: retire/restore in the UI, dashless item codes
Some checks failed
CI / backend (push) Successful in 1m42s
CI / naming (push) Successful in 1s
CI / frontend (push) Successful in 7s
CI / migrations-mysql (push) Failing after 7s

Retire button with confirmation on the detail page (item leaves the
storefront and the kiosk rejects its code; ledger history and label
survive), Restore on retired items, and an Include-retired list toggle
with a badge. Restore is its own permission-gated POST - the generic
update still cannot flip isactive. New codes mint as WJRP0042 style
without the dash; existing codes are immutable bin labels and keep
their form.
This commit is contained in:
cproudlock
2026-07-17 08:35:31 -04:00
parent a8a6baf979
commit eab225e1e6
7 changed files with 89 additions and 4 deletions

View File

@@ -91,7 +91,7 @@ def _imagedir():
def _mint_itemcode(item):
"""Set itemcode from the configured prefix + the flushed row id."""
prefix = Setting.get('printedparts_code_prefix') or '3DP'
item.itemcode = f'{prefix}-{item.printeditemid:04d}'
item.itemcode = f'{prefix}{item.printeditemid:04d}'
@printedparts_bp.route('/items', methods=['POST'])
@@ -159,6 +159,20 @@ def delete_item(item_id: int):
return success_response(message='Printed item retired')
@printedparts_bp.route('/items/<int:item_id>/restore', methods=['POST'])
@jwt_required()
@require_permission('printedparts.delete')
def restore_item(item_id: int):
"""Bring a retired item back; code, photo, and history are intact."""
item = db.session.get(PrintedItem, item_id)
if not item:
return error_response(ErrorCodes.NOT_FOUND,
f'Printed item {item_id} not found', http_code=404)
item.isactive = True
db.session.commit()
return success_response(item.to_dict(), message='Printed item restored')
# --- item image: the models.py upload/serve/delete trio ---------------------
@printedparts_bp.route('/items/<int:item_id>/image', methods=['POST'])