diff --git a/excel_report_designer/README.rst b/excel_report_designer/README.rst new file mode 100644 index 000000000..73e880f10 --- /dev/null +++ b/excel_report_designer/README.rst @@ -0,0 +1,48 @@ +.. image:: https://img.shields.io/badge/license-AGPL--3-blue.svg + :target: https://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +Excel Report Designer +===================== +This module helps to create reports from various modules + +Configuration +============= +* No additional configuration required + +Company +------- +*`Cybrosys Techno Solutions `__ + +License +------- +General Public License, version 3 (AGPL v3). +(https://www.gnu.org/licenses/agpl-3.0-standalone.html) + +Credits +------- +* Developer : (V15) Bhagyadev KP +* Contact: odoo@cybrosys.com + +Contacts +-------- +* Mail Contact : odoo@cybrosys.com +* Website : https://cybrosys.com + +Bug Tracker +----------- +Bugs are tracked on GitHub Issues. In case of trouble, please check there if +your issue has already been reported. + +Maintainer +========== +.. image:: https://cybrosys.com/images/logo.png + :target: https://cybrosys.com + +This module is maintained by Cybrosys Technologies. + +For further information, please visit `Our Website `__ + +Further information +=================== +HTML Description: ``__ \ No newline at end of file diff --git a/excel_report_designer/__init__.py b/excel_report_designer/__init__.py new file mode 100644 index 000000000..d15228aa8 --- /dev/null +++ b/excel_report_designer/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# Author: Bhagyadev KP (odoo@cybrosys.com) +# +# This program is free software: you can modify +# it under the terms of the GNU Affero General Public License (AGPL) as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +################################################################################ +from . import controllers +from . import models +from . import wizard diff --git a/excel_report_designer/__manifest__.py b/excel_report_designer/__manifest__.py new file mode 100644 index 000000000..57a031f95 --- /dev/null +++ b/excel_report_designer/__manifest__.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# Author: Bhagyadev KP (odoo@cybrosys.com) +# +# This program is free software: you can modify +# it under the terms of the GNU Affero General Public License (AGPL) as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +################################################################################ +{ + 'name': 'Excel Report Designer', + 'version': '15.0.1.0.0', + 'category': 'Extra Tools', + 'summary': """Create Excel Reports for Any Models""", + 'description': 'This module is used to create reports for models and can be select the fields the user want to print.', + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'maintainer': 'Cybrosys Techno Solutions', + 'website': 'https://www.cybrosys.com', + 'depends': ['base'], + 'data': [ + 'security/ir.model.access.csv', + 'views/report_excel_views.xml', + 'wizard/excel_report_views.xml', + ], + 'assets': { + 'web.assets_backend': [ + '/excel_report_designer/static/src/js/action_manager.js' + ], + }, + 'images': ['static/description/banner.png'], + 'license': 'AGPL-3', + 'installable': True, + 'auto_install': False, + 'application': False, +} diff --git a/excel_report_designer/controllers/__init__.py b/excel_report_designer/controllers/__init__.py new file mode 100644 index 000000000..381d35d32 --- /dev/null +++ b/excel_report_designer/controllers/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# Author: Bhagyadev KP (odoo@cybrosys.com) +# +# This program is free software: you can modify +# it under the terms of the GNU Affero General Public License (AGPL) as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +################################################################################ +from . import main diff --git a/excel_report_designer/controllers/main.py b/excel_report_designer/controllers/main.py new file mode 100644 index 000000000..573f4c631 --- /dev/null +++ b/excel_report_designer/controllers/main.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# Author: Bhagyadev KP (odoo@cybrosys.com) +# +# This program is free software: you can modify +# it under the terms of the GNU Affero General Public License (AGPL) as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +################################################################################ +import json +from odoo import http +from odoo.http import content_disposition, request +from odoo.tools import html_escape + + +class XLSXReportController(http.Controller): + """This is used to call the xlsx report function""" + @http.route('/xlsx_reports', type='http', auth='user', methods=['POST'], + csrf=False) + def get_report_xlsx(self, model, options, output_format, report_name, **kw): + """this is used to call the function""" + uid = request.session.uid + report_obj = request.env[model].with_user(uid) + options = json.loads(options) + token = 'dummy-because-api-expects-one' + try: + if output_format == 'xlsx': + response = request.make_response( + None, + headers=[ + ('Content-Type', 'application/vnd.ms-excel'), + ('Content-Disposition', + content_disposition(report_name + '.xlsx')) + ] + ) + report_obj.get_xlsx_report(options, response) + response.set_cookie('fileToken', token) + return response + except Exception as e: + se = http.serialize_exception(e) + error = { + 'code': 200, + 'message': 'Odoo Server Error', + 'data': se + } + return request.make_response(html_escape(json.dumps(error))) diff --git a/excel_report_designer/doc/RELEASE_NOTES.md b/excel_report_designer/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..05bfddb8b --- /dev/null +++ b/excel_report_designer/doc/RELEASE_NOTES.md @@ -0,0 +1,6 @@ +## Module + +#### 09.06.2024 +#### Version 15.0.1.0.0 +#### ADD +- Initial Commit for Excel Report Designer diff --git a/excel_report_designer/models/__init__.py b/excel_report_designer/models/__init__.py new file mode 100644 index 000000000..f8bcd38ca --- /dev/null +++ b/excel_report_designer/models/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# Author: Bhagyadev KP (odoo@cybrosys.com) +# +# This program is free software: you can modify +# it under the terms of the GNU Affero General Public License (AGPL) as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +################################################################################ +from . import report_excel diff --git a/excel_report_designer/models/report_excel.py b/excel_report_designer/models/report_excel.py new file mode 100644 index 000000000..4df48c015 --- /dev/null +++ b/excel_report_designer/models/report_excel.py @@ -0,0 +1,303 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# Author: Bhagyadev KP (odoo@cybrosys.com) +# +# This program is free software: you can modify +# it under the terms of the GNU Affero General Public License (AGPL) as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +################################################################################ +import xlsxwriter +import io +import json +import datetime +from odoo import api, fields, models, _ +from odoo.tools import date_utils + + +class ReportExcel(models.Model): + """this is used to create the a binding action""" + _name = 'report.excel' + _description = "report excel" + _rec_name = 'name' + + name = fields.Char(string='Name', help='Name of the report') + model_id = fields.Many2one('ir.model', string='Model', required=True, + ondelete="cascade", help="The binding model") + fields_ids = fields.Many2many('ir.model.fields', string='Fields', + required=True, ondelete="cascade", + help="the fields to be printed in the report") + date_field_id = fields.Many2one('ir.model.fields', string='Date Filter', + ondelete="cascade", + help="filter on the basis of date") + start_date = fields.Date(string='Start Date', help="start date") + end_date = fields.Date(string='End Date', help="end date") + field_order = fields.Char(default='[]', help="the field order") + action_button = fields.Boolean(default=False, string="Action", + help="visibility of action") + state = fields.Selection([ + ('code', 'Execute Python Code'), + ('object_create', 'Create a new Record'), + ('object_write', 'Update the Record'), + ('multi', 'Execute several actions')], string='Action To Do', + default='code', required=True, copy=True, + help="to execute the code on the basis") + binding_model_id = fields.Many2one('ir.model', ondelete="cascade", + string="Binding Model Id", + help="binding model id") + binding_type = fields.Selection([('action', 'Action'), + ('report', 'Report')], + required=True, default='action', + string="Binding Type", help="binding type") + ir_act_server_ref_id = fields.Many2one('ir.actions.act_window', readonly=True, + copy=False, string="Action Reference", + help="action reference") + + def print_report(self): + """ + Function to print report + """ + for rec in self: + data = { + 'report_name': rec.name, + 'model_name': rec.model_id.model, + 'fields_name': rec.fields_ids.mapped('name'), + 'field_label': rec.fields_ids.mapped('field_description'), + 'date_field_id': rec.date_field_id.name, + 'date_name': rec.date_field_id.field_description, + 'start_date': rec.start_date, + 'end_date': rec.end_date, + 'field_order': rec.field_order + } + return { + 'type': 'ir.actions.report', + 'data': {'model': 'report.excel', + 'options': json.dumps(data, + default=date_utils.json_default), + 'output_format': 'xlsx', + 'report_name': rec.name, + }, + 'report_type': 'stock_xlsx', + } + + def get_xlsx_report(self, data, response): + """this is used to print the report of all records""" + output = io.BytesIO() + workbook = xlsxwriter.Workbook(output, {'in_memory': True}) + sheet = workbook.add_worksheet() + # Formats + format1 = workbook.add_format( + {'font_size': 15, 'align': 'center', 'bold': True}) + format1.set_font_color('#000080') + format2 = workbook.add_format( + {'font_size': 11, 'bold': True, 'border': 1, 'bg_color': '#928E8E'}) + format4 = workbook.add_format( + {'font_size': 10, 'num_format': 'yyyy-m-d', 'align': 'center', 'bold': True}) + format5 = workbook.add_format({'font_size': 10, 'border': 1, 'text_wrap': True}) + format6 = workbook.add_format({'font_size': 10, 'bold': True}) + format8 = workbook.add_format({'font_size': 10, 'border': 1}) + format9 = workbook.add_format( + {'font_size': 10, 'num_format': 'yyyy-m-d'}) + format10 = workbook.add_format( + {'font_size': 10, 'num_format': 'yyyy-m-d', 'border': 1}) + format2.set_align('center') + format4.set_align('right') + format6.set_align('right') + format8.set_align('left') + sheet.merge_range(1, 1, 1, len(data['field_label']) + 1, + data['report_name'], format1) + sheet.write(2, 0, "Date :", format4) + sheet.write(2, 1, fields.Datetime.today(), format4) + if data['date_field_id']: + sheet.write(3, 0, data['date_name'], format4) + if data['start_date']: + sheet.write(3, 1, "From:", format4) + sheet.write(3, 2, data['start_date'], format9) + else: + sheet.write(3, 2, "", format9) + if data['end_date']: + sheet.write(3, 3, "To:", format4) + sheet.write(3, 4, data['end_date'], format9) + else: + sheet.write(3, 4, "", format9) + sl_no = 1 + sheet.write(5, 1, "SL No", format2) + row_num = 5 + col_num = 2 + order = data['field_order'].strip('][').split(', ') + for field_id in order: + field_name = self.env['ir.model.fields'].browse( + int(field_id)).field_description + sheet.write(row_num, col_num, field_name, format2) + col_num += 1 + row_num += 1 + records = [] + if data['date_field_id']: + if data['start_date'] and data['end_date']: + records = self.env[data['model_name']].search([ + (data['date_field_id'], '>=', data['start_date']), + (data['date_field_id'], '<=', data['end_date'])]) + elif data['start_date'] and not data['end_date']: + records = self.env[data['model_name']].search([ + (data['date_field_id'], '>=', data['start_date'])]) + elif not data['start_date'] and data['end_date']: + records = self.env[data['model_name']].search([ + (data['date_field_id'], '<=', data['end_date'])]) + else: + records = self.env[data['model_name']].search([]) + new_table = [] + for record in records: + order = data['field_order'].strip('][').split(', ') + record_dict = {} + for field_id in order: + field = self.env['ir.model.fields'].browse(int(field_id)) + field_name = field.name + field_type = self.env['ir.model.fields'].browse( + int(field_id)).ttype + if field_type in ['many2many']: + one2many_values = ', '.join(record[field_name].mapped('name')) + record_dict[field] = [one2many_values] + elif field_type in ['one2many']: + o2m_list = [] + for rec in record[field_name]: + if rec: + o2m_list.append(rec) + else: + o2m_list.append('') + record_dict[field] = o2m_list + else: + record_dict[field] = [record[field_name]] + new_table.append(record_dict) + for record in new_table: + col_num = 1 + sheet.write(row_num, col_num, sl_no, format5) + col_num += 1 + occupied_rows = max(len(value) for value in record.values()) + for field in record: + field_type = self.env['ir.model.fields'].browse(int(field.id)).ttype + if not field_type in ['one2many', 'many2many']: + try: + if isinstance(record[field][0], datetime.date): + sheet.write(row_num, col_num, record[field][0], format10) + elif isinstance(record[field][0], bool): + if not field: + sheet.write(row_num, col_num, " ", format5) + else: + sheet.write(row_num, col_num, "Yes", format5) + else: + sheet.write(row_num, col_num, record[field][0], format5) + except Exception as e: + if record[field][0]: + sheet.write(row_num, col_num, record[field][0].name_get()[0][1], + format5) + else: + sheet.write(row_num, col_num, "", + format5) + elif field_type == 'one2many': + for i in range(occupied_rows): + if len(record[field]) > i: + try: + if isinstance(record[field][i], datetime.date): + sheet.write(row_num+i, col_num, record[field][i], format10) + elif isinstance(record[field][i], bool): + if not field: + sheet.write(row_num+i, col_num, "NO", format5) + else: + sheet.write(row_num+i, col_num, "Yes", format5) + else: + sheet.write(row_num+i, col_num, record[field][i], format5) + except Exception as e: + if record[field][i]: + sheet.write(row_num+i, col_num, record[field][i].name_get()[0][1], format5) + else: + sheet.write(row_num+i, col_num, "", format5) + elif field_type == 'many2many': + if record[field]: + try: + if isinstance(record[field], datetime.date): + sheet.write(row_num, col_num, record[field][0], format10) + elif isinstance(record[field], bool): + if not field: + sheet.write(row_num, col_num, " ", format5) + else: + sheet.write(row_num, col_num, "Yes", format5) + else: + sheet.write(row_num, col_num, record[field][0], format5) + except Exception as e: + if record[field][0]: + sheet.write(row_num, col_num, record[field].name_get()[0][1], format5) + else: + sheet.write(row_num, col_num, "", format5) + col_num+=1 + row_num += occupied_rows + sl_no += 1 + workbook.close() + output.seek(0) + response.stream.write(output.read()) + output.close() + + def create_model_action(self): + """ Create a contextual action for each server action.""" + self.action_button = True + WindowAction = self.env['ir.actions.act_window'] + data = self.env['ir.model.data'] + for rec in self.browse(self._ids): + binding_model_id = rec.model_id.id + model_data_id = data._load_xmlid('excel_report_designer') + res_id = data.browse(model_data_id).res_id + button_name = _('Print Report (%s)') % rec.name + act_id = WindowAction.create({ + 'name': button_name, + 'type': 'ir.actions.act_window', + 'res_model': 'excel.report', + 'binding_model_id': binding_model_id, + 'context': "{'excel' : %d}" % (rec.id), + 'view_mode': 'form,tree', + 'view_id': res_id, + 'target': 'new', + }) + rec.write({ + 'ir_act_server_ref_id': act_id.id, + }) + return True + + def unlink_model_action(self): + """ Remove the contextual actions created for the server actions. """ + self.action_button = False + self.check_access_rights('write', raise_exception=True) + self.filtered('binding_model_id').write({'binding_model_id': False}) + return True + + @api.onchange('fields_ids') + def _onchange_fields_ids(self): + """this is used to find the fields of new models""" + self.fields_ids = [] + if self.fields_ids: + self.field_order = str(self.fields_ids._origin.ids) + + @api.onchange('model_id') + def _onchange_model_id(self): + """this is used to return the fields""" + if self.model_id: + self.name = self.model_id.name + ' Report' + self.fields_ids = False + self.date_field_id = False + return { + 'domain': { + 'fields_ids': [('model_id', '=', self.model_id.id)], + 'date_field_id': [('model_id', '=', self.model_id.id), + ('ttype', 'in', ['date', 'datetime'])], + } + } diff --git a/excel_report_designer/security/ir.model.access.csv b/excel_report_designer/security/ir.model.access.csv new file mode 100644 index 000000000..20713c858 --- /dev/null +++ b/excel_report_designer/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_excel_report_user,excel.report.user,model_excel_report,base.group_user,1,1,1,1 +access_report_excel_user,report.excel.user,model_report_excel,base.group_user,1,1,1,1 \ No newline at end of file diff --git a/excel_report_designer/static/description/assets/icons/check.png b/excel_report_designer/static/description/assets/icons/check.png new file mode 100755 index 000000000..c8e85f51d Binary files /dev/null and b/excel_report_designer/static/description/assets/icons/check.png differ diff --git a/excel_report_designer/static/description/assets/icons/chevron.png b/excel_report_designer/static/description/assets/icons/chevron.png new file mode 100755 index 000000000..2089293d6 Binary files /dev/null and b/excel_report_designer/static/description/assets/icons/chevron.png differ diff --git a/excel_report_designer/static/description/assets/icons/cogs.png b/excel_report_designer/static/description/assets/icons/cogs.png new file mode 100755 index 000000000..95d0bad62 Binary files /dev/null and b/excel_report_designer/static/description/assets/icons/cogs.png differ diff --git a/excel_report_designer/static/description/assets/icons/consultation.png b/excel_report_designer/static/description/assets/icons/consultation.png new file mode 100755 index 000000000..8319d4baa Binary files /dev/null and b/excel_report_designer/static/description/assets/icons/consultation.png differ diff --git a/excel_report_designer/static/description/assets/icons/ecom-black.png b/excel_report_designer/static/description/assets/icons/ecom-black.png new file mode 100755 index 000000000..a9385ff13 Binary files /dev/null and b/excel_report_designer/static/description/assets/icons/ecom-black.png differ diff --git a/excel_report_designer/static/description/assets/icons/education-black.png b/excel_report_designer/static/description/assets/icons/education-black.png new file mode 100755 index 000000000..3eb09b27b Binary files /dev/null and b/excel_report_designer/static/description/assets/icons/education-black.png differ diff --git a/excel_report_designer/static/description/assets/icons/hotel-black.png b/excel_report_designer/static/description/assets/icons/hotel-black.png new file mode 100755 index 000000000..130f613be Binary files /dev/null and b/excel_report_designer/static/description/assets/icons/hotel-black.png differ diff --git a/excel_report_designer/static/description/assets/icons/license.png b/excel_report_designer/static/description/assets/icons/license.png new file mode 100755 index 000000000..a5869797e Binary files /dev/null and b/excel_report_designer/static/description/assets/icons/license.png differ diff --git a/excel_report_designer/static/description/assets/icons/lifebuoy.png b/excel_report_designer/static/description/assets/icons/lifebuoy.png new file mode 100755 index 000000000..658d56ccc Binary files /dev/null and b/excel_report_designer/static/description/assets/icons/lifebuoy.png differ diff --git a/excel_report_designer/static/description/assets/icons/logo.png b/excel_report_designer/static/description/assets/icons/logo.png new file mode 100755 index 000000000..478462d3e Binary files /dev/null and b/excel_report_designer/static/description/assets/icons/logo.png differ diff --git a/excel_report_designer/static/description/assets/icons/manufacturing-black.png b/excel_report_designer/static/description/assets/icons/manufacturing-black.png new file mode 100755 index 000000000..697eb0e9f Binary files /dev/null and b/excel_report_designer/static/description/assets/icons/manufacturing-black.png differ diff --git a/excel_report_designer/static/description/assets/icons/pos-black.png b/excel_report_designer/static/description/assets/icons/pos-black.png new file mode 100755 index 000000000..97c0f90c1 Binary files /dev/null and b/excel_report_designer/static/description/assets/icons/pos-black.png differ diff --git a/excel_report_designer/static/description/assets/icons/puzzle.png b/excel_report_designer/static/description/assets/icons/puzzle.png new file mode 100755 index 000000000..65cf854e7 Binary files /dev/null and b/excel_report_designer/static/description/assets/icons/puzzle.png differ diff --git a/excel_report_designer/static/description/assets/icons/restaurant-black.png b/excel_report_designer/static/description/assets/icons/restaurant-black.png new file mode 100755 index 000000000..4a35eb939 Binary files /dev/null and b/excel_report_designer/static/description/assets/icons/restaurant-black.png differ diff --git a/excel_report_designer/static/description/assets/icons/service-black.png b/excel_report_designer/static/description/assets/icons/service-black.png new file mode 100755 index 000000000..301ab51cb Binary files /dev/null and b/excel_report_designer/static/description/assets/icons/service-black.png differ diff --git a/excel_report_designer/static/description/assets/icons/trading-black.png b/excel_report_designer/static/description/assets/icons/trading-black.png new file mode 100755 index 000000000..9398ba2f1 Binary files /dev/null and b/excel_report_designer/static/description/assets/icons/trading-black.png differ diff --git a/excel_report_designer/static/description/assets/icons/training.png b/excel_report_designer/static/description/assets/icons/training.png new file mode 100755 index 000000000..884ca024d Binary files /dev/null and b/excel_report_designer/static/description/assets/icons/training.png differ diff --git a/excel_report_designer/static/description/assets/icons/update.png b/excel_report_designer/static/description/assets/icons/update.png new file mode 100755 index 000000000..ecbc5a01a Binary files /dev/null and b/excel_report_designer/static/description/assets/icons/update.png differ diff --git a/excel_report_designer/static/description/assets/icons/user.png b/excel_report_designer/static/description/assets/icons/user.png new file mode 100755 index 000000000..6ffb23d9f Binary files /dev/null and b/excel_report_designer/static/description/assets/icons/user.png differ diff --git a/excel_report_designer/static/description/assets/icons/wrench.png b/excel_report_designer/static/description/assets/icons/wrench.png new file mode 100755 index 000000000..6c04dea0f Binary files /dev/null and b/excel_report_designer/static/description/assets/icons/wrench.png differ diff --git a/excel_report_designer/static/description/assets/misc/categories.png b/excel_report_designer/static/description/assets/misc/categories.png new file mode 100755 index 000000000..bedf1e0b1 Binary files /dev/null and b/excel_report_designer/static/description/assets/misc/categories.png differ diff --git a/excel_report_designer/static/description/assets/misc/check-box.png b/excel_report_designer/static/description/assets/misc/check-box.png new file mode 100755 index 000000000..42caf24b9 Binary files /dev/null and b/excel_report_designer/static/description/assets/misc/check-box.png differ diff --git a/excel_report_designer/static/description/assets/misc/compass.png b/excel_report_designer/static/description/assets/misc/compass.png new file mode 100755 index 000000000..d5fed8faa Binary files /dev/null and b/excel_report_designer/static/description/assets/misc/compass.png differ diff --git a/excel_report_designer/static/description/assets/misc/corporate.png b/excel_report_designer/static/description/assets/misc/corporate.png new file mode 100755 index 000000000..2eb13edbf Binary files /dev/null and b/excel_report_designer/static/description/assets/misc/corporate.png differ diff --git a/excel_report_designer/static/description/assets/misc/customer-support.png b/excel_report_designer/static/description/assets/misc/customer-support.png new file mode 100755 index 000000000..79efc72ed Binary files /dev/null and b/excel_report_designer/static/description/assets/misc/customer-support.png differ diff --git a/excel_report_designer/static/description/assets/misc/cybrosys-logo.png b/excel_report_designer/static/description/assets/misc/cybrosys-logo.png new file mode 100755 index 000000000..cc3cc0ccf Binary files /dev/null and b/excel_report_designer/static/description/assets/misc/cybrosys-logo.png differ diff --git a/excel_report_designer/static/description/assets/misc/features.png b/excel_report_designer/static/description/assets/misc/features.png new file mode 100755 index 000000000..b41769f77 Binary files /dev/null and b/excel_report_designer/static/description/assets/misc/features.png differ diff --git a/excel_report_designer/static/description/assets/misc/logo.png b/excel_report_designer/static/description/assets/misc/logo.png new file mode 100755 index 000000000..478462d3e Binary files /dev/null and b/excel_report_designer/static/description/assets/misc/logo.png differ diff --git a/excel_report_designer/static/description/assets/misc/pictures.png b/excel_report_designer/static/description/assets/misc/pictures.png new file mode 100755 index 000000000..56d255fe9 Binary files /dev/null and b/excel_report_designer/static/description/assets/misc/pictures.png differ diff --git a/excel_report_designer/static/description/assets/misc/pie-chart.png b/excel_report_designer/static/description/assets/misc/pie-chart.png new file mode 100755 index 000000000..426e05244 Binary files /dev/null and b/excel_report_designer/static/description/assets/misc/pie-chart.png differ diff --git a/excel_report_designer/static/description/assets/misc/right-arrow.png b/excel_report_designer/static/description/assets/misc/right-arrow.png new file mode 100755 index 000000000..730984a06 Binary files /dev/null and b/excel_report_designer/static/description/assets/misc/right-arrow.png differ diff --git a/excel_report_designer/static/description/assets/misc/star.png b/excel_report_designer/static/description/assets/misc/star.png new file mode 100755 index 000000000..2eb9ab29f Binary files /dev/null and b/excel_report_designer/static/description/assets/misc/star.png differ diff --git a/excel_report_designer/static/description/assets/misc/support.png b/excel_report_designer/static/description/assets/misc/support.png new file mode 100755 index 000000000..4f18b8b82 Binary files /dev/null and b/excel_report_designer/static/description/assets/misc/support.png differ diff --git a/excel_report_designer/static/description/assets/misc/whatsapp.png b/excel_report_designer/static/description/assets/misc/whatsapp.png new file mode 100755 index 000000000..d513a5356 Binary files /dev/null and b/excel_report_designer/static/description/assets/misc/whatsapp.png differ diff --git a/excel_report_designer/static/description/assets/modules/l1.png b/excel_report_designer/static/description/assets/modules/l1.png new file mode 100644 index 000000000..6bc155887 Binary files /dev/null and b/excel_report_designer/static/description/assets/modules/l1.png differ diff --git a/excel_report_designer/static/description/assets/modules/l2.png b/excel_report_designer/static/description/assets/modules/l2.png new file mode 100644 index 000000000..3599974eb Binary files /dev/null and b/excel_report_designer/static/description/assets/modules/l2.png differ diff --git a/excel_report_designer/static/description/assets/modules/l3.png b/excel_report_designer/static/description/assets/modules/l3.png new file mode 100644 index 000000000..f5174ab22 Binary files /dev/null and b/excel_report_designer/static/description/assets/modules/l3.png differ diff --git a/excel_report_designer/static/description/assets/modules/l4.png b/excel_report_designer/static/description/assets/modules/l4.png new file mode 100644 index 000000000..4fbe85ac1 Binary files /dev/null and b/excel_report_designer/static/description/assets/modules/l4.png differ diff --git a/excel_report_designer/static/description/assets/modules/l5.png b/excel_report_designer/static/description/assets/modules/l5.png new file mode 100644 index 000000000..53de17dbf Binary files /dev/null and b/excel_report_designer/static/description/assets/modules/l5.png differ diff --git a/excel_report_designer/static/description/assets/modules/l6.png b/excel_report_designer/static/description/assets/modules/l6.png new file mode 100644 index 000000000..e20126a45 Binary files /dev/null and b/excel_report_designer/static/description/assets/modules/l6.png differ diff --git a/excel_report_designer/static/description/assets/screenshots/1.png b/excel_report_designer/static/description/assets/screenshots/1.png new file mode 100644 index 000000000..875fe894c Binary files /dev/null and b/excel_report_designer/static/description/assets/screenshots/1.png differ diff --git a/excel_report_designer/static/description/assets/screenshots/2.png b/excel_report_designer/static/description/assets/screenshots/2.png new file mode 100644 index 000000000..6e90f76f0 Binary files /dev/null and b/excel_report_designer/static/description/assets/screenshots/2.png differ diff --git a/excel_report_designer/static/description/assets/screenshots/3.png b/excel_report_designer/static/description/assets/screenshots/3.png new file mode 100644 index 000000000..a11f23b3f Binary files /dev/null and b/excel_report_designer/static/description/assets/screenshots/3.png differ diff --git a/excel_report_designer/static/description/assets/screenshots/4.png b/excel_report_designer/static/description/assets/screenshots/4.png new file mode 100644 index 000000000..37bcbed20 Binary files /dev/null and b/excel_report_designer/static/description/assets/screenshots/4.png differ diff --git a/excel_report_designer/static/description/assets/screenshots/5.png b/excel_report_designer/static/description/assets/screenshots/5.png new file mode 100644 index 000000000..3b21f5755 Binary files /dev/null and b/excel_report_designer/static/description/assets/screenshots/5.png differ diff --git a/excel_report_designer/static/description/assets/screenshots/6.png b/excel_report_designer/static/description/assets/screenshots/6.png new file mode 100644 index 000000000..2f9a23b5c Binary files /dev/null and b/excel_report_designer/static/description/assets/screenshots/6.png differ diff --git a/excel_report_designer/static/description/assets/screenshots/7.png b/excel_report_designer/static/description/assets/screenshots/7.png new file mode 100644 index 000000000..845b4077b Binary files /dev/null and b/excel_report_designer/static/description/assets/screenshots/7.png differ diff --git a/excel_report_designer/static/description/assets/screenshots/8.png b/excel_report_designer/static/description/assets/screenshots/8.png new file mode 100644 index 000000000..021179057 Binary files /dev/null and b/excel_report_designer/static/description/assets/screenshots/8.png differ diff --git a/excel_report_designer/static/description/assets/screenshots/9.png b/excel_report_designer/static/description/assets/screenshots/9.png new file mode 100644 index 000000000..9774f1031 Binary files /dev/null and b/excel_report_designer/static/description/assets/screenshots/9.png differ diff --git a/excel_report_designer/static/description/assets/screenshots/hero.gif b/excel_report_designer/static/description/assets/screenshots/hero.gif new file mode 100644 index 000000000..09fc47add Binary files /dev/null and b/excel_report_designer/static/description/assets/screenshots/hero.gif differ diff --git a/excel_report_designer/static/description/banner.png b/excel_report_designer/static/description/banner.png new file mode 100644 index 000000000..fe7174641 Binary files /dev/null and b/excel_report_designer/static/description/banner.png differ diff --git a/excel_report_designer/static/description/icon.png b/excel_report_designer/static/description/icon.png new file mode 100644 index 000000000..74969c0c9 Binary files /dev/null and b/excel_report_designer/static/description/icon.png differ diff --git a/excel_report_designer/static/description/index.html b/excel_report_designer/static/description/index.html new file mode 100755 index 000000000..8dad44328 --- /dev/null +++ b/excel_report_designer/static/description/index.html @@ -0,0 +1,663 @@ +
+ +
+ +
+
+ Community +
+
+ Enterprise +
+
+ Odoo sh +
+
+
+ +
+
+
+ +

Excel Report Designer

+

Create Customised Excel Reports for Any Models

+ + +
+
+
+
+ +
+
+ +
+

+ Explore This + Module

+
+ + + + +
+
+ +
+

+ Overview +

+
+
+
In this Excel Report Designer module, we can create reports in XLSX format for any model with any fields in the model. We can also filter the report based on the date, using any date field in the model. +
+
+ + + +
+
+ +
+

+ Features +

+
+
+
+
+ + Fully configurable XLSX reports. +
+
+
+
+ + Custom report name. +
+
+
+
+ + Filter report data based on any date field. +
+
+
+
+ + Reports menu under the action menu. +
+
+
+ + + +
+
+ +
+

+ Screenshots +

+
+
+
+
+

Report Configuration

+

+ The reports can be configured and printed using the 'Excel Report Designer' menu at Settings. Select the desired model on which you want to create report, select the required fields and filter using any of the date field in the model. +

+ +
+
+

+ Configure the report for purchase +

+ +
+
+

+ Configure the report for Invoice +

+ +
+
+

+ Print report from the configuration form and also add as a action menu. +

+ +
+
+

+ Go to Purchase -> Purchase order and select orders to print the report from the action menu. +

+ +
+
+

+ Confirmation wizard for printing the report. +

+ +
+
+

+ Printed report. +

+ +
+
+ + + +
+
+

Suggested Products

+
+ +
+
+ + + + +
+
+ +
+

+ Our Services +

+
+ +
+
+
+
+ +
+
+ Odoo + Customization
+
+ +
+
+ +
+
+ Odoo + Implementation
+
+ +
+
+ +
+
+ Odoo + Support
+
+ + +
+
+ +
+
+ Hire + Odoo + Developer
+
+ +
+
+ +
+
+ Odoo + Integration
+
+ +
+
+ +
+
+ Odoo + Migration
+
+ + +
+
+ +
+
+ Odoo + Consultancy
+
+ +
+
+ +
+
+ Odoo + Implementation
+
+ +
+
+ +
+
+ Odoo + Licensing Consultancy
+
+
+ +
+ + + +
+
+ +
+

+ Our + Industries +

+
+ +
+
+
+
+ +
+ Trading +
+

+ Easily procure + and + sell your products

+
+
+ +
+
+ +
+ POS +
+

+ Easy + configuration + and convivial experience

+
+
+ +
+
+ +
+ Education +
+

+ A platform for + educational management

+
+
+ +
+
+ +
+ Manufacturing +
+

+ Plan, track and + schedule your operations

+
+
+ +
+
+ +
+ E-commerce & Website +
+

+ Mobile + friendly, + awe-inspiring product pages

+
+
+ +
+
+ +
+ Service Management +
+

+ Keep track of + services and invoice

+
+
+ +
+
+ +
+ Restaurant +
+

+ Run your bar or + restaurant methodically

+
+
+ +
+
+ +
+ Hotel Management +
+

+ An + all-inclusive + hotel management application

+
+
+
+
+ +
+
+ +
+

+ Support +

+
+
+
+
+
+
+ +
+
+

Need Help?

+

Got questions or need + help? + Get in touch.

+ +

+ odoo@cybrosys.com

+
+
+
+
+
+
+
+ +
+
+

WhatsApp

+

Say hi to us on + WhatsApp!

+ +

+ +91 86068 + 27707

+
+
+
+
+
+
+
+ +
+
+
+ +
diff --git a/excel_report_designer/static/src/js/action_manager.js b/excel_report_designer/static/src/js/action_manager.js new file mode 100644 index 000000000..2c24ca836 --- /dev/null +++ b/excel_report_designer/static/src/js/action_manager.js @@ -0,0 +1,21 @@ +/** @odoo-module */ +import { registry } from "@web/core/registry"; +import { download } from "@web/core/network/download"; +import framework from 'web.framework'; +import session from 'web.session'; +//this is used to call the controller and also passes the report data. +registry.category("ir.actions.report handlers").add("xlsx", async (action) => { + if (action.report_type === 'stock_xlsx') { + framework.blockUI(); + var self = this; + var def = $.Deferred(); + session.get_file({ + url: '/xlsx_reports', + data: action.data, + success: def.resolve.bind(def), + error: (error) => self.call('crash_manager', 'rpc_error', error), + complete: framework.unblockUI, + }); + return def; + } +}); diff --git a/excel_report_designer/views/report_excel_views.xml b/excel_report_designer/views/report_excel_views.xml new file mode 100644 index 000000000..51ba7e909 --- /dev/null +++ b/excel_report_designer/views/report_excel_views.xml @@ -0,0 +1,82 @@ + + + + + report.excel.view.form + report.excel + 20 + +
+
+
+ + + +
+
+
+

+ + + +

+
+ + + + + The column order will be as selected in the below + table + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + Select Report + report.excel + tree,form + + + + +
\ No newline at end of file diff --git a/excel_report_designer/wizard/__init__.py b/excel_report_designer/wizard/__init__.py new file mode 100644 index 000000000..86c213682 --- /dev/null +++ b/excel_report_designer/wizard/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# Author: Bhagyadev KP (odoo@cybrosys.com) +# +# This program is free software: you can modify +# it under the terms of the GNU Affero General Public License (AGPL) as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +################################################################################ +from . import excel_report diff --git a/excel_report_designer/wizard/excel_report.py b/excel_report_designer/wizard/excel_report.py new file mode 100644 index 000000000..194a81f97 --- /dev/null +++ b/excel_report_designer/wizard/excel_report.py @@ -0,0 +1,241 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# Author: Bhagyadev KP (odoo@cybrosys.com) +# +# This program is free software: you can modify +# it under the terms of the GNU Affero General Public License (AGPL) as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +################################################################################ +import xlsxwriter +import io +import json +import datetime +from odoo import fields, models +from odoo.tools import date_utils + + +class ExcelReport(models.TransientModel): + """This is used to the wizard class""" + _name = "excel.report" + _description = "excel report" + + def print_excel_report(self): + """this is used to do the report action""" + excel_report_id = self.env['report.excel'].browse( + self._context.get('excel')) + for rec in excel_report_id: + data = { + 'report_name': rec.name, + 'model_name': rec.model_id.model, + 'fields_name': rec.fields_ids.mapped('name'), + 'field_label': rec.fields_ids.mapped('field_description'), + 'date_field_id': rec.date_field_id.name, + 'date_name': rec.date_field_id.field_description, + 'start_date': rec.start_date, + 'end_date': rec.end_date, + 'field_order': rec.field_order, + 'active_model_id': self.env.context['active_ids'] + } + return { + 'type': 'ir.actions.report', + 'data': {'model': 'excel.report', + 'options': json.dumps(data, + default=date_utils.json_default), + 'output_format': 'xlsx', + 'report_name': rec.name, + }, + 'report_type': 'stock_xlsx', + } + + def get_xlsx_report(self, data, response): + """This is used to prin the report for selected records.""" + output = io.BytesIO() + workbook = xlsxwriter.Workbook(output, {'in_memory': True}) + sheet = workbook.add_worksheet() + # Formats + format1 = workbook.add_format( + {'font_size': 15, 'align': 'center', 'bold': True}) + format1.set_font_color('#000080') + format2 = workbook.add_format( + {'font_size': 11, 'bold': True, 'border': 1, 'bg_color': '#928E8E'}) + format4 = workbook.add_format( + {'font_size': 10, 'num_format': 'yyyy-m-d', 'align': 'center', + 'bold': True}) + format5 = workbook.add_format( + {'font_size': 10, 'border': 1, 'text_wrap': True}) + format6 = workbook.add_format({'font_size': 10, 'bold': True}) + format8 = workbook.add_format({'font_size': 10, 'border': 1}) + format9 = workbook.add_format( + {'font_size': 10, 'num_format': 'yyyy-m-d'}) + format10 = workbook.add_format( + {'font_size': 10, 'num_format': 'yyyy-m-d', 'border': 1}) + format2.set_align('center') + format4.set_align('right') + format6.set_align('right') + format8.set_align('left') + sheet.merge_range(1, 1, 1, len(data['field_label']) + 1, + data['report_name'], format1) + sheet.write(2, 0, "Date :", format4) + sheet.write(2, 1, fields.Datetime.today(), format4) + if data['date_field_id']: + sheet.write(3, 0, data['date_name'], format4) + if data['start_date']: + sheet.write(3, 1, "From:", format4) + sheet.write(3, 2, data['start_date'], format9) + else: + sheet.write(3, 2, "", format9) + if data['end_date']: + sheet.write(3, 3, "To:", format4) + sheet.write(3, 4, data['end_date'], format9) + else: + sheet.write(3, 4, "", format9) + sl_no = 1 + sheet.write(5, 1, "SL No", format2) + row_num = 5 + col_num = 2 + order = data['field_order'].strip('][').split(', ') + for field_id in order: + field_name = self.env['ir.model.fields'].browse( + int(field_id)).field_description + sheet.write(row_num, col_num, field_name, format2) + col_num += 1 + row_num += 1 + records = [] + if data['date_field_id']: + if data['start_date'] and data['end_date']: + records = self.env[data['model_name']].search([ + (data['date_field_id'], '>=', data['start_date']), + ('id', 'in', data['active_model_id']), + (data['date_field_id'], '<=', data['end_date'])]) + elif data['start_date'] and not data['end_date']: + records = self.env[data['model_name']].search([ + (data['date_field_id'], '>=', data['start_date']), + ('id', 'in', data['active_model_id'])]) + elif not data['start_date'] and data['end_date']: + records = self.env[data['model_name']].search([ + (data['date_field_id'], '<=', data['end_date']), + ('id', 'in', data['active_model_id'])]) + else: + records = self.env[data['model_name']].search( + [('id', 'in', data['active_model_id'])]) + new_table = [] + for record in records: + order = data['field_order'].strip('][').split(', ') + record_dict = {} + for field_id in order: + field = self.env['ir.model.fields'].browse(int(field_id)) + field_name = field.name + field_type = self.env['ir.model.fields'].browse( + int(field_id)).ttype + if field_type in ['many2many']: + one2many_values = ', '.join( + record[field_name].mapped('name')) + record_dict[field] = [one2many_values] + elif field_type in ['one2many']: + # if record[field_name]: + o2m_list = [] + for rec in record[field_name]: + if rec: + o2m_list.append(rec) + else: + o2m_list.append('') + record_dict[field] = o2m_list + else: + record_dict[field] = [record[field_name]] + new_table.append(record_dict) + for record in new_table: + col_num = 1 + sheet.write(row_num, col_num, sl_no, format5) + col_num += 1 + occupied_rows = max(len(value) for value in record.values()) + for field in record: + field_type = self.env['ir.model.fields'].browse( + int(field.id)).ttype + if not field_type in ['one2many', 'many2many']: + try: + if isinstance(record[field][0], datetime.date): + sheet.write(row_num, col_num, record[field][0], + format10) + elif isinstance(record[field][0], bool): + if not field: + sheet.write(row_num, col_num, " ", format5) + else: + sheet.write(row_num, col_num, "Yes", format5) + else: + sheet.write(row_num, col_num, record[field][0], + format5) + except Exception as e: + if record[field][0]: + sheet.write(row_num, col_num, + record[field][0].name_get()[0][1], + format5) + else: + sheet.write(row_num, col_num, "", + format5) + elif field_type == 'one2many': + for i in range(occupied_rows): + if len(record[field]) > i: + try: + if isinstance(record[field][i], datetime.date): + sheet.write(row_num + i, col_num, + record[field][i], format10) + elif isinstance(record[field][i], bool): + if not field: + sheet.write(row_num + i, col_num, "NO", + format5) + else: + sheet.write(row_num + i, col_num, "Yes", + format5) + else: + sheet.write(row_num + i, col_num, + record[field][i], format5) + except Exception as e: + if record[field][i]: + sheet.write(row_num + i, col_num, + record[field][i].name_get()[0][ + 1], format5) + else: + sheet.write(row_num + i, col_num, "", + format5) + elif field_type == 'many2many': + if record[field]: + try: + if isinstance(record[field], datetime.date): + sheet.write(row_num, col_num, record[field][0], + format10) + elif isinstance(record[field], bool): + if not field: + sheet.write(row_num, col_num, " ", format5) + else: + sheet.write(row_num, col_num, "Yes", + format5) + else: + sheet.write(row_num, col_num, record[field][0], + format5) + except Exception as e: + if record[field][0]: + sheet.write(row_num, col_num, + record[field].name_get()[0][1], + format5) + else: + sheet.write(row_num, col_num, "", format5) + col_num += 1 + row_num += occupied_rows + sl_no += 1 + workbook.close() + output.seek(0) + response.stream.write(output.read()) + output.close() diff --git a/excel_report_designer/wizard/excel_report_views.xml b/excel_report_designer/wizard/excel_report_views.xml new file mode 100644 index 000000000..89b180ad2 --- /dev/null +++ b/excel_report_designer/wizard/excel_report_views.xml @@ -0,0 +1,18 @@ + + + + + excel.report.view.form + excel.report + +
+

Do you want to print the report?

+ +
+
+
+
\ No newline at end of file