diff --git a/aspl_equipment_qrcode_generator/__init__.py b/aspl_equipment_qrcode_generator/__init__.py new file mode 100644 index 0000000..e7843e8 --- /dev/null +++ b/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/aspl_equipment_qrcode_generator/__manifest__.py b/aspl_equipment_qrcode_generator/__manifest__.py new file mode 100644 index 0000000..9b67b63 --- /dev/null +++ b/aspl_equipment_qrcode_generator/__manifest__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Aspire Softserv Pvt. Ltd. +# Copyright (C) Aspire Softserv Pvt. Ltd.(). +# +############################################################################### +{ + "name": "QR Code on Equipment", + 'category': '', + "summary": "Add QR Code on equipment for managing equipment.", + "version": "18.0.0.1.0", + "license": "AGPL-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": "Aspire Softserv Pvt. Ltd", + "website": "https://aspiresoftserv.com", + "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, + "maintainer": "Aspire Softserv Pvt. Ltd", + "support": "odoo@aspiresoftserv.com", + 'images': ['static/description/banner.gif'], +} diff --git a/aspl_equipment_qrcode_generator/models/__init__.py b/aspl_equipment_qrcode_generator/models/__init__.py new file mode 100644 index 0000000..e176a44 --- /dev/null +++ b/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/aspl_equipment_qrcode_generator/models/maintenance_equipment.py b/aspl_equipment_qrcode_generator/models/maintenance_equipment.py new file mode 100644 index 0000000..4e7b217 --- /dev/null +++ b/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/aspl_equipment_qrcode_generator/models/res_company.py b/aspl_equipment_qrcode_generator/models/res_company.py new file mode 100644 index 0000000..108d2ad --- /dev/null +++ b/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 + 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/aspl_equipment_qrcode_generator/report/__init__.py b/aspl_equipment_qrcode_generator/report/__init__.py new file mode 100644 index 0000000..d46550c --- /dev/null +++ b/aspl_equipment_qrcode_generator/report/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import custom_qrcode_generator diff --git a/aspl_equipment_qrcode_generator/report/custom_qrcode.xml b/aspl_equipment_qrcode_generator/report/custom_qrcode.xml new file mode 100644 index 0000000..91e70c3 --- /dev/null +++ b/aspl_equipment_qrcode_generator/report/custom_qrcode.xml @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + 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/aspl_equipment_qrcode_generator/report/custom_qrcode_generator.py b/aspl_equipment_qrcode_generator/report/custom_qrcode_generator.py new file mode 100644 index 0000000..88bb0fe --- /dev/null +++ b/aspl_equipment_qrcode_generator/report/custom_qrcode_generator.py @@ -0,0 +1,84 @@ +# -*- 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) + ) + # 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/aspl_equipment_qrcode_generator/security/ir.model.access.csv b/aspl_equipment_qrcode_generator/security/ir.model.access.csv new file mode 100644 index 0000000..c950bd9 --- /dev/null +++ b/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/aspl_equipment_qrcode_generator/static/description/banner.gif b/aspl_equipment_qrcode_generator/static/description/banner.gif new file mode 100644 index 0000000..848fe65 Binary files /dev/null and b/aspl_equipment_qrcode_generator/static/description/banner.gif differ diff --git a/aspl_equipment_qrcode_generator/static/description/icon.png b/aspl_equipment_qrcode_generator/static/description/icon.png new file mode 100644 index 0000000..8c9fe19 Binary files /dev/null and b/aspl_equipment_qrcode_generator/static/description/icon.png differ diff --git a/aspl_equipment_qrcode_generator/static/description/images/aspl_project_timesheet_activity.png b/aspl_equipment_qrcode_generator/static/description/images/aspl_project_timesheet_activity.png new file mode 100644 index 0000000..91472ce Binary files /dev/null and b/aspl_equipment_qrcode_generator/static/description/images/aspl_project_timesheet_activity.png differ diff --git a/aspl_equipment_qrcode_generator/static/description/images/aspl_save_view_to_favourite.png b/aspl_equipment_qrcode_generator/static/description/images/aspl_save_view_to_favourite.png new file mode 100644 index 0000000..726519e Binary files /dev/null and b/aspl_equipment_qrcode_generator/static/description/images/aspl_save_view_to_favourite.png differ diff --git a/aspl_equipment_qrcode_generator/static/description/images/aspl_select_multi_company.png b/aspl_equipment_qrcode_generator/static/description/images/aspl_select_multi_company.png new file mode 100644 index 0000000..8e9017d Binary files /dev/null and b/aspl_equipment_qrcode_generator/static/description/images/aspl_select_multi_company.png differ diff --git a/aspl_equipment_qrcode_generator/static/description/images/bg_image.png b/aspl_equipment_qrcode_generator/static/description/images/bg_image.png new file mode 100644 index 0000000..621cce8 Binary files /dev/null and b/aspl_equipment_qrcode_generator/static/description/images/bg_image.png differ diff --git a/aspl_equipment_qrcode_generator/static/description/images/logo.png b/aspl_equipment_qrcode_generator/static/description/images/logo.png new file mode 100644 index 0000000..8d661e9 Binary files /dev/null and b/aspl_equipment_qrcode_generator/static/description/images/logo.png differ diff --git a/aspl_equipment_qrcode_generator/static/description/images/project_task_milestone.png b/aspl_equipment_qrcode_generator/static/description/images/project_task_milestone.png new file mode 100644 index 0000000..b0f98c2 Binary files /dev/null and b/aspl_equipment_qrcode_generator/static/description/images/project_task_milestone.png differ diff --git a/aspl_equipment_qrcode_generator/static/description/images/service_banner.png b/aspl_equipment_qrcode_generator/static/description/images/service_banner.png new file mode 100644 index 0000000..13e0c84 Binary files /dev/null and b/aspl_equipment_qrcode_generator/static/description/images/service_banner.png differ diff --git a/aspl_equipment_qrcode_generator/static/description/index.html b/aspl_equipment_qrcode_generator/static/description/index.html new file mode 100644 index 0000000..3246bd7 --- /dev/null +++ b/aspl_equipment_qrcode_generator/static/description/index.html @@ -0,0 +1,165 @@ +
+
+
+
+
Request A Demo
+
+
+
+

Euipment Qr-code

+
+ The Equipment Management Module streamlines the intricate process of equipment management by generating unique QR codes for each asset. Scanning these QR codes instantly provides comprehensive details about the equipment. Additionally, the QR code features a direct link to the equipment's profile in Odoo, facilitating seamless management and updates.
+
+

Prerequisite:-

+ +
+ pip install qrcode==6.1 +
+
+
+
+ +
+
+
+

Screenshots

+
+
+
+
+
+

Sequence Configuration

+
Once you install the module, It will automatically create maintenance sequence for available company.
+
+
+ +
+
+
+
+

Serial number Generation

+
In the equipment, you'll find a "Generate Serial Number" button. When you click this button, it automatically creates a serial number based on the company's predefined sequence, which is set up when the module is installed (check above screenshot related to sequence configuration). +
+
+
+ +
+
+
+
+

Print QR-Code View

+
In the equipment tree view, When you select an item, It will display a "QR Code" button.
+
+
+ +
+
+
+
+

QR Code Size Options

+
The module will display all available options for QR code sizes, allowing you to choose the appropriate dimensions for generating your QR codes.
+
+
+ +
+
+
+
+
+

Suggested Apps

+
+ +
+
+ +
+
+
+
+ +
+
+
Free Support
+

We will provide free support for any issues,queries and bug fixing
upto + 90 days from the date of purchase of this application.

+
+ +
+ +
+
+
+
+
sales@aspiresoftserv.com
+
aspire.software
+
+916351895006
+
+
+
diff --git a/aspl_equipment_qrcode_generator/static/description/screenshots/1_sequence.png b/aspl_equipment_qrcode_generator/static/description/screenshots/1_sequence.png new file mode 100644 index 0000000..9ce8eb6 Binary files /dev/null and b/aspl_equipment_qrcode_generator/static/description/screenshots/1_sequence.png differ diff --git a/aspl_equipment_qrcode_generator/static/description/screenshots/2_equipment_screen.png b/aspl_equipment_qrcode_generator/static/description/screenshots/2_equipment_screen.png new file mode 100644 index 0000000..76f1f04 Binary files /dev/null and b/aspl_equipment_qrcode_generator/static/description/screenshots/2_equipment_screen.png differ diff --git a/aspl_equipment_qrcode_generator/static/description/screenshots/3_equipment_tree.png b/aspl_equipment_qrcode_generator/static/description/screenshots/3_equipment_tree.png new file mode 100644 index 0000000..b983843 Binary files /dev/null and b/aspl_equipment_qrcode_generator/static/description/screenshots/3_equipment_tree.png differ diff --git a/aspl_equipment_qrcode_generator/static/description/screenshots/4_qrcode_size_selection.png b/aspl_equipment_qrcode_generator/static/description/screenshots/4_qrcode_size_selection.png new file mode 100644 index 0000000..1e6639f Binary files /dev/null and b/aspl_equipment_qrcode_generator/static/description/screenshots/4_qrcode_size_selection.png differ diff --git a/aspl_equipment_qrcode_generator/static/description/screenshots/5_barcode_result.png b/aspl_equipment_qrcode_generator/static/description/screenshots/5_barcode_result.png new file mode 100644 index 0000000..6e7d5ea Binary files /dev/null and b/aspl_equipment_qrcode_generator/static/description/screenshots/5_barcode_result.png differ diff --git a/aspl_equipment_qrcode_generator/views/maintenance_equipment.xml b/aspl_equipment_qrcode_generator/views/maintenance_equipment.xml new file mode 100644 index 0000000..3396803 --- /dev/null +++ b/aspl_equipment_qrcode_generator/views/maintenance_equipment.xml @@ -0,0 +1,56 @@ + + + + + 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/aspl_equipment_qrcode_generator/wizard/__init__.py b/aspl_equipment_qrcode_generator/wizard/__init__.py new file mode 100644 index 0000000..0ccb5a5 --- /dev/null +++ b/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/aspl_equipment_qrcode_generator/wizard/equipment_label_layout.py b/aspl_equipment_qrcode_generator/wizard/equipment_label_layout.py new file mode 100644 index 0000000..71598c8 --- /dev/null +++ b/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/aspl_equipment_qrcode_generator/wizard/equipment_label_layout_views.xml b/aspl_equipment_qrcode_generator/wizard/equipment_label_layout_views.xml new file mode 100644 index 0000000..9e7dc5c --- /dev/null +++ b/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 + +