@ -0,0 +1,45 @@ |
|||||
|
.. image:: https://img.shields.io/badge/license-AGPL--3-blue.svg |
||||
|
:target: https://www.gnu.org/licenses/agpl-3.0-standalone.html |
||||
|
:alt: License: AGPL-3 |
||||
|
|
||||
|
Odoo Dynamic Dashboard |
||||
|
========================== |
||||
|
* Dynamically Arrange the dashboard to get the information that are relevant to your business, department, or a specific process or need. |
||||
|
|
||||
|
Configuration |
||||
|
============= |
||||
|
- No configuration needed |
||||
|
|
||||
|
License |
||||
|
======= |
||||
|
Affero General Public License v3.0 (AGPL v3) |
||||
|
(https://www.gnu.org/licenses/agpl-3.0-standalone.html) |
||||
|
|
||||
|
Company |
||||
|
------- |
||||
|
* `Cybrosys Techno Solutions <https://cybrosys.com/>`__ |
||||
|
|
||||
|
Credits |
||||
|
------- |
||||
|
* Developers: (V18) Bhagyadev KP, |
||||
|
* Contact: odoo@cybrosys.com |
||||
|
|
||||
|
Contacts |
||||
|
-------- |
||||
|
* Mail Contact : odoo@cybrosys.com |
||||
|
* Website : http://www.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 https://www.cybrosys.com |
||||
|
|
||||
|
Further information |
||||
|
=================== |
||||
|
HTML Description: `<static/description/index.html>`__ |
@ -0,0 +1,24 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Bhagyadev KP (odoo@cybrosys.com) |
||||
|
# |
||||
|
# This program is free software: you can modify |
||||
|
# it under the terms of the GNU Affero General Public License (AGPL) as |
||||
|
# published by the Free Software Foundation, either version 3 of the |
||||
|
# License, or (at your option) any later version. |
||||
|
# |
||||
|
# This program is distributed in the hope that it will be useful, |
||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
# GNU Affero General Public License for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU Affero General Public License |
||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from . import controllers |
||||
|
from . import models |
||||
|
from . import wizard |
@ -0,0 +1,63 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Bhagyadev KP (odoo@cybrosys.com) |
||||
|
# |
||||
|
# This program is free software: you can modify |
||||
|
# it under the terms of the GNU Affero General Public License (AGPL) as |
||||
|
# published by the Free Software Foundation, either version 3 of the |
||||
|
# License, or (at your option) any later version. |
||||
|
# |
||||
|
# This program is distributed in the hope that it will be useful, |
||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
# GNU Affero General Public License for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU Affero General Public License |
||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
{ |
||||
|
'name': "Odoo Dynamic Dashboard", |
||||
|
'version': '18.0.1.0.0', |
||||
|
'category': 'Productivity', |
||||
|
'summary': """Create Configurable Dashboards Easily""", |
||||
|
'description': """Create Configurable Odoo Dynamic Dashboard to get the |
||||
|
information that are relevant to your business, department, or a specific |
||||
|
process or need""", |
||||
|
'author': 'Cybrosys Techno Solutions', |
||||
|
'company': 'Cybrosys Techno Solutions', |
||||
|
'maintainer': 'Cybrosys Techno Solutions', |
||||
|
'website': "https://www.cybrosys.com", |
||||
|
'depends': ['web'], |
||||
|
'data': [ |
||||
|
'security/ir.model.access.csv', |
||||
|
'data/dashboard_theme_data.xml', |
||||
|
'views/dashboard_views.xml', |
||||
|
'views/dynamic_block_views.xml', |
||||
|
'views/dashboard_menu_views.xml', |
||||
|
'views/dashboard_theme_views.xml', |
||||
|
'wizard/dashboard_mail_views.xml', |
||||
|
], |
||||
|
'assets': { |
||||
|
'web.assets_backend': [ |
||||
|
'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js', |
||||
|
'odoo_dynamic_dashboard/static/src/css/**/*.css', |
||||
|
'odoo_dynamic_dashboard/static/src/scss/**/*.scss', |
||||
|
'odoo_dynamic_dashboard/static/src/js/**/*.js', |
||||
|
'odoo_dynamic_dashboard/static/src/xml/**/*.xml', |
||||
|
'https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css', |
||||
|
'odoo_dynamic_dashboard/static/lib/js/interactjs.js', |
||||
|
], |
||||
|
}, |
||||
|
'images': ['static/description/banner.gif'], |
||||
|
'license': "AGPL-3", |
||||
|
'installable': True, |
||||
|
'auto_install': False, |
||||
|
'application': True, |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
@ -0,0 +1,22 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Bhagyadev KP (odoo@cybrosys.com) |
||||
|
# |
||||
|
# This program is free software: you can modify |
||||
|
# it under the terms of the GNU Affero General Public License (AGPL) as |
||||
|
# published by the Free Software Foundation, either version 3 of the |
||||
|
# License, or (at your option) any later version. |
||||
|
# |
||||
|
# This program is distributed in the hope that it will be useful, |
||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
# GNU Affero General Public License for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU Affero General Public License |
||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from . import odoo_dynamic_dashboard |
@ -0,0 +1,34 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Bhagyadev KP (odoo@cybrosys.com) |
||||
|
# |
||||
|
# This program is free software: you can modify |
||||
|
# it under the terms of the GNU Affero General Public License (AGPL) as |
||||
|
# published by the Free Software Foundation, either version 3 of the |
||||
|
# License, or (at your option) any later version. |
||||
|
# |
||||
|
# This program is distributed in the hope that it will be useful, |
||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
# GNU Affero General Public License for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU Affero General Public License |
||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import http |
||||
|
from odoo.http import request |
||||
|
|
||||
|
|
||||
|
class DynamicDashboard(http.Controller): |
||||
|
"""Class to search and filter values in dashboard""" |
||||
|
|
||||
|
@http.route('/custom_dashboard/search_input_chart', type='json', |
||||
|
auth="public", website=True) |
||||
|
def dashboard_search_input_chart(self, search_input): |
||||
|
"""Function to filter search input in dashboard""" |
||||
|
return request.env['dashboard.block'].search([ |
||||
|
('name', 'ilike', search_input)]).ids |
@ -0,0 +1,12 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8" ?> |
||||
|
<odoo> |
||||
|
<data> |
||||
|
<!-- Demo Dashboard Theme --> |
||||
|
<record id="demo_theme" model="dashboard.theme"> |
||||
|
<field name="name">Demo</field> |
||||
|
<field name="color_x">#4158D0</field> |
||||
|
<field name="color_y">#C850C0</field> |
||||
|
<field name="color_z">#FFCC70</field> |
||||
|
</record> |
||||
|
</data> |
||||
|
</odoo> |
@ -0,0 +1,6 @@ |
|||||
|
## Module <odoo_dynamic_dashboard> |
||||
|
|
||||
|
#### 15.10.2024 |
||||
|
#### Version 18.0.1.0.0 |
||||
|
##### ADD |
||||
|
- Initial commit for Odoo Dynamic Dashboard |
@ -0,0 +1,25 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Bhagyadev KP (odoo@cybrosys.com) |
||||
|
# |
||||
|
# This program is free software: you can modify |
||||
|
# it under the terms of the GNU Affero General Public License (AGPL) as |
||||
|
# published by the Free Software Foundation, either version 3 of the |
||||
|
# License, or (at your option) any later version. |
||||
|
# |
||||
|
# This program is distributed in the hope that it will be useful, |
||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
# GNU Affero General Public License for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU Affero General Public License |
||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from . import dashboard_block |
||||
|
from . import dashboard_menu |
||||
|
from . import dashboard_theme |
||||
|
from . import domain_to_sql |
@ -0,0 +1,181 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Bhagyadev KP (odoo@cybrosys.com) |
||||
|
# |
||||
|
# This program is free software: you can modify |
||||
|
# it under the terms of the GNU Affero General Public License (AGPL) as |
||||
|
# published by the Free Software Foundation, either version 3 of the |
||||
|
# License, or (at your option) any later version. |
||||
|
# |
||||
|
# This program is distributed in the hope that it will be useful, |
||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
# GNU Affero General Public License for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU Affero General Public License |
||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from ast import literal_eval |
||||
|
from odoo import api, fields, models |
||||
|
from odoo.osv import expression |
||||
|
|
||||
|
|
||||
|
class DashboardBlock(models.Model): |
||||
|
"""Class is used to create charts and tiles in dashboard""" |
||||
|
_name = "dashboard.block" |
||||
|
_description = "Dashboard Block" |
||||
|
|
||||
|
def get_default_action(self): |
||||
|
"""Function to get values from dashboard if action_id is true return |
||||
|
id else return false""" |
||||
|
action_id = self.env.ref( |
||||
|
'odoo_dynamic_dashboard.dashboard_view_action') |
||||
|
if action_id: |
||||
|
return action_id.id |
||||
|
return False |
||||
|
|
||||
|
name = fields.Char(string="Name", help='Name of the block') |
||||
|
fa_icon = fields.Char(string="Icon", help="Add icon for tile") |
||||
|
operation = fields.Selection( |
||||
|
selection=[("sum", "Sum"), ("avg", "Average"), ("count", "Count")], |
||||
|
string="Operation", |
||||
|
help='Tile Operation that needs to bring values for tile', |
||||
|
required=True) |
||||
|
graph_type = fields.Selection( |
||||
|
selection=[("bar", "Bar"), ("radar", "Radar"), ("pie", "Pie"), |
||||
|
("polarArea", "polarArea"), ("line", "Line"), |
||||
|
("doughnut", "Doughnut")], |
||||
|
string="Chart Type", help='Type of Chart') |
||||
|
measured_field_id = fields.Many2one("ir.model.fields", |
||||
|
string="Measured Field", |
||||
|
help="Select the Measured") |
||||
|
client_action_id = fields.Many2one('ir.actions.client', |
||||
|
string="Client action", |
||||
|
default=get_default_action, |
||||
|
help="Client action") |
||||
|
type = fields.Selection( |
||||
|
selection=[("graph", "Chart"), ("tile", "Tile")], |
||||
|
string="Type", help='Type of Block ie, Chart or Tile') |
||||
|
x_axis = fields.Char(string="X-Axis", help="Chart X-axis") |
||||
|
y_axis = fields.Char(string="Y-Axis", help="Chart Y-axis") |
||||
|
height = fields.Char(string="Height ", help="Height of the block") |
||||
|
width = fields.Char(string="Width", help="Width of the block") |
||||
|
translate_x = fields.Char(string="Translate_X", |
||||
|
help="x value for the style transform translate") |
||||
|
translate_y = fields.Char(string="Translate_Y", |
||||
|
help="y value for the style transform translate") |
||||
|
data_x = fields.Char(string="Data_X", help="Data x value for resize") |
||||
|
data_y = fields.Char(string="Data_Y", help="Data y value for resize") |
||||
|
group_by_id = fields.Many2one("ir.model.fields", |
||||
|
string="Group by(Y-Axis)", |
||||
|
help='Field value for Y-Axis') |
||||
|
tile_color = fields.Char(string="Tile Color", help='Primary Color of Tile') |
||||
|
text_color = fields.Char(string="Text Color", help='Text Color of Tile') |
||||
|
val_color = fields.Char(string="Value Color", help='Value Color of Tile') |
||||
|
fa_color = fields.Char(string="Icon Color", help='Icon Color of Tile') |
||||
|
filter = fields.Char(string="Filter", help="Add filter") |
||||
|
model_id = fields.Many2one('ir.model', string='Model', |
||||
|
help="Select the module name") |
||||
|
model_name = fields.Char(related='model_id.model', string="Model Name", |
||||
|
help="Added model_id model") |
||||
|
edit_mode = fields.Boolean(string="Edit Mode", |
||||
|
help="Enable to edit chart and tile",) |
||||
|
|
||||
|
@api.onchange('model_id') |
||||
|
def _onchange_model_id(self): |
||||
|
if self.operation or self.measured_field_id: |
||||
|
self.operation = False |
||||
|
self.measured_field_id = False |
||||
|
|
||||
|
def get_dashboard_vals(self, action_id, start_date=None, end_date=None): |
||||
|
"""Fetch block values from js and create chart""" |
||||
|
block_id = [] |
||||
|
for rec in self.env['dashboard.block'].sudo().search( |
||||
|
[('client_action_id', '=', int(action_id))]): |
||||
|
if rec.filter is False: |
||||
|
rec.filter = "[]" |
||||
|
filter_list = literal_eval(rec.filter) |
||||
|
filter_list = [filter_item for filter_item in filter_list if not ( |
||||
|
isinstance(filter_item, tuple) and filter_item[ |
||||
|
0] == 'create_date')] |
||||
|
rec.filter = repr(filter_list) |
||||
|
vals = {'id': rec.id, 'name': rec.name, 'type': rec.type, |
||||
|
'graph_type': rec.graph_type, 'icon': rec.fa_icon, |
||||
|
'model_name': rec.model_name, |
||||
|
'color': f'background-color: {rec.tile_color};' if rec.tile_color else '#1f6abb;', |
||||
|
'text_color': f'color: {rec.text_color};' if rec.text_color else '#FFFFFF;', |
||||
|
'val_color': f'color: {rec.val_color};' if rec.val_color else '#FFFFFF;', |
||||
|
'icon_color': f'color: {rec.tile_color};' if rec.tile_color else '#1f6abb;', |
||||
|
'height': rec.height, |
||||
|
'width': rec.width, |
||||
|
'translate_x': rec.translate_x, |
||||
|
'translate_y': rec.translate_y, |
||||
|
'data_x': rec.data_x, |
||||
|
'data_y': rec.data_y, |
||||
|
'domain': filter_list, |
||||
|
} |
||||
|
domain = [] |
||||
|
if rec.filter: |
||||
|
domain = expression.AND([literal_eval(rec.filter)]) |
||||
|
if rec.model_name: |
||||
|
if rec.type == 'graph': |
||||
|
self._cr.execute(self.env[rec.model_name].get_query(domain, |
||||
|
rec.operation, |
||||
|
rec.measured_field_id, |
||||
|
start_date, |
||||
|
end_date, |
||||
|
group_by=rec.group_by_id)) |
||||
|
records = self._cr.dictfetchall() |
||||
|
x_axis = [] |
||||
|
for record in records: |
||||
|
if record.get('name') and type( |
||||
|
record.get('name')) == dict: |
||||
|
x_axis.append(record.get('name')[self._context.get( |
||||
|
'lang') or 'en_US']) |
||||
|
else: |
||||
|
x_axis.append(record.get(rec.group_by_id.name)) |
||||
|
y_axis = [] |
||||
|
for record in records: |
||||
|
y_axis.append(record.get('value')) |
||||
|
vals.update({'x_axis': x_axis, 'y_axis': y_axis}) |
||||
|
else: |
||||
|
self._cr.execute(self.env[rec.model_name].get_query(domain, |
||||
|
rec.operation, |
||||
|
rec.measured_field_id, |
||||
|
start_date, |
||||
|
end_date)) |
||||
|
records = self._cr.dictfetchall() |
||||
|
magnitude = 0 |
||||
|
total = records[0].get('value') |
||||
|
while abs(total) >= 1000: |
||||
|
magnitude += 1 |
||||
|
total /= 1000.0 |
||||
|
val = '%.2f%s' % ( |
||||
|
total, ['', 'K', 'M', 'G', 'T', 'P'][magnitude]) |
||||
|
records[0]['value'] = val |
||||
|
vals.update(records[0]) |
||||
|
block_id.append(vals) |
||||
|
return block_id |
||||
|
|
||||
|
def get_save_layout(self, grid_data_list): |
||||
|
"""Function fetch edited values while edit layout of the chart or tile |
||||
|
and save values in a database""" |
||||
|
for data in grid_data_list: |
||||
|
block = self.browse(int(data['id'])) |
||||
|
if data.get('data-x'): |
||||
|
block.write({ |
||||
|
'translate_x': f"{data['data-x']}px", |
||||
|
'translate_y': f"{data['data-y']}px", |
||||
|
'data_x': data['data-x'], |
||||
|
'data_y': data['data-y'], |
||||
|
}) |
||||
|
if data.get('height'): |
||||
|
block.write({ |
||||
|
'height': f"{data['height']}px", |
||||
|
'width': f"{data['width']}px", |
||||
|
}) |
||||
|
return True |
@ -0,0 +1,80 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Bhagyadev KP (odoo@cybrosys.com) |
||||
|
# |
||||
|
# This program is free software: you can modify |
||||
|
# it under the terms of the GNU Affero General Public License (AGPL) as |
||||
|
# published by the Free Software Foundation, either version 3 of the |
||||
|
# License, or (at your option) any later version. |
||||
|
# |
||||
|
# This program is distributed in the hope that it will be useful, |
||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
# GNU Affero General Public License for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU Affero General Public License |
||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import api, fields, models |
||||
|
|
||||
|
|
||||
|
class DashboardMenu(models.Model): |
||||
|
"""Class to create new dashboard menu""" |
||||
|
_name = "dashboard.menu" |
||||
|
_description = "Dashboard Menu" |
||||
|
|
||||
|
name = fields.Char(string="Name", ondelete='cascade', |
||||
|
help="Enter a name for the dashboard menu") |
||||
|
menu_id = fields.Many2one('ir.ui.menu', string="Parent Menu", |
||||
|
help="Parent Menu Location of New Dashboard", |
||||
|
ondelete='cascade') |
||||
|
group_ids = fields.Many2many('res.groups', string='Groups', |
||||
|
related='menu_id.groups_id', |
||||
|
help="User need to be at least in one of " |
||||
|
"these groups to see the menu") |
||||
|
client_action_id = fields.Many2one('ir.actions.client', |
||||
|
string="Client Action", |
||||
|
help="Client action of the " |
||||
|
"corresponding dashboard menu") |
||||
|
|
||||
|
@api.model |
||||
|
def create(self, vals): |
||||
|
"""Function to create new dashboard menu""" |
||||
|
action_id = self.env['ir.actions.client'].create([{ |
||||
|
'name': vals['name'], |
||||
|
'tag': 'OdooDynamicDashboard', |
||||
|
}]) |
||||
|
vals['client_action_id'] = action_id.id |
||||
|
self.env['ir.ui.menu'].create([{ |
||||
|
'name': vals['name'], |
||||
|
'parent_id': vals['menu_id'], |
||||
|
'action': 'ir.actions.client,%d' % (action_id.id,) |
||||
|
}]) |
||||
|
return super(DashboardMenu, self).create(vals) |
||||
|
|
||||
|
def write(self, vals): |
||||
|
"""Function to save edited data in dashboard menu""" |
||||
|
for rec in self: |
||||
|
client_act_id = rec['client_action_id'].id |
||||
|
self.env['ir.ui.menu'].search( |
||||
|
[('parent_id', '=', rec['menu_id'].id), |
||||
|
('action', '=', f'ir.actions.client,{client_act_id}')]).write({ |
||||
|
'name': vals['name'] if 'name' in vals.keys() else rec['name'], |
||||
|
'parent_id': vals['menu_id'] if 'menu_id' in vals.keys() else |
||||
|
rec['menu_id'], |
||||
|
'action': f'ir.actions.client,{client_act_id}' |
||||
|
}) |
||||
|
return super(DashboardMenu, self).write(vals) |
||||
|
|
||||
|
def unlink(self): |
||||
|
"""Delete dashboard along with menu item""" |
||||
|
for rec in self: |
||||
|
self.env['ir.ui.menu'].search( |
||||
|
[('parent_id', '=', rec['menu_id'].id), |
||||
|
('action', '=', |
||||
|
f'ir.actions.client,{rec["client_action_id"].id}')]).unlink() |
||||
|
return super(DashboardMenu, self).unlink() |
@ -0,0 +1,53 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Bhagyadev KP (odoo@cybrosys.com) |
||||
|
# |
||||
|
# This program is free software: you can modify |
||||
|
# it under the terms of the GNU Affero General Public License (AGPL) as |
||||
|
# published by the Free Software Foundation, either version 3 of the |
||||
|
# License, or (at your option) any later version. |
||||
|
# |
||||
|
# This program is distributed in the hope that it will be useful, |
||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
# GNU Affero General Public License for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU Affero General Public License |
||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import api, fields, models |
||||
|
|
||||
|
|
||||
|
class DashboardTheme(models.Model): |
||||
|
_name = 'dashboard.theme' |
||||
|
_description = 'Dashboard Theme' |
||||
|
|
||||
|
name = fields.Char(string='Theme Name', help='Name of the theme') |
||||
|
color_x = fields.Char(string='Color X', help='Select the color_x for theme', |
||||
|
default='#4158D0') |
||||
|
color_y = fields.Char(string='Color Y', help='Select the color_y for theme', |
||||
|
default='#C850C0') |
||||
|
color_z = fields.Char(string='Color Z', help='Select the color_z for theme', |
||||
|
default='#FFCC70') |
||||
|
body = fields.Html(string='Body', help='Preview of the theme will be shown') |
||||
|
style = fields.Char(string='Style', |
||||
|
help='It store the style of the gradient') |
||||
|
|
||||
|
@api.constrains('name', 'color_x', 'color_y', 'color_z') |
||||
|
def save_record(self): |
||||
|
""" |
||||
|
Function for saving the datas including body and style |
||||
|
""" |
||||
|
self.body = f"<div style='width:300px; height:300px;background-image: linear-gradient(50deg, {self.color_x} 0%, {self.color_y} 46%, {self.color_z} 100%);'/>" |
||||
|
self.style = f"background-image: linear-gradient(50deg, {self.color_x} 0%, {self.color_y} 46%, {self.color_z} 100%);" |
||||
|
|
||||
|
def get_records(self): |
||||
|
""" |
||||
|
Function for returning all records with fields name and style |
||||
|
""" |
||||
|
records = self.search_read([], ['name', 'style']) |
||||
|
return records |
@ -0,0 +1,72 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Bhagyadev KP (odoo@cybrosys.com) |
||||
|
# |
||||
|
# This program is free software: you can modify |
||||
|
# it under the terms of the GNU Affero General Public License (AGPL) as |
||||
|
# published by the Free Software Foundation, either version 3 of the |
||||
|
# License, or (at your option) any later version. |
||||
|
# |
||||
|
# This program is distributed in the hope that it will be useful, |
||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
# GNU Affero General Public License for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU Affero General Public License |
||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import models |
||||
|
|
||||
|
|
||||
|
def get_query(self, args, operation, field, start_date=None, end_date=None, |
||||
|
group_by=False, apply_ir_rules=False): |
||||
|
""" Dashboard block Query Creation """ |
||||
|
query = self._where_calc(args) |
||||
|
if apply_ir_rules: |
||||
|
self._apply_ir_rules(query, 'read') |
||||
|
if operation and field: |
||||
|
data = 'COALESCE(%s("%s".%s),0) AS value' % ( |
||||
|
operation.upper(), self._table, field.name) |
||||
|
join = '' |
||||
|
group_by_str = '' |
||||
|
if group_by: |
||||
|
if group_by.ttype == 'many2one': |
||||
|
relation_model = group_by.relation.replace('.', '_') |
||||
|
join = ' INNER JOIN %s on "%s".id = "%s".%s' % ( |
||||
|
relation_model, relation_model, self._table, group_by.name) |
||||
|
rec_name = self.env[group_by.relation]._rec_name_fallback() |
||||
|
data = data + ',"%s".%s AS %s' % ( |
||||
|
relation_model, rec_name, group_by.name) |
||||
|
group_by_str = ' Group by "%s".%s' % (relation_model, rec_name) |
||||
|
else: |
||||
|
data = data + ',"%s".%s' % (self._table, group_by.name) |
||||
|
group_by_str = ' Group by "%s".%s' % ( |
||||
|
self._table, str(group_by.name)) |
||||
|
else: |
||||
|
data = '"%s".id' % (self._table) |
||||
|
from_clause, from_params = query.from_clause |
||||
|
where_clause, where_clause_params = query.where_clause |
||||
|
where_str = where_clause and (" WHERE %s" % where_clause) or '' |
||||
|
if start_date and start_date != 'null': |
||||
|
start_date_query = f' AND ({from_clause}."create_date" >= \'{start_date}\')' |
||||
|
else: |
||||
|
start_date_query = '' |
||||
|
if end_date and end_date != 'null': |
||||
|
end_date_query = f' AND ({from_clause}."create_date" <= \'{end_date}\')' |
||||
|
else: |
||||
|
end_date_query = '' |
||||
|
query_str = 'SELECT %s FROM ' % data + from_clause + join + where_str + start_date_query + end_date_query + group_by_str |
||||
|
def format_param(x): |
||||
|
if not isinstance(x, tuple): |
||||
|
return "'" + str(x) + "'" |
||||
|
elif isinstance(x, tuple) and len(x) == 1: |
||||
|
return "(" + str(x[0]) + ")" |
||||
|
else: |
||||
|
return str(x) |
||||
|
exact_query = query_str % tuple(map(format_param, where_clause_params)) |
||||
|
return exact_query |
||||
|
models.BaseModel.get_query = get_query |
|
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 209 KiB |
After Width: | Height: | Size: 495 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 624 B |
After Width: | Height: | Size: 136 KiB |
After Width: | Height: | Size: 214 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 929 B |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 542 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 600 B |
After Width: | Height: | Size: 462 B |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 926 B |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 800 B |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 875 B |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 89 KiB |
After Width: | Height: | Size: 72 KiB |
After Width: | Height: | Size: 100 KiB |
After Width: | Height: | Size: 172 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 91 KiB |
After Width: | Height: | Size: 171 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 581 KiB |
After Width: | Height: | Size: 188 KiB |
After Width: | Height: | Size: 43 KiB |