From 7122e23e60df95c02da4d93f07728f697e2d9ffd Mon Sep 17 00:00:00 2001 From: Raman Marikanti Date: Thu, 27 Nov 2025 15:05:25 +0530 Subject: [PATCH] qr on equipment --- .../__init__.py | 23 +++ .../__manifest__.py | 25 +++ .../models/__init__.py | 4 + .../models/maintenance_equipment.py | 28 +++ .../models/res_company.py | 22 ++ .../report/__init__.py | 3 + .../report/custom_qrcode.xml | 188 ++++++++++++++++++ .../report/custom_qrcode_generator.py | 86 ++++++++ .../security/ir.model.access.csv | 2 + .../static/description/icon.png | Bin 0 -> 9408 bytes .../views/maintenance_equipment.xml | 56 ++++++ .../wizard/__init__.py | 3 + .../wizard/equipment_label_layout.py | 36 ++++ .../wizard/equipment_label_layout_views.xml | 30 +++ 14 files changed, 506 insertions(+) create mode 100644 addons_extensions/aspl_equipment_qrcode_generator/__init__.py create mode 100644 addons_extensions/aspl_equipment_qrcode_generator/__manifest__.py create mode 100644 addons_extensions/aspl_equipment_qrcode_generator/models/__init__.py create mode 100644 addons_extensions/aspl_equipment_qrcode_generator/models/maintenance_equipment.py create mode 100644 addons_extensions/aspl_equipment_qrcode_generator/models/res_company.py create mode 100644 addons_extensions/aspl_equipment_qrcode_generator/report/__init__.py create mode 100644 addons_extensions/aspl_equipment_qrcode_generator/report/custom_qrcode.xml create mode 100644 addons_extensions/aspl_equipment_qrcode_generator/report/custom_qrcode_generator.py create mode 100644 addons_extensions/aspl_equipment_qrcode_generator/security/ir.model.access.csv create mode 100644 addons_extensions/aspl_equipment_qrcode_generator/static/description/icon.png create mode 100644 addons_extensions/aspl_equipment_qrcode_generator/views/maintenance_equipment.xml create mode 100644 addons_extensions/aspl_equipment_qrcode_generator/wizard/__init__.py create mode 100644 addons_extensions/aspl_equipment_qrcode_generator/wizard/equipment_label_layout.py create mode 100644 addons_extensions/aspl_equipment_qrcode_generator/wizard/equipment_label_layout_views.xml diff --git a/addons_extensions/aspl_equipment_qrcode_generator/__init__.py b/addons_extensions/aspl_equipment_qrcode_generator/__init__.py new file mode 100644 index 000000000..e7843e8bf --- /dev/null +++ b/addons_extensions/aspl_equipment_qrcode_generator/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- + +from odoo import api, SUPERUSER_ID + +from . import models +from . import report +from . import wizard + + +# TODO: Generate Sequence For each company for Equipment +def pre_init_hook(env): + company_ids = env['res.company'].search([]) + for company_id in company_ids: + sequence_id = env['ir.sequence'].search( + [('name', '=', 'Equipment Company Sequence'), ('company_id', '=', company_id.id)]) + if not sequence_id: + env['ir.sequence'].create({ + 'name': 'Equipment Company Sequence', + 'prefix': company_id.id, + 'padding': 5, + 'number_increment': 1, + 'company_id': company_id.id + }) diff --git a/addons_extensions/aspl_equipment_qrcode_generator/__manifest__.py b/addons_extensions/aspl_equipment_qrcode_generator/__manifest__.py new file mode 100644 index 000000000..f2d08eb66 --- /dev/null +++ b/addons_extensions/aspl_equipment_qrcode_generator/__manifest__.py @@ -0,0 +1,25 @@ + +{ + "name": "QR Code on Equipment", + 'category': '', + "summary": "Add QR Code on equipment .", + 'license': 'LGPL-3', + "price": 00.00, + 'description': """ + The Equipment Management Module generates unique QR codes for each asset, offering instant details and direct Odoo profile access for seamless management. + """, + "author": "Raman Marikanti", + "depends": ['account','maintenance'], + "external_dependencies": { + 'python': ['qrcode'] + }, + "data": [ + 'views/maintenance_equipment.xml', + 'security/ir.model.access.csv', + 'report/custom_qrcode.xml', + 'wizard/equipment_label_layout_views.xml', + ], + 'pre_init_hook': 'pre_init_hook', + "application": True, + "installable": True, +} diff --git a/addons_extensions/aspl_equipment_qrcode_generator/models/__init__.py b/addons_extensions/aspl_equipment_qrcode_generator/models/__init__.py new file mode 100644 index 000000000..e176a441b --- /dev/null +++ b/addons_extensions/aspl_equipment_qrcode_generator/models/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- + +from . import maintenance_equipment +from . import res_company diff --git a/addons_extensions/aspl_equipment_qrcode_generator/models/maintenance_equipment.py b/addons_extensions/aspl_equipment_qrcode_generator/models/maintenance_equipment.py new file mode 100644 index 000000000..4e7b2172c --- /dev/null +++ b/addons_extensions/aspl_equipment_qrcode_generator/models/maintenance_equipment.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- + +from odoo import models, fields + + +class MaintenanceEquipment(models.Model): + _inherit = 'maintenance.equipment' + + qr_code = fields.Binary("QR Code") + comp_serial_no = fields.Char("Inventory Serial No", tracking=True) + serial_no = fields.Char('Mfg. Serial Number', copy=False) + + def action_print_qrcode_layout(self): + action = self.env['ir.actions.act_window']._for_xml_id('aspl_equipment_qrcode_generator.action_open_label_layout_equipment') + action['context'] = {'default_equipment_ids': self.ids} + return action + + def generate_serial_no(self): + for equipment_id in self: + if not equipment_id.comp_serial_no: + company_id = equipment_id.company_id.id + sequence_id = self.env['ir.sequence'].search( + [('name', '=', 'Equipment Company Sequence'), ('company_id', '=', company_id)]) + if sequence_id: + data = sequence_id._next() + equipment_id.write({ + 'comp_serial_no': data + }) diff --git a/addons_extensions/aspl_equipment_qrcode_generator/models/res_company.py b/addons_extensions/aspl_equipment_qrcode_generator/models/res_company.py new file mode 100644 index 000000000..5d23f92da --- /dev/null +++ b/addons_extensions/aspl_equipment_qrcode_generator/models/res_company.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- + +from odoo import models, api + + +class ResCompany(models.Model): + _inherit = 'res.company' + + @api.model_create_multi + def create(self, vals): + result = super(ResCompany, self).create(vals) + sequence_id = self.env['ir.sequence'].search( + [('name', '=', 'Equipment Company Sequence'), ('company_id', '=', result.id)]) + if not sequence_id: + self.env['ir.sequence'].create({ + 'name': 'Equipment Company Sequence', + 'prefix': result.id, + 'padding': 5, + 'number_increment': 1, + 'company_id': result.id + }) + return result diff --git a/addons_extensions/aspl_equipment_qrcode_generator/report/__init__.py b/addons_extensions/aspl_equipment_qrcode_generator/report/__init__.py new file mode 100644 index 000000000..d46550c1b --- /dev/null +++ b/addons_extensions/aspl_equipment_qrcode_generator/report/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import custom_qrcode_generator diff --git a/addons_extensions/aspl_equipment_qrcode_generator/report/custom_qrcode.xml b/addons_extensions/aspl_equipment_qrcode_generator/report/custom_qrcode.xml new file mode 100644 index 000000000..bdb3f1ebd --- /dev/null +++ b/addons_extensions/aspl_equipment_qrcode_generator/report/custom_qrcode.xml @@ -0,0 +1,188 @@ + + + + + + + + + + + + + + + A4 Label Sheet + + A4 + 0 + 0 + Portrait + 0 + 0 + 0 + 0 + + 96 + + + + Equipment QR-code (PDF) + maintenance.equipment + qweb-pdf + aspl_equipment_qrcode_generator.maintenance_quip + aspl_equipment_qrcode_generator.maintenance_quip + + 'Products Labels - %s' % (object.name) + + report + + + \ No newline at end of file diff --git a/addons_extensions/aspl_equipment_qrcode_generator/report/custom_qrcode_generator.py b/addons_extensions/aspl_equipment_qrcode_generator/report/custom_qrcode_generator.py new file mode 100644 index 000000000..3e83581fb --- /dev/null +++ b/addons_extensions/aspl_equipment_qrcode_generator/report/custom_qrcode_generator.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +import base64 +import math +from io import BytesIO + +import qrcode +from odoo import models + + +def generate_qr_code(value): + qr = qrcode.QRCode( + version=1, + error_correction=qrcode.constants.ERROR_CORRECT_L, + box_size=20, + border=4, + ) + qr.add_data(value) + qr.make(fit=True) + img = qr.make_image() + temp = BytesIO() + img.save(temp, format="PNG") + qr_img = base64.b64encode(temp.getvalue()) + return qr_img + + +def _prepare_data(env, data): + equipment_label_layout_id = env['equipment.label.layout'].browse(data['equipment_label_layout_id']) + equipment_dict = {} + equipment_ids = equipment_label_layout_id.equipment_ids + for equipment in equipment_ids: + if not equipment.name: + continue + equipment_dict[equipment] = 1 + combine_equipment_detail = "" + + # Generate Equipment Redirect LInk + url = env['ir.config_parameter'].sudo().get_param('web.base.url') + menuId = env.ref('maintenance.menu_equipment_form').sudo().id + actionId = env.ref('maintenance.hr_equipment_action').sudo().id + + equipment_link = url + '/web#id=' + str(equipment.id) + '&menu_id=' + str(menuId) + '&action=' + str( + actionId) + '&model=maintenance.equipment&view_type=form' + + # Prepare main Equipment Detail + main_equipment_detail = "" + main_equipment_detail = main_equipment_detail.join( + "Name: " + str(equipment.name) + "\n" + + "Model: " + str(equipment.model) + "\n" + + "Mfg serial no: " + str(equipment.serial_no) + "\n" + "Warranty Exp. Date: " +str(equipment.warranty_date) + "\n" + "Category: " +str(equipment.category_id.name)+ "\n" + "Contact No: "+str(equipment.technician_user_id.phone) +"\n" + "Contact Email: "+str(equipment.technician_user_id.login) + ) + # main_equipment_detail = equipment_link + '\n' + '\n' + main_equipment_detail + + # Prepare Child Equipment Detail + combine_equipment_detail = main_equipment_detail + + combine_equipment_detail += '\n' + '\n' + equipment_link + + # Generate Qr Code depends on Details + qr_image = generate_qr_code(combine_equipment_detail) + equipment.write({ + 'qr_code': qr_image + }) + env.cr.commit() + page_numbers = (len(equipment_ids) - 1) // (equipment_label_layout_id.rows * equipment_label_layout_id.columns) + 1 + + dict_equipment = { + 'rows': equipment_label_layout_id.rows, + 'columns': equipment_label_layout_id.columns, + 'page_numbers': page_numbers, + 'equipment_data': equipment_dict + } + return dict_equipment + + +class ReportProductTemplateLabel(models.AbstractModel): + _name = 'report.aspl_equipment_qrcode_generator.maintenance_quip' + _description = 'Equipment QR-code Report' + + def _get_report_values(self, docids, data): + return _prepare_data(self.env, data) diff --git a/addons_extensions/aspl_equipment_qrcode_generator/security/ir.model.access.csv b/addons_extensions/aspl_equipment_qrcode_generator/security/ir.model.access.csv new file mode 100644 index 000000000..c950bd953 --- /dev/null +++ b/addons_extensions/aspl_equipment_qrcode_generator/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_equipment_label_layout,access.equipment_label_layout,model_equipment_label_layout,,1,1,1,1 \ No newline at end of file diff --git a/addons_extensions/aspl_equipment_qrcode_generator/static/description/icon.png b/addons_extensions/aspl_equipment_qrcode_generator/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..8c9fe192369455192695f36c0556154186c1cb39 GIT binary patch literal 9408 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 z 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 + + + + maintenance.equipment.tree.inherit + maintenance.equipment + + + + +
+
+
+
+
+ + + maintenance.equipment.form.inherit + maintenance.equipment + + + + + + + + + +
+
+ +
+
+
+ + + Generate Serial Number + + + list + code + action = records.generate_serial_no() + + + + Print QR-Code + + + form + code + action = records.action_print_qrcode_layout() + + +
diff --git a/addons_extensions/aspl_equipment_qrcode_generator/wizard/__init__.py b/addons_extensions/aspl_equipment_qrcode_generator/wizard/__init__.py new file mode 100644 index 000000000..0ccb5a51f --- /dev/null +++ b/addons_extensions/aspl_equipment_qrcode_generator/wizard/__init__.py @@ -0,0 +1,3 @@ +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import equipment_label_layout diff --git a/addons_extensions/aspl_equipment_qrcode_generator/wizard/equipment_label_layout.py b/addons_extensions/aspl_equipment_qrcode_generator/wizard/equipment_label_layout.py new file mode 100644 index 000000000..71598c803 --- /dev/null +++ b/addons_extensions/aspl_equipment_qrcode_generator/wizard/equipment_label_layout.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import _, api, fields, models + + +class EquipmentLabelLayout(models.TransientModel): + _name = 'equipment.label.layout' + _description = 'Choose the sheet layout to print the labels' + + print_format = fields.Selection([ + ('2x5', '2 x 5'), + ('2x7', '2 x 7'), + ('4x7', '4 x 7')], string="Format", default='2x5', required=True) + equipment_ids = fields.Many2many('maintenance.equipment') + rows = fields.Integer(compute='_compute_dimensions') + columns = fields.Integer(compute='_compute_dimensions') + + @api.depends('print_format') + def _compute_dimensions(self): + for wizard in self: + if 'x' in wizard.print_format: + columns, rows = wizard.print_format.split('x')[:2] + wizard.columns = int(columns) + wizard.rows = int(rows) + else: + wizard.columns, wizard.rows = 1, 1 + + + def process_label(self): + xml_id = 'aspl_equipment_qrcode_generator.report_equipment_label' + data = { + 'equipment_label_layout_id':self.id + } + + return self.env.ref(xml_id).report_action(None, data=data) \ No newline at end of file diff --git a/addons_extensions/aspl_equipment_qrcode_generator/wizard/equipment_label_layout_views.xml b/addons_extensions/aspl_equipment_qrcode_generator/wizard/equipment_label_layout_views.xml new file mode 100644 index 000000000..9e7dc5ca2 --- /dev/null +++ b/addons_extensions/aspl_equipment_qrcode_generator/wizard/equipment_label_layout_views.xml @@ -0,0 +1,30 @@ + + + + equipment.label.layout.form + equipment.label.layout + primary + +
+ + + + + +
+
+
+
+
+ + + Choose Labels Layout + equipment.label.layout + + new + +