diff --git a/plugins/printedparts/api/routes.py b/plugins/printedparts/api/routes.py index 97e9654..ba48c12 100644 --- a/plugins/printedparts/api/routes.py +++ b/plugins/printedparts/api/routes.py @@ -266,7 +266,8 @@ from ..models import PrintedItemTransaction from ..services.badges import BadgeError, resolve_badge -def _ledger_write(item, transactiontype, quantitychange, sso, name, reason=None): +def _ledger_write(item, transactiontype, quantitychange, sso, name, reason=None, + revision=None): """Append a ledger row and move the cached quantity in ONE commit. The single-commit invariant is what keeps quantityonhand equal to the @@ -284,6 +285,7 @@ def _ledger_write(item, transactiontype, quantitychange, sso, name, reason=None) employeesso=sso, employeename=name, reason=reason, + revision=revision, )) db.session.commit() if (quantitychange < 0 @@ -413,8 +415,10 @@ def _kiosk_find_item(itemcode): """Resolve a scanned or typed code to an active item. Accepts the full code (WJRP0042) or bare digits from the touch keypad - (42 -> prefix + zero-pad), so manual entry never needs letters.""" - scanned = (itemcode or '').strip().upper() + (42 -> prefix + zero-pad), so manual entry never needs letters. A label QR + carries 'TAG|rev'; the revision is stripped here (it identifies the physical + part's file rev, not a different item).""" + scanned = (itemcode or '').split('|', 1)[0].strip().upper() item = PrintedItem.query.filter( or_(PrintedItem.itemcode == scanned, PrintedItem.gagelabtag == scanned), @@ -472,7 +476,19 @@ def kiosk_take(): return error_response(ErrorCodes.VALIDATION_ERROR, str(badge_error), http_code=422) - _ledger_write(item, 'take', -quantity, sso, name) + # Print-file revision the scanned part carried: explicit field, else the + # 'TAG|rev' tail of the scanned code. Recorded for traceability. + revision = data.get('revision') + if revision is None and '|' in (data.get('itemcode') or ''): + tail = data['itemcode'].split('|', 1)[1].strip() + revision = tail if tail.isdigit() else None + if revision is not None: + try: + revision = int(revision) + except (ValueError, TypeError): + revision = None + + _ledger_write(item, 'take', -quantity, sso, name, revision=revision) return success_response(item.to_dict(), message=f'Took {quantity}, {item.quantityonhand} left') diff --git a/plugins/printedparts/frontend/views/PartsKiosk.vue b/plugins/printedparts/frontend/views/PartsKiosk.vue index 7646093..53d4e9a 100644 --- a/plugins/printedparts/frontend/views/PartsKiosk.vue +++ b/plugins/printedparts/frontend/views/PartsKiosk.vue @@ -106,6 +106,7 @@ const doneMessage = ref('') const submitting = ref(false) const manualCode = ref('') const manualBadge = ref('') +const scannedRevision = ref(null) const entryInput = ref(null) let resetTimer = null @@ -126,6 +127,9 @@ async function lookupItem(itemcode) { error.value = '' const code = (itemcode || '').trim() if (!code) return + // A label QR carries "TAG|rev"; capture the revision, resolve by the TAG part. + const pipe = code.indexOf('|') + scannedRevision.value = pipe >= 0 ? (parseInt(code.slice(pipe + 1), 10) || null) : null try { const response = await printedpartsApi.kioskItem(code) item.value = response.data.data @@ -156,7 +160,8 @@ async function submitTake() { const response = await printedpartsApi.kioskTake({ itemcode: item.value.itemcode, badge: badge.value, - quantity: parseInt(quantity.value, 10) + quantity: parseInt(quantity.value, 10), + revision: scannedRevision.value }) doneMessage.value = response.data.message step.value = 'done' @@ -182,6 +187,7 @@ function reset() { quantity.value = '' manualCode.value = '' manualBadge.value = '' + scannedRevision.value = null error.value = '' doneMessage.value = '' focusEntry() diff --git a/plugins/printedparts/frontend/views/PrintedPartsLabels.vue b/plugins/printedparts/frontend/views/PrintedPartsLabels.vue index 56ef8c2..7b15ef6 100644 --- a/plugins/printedparts/frontend/views/PrintedPartsLabels.vue +++ b/plugins/printedparts/frontend/views/PrintedPartsLabels.vue @@ -4,9 +4,9 @@

Print 3D Parts Bin Labels (1in x 0.5in)

- Each label is one page on 1in x 0.5in roll stock: CODE128 barcode of - the gage lab tag (the internal code is used when a part has no tag), - scannable at the parts kiosk. + Each label is one page on 1in x 0.5in roll stock: a QR of the gage lab + tag plus its latest print-file revision (TAG|rev), so a scanned part + carries which revision it was printed from. Scannable at the parts kiosk.

Loading parts...
@@ -43,23 +43,38 @@
- -
{{ label.gagelabtag || label.itemcode }}
+ +
{{ labelText(label) }}