@ -0,0 +1,48 @@ |
|||
.. 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 <https://cybrosys.com/>`__ |
|||
|
|||
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 |
|||
Developer : (V17) Anfas Faisal K, 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 <https://cybrosys.com/>`__ |
|||
|
|||
Further information |
|||
=================== |
|||
HTML Description: `<static/description/index.html>`__ |
@ -0,0 +1,31 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Anfas Faisal K (odoo@cybrosys.info) |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################### |
|||
from . import models |
|||
from . import wizard |
|||
|
|||
|
|||
def _uninstall_hook(env): |
|||
"""Unlink all the window action while uninstall this module """ |
|||
window_action = env['ir.actions.act_window'].search( |
|||
[('is_action_created_from_pdf_report', '!=', False)]) |
|||
for rec in window_action: |
|||
rec.unlink() |
@ -0,0 +1,48 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Anfas Faisal K (odoo@cybrosys.info) |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################### |
|||
{ |
|||
'name': 'PDF Report Designer', |
|||
'version': '17.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.jpg'], |
|||
'license': 'LGPL-3', |
|||
'uninstall_hook': '_uninstall_hook', |
|||
'installable': True, |
|||
'auto_install': False, |
|||
'application': False, |
|||
} |
@ -0,0 +1,6 @@ |
|||
## Module <pdf_report_designer> |
|||
#### 31.08.2024 |
|||
#### Version 17.0.1.0.0 |
|||
#### ADD |
|||
|
|||
- Initial commit for PDF Report Designer |
@ -0,0 +1,24 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Anfas Faisal K (odoo@cybrosys.info) |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################### |
|||
from . import report_pdf |
|||
from . import report_pdf_fields |
|||
from . import ir_actions_act_window |
@ -0,0 +1,34 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Anfas Faisal K (odoo@cybrosys.info) |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################### |
|||
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') |
@ -0,0 +1,333 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Anfas Faisal K (odoo@cybrosys.info) |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################### |
|||
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 = [] |
|||
rec_currency_symbol = '' |
|||
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): |
|||
""" |
|||
Unlink an action button and reload the view. |
|||
""" |
|||
self.ensure_one() |
|||
if self.ir_act_server_ref_id: |
|||
# Remove the action window |
|||
self.ir_act_server_ref_id.unlink() |
|||
self.write({ |
|||
'ir_act_server_ref_id': False, |
|||
'action_button': False |
|||
}) |
|||
else: |
|||
self.action_button = False |
|||
|
|||
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), |
|||
('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', |
|||
} |
@ -0,0 +1,89 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Anfas Faisal K (odoo@cybrosys.info) |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################### |
|||
from odoo import api, fields, models, _ |
|||
from odoo.exceptions import UserError |
|||
|
|||
|
|||
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", |
|||
domain="[('id', 'in', field_value_ids)]") |
|||
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") |
|||
field_value_ids = fields.Many2many('ir.model.fields', |
|||
string='Fields', |
|||
help="Storing Values", |
|||
compute='_compute_field_value_ids') |
|||
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.depends('report_id.model_id') |
|||
def _compute_field_value_ids(self): |
|||
""" |
|||
Compute method to populate `field_value_ids` based on the model |
|||
specified in `report_id`. |
|||
|
|||
This method searches for fields in the `ir.model.fields` model |
|||
that belong to the specified `model_id` in the report and are |
|||
stored in the database. The resulting field IDs are assigned to |
|||
the `field_value_ids` field of the current record. |
|||
""" |
|||
for rec in self: |
|||
if rec.report_id.model_id: |
|||
model_field_ids = self.env['ir.model.fields'].search([ |
|||
('model_id', '=', rec.report_id.model_id.id), |
|||
('store', '=', True) |
|||
]).ids |
|||
rec.field_value_ids = [(6, 0, model_field_ids)] |
|||
|
|||
@api.onchange('report_field_id') |
|||
def _onchange_report_field_id(self): |
|||
""" |
|||
Onchange method to ensure the model is set in the report before |
|||
allowing selection of a report field. |
|||
""" |
|||
if not self.report_id.model_id: |
|||
raise (UserError |
|||
(_("Please set the model in the report before selecting a " |
|||
"report field."))) |
@ -0,0 +1,11 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<!--Report acton for pdf reports--> |
|||
<record id="action_wizard_pdf_designer" model="ir.actions.report"> |
|||
<field name="name">PDF Reports</field> |
|||
<field name="model">pdf.report</field> |
|||
<field name="report_type">qweb-pdf</field> |
|||
<field name="report_name">pdf_report_designer.report_pdf_designer</field> |
|||
<field name="report_file">pdf_report_designer.report_pdf_designer</field> |
|||
</record> |
|||
</odoo> |
@ -0,0 +1,134 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<!-- Template for pdf reports--> |
|||
<template id="report_pdf_designer"> |
|||
<t t-call="web.html_container"> |
|||
<t t-call="web.external_layout"> |
|||
<div class="page"> |
|||
<div style="padding-bottom:20px !important;" |
|||
class="oe_structure"/> |
|||
<t t-if="report_name"> |
|||
<h2 align="center"> |
|||
<b> |
|||
<t t-esc="report_name"/> |
|||
</b> |
|||
</h2> |
|||
<t t-if="today_date"> |
|||
<h6 align="center"> |
|||
Date: |
|||
<t t-esc="today_date"/> |
|||
</h6> |
|||
</t> |
|||
<br/> |
|||
</t> |
|||
<t t-if="date_field_id"> |
|||
<t t-if="start_date"> |
|||
<h5 align="left"> |
|||
From: |
|||
<t t-esc="start_date"/> |
|||
</h5> |
|||
</t> |
|||
<t t-if="end_date"> |
|||
<h5 align="left"> |
|||
To: |
|||
<t t-esc="end_date"/> |
|||
</h5> |
|||
</t> |
|||
</t> |
|||
<t t-if="child_field_data"> |
|||
<table class="table table-condensed"> |
|||
<thead> |
|||
<tr> |
|||
<th>SL.No</th> |
|||
<t t-foreach="field_label" t-as="item"> |
|||
<t t-if="item_value[0]=='one2many'"> |
|||
<t t-if="child_field_label"> |
|||
<t t-foreach="child_field_label" |
|||
t-as="c_field"> |
|||
<th> |
|||
<t t-esc="c_field"/> |
|||
</th> |
|||
</t> |
|||
</t> |
|||
<t t-else=""> |
|||
<th> |
|||
<t t-esc="item"/> |
|||
</th> |
|||
</t> |
|||
</t> |
|||
<t t-if="not item_value[0]=='one2many'"> |
|||
<th> |
|||
<t t-esc="item"/> |
|||
</th> |
|||
</t> |
|||
</t> |
|||
</tr> |
|||
</thead> |
|||
|
|||
<tbody> |
|||
<t t-set="sl_no" t-value="1"/> |
|||
<t t-foreach="table_data" t-as="rec"> |
|||
<tr> |
|||
<td> |
|||
<t t-esc="sl_no"/> |
|||
</td> |
|||
<t t-foreach="rec" t-as="j"> |
|||
<t t-if="isinstance(j, list)"> |
|||
<t t-foreach="j" t-as="i"> |
|||
<td align="center"> |
|||
<t t-esc="i"/> |
|||
</td> |
|||
</t> |
|||
</t> |
|||
<t t-if="not isinstance(j, list)"> |
|||
<td align="center"> |
|||
<span t-esc="j"/> |
|||
</td> |
|||
</t> |
|||
|
|||
</t> |
|||
<t t-set="sl_no" t-value="sl_no + 1"/> |
|||
</tr> |
|||
</t> |
|||
</tbody> |
|||
</table> |
|||
</t> |
|||
<t t-else=""> |
|||
<table class="table table-condensed"> |
|||
<thead> |
|||
<tr> |
|||
<t t-if="field_label"> |
|||
<th><centre>SL.No</centre></th> |
|||
<t t-foreach="field_label" t-as="head"> |
|||
<th> |
|||
<t t-esc="head"/> |
|||
</th> |
|||
</t> |
|||
</t> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
<t t-set="slno" t-value="1"/> |
|||
<t t-if="table_data"> |
|||
<t t-foreach="table_data" t-as="record"> |
|||
<tr> |
|||
<td> |
|||
<t t-esc="slno"/> |
|||
</td> |
|||
<t t-foreach="record" t-as="rec"> |
|||
<td> |
|||
<span t-esc="rec"/> |
|||
</td> |
|||
</t> |
|||
<t t-set="slno" t-value="slno + 1"/> |
|||
</tr> |
|||
</t> |
|||
</t> |
|||
</tbody> |
|||
</table> |
|||
</t> |
|||
</div> |
|||
</t> |
|||
</t> |
|||
</template> |
|||
</odoo> |
@ -0,0 +1,11 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<!--Report action for pdf reports--> |
|||
<record id="action_report_print_pdf_designer" model="ir.actions.report"> |
|||
<field name="name">PDF Reports</field> |
|||
<field name="model">report.pdf</field> |
|||
<field name="report_type">qweb-pdf</field> |
|||
<field name="report_name">pdf_report_designer.report_pdf_designer</field> |
|||
<field name="report_file">pdf_report_designer.report_pdf_designer</field> |
|||
</record> |
|||
</odoo> |
|
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 310 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 576 B |
After Width: | Height: | Size: 733 B |
After Width: | Height: | Size: 911 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 673 B |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 878 B |
After Width: | Height: | Size: 653 B |
After Width: | Height: | Size: 905 B |
After Width: | Height: | Size: 839 B |
After Width: | Height: | Size: 427 B |
After Width: | Height: | Size: 627 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 988 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 80 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 565 B |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 43 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 87 KiB |
After Width: | Height: | Size: 82 KiB |
After Width: | Height: | Size: 96 KiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 85 KiB |
After Width: | Height: | Size: 84 KiB |
After Width: | Height: | Size: 57 KiB |
After Width: | Height: | Size: 58 KiB |
After Width: | Height: | Size: 109 KiB |
After Width: | Height: | Size: 57 KiB |
After Width: | Height: | Size: 172 KiB |
After Width: | Height: | Size: 135 KiB |
After Width: | Height: | Size: 51 KiB |
After Width: | Height: | Size: 217 KiB |
After Width: | Height: | Size: 79 KiB |
After Width: | Height: | Size: 7.6 KiB |
@ -0,0 +1,642 @@ |
|||
<!DOCTYPE html> |
|||
<html lang="en"> |
|||
|
|||
<head> |
|||
<meta charset="UTF-8"> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|||
<title>Odoo App 3 Index</title> |
|||
<!-- Bootstrap CSS --> |
|||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css" |
|||
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"> |
|||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css"> |
|||
<link rel="preconnect" href="https://fonts.googleapis.com"> |
|||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> |
|||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet"> |
|||
</head> |
|||
<body> |
|||
<section> |
|||
<div class="container" style="font-family: 'Inter', sans-serif !important;background-color: #fff !important;"> |
|||
<div class="row"> |
|||
<div class="col-sm-12 col-md-12 col-lg-12 d-flex justify-content-between flex-wrap align-items-sm-center" |
|||
style="border-bottom:1px solid rgba(0, 0, 0, 0.22)"> |
|||
<div class="my-3"> |
|||
<img src="assets/misc/Cybrosys R.png" style="width:auto !important; height:40px !important"> |
|||
</div> |
|||
<div class="my-3 d-flex align-items-center"> |
|||
<div class="text-center" |
|||
style="background-color:#017E84 !important;font-size: 0.8rem !important; color:#fff !important; font-weight:500 !important; padding:4px !important; margin:0 3px !important; border-radius:50px !important; min-width: 120px !important;"> |
|||
Community |
|||
</div> |
|||
<div class="text-center" |
|||
style="background-color:#875A7B !important; color:#fff !important;font-size: 0.8rem !important; font-weight:500 !important; padding:4px !important; margin:0 3px !important; border-radius:50px !important;min-width: 120px !important;"> |
|||
Enterprise |
|||
</div> |
|||
<div class="text-center" |
|||
style="background-color:#7C7BAD !important; color:#fff !important;font-size: 0.8rem !important; font-weight:500 !important; padding:4px !important; margin:0 3px !important; border-radius:50px !important; min-width: 120px !important;"> |
|||
Odoo.sh |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="row"> |
|||
<div class="col-sm-12 col-md-12 col-lg-12 text-center d-flex align-items-center flex-column" |
|||
style="margin: 80px 0px !important;"> |
|||
<h1 style="font-size: 2.8rem;font-weight: 700; color: |
|||
#1A202C;"> |
|||
PDF Report Designer |
|||
</h1> |
|||
<p class="my-3 mb-4" |
|||
style="max-width: 80%; font-weight: 400 !important; line-height: 32px; color: #718096;"> |
|||
Create Customised PDF Reports for Any Models. |
|||
</p> |
|||
<div style="width: 80%; margin-top: 3rem;"> |
|||
<img src="assets/screenshots/hero-v17.gif" class="img-responsive" width="100%" height="auto"> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="container mt-5 mb-5"> |
|||
<div class="col-lg-12 d-flex flex-column justify-content-center align-items-center mt-4"> |
|||
<p class="m-0" style="font-weight: 600; font-size: 24px; color:#714b67 !important">Key Highlights |
|||
</p> |
|||
</div> |
|||
<div class="row py-4"> |
|||
<div class="col-md-6 col-sm-12 p-3"> |
|||
<div class="d-flex h-100" style="padding: 30px;border-radius: 12px; |
|||
background: #FFF; |
|||
box-shadow: 1px 2px 3px 0px rgba(0, 0, 0, 0.25); "> |
|||
<div style="width: 36px; height: 36px; border-radius: 50%; background: #714B67; |
|||
display: flex; justify-content: center; align-items: center; |
|||
margin-right: 10px; flex-shrink: 0;"> |
|||
<i class="fa-solid fa-star " style="color: #fff;font-size:14px;"></i> |
|||
</div> |
|||
<div> |
|||
<p style="color: #1A202C;font-weight: 600; |
|||
font-size: 1.2rem; margin-bottom: 2px;">Fully Configurable PDF reports.</p> |
|||
|
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-6 col-sm-12 p-3"> |
|||
<div class="d-flex h-100" style="padding: 30px;border-radius: 12px; |
|||
background: #FFF; |
|||
box-shadow: 1px 2px 3px 0px rgba(0, 0, 0, 0.25); "> |
|||
<div style="width: 36px; height: 36px; border-radius: 50%; background: #714B67; |
|||
display: flex; justify-content: center; align-items: center; |
|||
margin-right: 10px; flex-shrink: 0;"> |
|||
<i class="fa-solid fa-star " style="color: #fff;font-size:14px;"></i> |
|||
</div> |
|||
<div> |
|||
<p style="color: #1A202C;font-weight: 600; |
|||
font-size: 1.2rem; margin-bottom: 2px;">Filter Report data based on any Date Field.</p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-6 col-sm-12 p-3"> |
|||
<div class="d-flex h-100" style="padding: 30px;border-radius: 12px; |
|||
background: #FFF; |
|||
box-shadow: 1px 2px 3px 0px rgba(0, 0, 0, 0.25); "> |
|||
<div style="width: 36px; height: 36px; border-radius: 50%; background: #714B67; |
|||
display: flex; justify-content: center; align-items: center; |
|||
margin-right: 10px; flex-shrink: 0;"> |
|||
<i class="fa-solid fa-star " style="color: #fff;font-size:14px;"></i> |
|||
</div> |
|||
<div> |
|||
<p style="color: #1A202C;font-weight: 600; |
|||
font-size: 1.2rem; margin-bottom: 2px;">Custom Report Name.</p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-md-6 col-sm-12 p-3"> |
|||
<div class="d-flex h-100" style="padding: 30px;border-radius: 12px; |
|||
background: #FFF; |
|||
box-shadow: 1px 2px 3px 0px rgba(0, 0, 0, 0.25); "> |
|||
<div style="width: 36px; height: 36px; border-radius: 50%; background: #714B67; |
|||
display: flex; justify-content: center; align-items: center; |
|||
margin-right: 10px; flex-shrink: 0;"> |
|||
<i class="fa-solid fa-star " style="color: #fff;font-size:14px;"></i> |
|||
</div> |
|||
<div> |
|||
<p style="color: #1A202C;font-weight: 600; |
|||
font-size: 1.2rem; margin-bottom: 2px;">Reports Menu under the Action Menu.</p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="container rounded" > |
|||
<ul class="nav nav-tabs d-flex" style="width: fit-content;margin: 0 auto;gap: 1rem;"> |
|||
<li class="col text-center py-2 text-nowrap " |
|||
style="color: #fff; background-color: #714B67;border-radius: 6px 6px 0px 0px;"><a |
|||
class="active show" data-toggle="tab" href="#tab1" |
|||
style="color: #fff;font-weight: 500; background-color: #714B67; text-decoration: none;"> |
|||
<i class="fa-regular fa-image pr-2" style="color: #fff;"></i> |
|||
Screenshots</a></li> |
|||
<li class="col text-center py-2 text-nowrap " |
|||
style="color: #fff; background-color: #714B67;border-radius: 6px 6px 0px 0px;"><a |
|||
data-toggle="tab" href="#tab2" |
|||
style="color: #fff;font-weight: 500; text-decoration: none;"><i |
|||
class="fa-solid fa-star pr-2" style="color: #fff;"></i>Features</a></li> |
|||
<li class="col text-center py-2 text-nowrap " |
|||
style="color: #fff; background-color: #714B67;border-radius: 6px 6px 0px 0px;"><a |
|||
data-toggle="tab" href="#tab3" |
|||
style="color: #fff;font-weight: 500; text-decoration: none; background-color: #714B67;"><i |
|||
class="fa-solid fa-book-open pr-2" style="color: #fff;"></i>Released Notes</a></li> |
|||
</ul> |
|||
<div class="tab-content" style="background-color: rgba(121, 113, 119, 0.04);"> |
|||
<div id="tab1" class="tab-pane fade in active show"> |
|||
<div class="col-lg-12 py-2" style="padding: 1rem 4rem !important;"> |
|||
<div |
|||
style="border: 1px solid #d8d6d6; border-radius: 4px; background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> |
|||
<div class="row justify-content-center p-3 w-100 m-0"> |
|||
<img src="assets/screenshots/1.png" class="img-responsive" width="100%" height="auto"> |
|||
</div> |
|||
<div class="px-3"> |
|||
<h4 class="mt-2" |
|||
style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important"> |
|||
Report Configuration.</h4> |
|||
<p>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.<p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-lg-12 py-2" style="padding: 1rem 4rem !important;"> |
|||
<div |
|||
style="border: 1px solid #d8d6d6; border-radius: 4px; background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> |
|||
<div class="row justify-content-center p-3 w-100 m-0"> |
|||
<img src="assets/screenshots/2.png" class="img-responsive" width="100%" height="auto"> |
|||
</div> |
|||
<div class="px-3"> |
|||
<h4 class="mt-2" |
|||
style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important"> |
|||
By clicking on PRINT REPORT button, you can print the reports of all the record of that model.</h4> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-lg-12 py-2" style="padding: 1rem 4rem !important;"> |
|||
<div |
|||
style="border: 1px solid #d8d6d6; border-radius: 4px; background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> |
|||
<div class="row justify-content-center p-3 w-100 m-0"> |
|||
<img src="assets/screenshots/3.png" class="img-responsive" width="100%" height="auto"> |
|||
</div> |
|||
<div class="px-3"> |
|||
<h4 class="mt-2" |
|||
style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important"> |
|||
Report.</h4> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-lg-12 py-2" style="padding: 1rem 4rem !important;"> |
|||
<div |
|||
style="border: 1px solid #d8d6d6; border-radius: 4px; background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> |
|||
<div class="row justify-content-center p-3 w-100 m-0"> |
|||
<img src="assets/screenshots/4.png" class="img-responsive" width="100%" height="auto"> |
|||
</div> |
|||
<div class="px-3"> |
|||
<h4 class="mt-2" |
|||
style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important"> |
|||
By clicking on 'Add Action', can create an action in the specified model.</h4> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-lg-12 py-2" style="padding: 1rem 4rem !important;"> |
|||
<div |
|||
style="border: 1px solid #d8d6d6; border-radius: 4px; background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> |
|||
<div class="row justify-content-center p-3 w-100 m-0"> |
|||
<img src="assets/screenshots/5.png" class="img-responsive" width="100%" height="auto"> |
|||
</div> |
|||
<div class="px-3"> |
|||
<h4 class="mt-2" |
|||
style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important"> |
|||
Action in specified model.</h4> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-lg-12 py-2" style="padding: 1rem 4rem !important;"> |
|||
<div |
|||
style="border: 1px solid #d8d6d6; border-radius: 4px; background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> |
|||
<div class="row justify-content-center p-3 w-100 m-0"> |
|||
<img src="assets/screenshots/6.png" class="img-responsive" width="100%" height="auto"> |
|||
</div> |
|||
<div class="px-3"> |
|||
<h4 class="mt-2" |
|||
style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important"> |
|||
Confirmation Wizard for Printing the Report.</h4> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-lg-12 py-2" style="padding: 1rem 4rem !important;"> |
|||
<div |
|||
style="border: 1px solid #d8d6d6; border-radius: 4px; background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> |
|||
<div class="row justify-content-center p-3 w-100 m-0"> |
|||
<img src="assets/screenshots/7.png" class="img-responsive" width="100%" height="auto"> |
|||
</div> |
|||
<div class="px-3"> |
|||
<h4 class="mt-2" |
|||
style=" font-weight:600 !important; color:#282F33 !important; font-size:1.3rem !important"> |
|||
|
|||
PDF Report |
|||
.</h4> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div id="tab2" class="tab-pane fade"> |
|||
<div class="col-mg-12" style="padding: 1rem 4rem;"> |
|||
<ul style="list-style: none; padding: 1rem 0;font-weight: 500;"> |
|||
<li class="py-3" |
|||
style="font-weight: 500;background-color: #fff; border-radius: 4px; padding: 1rem; margin-bottom: 1rem; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> |
|||
<span style="margin-right: 12px;"><img src="assets/misc/star (1) 2.svg" alt="" |
|||
width="16px"></span>Can choose Employee from Work Order itself. |
|||
</li> |
|||
<li class="py-3" |
|||
style="font-weight: 500;background-color: #fff; border-radius: 4px; padding: 1rem; margin-bottom: 1rem; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> |
|||
<span style="margin-right: 12px;"><img src="assets/misc/star (1) 2.svg" alt="" |
|||
width="16px"></span>Using Project and Tasks makes it easier. |
|||
</li> |
|||
<li class="py-3" |
|||
style="font-weight: 500;background-color: #fff; border-radius: 4px; padding: 1rem; margin-bottom: 1rem; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> |
|||
<span style="margin-right: 12px;"><img src="assets/misc/star (1) 2.svg" alt="" |
|||
width="16px"></span>Timesheet for Manufacturing. |
|||
<ul style="list-style: none;font-weight: 400; color:#718096"> |
|||
<li>A Project will be created in the name of Manufacturing Order , |
|||
and Task will be created in the name of Work Order. The Time |
|||
tracking of the Work Order will be added as Timesheet.</li> |
|||
</ul> |
|||
</li> |
|||
|
|||
</ul> |
|||
</div> |
|||
</div> |
|||
<div id="tab3" class="tab-pane fade"> |
|||
<div class="col-mg-12 active" style="padding: 1rem 4rem;"> |
|||
<div class="py-3" |
|||
style="font-weight: 500;background-color: #fff; border-radius: 4px; padding: 1rem; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> |
|||
<div class="d-flex mb-3" style="font-size: 0.8rem; font-weight: 500;"><span>Version |
|||
16.0.1.0.0</span><span class="px-2">|</span><span |
|||
style="color: #714B67;font-weight: 600;">Released on:25th May 2023</span> |
|||
</div> |
|||
<p class="m-0" |
|||
style=" color:#718096!important; font-size:1rem !important;line-height: 28px;"> |
|||
|
|||
Initial Commit for Manufacturing (MRP) Timesheet.</p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="container mt-5"> |
|||
<div class="col-lg-12 d-flex flex-column justify-content-center align-items-center mt-5"> |
|||
<p class="m-0" style="font-weight: 600; font-size: 24px; color:#000 !important">Related Products</p> |
|||
</div> |
|||
</div> |
|||
<div id="myCarousel" class="carousel slide py-3" data-ride="carousel"> |
|||
<div class="carousel-inner"> |
|||
<div class="carousel-item active"> |
|||
<div class="row p-4"> |
|||
<div class="col"> |
|||
<div class="p-3"> |
|||
<a href="https://apps.odoo.com/apps/modules/17.0/database_delete_protection/" style="color: #000; text-decoration: none;"> |
|||
<div style="border:1px solid #CBCBCB !important;border-radius: 4px;"> |
|||
<div style="width: 300px; "> |
|||
<img src="assets/modules/1.jpg" alt="" width="100%" height="auto"> |
|||
|
|||
</div> |
|||
<p class="text-center pt-2 text-black font-weight-bold">Database Delete Protection </p> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<div class="col"> |
|||
<div class="p-3"> |
|||
<a href="https://apps.odoo.com/apps/modules/17.0/widget_preview_image/#" style="color: #000; text-decoration: none;"> |
|||
<div style="border:1px solid #CBCBCB !important;border-radius: 4px;"> |
|||
<div style="width: 300px; "> |
|||
<img src="assets/modules/2.jpg" alt="" width="100%" height="auto"> |
|||
|
|||
</div> |
|||
<p class="text-center pt-2 text-black font-weight-bold">Image Preview Widget</p> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<div class="col"> |
|||
<div class="p-3"> |
|||
<a href="https://apps.odoo.com/apps/modules/17.0/listview_change_background_color/#" style="color: #000; text-decoration: none;"> |
|||
<div style="border:1px solid #CBCBCB !important;border-radius: 4px;"> |
|||
<div style="width: 300px; "> |
|||
<img src="assets/modules/3.jpg" alt="" width="100%" height="auto"> |
|||
|
|||
</div> |
|||
<p class="text-center pt-2 text-black font-weight-bold">Listview Change Background Color </p> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="carousel-item"> |
|||
<div class="row p-4"> |
|||
<div class="col"> |
|||
<div class="p-3"> |
|||
<a href="https://apps.odoo.com/apps/modules/17.0/chatter_camera/#" style="color: #000; text-decoration: none;"> |
|||
<div style="border:1px solid #CBCBCB !important;border-radius: 4px;"> |
|||
<div style="width: 300px; "> |
|||
<img src="assets/modules/4.png" alt="" width="100%" height="auto"> |
|||
|
|||
</div> |
|||
<p class="text-center pt-2 text-black font-weight-bold">Chatter Camera |
|||
</p> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<div class="col"> |
|||
<div class="p-3"> |
|||
<a href="https://apps.odoo.com/apps/modules/17.0/easy_language_selector/" style="color: #000; text-decoration: none;"> |
|||
<div style="border:1px solid #CBCBCB !important;border-radius: 4px;"> |
|||
<div style="width: 300px;"> |
|||
<img src="assets/modules/5.png" alt="" width="100%" height="auto"> |
|||
|
|||
</div> |
|||
<p class="text-center pt-2 text-black font-weight-bold">Easy Language Selector </p> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<div class="col"> |
|||
<div class="p-3"> |
|||
<a href="https://apps.odoo.com/apps/modules/17.0/web_login_styles/#" style="color: #000; text-decoration: none;"> |
|||
<div style="border:1px solid #CBCBCB !important;border-radius: 4px;"> |
|||
<div style="width: 300px;"> |
|||
<img src="assets/modules/6.png" alt="" width="100%" height="auto"> |
|||
</div> |
|||
<p class="text-center pt-2 text-black font-weight-bold">Customize Login Page Style </p> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<a class="carousel-control-prev" href="#myCarousel" data-slide="prev" style="width: 35px; color: #000;"> |
|||
<span class="carousel-control-prev-icon"> |
|||
<i class="fa fa-chevron-left" style="font-size: 24px;"></i> |
|||
</span> |
|||
</a> |
|||
<a class="carousel-control-next" href="#myCarousel" data-slide="next" style="width: 35px; color: #000;"> |
|||
<span class="carousel-control-next-icon"> |
|||
<i class="fa fa-chevron-right" style="font-size: 24px;"></i> |
|||
</span> |
|||
</a> |
|||
</div> |
|||
<div class="container mt-5"> |
|||
<div class="col-lg-12 d-flex flex-column justify-content-center align-items-center mt-4"> |
|||
<p class="m-0" style="font-weight: 600; font-size: 24px; color:#000 !important">Our Services</p> |
|||
|
|||
</div> |
|||
</div> |
|||
<div class="container my-5"> |
|||
<div class="row py-3"> |
|||
<div class="col-md-4 col-sm-6 px-4 py-4"> |
|||
<div |
|||
style="background-color: #fff; padding: 25px; text-align: center; box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px, rgba(0, 0, 0, 0.06) 0px 1px 2px 0px; position: relative;border-radius: 4px;"> |
|||
<div style="position: absolute; top: 0%; left: 50%; transform: translate(-50%, -50%);"> |
|||
<div style="background-color:#13EA36 ; border-radius: 50%; padding: 15px; width: 68px; |
|||
height: 68px; display: inline-block; box-shadow:0px 4px 4px rgba(0, 0, 0, 0.25);"> |
|||
<img src="assets/icons/cogs.png" alt="service-icon" width="38px" height="auto"> |
|||
</div> |
|||
</div> |
|||
<p style="margin-top: 20px; font-weight: bold;">Odoo Customization</p> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-4 col-sm-6 px-4 py-4"> |
|||
<div |
|||
style="background-color: #fff; padding: 25px; text-align: center; box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px, rgba(0, 0, 0, 0.06) 0px 1px 2px 0px; position: relative;border-radius: 4px;"> |
|||
<div style="position: absolute; top: 0%; left: 50%; transform: translate(-50%, -50%);"> |
|||
<div style="background-color:#DBC711; border-radius: 50%; padding: 15px; width: 68px; |
|||
height: 68px; display: inline-block; box-shadow:0px 4px 4px rgba(0, 0, 0, 0.25);"> |
|||
<img src="assets/icons/wrench.png" alt="service-icon" width="38px" height="auto"> |
|||
</div> |
|||
</div> |
|||
<p style="margin-top: 20px; font-weight: bold;">Odoo Implementation</p> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-4 col-sm-6 px-4 py-4"> |
|||
<div |
|||
style="background-color: #fff; padding: 25px; text-align: center; box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px, rgba(0, 0, 0, 0.06) 0px 1px 2px 0px; position: relative; border-radius: 4px;"> |
|||
<div style="position: absolute; top: 0%; left: 50%; transform: translate(-50%, -50%);"> |
|||
<div style="background-color:#FF6B6B ; border-radius: 50%; padding: 15px; width: 68px; |
|||
height: 68px; display: inline-block; box-shadow:0px 4px 4px rgba(0, 0, 0, 0.25);"> |
|||
<img src="assets/icons/lifebuoy.png" alt="service-icon" width="38px" height="auto"> |
|||
</div> |
|||
</div> |
|||
<p style="margin-top: 20px; font-weight: bold;">Odoo Support</p> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-4 col-sm-6 px-4 py-4"> |
|||
<div |
|||
style="background-color: #fff; padding: 25px; text-align: center; box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px, rgba(0, 0, 0, 0.06) 0px 1px 2px 0px; position: relative; border-radius: 4px;"> |
|||
<div style="position: absolute; top: 0%; left: 50%; transform: translate(-50%, -50%);"> |
|||
<div style="background-color:#FFA801 ; border-radius: 50%; padding: 15px; width: 68px; |
|||
height: 68px; display: inline-block; box-shadow:0px 4px 4px rgba(0, 0, 0, 0.25);"> |
|||
<img src="assets/icons/user.png" alt="service-icon" width="38px" height="auto"> |
|||
</div> |
|||
</div> |
|||
<p style="margin-top: 20px; font-weight: bold;">Hire Odoo Developer</p> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-4 col-sm-6 px-4 py-4"> |
|||
<div |
|||
style="background-color: #fff; padding: 25px; text-align: center; box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px, rgba(0, 0, 0, 0.06) 0px 1px 2px 0px; position: relative; border-radius: 4px;"> |
|||
|
|||
<div style="position: absolute; top: 0%; left: 50%; transform: translate(-50%, -50%);"> |
|||
<div style="background-color:#54A0FF; border-radius: 50%; padding: 15px; width: 68px; |
|||
height: 68px; display: inline-block; box-shadow:0px 4px 4px rgba(0, 0, 0, 0.25);"> |
|||
<img src="assets/icons/puzzle.png" alt="service-icon" width="38px" height="auto"> |
|||
</div> |
|||
</div> |
|||
<p style="margin-top: 20px; font-weight: bold;">Odoo Integration</p> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-4 col-sm-6 px-4 py-4"> |
|||
<div |
|||
style="background-color: #fff; padding: 25px; text-align: center; box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px, rgba(0, 0, 0, 0.06) 0px 1px 2px 0px; position: relative;border-radius: 4px;"> |
|||
<div style="position: absolute; top: 0%; left: 50%; transform: translate(-50%, -50%);"> |
|||
<div style="background-color:#6D7680 ; border-radius: 50%; padding: 15px; width: 68px; |
|||
height: 68px; display: inline-block; box-shadow:0px 4px 4px rgba(0, 0, 0, 0.25);"> |
|||
<img src="assets/icons/update.png" alt="service-icon" width="38px" height="auto"> |
|||
</div> |
|||
</div> |
|||
<p style="margin-top: 20px; font-weight: bold;">Odoo Migration</p> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-4 col-sm-6 px-4 py-4"> |
|||
<div |
|||
style="background-color: #fff; padding: 25px; text-align: center; box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px, rgba(0, 0, 0, 0.06) 0px 1px 2px 0px; position: relative;border-radius: 4px;"> |
|||
<div style="position: absolute; top: 0%; left: 50%; transform: translate(-50%, -50%);"> |
|||
<div style="background-color:#786FA6 ; border-radius: 50%; padding: 15px; width: 68px; |
|||
height: 68px; display: inline-block; box-shadow:0px 4px 4px rgba(0, 0, 0, 0.25);"> |
|||
<img src="assets/icons/consultation.png" alt="service-icon" width="38px" height="auto"> |
|||
</div> |
|||
</div> |
|||
<p style="margin-top: 20px; font-weight: bold;">Odoo Consultancy</p> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-4 col-sm-6 px-4 py-4"> |
|||
<div |
|||
style="background-color: #fff; padding: 25px; text-align: center; box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px, rgba(0, 0, 0, 0.06) 0px 1px 2px 0px;position: relative;border-radius: 4px;"> |
|||
<div style="position: absolute; top: 0%; left: 50%; transform: translate(-50%, -50%);"> |
|||
<div style="background-color:#F8A5C2 ; border-radius: 50%; padding: 15px; width: 68px; |
|||
height: 68px; display: inline-block; box-shadow:0px 4px 4px rgba(0, 0, 0, 0.25);"> |
|||
<img src="assets/icons/training.png" alt="service-icon" width="38px" height="auto"> |
|||
</div> |
|||
</div> |
|||
<p style="margin-top: 20px; font-weight: bold;">Odoo Implementation</p> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-4 col-sm-6 px-4 py-4"> |
|||
<div |
|||
style="background-color: #fff; padding: 25px; text-align: center; box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px, rgba(0, 0, 0, 0.06) 0px 1px 2px 0px; position: relative;border-radius: 4px;"> |
|||
<div style="position: absolute; top: 0%; left: 50%; transform: translate(-50%, -50%);"> |
|||
<div style="background-color:#E6BE26; border-radius: 50%; padding: 15px; width: 68px; |
|||
height: 68px; display: inline-block; box-shadow:0px 4px 4px rgba(0, 0, 0, 0.25);"> |
|||
<img src="assets/icons/license.png" alt="service-icon" width="38px" height="auto"> |
|||
</div> |
|||
</div> |
|||
<p style="margin-top: 20px; font-weight: bold;">Odoo Licensing Consultancy</p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="container mt-5"> |
|||
<div class="col-lg-12 d-flex flex-column justify-content-center align-items-center mt-4"> |
|||
<p class="m-0" style="font-weight: 600; font-size: 24px; color:#000 !important">Our Industries</p> |
|||
|
|||
</div> |
|||
</div> |
|||
<div class="container"> |
|||
<div class="row my-5 py-4"> |
|||
<div class="col-md-3 col-sm-6 p-0"> |
|||
<div class="d-flex flex-column h-100 " |
|||
style="border-right: 1px solid rgb(209, 209, 209); border-bottom: 1px solid rgb(209, 209, 209); padding: 30px; box-shadow: 6px 0 10px rgba(228, 227, 227, 0.373);"> |
|||
<img src="assets/icons/trading-black.png" width="42px" height="auto" alt=""> |
|||
<p style="color: #714B67;font-weight: 600; margin-top: 10px; |
|||
font-size: 1.2rem; margin-bottom: 2px;">Trading</p> |
|||
<p>Easily procure and sell your products</p> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-3 col-sm-6 p-0"> |
|||
<div class="d-flex flex-column h-100" |
|||
style="border-right: 1px solid rgb(209, 209, 209);border-bottom: 1px solid rgb(209, 209, 209); padding: 30px;"> |
|||
<img src="assets/icons/pos-black.png" width="42px" height="auto" alt=""> |
|||
<p style="color: #714B67;font-weight: 600; margin-top: 10px; |
|||
font-size: 1.2rem; margin-bottom: 2px;">POS</p> |
|||
<p>Easy configuration and convivial experience</p> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-3 col-sm-6 p-0"> |
|||
<div class="d-flex flex-column h-100" |
|||
style="border-right: 1px solid rgb(209, 209, 209);border-bottom: 1px solid rgba(0, 0, 0, 0.2); padding: 30px; box-shadow: 0 5px 10px rgba(228, 227, 227, 0.373)"> |
|||
<img src="assets/icons/education-black.png" width="42px" height="auto" alt=""> |
|||
<p style="color: #714B67;font-weight: 600; margin-top: 10px; |
|||
font-size: 1.2rem; margin-bottom: 2px;">Education</p> |
|||
<p>A platform for educational management</p> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-3 col-sm-6 p-0"> |
|||
<div class="d-flex flex-column h-100" |
|||
style="border-bottom: 1px solid rgb(209, 209, 209); padding: 30px; "> |
|||
<img src="assets/icons/manufacturing-black.png" width="42px" height="auto" alt=""> |
|||
<p style="color: #714B67;font-weight: 600; margin-top: 10px; |
|||
font-size: 1.2rem; margin-bottom: 2px;">Manufacturing</p> |
|||
<p>Plan, track and schedule your operations</p> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-3 col-sm-6 p-0"> |
|||
<div class="d-flex flex-column h-100" |
|||
style="border-right: 1px solid rgb(209, 209, 209); padding: 30px;"> |
|||
<img src="assets/icons/ecom-black.png" width="42px" height="auto" alt=""> |
|||
<p style="color: #714B67;font-weight: 600; margin-top: 10px; |
|||
font-size: 1.2rem; margin-bottom: 2px;">E-commerce & Website</p> |
|||
<p>Mobile friendly, awe-inspiring product pages</p> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-3 col-sm-6 p-0"> |
|||
<div class="d-flex flex-column h-100" |
|||
style="border-right: 1px solid rgb(209, 209, 209); padding: 30px;box-shadow: 0 -5px 10px rgba(228, 227, 227, 0.373);"> |
|||
<img src="assets/icons/service-black.png" width="42px" height="auto" alt=""> |
|||
<p style="color: #714B67;font-weight: 600; margin-top: 10px; |
|||
font-size: 1.2rem; margin-bottom: 2px;">Service Management</p> |
|||
<p>Keep track of services and invoice</p> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-3 col-sm-6 p-0"> |
|||
<div class="d-flex flex-column h-100" |
|||
style="border-right: 1px solid rgb(209, 209, 209); padding: 30px; "> |
|||
<img src="assets/icons/restaurant-black.png" width="42px" height="auto" alt=""> |
|||
<p style="color: #714B67;font-weight: 600; margin-top: 10px; |
|||
font-size: 1.2rem; margin-bottom: 2px;">Restaurant</p> |
|||
<p>Run your bar or restaurant methodically</p> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-3 col-sm-6 p-0"> |
|||
<div class="d-flex flex-column h-100" |
|||
style=" padding: 30px;box-shadow: -5px 0 10px rgba(228, 227, 227, 0.373);"> |
|||
<img src="assets/icons/hotel-black.png" width="42px" height="auto" alt=""> |
|||
<p style="color: #714B67;font-weight: 600; margin-top: 10px; |
|||
font-size: 1.2rem; margin-bottom: 2px;">Hotel Management</p> |
|||
<p>An all-inclusive hotel management application</p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="container mt-5"> |
|||
<div class="col-lg-12 d-flex flex-column justify-content-center align-items-center mt-5"> |
|||
<p class="m-0" style="font-weight: 600; font-size: 24px; color:#000 !important">Support</p> |
|||
</div> |
|||
</div> |
|||
<div class="container my-5"> |
|||
<div class="row" style="background-color: #FFFAFE;"> |
|||
<div class="col-md-6 pb-4 d-flex align-items-center justify-content-center" |
|||
style="border-right: 1px solid #D9D9D9;"> |
|||
<div style="padding: 30px;"> |
|||
<div class="d-flex align-items-center"> |
|||
<img src="assets/misc/support (1) 1.svg" alt="" width="60px" style="margin-right: 12px;"> |
|||
<div style="padding: 0px 8px;"> |
|||
<span |
|||
style="color: #714B67;font-size: 24px;font-weight: 600;padding-bottom: 1rem;">Need |
|||
Help?</span> |
|||
<p class="m-0" style="color:#718096;">Got questions or need help? Get in touch.</p> |
|||
<div style="font-weight: 400;"><span><img src="assets/misc/support-email.svg" alt="" |
|||
width="18px" |
|||
style="filter: invert(1);margin-right: 0.8rem;"></span>odoo@cybrosys.com |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-6 pb-4 d-flex align-items-center justify-content-center"> |
|||
<div style="padding: 30px;"> |
|||
<div class="d-flex align-items-center"> |
|||
<img src="assets/misc/whatsapp 1.svg" alt="" width="60px" style="margin-right: 12px;"> |
|||
<div> |
|||
<span style="color: #714B67;font-size: 24px;font-weight: 600;">WhatsApp</span> |
|||
<p class="m-0" style="color:#718096;">Say hi to us on WhatsApp!</p> |
|||
<div style="font-weight: 400; font-size: 16px;"><span><img src="assets/misc/phone.svg" |
|||
alt="" width="14px" |
|||
style="filter: invert(1); margin-right: 0.8rem;"></span>+91 |
|||
99456767686</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
<!-- Optional JavaScript --> |
|||
<!-- jQuery first, then Popper.js, then Bootstrap JS --> |
|||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> |
|||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script> |
|||
</body> |
|||
</html> |
@ -0,0 +1,100 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<!-- Form view of report.pdf--> |
|||
<record id="report_pdf_view_form" model="ir.ui.view"> |
|||
<field name="name">report.pdf.view.form</field> |
|||
<field name="model">report.pdf</field> |
|||
<field name="priority">20</field> |
|||
<field name="arch" type="xml"> |
|||
<form> |
|||
<header> |
|||
<button name="action_print_report" type="object" |
|||
string="Print Report" class="oe_highlight"/> |
|||
</header> |
|||
<field name="binding_model_id" invisible="1"/> |
|||
<field name="action_button" invisible="1"/> |
|||
<sheet> |
|||
<div class="oe_button_box" name="button_box"> |
|||
<button name="action_create_model" type="object" |
|||
string="Add Action" |
|||
invisible="action_button != False" |
|||
icon="fa-plus-square" |
|||
class="oe_stat_button"/> |
|||
|
|||
<button name="action_unlink_action" type="object" |
|||
string="Remove Action" |
|||
invisible="action_button != True" |
|||
icon="fa-plus-square" |
|||
class="oe_stat_button"/> |
|||
|
|||
</div> |
|||
<div class="oe_title"> |
|||
<h1> |
|||
<group> |
|||
<field name="name"/> |
|||
</group> |
|||
</h1> |
|||
</div> |
|||
<group> |
|||
<field name="model_id"/> |
|||
</group> |
|||
|
|||
<span>The column order will be as selected in the below |
|||
table |
|||
</span> |
|||
|
|||
<notebook> |
|||
<page string="Fields To View"> |
|||
<group> |
|||
<field name="fields_ids"> |
|||
<tree editable="bottom"> |
|||
<field name="field_model" |
|||
column_invisible="True"/> |
|||
<field name="field_relation" |
|||
column_invisible="True"/> |
|||
<field name="report_field_id" |
|||
options="{'no_create': True, 'no_create_edit':True}" |
|||
/> |
|||
<field name="field_label"/> |
|||
<field name="field_type"/> |
|||
<field name="field_value_ids" |
|||
column_invisible="True"/> |
|||
|
|||
<field name="one2many_model_field_ids" |
|||
widget="many2many_tags" |
|||
string="Child Fields" |
|||
invisible="field_type != 'one2many'" |
|||
domain="[('model', '=', field_relation)]"/> |
|||
</tree> |
|||
</field> |
|||
<field name="date_field_id" |
|||
domain="[('model_id', '=', model_id)]"/> |
|||
<field name="field_order" invisible="1"/> |
|||
</group> |
|||
<group invisible="date_field_id == False"> |
|||
<field name="start_date" class="oe_inline" |
|||
invisible="date_field_id == False"/> |
|||
<field name="end_date" class="oe_inline" |
|||
invisible="date_field_id == False"/> |
|||
</group> |
|||
</page> |
|||
</notebook> |
|||
</sheet> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<!-- Record action of report.pdf--> |
|||
<record id="report_pdf_action" model="ir.actions.act_window"> |
|||
<field name="name">Report PDF</field> |
|||
<field name="res_model">report.pdf</field> |
|||
<field name="view_mode">tree,form</field> |
|||
</record> |
|||
|
|||
<!-- Menu of report.pdf--> |
|||
<menuitem id="report_pdf_menu" |
|||
name="PDF Report Designer" |
|||
action="report_pdf_action" |
|||
parent="base.menu_administration" |
|||
sequence="50"/> |
|||
</odoo> |
@ -0,0 +1,22 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Anfas Faisal K (odoo@cybrosys.info) |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################### |
|||
from . import pdf_report |
@ -0,0 +1,197 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Anfas Faisal K (odoo@cybrosys.info) |
|||
# |
|||
# 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 <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################### |
|||
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( |
|||
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) |
@ -0,0 +1,18 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<!-- Form view of pdf.report--> |
|||
<record id="pdf_report_view_form" model="ir.ui.view"> |
|||
<field name="name">pdf.report.view.form</field> |
|||
<field name="model">pdf.report</field> |
|||
<field name="arch" type="xml"> |
|||
<form> |
|||
<h2>Do you want to print the report??</h2> |
|||
<footer> |
|||
<button name="action_print_pdf_report" string="Print" |
|||
type="object" class="oe_highlight"/> |
|||
<button string="Cancel" special="cancel" class="oe_link"/> |
|||
</footer> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
</odoo> |