diff --git a/pdf_report_designer/README.rst b/pdf_report_designer/README.rst new file mode 100755 index 000000000..f20f1daf6 --- /dev/null +++ b/pdf_report_designer/README.rst @@ -0,0 +1,47 @@ +.. image:: https://img.shields.io/badge/licence-LGPL--3-green.svg + :target: https://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 + +PDF Report Designer +=================== +This module helps in generating customized PDF reports for any model. + +Configuration +============= +The user should be added to the security group: Administrator(Settings/Base) +inorder to get access to the new menu. + +Company +------- +* `Cybrosys Techno Solutions `__ + +License +------- +General Public License, Version 3 (LGPL v3). +( https://www.gnu.org/licenses/lgpl-3.0-standalone.html) + +Credits +------- +Developer : (V16) Prasanna Kumara B, 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 support and more information, please visit `Our Website `__ + +Further information +=================== +HTML Description: ``__ diff --git a/pdf_report_designer/__init__.py b/pdf_report_designer/__init__.py new file mode 100644 index 000000000..1d8669435 --- /dev/null +++ b/pdf_report_designer/__init__.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Prasanna Kumara B (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################### +from . import models +from . import wizard +from odoo import api, SUPERUSER_ID + + +def _uninstall_hook(cr, registry): + """Unlink all the window action while uninstall this module """ + env = api.Environment(cr, SUPERUSER_ID, {}) + window_action = env['ir.actions.act_window'].search( + [('is_action_created_from_pdf_report', '!=', False)]) + for rec in window_action: + rec.unlink() diff --git a/pdf_report_designer/__manifest__.py b/pdf_report_designer/__manifest__.py new file mode 100644 index 000000000..762047a37 --- /dev/null +++ b/pdf_report_designer/__manifest__.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Prasanna Kumara B (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################### +{ + 'name': 'PDF Report Designer', + 'version': '16.0.1.0.0', + 'category': 'Extra Tools', + 'summary': 'Create Customised PDF Reports for Any Models', + 'description': """This module helps in generating customized + PDF reports for any model""", + '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_pdf_views.xml', + 'wizard/pdf_report_views.xml', + 'report/report_pdf_reports.xml', + 'report/pdf_report_reports.xml', + 'report/pdf_report_templates.xml', + ], + 'images': ['static/description/banner.png'], + 'license': 'LGPL-3', + 'uninstall_hook': '_uninstall_hook', + 'installable': True, + 'auto_install': False, + 'application': False, +} diff --git a/pdf_report_designer/doc/RELEASE_NOTES.md b/pdf_report_designer/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..d2fb90018 --- /dev/null +++ b/pdf_report_designer/doc/RELEASE_NOTES.md @@ -0,0 +1,5 @@ +## Module +#### 27.05.2024 +#### Version 16.0.1.0.0 +#### ADD +- Initial commit for PDF Report Designer diff --git a/pdf_report_designer/models/__init__.py b/pdf_report_designer/models/__init__.py new file mode 100644 index 000000000..a3164c68e --- /dev/null +++ b/pdf_report_designer/models/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Prasanna Kumara B (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################### +from . import report_pdf +from . import report_pdf_fields +from . import ir_actions_act_window diff --git a/pdf_report_designer/models/ir_actions_act_window.py b/pdf_report_designer/models/ir_actions_act_window.py new file mode 100644 index 000000000..7a6e6fcae --- /dev/null +++ b/pdf_report_designer/models/ir_actions_act_window.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Prasanna Kumara B (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################### +from odoo import fields, models + + +class IrActionsActWindow(models.Model): + """Adding a field to the model ir.actions.act_window to know whether this + action is created as a part of this module""" + + _inherit = 'ir.actions.act_window' + + is_action_created_from_pdf_report = fields.Boolean(string='Is created from ' + 'Pdf Report Design', + help='Used to know' + ' whether this' + ' action is ' + 'created from' + ' the Pdf Report' + ' Design') diff --git a/pdf_report_designer/models/report_pdf.py b/pdf_report_designer/models/report_pdf.py new file mode 100644 index 000000000..bd5cf22e1 --- /dev/null +++ b/pdf_report_designer/models/report_pdf.py @@ -0,0 +1,321 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Prasanna Kumara B (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################### +from collections import OrderedDict +from odoo import api, exceptions, fields, models, _ +from odoo.exceptions import ValidationError + + +class ReportPDF(models.Model): + """Class to handle PDF Report model""" + _name = 'report.pdf' + _description = 'PDF Reports' + _order = 'id DESC' + + name = fields.Char(string='Name', help="Name of the report") + model_id = fields.Many2one('ir.model', string='Model', + required=True, + ondelete="cascade", help="Name of the model") + fields_ids = fields.One2many('report.pdf.field', + 'report_id', + string='Fields', + required=True, ondelete="cascade", + help="Name of the fields") + date_field_id = fields.Many2one('ir.model.fields', + string='Date Filter', + ondelete="cascade", + help="Name of the fields", + ) + start_date = fields.Date(string='Start Date', help="Set the start date") + end_date = fields.Date(string='End Date', help="Set the end date") + field_order = fields.Char(default='[]', string="First Order", + help="First order") + action_button = fields.Boolean(default=False, string="Action button", + help="Action button") + binding_model_id = fields.Many2one('ir.model', + ondelete="cascade", + string="Binding model", + help="Choose binding model") + binding_type = fields.Selection([('action', 'Action'), + ('report', 'Report')], + required=True, default='action', + string="Binding Type", + help="Choose binding type") + ir_act_server_ref_id = fields.Many2one('ir.actions.act_window', + readonly=True, copy=False, + string="Server Id", + help="We can get the server id") + + @api.constrains('start_date', 'end_date') + def _check_start_date_end_date(self): + """This will give validation at the time of end date and start + date have any problem or mismatch""" + if self.start_date and self.end_date: + if self.start_date > self.end_date or fields.Date.today() > \ + self.end_date: + raise ValidationError( + 'The Start Date And End Date Is Misplaced') + + @api.constrains('fields_ids') + def _check_fields_ids(self): + """ Checks whether the user has entered least one fields for the + report""" + if not self.fields_ids: + raise exceptions.ValidationError('Please select a field.') + + def action_print_report(self): + """ When the user requests to print the report, this function will be + called. Parameters and return values of the function is noted below. + @param self: The current report.pdf record. @return: A dictionary + with report data like field headers and field datas. + """ + for rec in self: + domain = [] + if rec.date_field_id and rec.start_date: + domain.append((rec.date_field_id.name, '>=', rec.start_date)) + if rec.date_field_id and rec.end_date: + domain.append((rec.date_field_id.name, '<=', rec.end_date)) + if rec.date_field_id and(rec.start_date and rec.end_date): + domain = [(rec.date_field_id.name, '>=', rec.start_date), + (rec.date_field_id.name, '<=', rec.end_date)] + model_data = self.env[rec.model_id.model].search(domain) + table_data = [] + child_table_data = [] + for record in model_data: + rec_currency_symbol = record.currency_id.symbol + data_list = [] + list_b = [] + order = rec.field_order.strip('][').split(', ') + for field_id in order: + field_obj = self.env['ir.model.fields'].browse( + int(field_id)) + field_name = field_obj.name + if field_obj.ttype == 'datetime': + field_data = record[field_name].strftime("%d/%m/%Y") + elif field_obj.ttype == 'boolean': + if not record[field_name]: + field_data = "No" + else: + field_data = "Yes" + elif field_obj.ttype == 'many2one' or field_obj.ttype == 'many2one_reference': + if record[field_name]: + field_data = record[field_name].name_get()[0][1] + else: + field_data = "Null" + elif field_obj.ttype == 'many2many': + if record[field_name]: + field_data = "" + for count, value in enumerate(record[field_name]): + if not count == len(record[field_name]) - 1: + field_data += value.name_get()[0][1] + ", " + else: + field_data += value.name_get()[0][1] + else: + field_data = "Null" + elif field_obj.ttype == 'one2many': + if record[field_name]: + child_fields = rec.fields_ids.one2many_model_field_ids + if child_fields: + field_data = "one2many" + list_b = [] + for o2m_c_field in record[field_name]: + list_a = [] + for c_field in child_fields: + c_field_name = c_field.name + if c_field.ttype == 'datetime': + child_field_data = o2m_c_field[ + c_field_name].strftime( + "%d/%m/%Y") + elif c_field.ttype == 'boolean': + if o2m_c_field[c_field_name]: + child_field_data = "Yes" + else: + child_field_data = "No" + elif c_field.ttype in ( + 'many2one', + 'many2one_reference'): + if o2m_c_field[c_field_name]: + child_field_data = o2m_c_field[ + c_field_name].name_get()[0][ + 1] + else: + child_field_data = "Null" + elif c_field.ttype in ( + 'many2one', + 'many2one_reference'): + if o2m_c_field[c_field_name]: + child_field_data = o2m_c_field[ + c_field_name].name_get()[0][ + 1] + else: + child_field_data = "Null" + elif c_field.ttype in ( + 'many2many', 'one2many'): + if o2m_c_field[c_field_name]: + child_field_data = "" + for c_count, c_value in enumerate( + o2m_c_field[ + c_field_name]): + if not c_count == len( + o2m_c_field[ + c_field_name]) - 1: + child_field_data += \ + c_value.name_get()[ + 0][ + 1] + ", " + else: + child_field_data += \ + c_value.name_get()[ + 0][1] + else: + child_field_data = "Null" + else: + child_field_data = o2m_c_field[ + c_field_name] + list_a.append(child_field_data) + field_data = list_a + list_b.append(list_a) + else: + field_data = "" + for count, value in enumerate( + record[field_name]): + if not count == len(record[field_name]) - 1: + field_data += value.name_get()[0][ + 1] + ", " + else: + field_data += value.name_get()[0][1] + else: + field_data = "Null" + elif field_obj.ttype == 'monetary': + if record.currency_id.position == 'before': + field_data = record.currency_id.symbol+str(record[field_name]) + else: + field_data = str(record[field_name])+record.currency_id.symbol + else: + field_data = record[field_name] + data_list.append(field_data) + table_data.append(data_list) + child_table_data.append(list_b) + child_label = rec.fields_ids.one2many_model_field_ids + child_field_label = "" + if child_label: + child_field_label = child_label.mapped('field_description') + field_heading = {} + for field in rec.fields_ids.report_field_id: + field_heading.update({field.field_description: ( + field.ttype, field.field_description,rec_currency_symbol)}) + ordered_field_heading = OrderedDict( + list(field_heading.items())) + data = { + 'report_name': rec.name, + 'model_name': rec.model_id.model, + 'fields_name': rec.fields_ids.report_field_id.mapped('name'), + 'field_label': ordered_field_heading, + '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, + 'table_data': table_data, + 'child_field_data': child_table_data, + 'child_field_label': child_field_label, + 'today_date': fields.Datetime.now() + } + return self.env.ref( + 'pdf_report_designer.action_report_print_pdf_designer').report_action( + self, data=data) + + def action_unlink_action(self): + self.action_button = False + self.env['ir.actions.act_window'].search( + [('name', '=', self.name)]) + return { + 'type': 'ir.actions.client', + 'tag': 'reload', + } + + def action_create_model(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('pdf_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, + 'is_action_created_from_pdf_report':True, + 'type': 'ir.actions.act_window', + 'res_model': 'pdf.report', + 'binding_model_id': binding_model_id, + 'context': "{'pdf' : %d}" % rec.id, + 'view_mode': 'form,tree', + 'view_id': res_id, + 'target': 'new', + }) + rec.write({ + 'ir_act_server_ref_id': act_id.id, + }) + return { + 'type': 'ir.actions.client', + 'tag': 'reload', + } + + @api.onchange('fields_ids') + def _onchange_fields_ids(self): + """ + This method is used to create a list of selected fields ids + @param self: object pointer + """ + self.fields_ids = [] + if self.fields_ids: + self.field_order = str(self.fields_ids.report_field_id._origin.ids) + + @api.onchange('model_id') + def _onchange_model_id(self): + """ + This method is used to return domain on date_field_id on change of + model_id @param self: object pointer @return: returns a domain on + date_field_id field based on selected model id.""" + if self.model_id: + self.fields_ids = False + self.date_field_id = False + return { + 'domain': { + 'date_field_id': [('model_id', '=', self.model_id.id), + ('ttype', 'in', ['date', 'datetime'])], + } + } + + def unlink(self): + """ Regular unlink method, but make sure to clear the caches. """ + for attachment in self: + action_rec = _('Print Report (%s)') % attachment.name + actions = self.env['ir.actions.act_window'].search( + [('name', '=', action_rec)]) + actions.unlink() + super(ReportPDF, self).unlink() + return { + 'type': 'ir.actions.client', + 'tag': 'reload', + } diff --git a/pdf_report_designer/models/report_pdf_fields.py b/pdf_report_designer/models/report_pdf_fields.py new file mode 100644 index 000000000..dacbf2e88 --- /dev/null +++ b/pdf_report_designer/models/report_pdf_fields.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Prasanna Kumara B (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################### +from odoo import api, fields, models + + +class ReportPdfFields(models.Model): + """Class to handle fields of selected model in report form""" + _name = 'report.pdf.field' + _description = 'PDF Reports Fields' + + report_field_id = fields.Many2one('ir.model.fields', + string="Field", help="Choose fields") + report_id = fields.Many2one('report.pdf', + string="Relation Field", + help="Relational Field") + field_label = fields.Char(string="Field Label", + related='report_field_id.field_description', + help="Label for field") + field_type = fields.Selection(string="Field Type", + related='report_field_id.ttype', + help="Type of the field") + field_model = fields.Char(string="Field Type", + related='report_field_id.model', help="Model") + field_relation = fields.Char(string="Field Type", + related='report_field_id.relation', + help="Field relation") + one2many_model_field_ids = fields.Many2many('ir.model.fields', + 'ir_model_fields_report_' + 'pdf_field_rel', + 'one2many_id', + 'many2many_ids', + string="Model Fields", + help="One2many model fields") + + @api.onchange('report_field_id') + def _onchange_report_field_id(self): + """ + Returns a domain on change of report_field_id to itself. @param self: + object pointer. @return: returns a domain to report_field_id field + based on selected model. + """ + if self.report_id.model_id: + return { + 'domain': { + 'report_field_id': [ + ('model_id', '=', self.report_id.model_id.id), + ('store', '=', True)], + } + } diff --git a/pdf_report_designer/report/pdf_report_reports.xml b/pdf_report_designer/report/pdf_report_reports.xml new file mode 100644 index 000000000..6b0926042 --- /dev/null +++ b/pdf_report_designer/report/pdf_report_reports.xml @@ -0,0 +1,11 @@ + + + + + PDF Reports + pdf.report + qweb-pdf + pdf_report_designer.report_pdf_designer + pdf_report_designer.report_pdf_designer + + diff --git a/pdf_report_designer/report/pdf_report_templates.xml b/pdf_report_designer/report/pdf_report_templates.xml new file mode 100644 index 000000000..7322cff26 --- /dev/null +++ b/pdf_report_designer/report/pdf_report_templates.xml @@ -0,0 +1,134 @@ + + + + + diff --git a/pdf_report_designer/report/report_pdf_reports.xml b/pdf_report_designer/report/report_pdf_reports.xml new file mode 100644 index 000000000..858fc5302 --- /dev/null +++ b/pdf_report_designer/report/report_pdf_reports.xml @@ -0,0 +1,11 @@ + + + + + PDF Reports + report.pdf + qweb-pdf + pdf_report_designer.report_pdf_designer + pdf_report_designer.report_pdf_designer + + diff --git a/pdf_report_designer/security/ir.model.access.csv b/pdf_report_designer/security/ir.model.access.csv new file mode 100644 index 000000000..8ca6c64af --- /dev/null +++ b/pdf_report_designer/security/ir.model.access.csv @@ -0,0 +1,4 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_pdf_report_group_user,access.pdf.report.group.user,model_pdf_report,base.group_user,1,1,1,1 +access_report_pdf_group_user,access.report.pdf.group.user,model_report_pdf,base.group_user,1,1,1,1 +access_report_pdf_field_group_user,access.report.pdf.field.group.user,model_report_pdf_field,base.group_user,1,1,1,1 diff --git a/pdf_report_designer/static/description/assets/icons/check.png b/pdf_report_designer/static/description/assets/icons/check.png new file mode 100644 index 000000000..c8e85f51d Binary files /dev/null and b/pdf_report_designer/static/description/assets/icons/check.png differ diff --git a/pdf_report_designer/static/description/assets/icons/chevron.png b/pdf_report_designer/static/description/assets/icons/chevron.png new file mode 100644 index 000000000..2089293d6 Binary files /dev/null and b/pdf_report_designer/static/description/assets/icons/chevron.png differ diff --git a/pdf_report_designer/static/description/assets/icons/cogs.png b/pdf_report_designer/static/description/assets/icons/cogs.png new file mode 100644 index 000000000..95d0bad62 Binary files /dev/null and b/pdf_report_designer/static/description/assets/icons/cogs.png differ diff --git a/pdf_report_designer/static/description/assets/icons/consultation.png b/pdf_report_designer/static/description/assets/icons/consultation.png new file mode 100644 index 000000000..8319d4baa Binary files /dev/null and b/pdf_report_designer/static/description/assets/icons/consultation.png differ diff --git a/pdf_report_designer/static/description/assets/icons/ecom-black.png b/pdf_report_designer/static/description/assets/icons/ecom-black.png new file mode 100644 index 000000000..a9385ff13 Binary files /dev/null and b/pdf_report_designer/static/description/assets/icons/ecom-black.png differ diff --git a/pdf_report_designer/static/description/assets/icons/education-black.png b/pdf_report_designer/static/description/assets/icons/education-black.png new file mode 100644 index 000000000..3eb09b27b Binary files /dev/null and b/pdf_report_designer/static/description/assets/icons/education-black.png differ diff --git a/pdf_report_designer/static/description/assets/icons/hotel-black.png b/pdf_report_designer/static/description/assets/icons/hotel-black.png new file mode 100644 index 000000000..130f613be Binary files /dev/null and b/pdf_report_designer/static/description/assets/icons/hotel-black.png differ diff --git a/pdf_report_designer/static/description/assets/icons/license.png b/pdf_report_designer/static/description/assets/icons/license.png new file mode 100644 index 000000000..a5869797e Binary files /dev/null and b/pdf_report_designer/static/description/assets/icons/license.png differ diff --git a/pdf_report_designer/static/description/assets/icons/lifebuoy.png b/pdf_report_designer/static/description/assets/icons/lifebuoy.png new file mode 100644 index 000000000..658d56ccc Binary files /dev/null and b/pdf_report_designer/static/description/assets/icons/lifebuoy.png differ diff --git a/pdf_report_designer/static/description/assets/icons/manufacturing-black.png b/pdf_report_designer/static/description/assets/icons/manufacturing-black.png new file mode 100644 index 000000000..697eb0e9f Binary files /dev/null and b/pdf_report_designer/static/description/assets/icons/manufacturing-black.png differ diff --git a/pdf_report_designer/static/description/assets/icons/pos-black.png b/pdf_report_designer/static/description/assets/icons/pos-black.png new file mode 100644 index 000000000..97c0f90c1 Binary files /dev/null and b/pdf_report_designer/static/description/assets/icons/pos-black.png differ diff --git a/pdf_report_designer/static/description/assets/icons/puzzle.png b/pdf_report_designer/static/description/assets/icons/puzzle.png new file mode 100644 index 000000000..65cf854e7 Binary files /dev/null and b/pdf_report_designer/static/description/assets/icons/puzzle.png differ diff --git a/pdf_report_designer/static/description/assets/icons/restaurant-black.png b/pdf_report_designer/static/description/assets/icons/restaurant-black.png new file mode 100644 index 000000000..4a35eb939 Binary files /dev/null and b/pdf_report_designer/static/description/assets/icons/restaurant-black.png differ diff --git a/pdf_report_designer/static/description/assets/icons/service-black.png b/pdf_report_designer/static/description/assets/icons/service-black.png new file mode 100644 index 000000000..301ab51cb Binary files /dev/null and b/pdf_report_designer/static/description/assets/icons/service-black.png differ diff --git a/pdf_report_designer/static/description/assets/icons/trading-black.png b/pdf_report_designer/static/description/assets/icons/trading-black.png new file mode 100644 index 000000000..9398ba2f1 Binary files /dev/null and b/pdf_report_designer/static/description/assets/icons/trading-black.png differ diff --git a/pdf_report_designer/static/description/assets/icons/training.png b/pdf_report_designer/static/description/assets/icons/training.png new file mode 100644 index 000000000..884ca024d Binary files /dev/null and b/pdf_report_designer/static/description/assets/icons/training.png differ diff --git a/pdf_report_designer/static/description/assets/icons/update.png b/pdf_report_designer/static/description/assets/icons/update.png new file mode 100644 index 000000000..ecbc5a01a Binary files /dev/null and b/pdf_report_designer/static/description/assets/icons/update.png differ diff --git a/pdf_report_designer/static/description/assets/icons/user.png b/pdf_report_designer/static/description/assets/icons/user.png new file mode 100644 index 000000000..6ffb23d9f Binary files /dev/null and b/pdf_report_designer/static/description/assets/icons/user.png differ diff --git a/pdf_report_designer/static/description/assets/icons/wrench.png b/pdf_report_designer/static/description/assets/icons/wrench.png new file mode 100644 index 000000000..6c04dea0f Binary files /dev/null and b/pdf_report_designer/static/description/assets/icons/wrench.png differ diff --git a/pdf_report_designer/static/description/assets/misc/categories.png b/pdf_report_designer/static/description/assets/misc/categories.png new file mode 100644 index 000000000..bedf1e0b1 Binary files /dev/null and b/pdf_report_designer/static/description/assets/misc/categories.png differ diff --git a/pdf_report_designer/static/description/assets/misc/check-box.png b/pdf_report_designer/static/description/assets/misc/check-box.png new file mode 100644 index 000000000..42caf24b9 Binary files /dev/null and b/pdf_report_designer/static/description/assets/misc/check-box.png differ diff --git a/pdf_report_designer/static/description/assets/misc/compass.png b/pdf_report_designer/static/description/assets/misc/compass.png new file mode 100644 index 000000000..d5fed8faa Binary files /dev/null and b/pdf_report_designer/static/description/assets/misc/compass.png differ diff --git a/pdf_report_designer/static/description/assets/misc/corporate.png b/pdf_report_designer/static/description/assets/misc/corporate.png new file mode 100644 index 000000000..2eb13edbf Binary files /dev/null and b/pdf_report_designer/static/description/assets/misc/corporate.png differ diff --git a/pdf_report_designer/static/description/assets/misc/customer-support.png b/pdf_report_designer/static/description/assets/misc/customer-support.png new file mode 100644 index 000000000..79efc72ed Binary files /dev/null and b/pdf_report_designer/static/description/assets/misc/customer-support.png differ diff --git a/pdf_report_designer/static/description/assets/misc/cybrosys-logo.png b/pdf_report_designer/static/description/assets/misc/cybrosys-logo.png new file mode 100644 index 000000000..cc3cc0ccf Binary files /dev/null and b/pdf_report_designer/static/description/assets/misc/cybrosys-logo.png differ diff --git a/pdf_report_designer/static/description/assets/misc/features.png b/pdf_report_designer/static/description/assets/misc/features.png new file mode 100644 index 000000000..b41769f77 Binary files /dev/null and b/pdf_report_designer/static/description/assets/misc/features.png differ diff --git a/pdf_report_designer/static/description/assets/misc/logo.png b/pdf_report_designer/static/description/assets/misc/logo.png new file mode 100644 index 000000000..478462d3e Binary files /dev/null and b/pdf_report_designer/static/description/assets/misc/logo.png differ diff --git a/pdf_report_designer/static/description/assets/misc/pictures.png b/pdf_report_designer/static/description/assets/misc/pictures.png new file mode 100644 index 000000000..56d255fe9 Binary files /dev/null and b/pdf_report_designer/static/description/assets/misc/pictures.png differ diff --git a/pdf_report_designer/static/description/assets/misc/pie-chart.png b/pdf_report_designer/static/description/assets/misc/pie-chart.png new file mode 100644 index 000000000..426e05244 Binary files /dev/null and b/pdf_report_designer/static/description/assets/misc/pie-chart.png differ diff --git a/pdf_report_designer/static/description/assets/misc/right-arrow.png b/pdf_report_designer/static/description/assets/misc/right-arrow.png new file mode 100644 index 000000000..730984a06 Binary files /dev/null and b/pdf_report_designer/static/description/assets/misc/right-arrow.png differ diff --git a/pdf_report_designer/static/description/assets/misc/star.png b/pdf_report_designer/static/description/assets/misc/star.png new file mode 100644 index 000000000..2eb9ab29f Binary files /dev/null and b/pdf_report_designer/static/description/assets/misc/star.png differ diff --git a/pdf_report_designer/static/description/assets/misc/support.png b/pdf_report_designer/static/description/assets/misc/support.png new file mode 100644 index 000000000..4f18b8b82 Binary files /dev/null and b/pdf_report_designer/static/description/assets/misc/support.png differ diff --git a/pdf_report_designer/static/description/assets/misc/whatsapp.png b/pdf_report_designer/static/description/assets/misc/whatsapp.png new file mode 100644 index 000000000..d513a5356 Binary files /dev/null and b/pdf_report_designer/static/description/assets/misc/whatsapp.png differ diff --git a/pdf_report_designer/static/description/assets/modules/1.png b/pdf_report_designer/static/description/assets/modules/1.png new file mode 100644 index 000000000..489f44e86 Binary files /dev/null and b/pdf_report_designer/static/description/assets/modules/1.png differ diff --git a/pdf_report_designer/static/description/assets/modules/2.png b/pdf_report_designer/static/description/assets/modules/2.png new file mode 100644 index 000000000..8658f1826 Binary files /dev/null and b/pdf_report_designer/static/description/assets/modules/2.png differ diff --git a/pdf_report_designer/static/description/assets/modules/3.png b/pdf_report_designer/static/description/assets/modules/3.png new file mode 100644 index 000000000..57eebc5b2 Binary files /dev/null and b/pdf_report_designer/static/description/assets/modules/3.png differ diff --git a/pdf_report_designer/static/description/assets/modules/4.png b/pdf_report_designer/static/description/assets/modules/4.png new file mode 100644 index 000000000..a3060d797 Binary files /dev/null and b/pdf_report_designer/static/description/assets/modules/4.png differ diff --git a/pdf_report_designer/static/description/assets/modules/5.png b/pdf_report_designer/static/description/assets/modules/5.png new file mode 100644 index 000000000..571c6b8fe Binary files /dev/null and b/pdf_report_designer/static/description/assets/modules/5.png differ diff --git a/pdf_report_designer/static/description/assets/modules/6.png b/pdf_report_designer/static/description/assets/modules/6.png new file mode 100644 index 000000000..028461c15 Binary files /dev/null and b/pdf_report_designer/static/description/assets/modules/6.png differ diff --git a/pdf_report_designer/static/description/assets/screenshots/hero.gif b/pdf_report_designer/static/description/assets/screenshots/hero.gif new file mode 100644 index 000000000..32ce1d103 Binary files /dev/null and b/pdf_report_designer/static/description/assets/screenshots/hero.gif differ diff --git a/pdf_report_designer/static/description/assets/screenshots/pdf_desi_001.png b/pdf_report_designer/static/description/assets/screenshots/pdf_desi_001.png new file mode 100644 index 000000000..85ae28b1d Binary files /dev/null and b/pdf_report_designer/static/description/assets/screenshots/pdf_desi_001.png differ diff --git a/pdf_report_designer/static/description/assets/screenshots/pdf_desi_002.png b/pdf_report_designer/static/description/assets/screenshots/pdf_desi_002.png new file mode 100644 index 000000000..73a859fa5 Binary files /dev/null and b/pdf_report_designer/static/description/assets/screenshots/pdf_desi_002.png differ diff --git a/pdf_report_designer/static/description/assets/screenshots/pdf_desi_003.png b/pdf_report_designer/static/description/assets/screenshots/pdf_desi_003.png new file mode 100644 index 000000000..4f256ad54 Binary files /dev/null and b/pdf_report_designer/static/description/assets/screenshots/pdf_desi_003.png differ diff --git a/pdf_report_designer/static/description/assets/screenshots/pdf_desi_004.png b/pdf_report_designer/static/description/assets/screenshots/pdf_desi_004.png new file mode 100644 index 000000000..7a15f3f2f Binary files /dev/null and b/pdf_report_designer/static/description/assets/screenshots/pdf_desi_004.png differ diff --git a/pdf_report_designer/static/description/assets/screenshots/pdf_desi_005.png b/pdf_report_designer/static/description/assets/screenshots/pdf_desi_005.png new file mode 100644 index 000000000..266ed17b4 Binary files /dev/null and b/pdf_report_designer/static/description/assets/screenshots/pdf_desi_005.png differ diff --git a/pdf_report_designer/static/description/assets/screenshots/pdf_desi_006.png b/pdf_report_designer/static/description/assets/screenshots/pdf_desi_006.png new file mode 100644 index 000000000..e7dcc4ffd Binary files /dev/null and b/pdf_report_designer/static/description/assets/screenshots/pdf_desi_006.png differ diff --git a/pdf_report_designer/static/description/assets/screenshots/pdf_desi_007.png b/pdf_report_designer/static/description/assets/screenshots/pdf_desi_007.png new file mode 100644 index 000000000..3a9e1351b Binary files /dev/null and b/pdf_report_designer/static/description/assets/screenshots/pdf_desi_007.png differ diff --git a/pdf_report_designer/static/description/banner.png b/pdf_report_designer/static/description/banner.png new file mode 100644 index 000000000..a9bb75eb1 Binary files /dev/null and b/pdf_report_designer/static/description/banner.png differ diff --git a/pdf_report_designer/static/description/icon.png b/pdf_report_designer/static/description/icon.png new file mode 100644 index 000000000..f791aba7c Binary files /dev/null and b/pdf_report_designer/static/description/icon.png differ diff --git a/pdf_report_designer/static/description/index.html b/pdf_report_designer/static/description/index.html new file mode 100644 index 000000000..1e7ba8000 --- /dev/null +++ b/pdf_report_designer/static/description/index.html @@ -0,0 +1,726 @@ +
+ +
+ +
+
+ Community +
+
+ Enterprise +
+
+ Odoo.sh +
+
+
+ +
+
+
+ +

+ PDF Report Designer

+

+ Create Customised PDF Reports for Any Models +

+ +

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

+ Explore This + Module

+
+ + + + +
+
+ +
+

+ Overview +

+
+
+
+ In this PDF Report Designer module, We can Create Reports in PDF 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 PDF reports. +
+
+ + Filter Report data based on any Date Field. +
+
+ + Custom Report Name. +
+
+ + Reports Menu under the Action Menu. +
+
+
+ + + +
+
+ +
+

+ Screenshots +

+
+
+
+
+

+ Report Configuration

+

+ The reports can be configured and printed using the 'PDF Report + Designer' menu at Settings. + Select the desired model on which you want to create report, + select the required fields that want to appear in the report. + Filtration using date fields in the model is also possible +

+
+ +
+
+
+

+ By clicking on PRINT REPORT button, you can print the reports + of all the record of that model.

+

+

+
+ +
+
+
+

+ Report

+

+

+
+ +
+
+

+ By clicking on 'Add Action', can create an action in the specified model.

+

+

+ +
+
+

+ Action in specified model.

+

+

+ +
+
+

+ Confirmation Wizard for Printing the Report.

+ +
+
+

+ PDF Report

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

+ Related + 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

+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ \ No newline at end of file diff --git a/pdf_report_designer/views/report_pdf_views.xml b/pdf_report_designer/views/report_pdf_views.xml new file mode 100644 index 000000000..c3f593802 --- /dev/null +++ b/pdf_report_designer/views/report_pdf_views.xml @@ -0,0 +1,96 @@ + + + + + report.pdf.view.form + report.pdf + 20 + +
+
+
+ + + +
+
+
+

+ + + +

+
+ + + + + The column order will be as selected in the below + table + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + Report PDF + report.pdf + tree,form + + + + +
diff --git a/pdf_report_designer/wizard/__init__.py b/pdf_report_designer/wizard/__init__.py new file mode 100644 index 000000000..d0d0c3af9 --- /dev/null +++ b/pdf_report_designer/wizard/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Prasanna Kumara B (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################### +from . import pdf_report diff --git a/pdf_report_designer/wizard/pdf_report.py b/pdf_report_designer/wizard/pdf_report.py new file mode 100644 index 000000000..9a0ecfcd5 --- /dev/null +++ b/pdf_report_designer/wizard/pdf_report.py @@ -0,0 +1,197 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Prasanna Kumara B (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################### +from collections import OrderedDict +from odoo import fields, models + + +class PDFReportWizard(models.TransientModel): + """Class to manage PDF Report Wizard model""" + _name = "pdf.report" + _description = "PDF Report Wizard" + _order = 'id DESC' + + def action_print_pdf_report(self): + """ + When the user requests to print the report in the action menu, + this function will be called. Parameters and return values of the + function is noted below. :param self: The current report.pdf record. + :return: A dictionary with report data like field headers and field + datas. + """ + record_ids = self.env.context.get('active_ids', []) + record_model = self.env.context.get('active_model') + pdf_report_id = self.env['report.pdf'].browse(self._context.get('pdf')) + for rec in pdf_report_id: + domain = [] + if rec.date_field_id and rec.start_date: + domain.append((rec.date_field_id.name, '>=', rec.start_date)) + if rec.date_field_id and rec.end_date: + domain.append((rec.date_field_id.name, '<=', rec.end_date)) + if rec.date_field_id and (rec.start_date and rec.end_date): + domain = [(rec.date_field_id.name, '>=', rec.start_date), + (rec.date_field_id.name, '<=', rec.end_date)] + model_records = self.env[record_model].browse(record_ids) + model_data = model_records.filtered_domain(domain) + table_data = [] + child_table_data = [] + for record in model_data: + data_list = [] + list_b = [] + order = rec.field_order.strip('][').split(', ') + for field_id in order: + field_obj = self.env['ir.model.fields'].browse( + int(field_id)) + field_name = field_obj.name + if field_obj.ttype == 'datetime': + field_data = record[field_name].strftime("%d/%m/%Y") + elif field_obj.ttype == 'boolean': + if not record[field_name]: + field_data = "No" + else: + field_data = "Yes" + elif field_obj.ttype == 'monetary': + if record.currency_id.position == 'before': + field_data = record.currency_id.symbol+str(record[field_name]) + else: + field_data = str(record[field_name])+record.currency_id.symbol + elif field_obj.ttype == 'many2one' or field_obj.ttype == 'many2one_reference': + if record[field_name]: + field_data = record[field_name].name_get()[0][1] + else: + field_data = "Null" + elif field_obj.ttype == 'many2many': + if record[field_name]: + field_data = "" + for count, value in enumerate(record[field_name]): + if not count == len(record[field_name]) - 1: + field_data += value.name_get()[0][1] + ", " + else: + field_data += value.name_get()[0][1] + else: + field_data = "Null" + elif field_obj.ttype == 'one2many': + if record[field_name]: + child_fields = rec.fields_ids.one2many_model_field_ids + if child_fields: + field_data = "one2many" + list_b = [] + for o2m_c_field in record[field_name]: + list_a = [] + for c_field in child_fields: + c_field_name = c_field.name + if c_field.ttype == 'datetime': + child_field_data = o2m_c_field[ + c_field_name].strftime( + "%d/%m/%Y") + elif c_field.ttype == 'boolean': + if o2m_c_field[c_field_name]: + child_field_data = "Yes" + else: + child_field_data = "No" + elif c_field.ttype in ( + 'many2one', + 'many2one_reference'): + if o2m_c_field[c_field_name]: + child_field_data = o2m_c_field[ + c_field_name].name_get()[0][ + 1] + else: + child_field_data = "Null" + elif c_field.ttype in ( + 'many2one', + 'many2one_reference'): + if o2m_c_field[c_field_name]: + child_field_data = o2m_c_field[ + c_field_name].name_get()[0][ + 1] + else: + child_field_data = "Null" + elif c_field.ttype in ( + 'many2many', 'one2many'): + if o2m_c_field[c_field_name]: + child_field_data = "" + for c_count, c_value in enumerate( + o2m_c_field[ + c_field_name]): + if not c_count == len( + o2m_c_field[ + c_field_name]) - 1: + child_field_data += \ + c_value.name_get()[ + 0][ + 1] + ", " + else: + child_field_data += \ + c_value.name_get()[ + 0][1] + else: + child_field_data = "Null" + else: + child_field_data = o2m_c_field[ + c_field_name] + list_a.append(child_field_data) + field_data = list_a + list_b.append(list_a) + else: + field_data = "" + for count, value in enumerate( + record[field_name]): + if not count == len(record[field_name]) - 1: + field_data += value.name_get()[0][ + 1] + ", " + else: + field_data += value.name_get()[0][1] + else: + field_data = "Null" + else: + field_data = record[field_name] + data_list.append(field_data) + table_data.append(data_list) + child_table_data.append(list_b) + child_label = rec.fields_ids.one2many_model_field_ids + child_field_label = "" + if child_label: + child_field_label = child_label.mapped('field_description') + field_heading = {} + for field in rec.fields_ids.report_field_id: + field_heading.update({field.field_description: ( + field.ttype, field.field_description)}) + ordered_field_heading = OrderedDict( + reversed(list(field_heading.items()))) + data = { + 'report_name': rec.name, + 'model_name': rec.model_id.model, + 'fields_name': rec.fields_ids.report_field_id.mapped('name'), + 'field_label': ordered_field_heading, + '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, + 'table_data': table_data, + 'child_field_data': child_table_data, + 'child_field_label': child_field_label, + 'today_date': fields.Datetime.now() + } + return self.env.ref( + 'pdf_report_designer.action_wizard_pdf_designer').report_action( + self, data=data) diff --git a/pdf_report_designer/wizard/pdf_report_views.xml b/pdf_report_designer/wizard/pdf_report_views.xml new file mode 100644 index 000000000..12c35234f --- /dev/null +++ b/pdf_report_designer/wizard/pdf_report_views.xml @@ -0,0 +1,18 @@ + + + + + pdf.report.view.form + pdf.report + +
+

Do you want to print the report??

+ +
+
+
+