# -*- coding: utf-8 -*- # Copyright 2024-2026 Nexa Systems Inc. # License OPL-1 (Odoo Proprietary License v1.0) """QR sticker generator (CL17). Generates a printable PDF with one sticker per selected serial number. Each sticker has a QR code linking to /repair?sn=. Stick on the equipment; client scans -> public client portal opens with the unit pre-filled. Accessible from stock.lot via a server action AND as a standalone wizard under Fusion Repairs > Configuration. """ import base64 import io import logging from odoo import _, api, fields, models from odoo.exceptions import UserError _logger = logging.getLogger(__name__) class FusionRepairQRStickerWizard(models.TransientModel): _name = 'fusion.repair.qr.sticker.wizard' _description = 'QR Sticker Generator Wizard' lot_ids = fields.Many2many( 'stock.lot', string='Serials', help='One sticker will be generated per serial.', ) product_id = fields.Many2one( 'product.product', string='Filter by Product', help='Optional - limits the serial picker to lots of this product.', ) company_id = fields.Many2one( 'res.company', default=lambda self: self.env.company, ) def action_generate(self): self.ensure_one() if not self.lot_ids: raise UserError(_('Select at least one serial number to print stickers for.')) return self.env.ref('fusion_repairs.action_report_qr_stickers') \ .report_action(self) # ------------------------------------------------------------------ # Helpers used by the QWeb report # ------------------------------------------------------------------ def _portal_base_url(self): ICP = self.env['ir.config_parameter'].sudo() base = (ICP.get_param('web.base.url', '') or '').rstrip('/') path = ICP.get_param('fusion_repairs.client_portal_url', '/repair') or '/repair' return base + path def get_sticker_url(self, lot): """Return the full URL that the QR code on this sticker encodes.""" url = self._portal_base_url() serial = (lot.name or '').strip() return f"{url}?sn={serial}" if serial else url def get_qr_data_uri(self, url, size=180): """Return a base64 PNG data URI for the QR code of the given URL. Uses the `qrcode` library if available (it's a transitive dep of many Odoo modules); falls back to a simple ASCII placeholder if not so the report still renders (with a warning). """ try: import qrcode img = qrcode.make(url) buf = io.BytesIO() img.save(buf, format='PNG') b64 = base64.b64encode(buf.getvalue()).decode('ascii') return f"data:image/png;base64,{b64}" except Exception as e: _logger.warning('QR sticker generation failed for %s: %s', url, e) return ""