diff --git a/fusion_plating/fusion_plating_reports/__manifest__.py b/fusion_plating/fusion_plating_reports/__manifest__.py index c53bc336..a0da068d 100644 --- a/fusion_plating/fusion_plating_reports/__manifest__.py +++ b/fusion_plating/fusion_plating_reports/__manifest__.py @@ -3,7 +3,7 @@ # License OPL-1 (Odoo Proprietary License v1.0) { 'name': 'Fusion Plating — Reports', - 'version': '19.0.7.15.0', + 'version': '19.0.7.16.0', 'category': 'Manufacturing/Plating', 'summary': 'PDF reports for Fusion Plating: quote, SO, WO, packing, BoL, CoC, invoice, receipt, quality + compliance.', 'depends': [ diff --git a/fusion_plating/fusion_plating_reports/controllers/wo_scan.py b/fusion_plating/fusion_plating_reports/controllers/wo_scan.py index 424928bd..fcd462af 100644 --- a/fusion_plating/fusion_plating_reports/controllers/wo_scan.py +++ b/fusion_plating/fusion_plating_reports/controllers/wo_scan.py @@ -22,25 +22,42 @@ class FpWoScanController(http.Controller): def wo_scan_redirect(self, wo_id, **kwargs): """Redirect a scanned sticker to the right backend form. - Stickers are printed from two sources — mrp.workorder (WO) and - mrp.production (MO) — and both embed their own numeric id in - the QR. Try the MO table first (operators live on the MO - form — customer, SO, all WOs visible) and fall back to WO. + Resolution order: + 1. fp.job mapped from this MO id via legacy_mrp_production_id + (post-migration: physical stickers still encode the old MO + id, but the canonical record is now an fp.job) + 2. mrp.production with this id (pre-migration callers, or if + the legacy mapping wasn't run) + 3. mrp.workorder with this id (older stickers that encoded + the WO id rather than the MO id) + 4. fall back to the jobs list so staff can search manually. """ - MO = request.env['mrp.production'].sudo() - WO = request.env['mrp.workorder'].sudo() + env = request.env - mo = MO.browse(wo_id).exists() + # 1) New native model — preferred when migration has run. + if 'fp.job' in env and 'legacy_mrp_production_id' in env['fp.job']._fields: + job = env['fp.job'].sudo().search( + [('legacy_mrp_production_id', '=', wo_id)], limit=1) + if job: + return request.redirect( + '/odoo/action-fusion_plating.action_fp_job/%d' % job.id + ) + + # 2) Legacy MO form (pre-migration or non-migrated records). + mo = env['mrp.production'].sudo().browse(wo_id).exists() if mo: return request.redirect( '/odoo/action-mrp.mrp_production_action/%d' % mo.id ) - wo = WO.browse(wo_id).exists() + # 3) Legacy WO form. + wo = env['mrp.workorder'].sudo().browse(wo_id).exists() if wo: return request.redirect( '/odoo/action-mrp.action_mrp_workorder/%d' % wo.id ) - # Neither resolved — land on the WO list so staff can search manually. + # 4) Fall back: native jobs list if it exists, otherwise WO list. + if 'fp.job' in env: + return request.redirect('/odoo/plating-jobs') return request.redirect('/odoo/manufacturing/work-orders') diff --git a/fusion_plating/fusion_plating_shopfloor/__manifest__.py b/fusion_plating/fusion_plating_shopfloor/__manifest__.py index d7f35980..a43f57e4 100644 --- a/fusion_plating/fusion_plating_shopfloor/__manifest__.py +++ b/fusion_plating/fusion_plating_shopfloor/__manifest__.py @@ -5,7 +5,7 @@ { 'name': 'Fusion Plating — Shop Floor', - 'version': '19.0.17.0.0', + 'version': '19.0.18.0.0', 'category': 'Manufacturing/Plating', 'summary': 'Shop-floor tablet stations, QR scanning, bake window enforcer, ' 'first-piece inspection gates.', diff --git a/fusion_plating/fusion_plating_shopfloor/static/src/js/qr_scanner.js b/fusion_plating/fusion_plating_shopfloor/static/src/js/qr_scanner.js index a2d213c4..6dad2c29 100644 --- a/fusion_plating/fusion_plating_shopfloor/static/src/js/qr_scanner.js +++ b/fusion_plating/fusion_plating_shopfloor/static/src/js/qr_scanner.js @@ -42,7 +42,6 @@ export class QrScanner extends Component { }; setup() { - this.action = useService("action"); this.notification = useService("notification"); this.videoRef = useRef("video"); const hasNative = typeof BarcodeDetector !== "undefined"; @@ -51,6 +50,7 @@ export class QrScanner extends Component { open: false, error: null, manualUrl: "", + detected: "", // last decoded value (for user feedback) // True whenever ANY decoder (native or jsQR) is available. // Drives the template: when true we show the camera