diff --git a/crm_dashboard/README.rst b/crm_dashboard/README.rst new file mode 100755 index 000000000..8cf6488d1 --- /dev/null +++ b/crm_dashboard/README.rst @@ -0,0 +1,47 @@ +.. 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 + +CRM Dashboard +============== +* Visual report of CRM through Dashboard. + +Configuration +============= +* No additional configurations needed + +Company +------- +* `Cybrosys Techno Solutions `__ + +License +------- +Affero General Public License, Version 3 (AGPL v3). +(https://www.gnu.org/licenses/agpl-3.0-standalone.html) + +Credits +------- +Developer: (V17) Mruthul Raj, + (V18) Raneesha, +Contact:odoo@cybrosys.com + +Contacts +-------- +* Mail Contact : odoo@cybrosys.com +* Website : https://cybrosys.com + +Bug Tracker +----------- +Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. + +Maintainer +========== +.. image:: https://cybrosys.com/images/logo.png + :target: https://cybrosys.com + +This module is maintained by Cybrosys Technologies. +For support and more information, please visit `Our Website `__ + +Further information +=================== +HTML Description: ``__ diff --git a/crm_dashboard/__init__.py b/crm_dashboard/__init__.py new file mode 100644 index 000000000..70c889f60 --- /dev/null +++ b/crm_dashboard/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2025-TODAY Cybrosys Technologies(). +# Author: Raneesha (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +################################################################################ +from . import models diff --git a/crm_dashboard/__manifest__.py b/crm_dashboard/__manifest__.py new file mode 100644 index 000000000..36031f008 --- /dev/null +++ b/crm_dashboard/__manifest__.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2025-TODAY Cybrosys Technologies(). +# Author: Raneesha (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +################################################################################ +{ + 'name': "CRM Dashboard", + 'version': '18.0.1.0.0', + 'category': 'Extra Tools', + 'summary': """Get a visual report of CRM through a Dashboard in CRM """, + 'description': """CRM dashboard module brings a multipurpose graphical + dashboard for CRM module and making the relationship management + better and easier""", + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'maintainer': 'Cybrosys Techno Solutions', + 'website': "https://www.cybrosys.com", + 'depends': ['crm', 'sale_management'], + 'data': ['views/crm_dashboard_views.xml', + 'views/res_users_views.xml', + 'views/utm_campaign_views.xml', + 'views/crm_team_views.xml', + ], + 'assets': { + 'web.assets_backend': [ + 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.0/chart.umd.min.js', + 'crm_dashboard/static/src/css/style.css', + 'crm_dashboard/static/src/js/crm_dashboard.js', + 'crm_dashboard/static/src/xml/dashboard_templates.xml', + ], + }, + 'images': ['static/description/banner.png'], + 'license': 'AGPL-3', + 'installable': True, + 'application': False, + 'auto_install': False, +} diff --git a/crm_dashboard/doc/RELEASE_NOTES.md b/crm_dashboard/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..5d5c3e3f0 --- /dev/null +++ b/crm_dashboard/doc/RELEASE_NOTES.md @@ -0,0 +1,6 @@ +## Module + +#### 07.01.2025 +#### Version 18.0.1.0.0 +#### ADD +- Initial commit for CRM Dashboard diff --git a/crm_dashboard/models/__init__.py b/crm_dashboard/models/__init__.py new file mode 100644 index 000000000..266d14322 --- /dev/null +++ b/crm_dashboard/models/__init__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2025-TODAY Cybrosys Technologies(). +# Author: Raneesha (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +################################################################################ +from . import crm_lead +from . import crm_team +from . import res_user +from . import sale_order +from . import utm_campaign diff --git a/crm_dashboard/models/crm_lead.py b/crm_dashboard/models/crm_lead.py new file mode 100644 index 000000000..d3cdad6fe --- /dev/null +++ b/crm_dashboard/models/crm_lead.py @@ -0,0 +1,438 @@ +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2025-TODAY Cybrosys Technologies(). +# Author: Raneesha (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +################################################################################ +import calendar +from dateutil.relativedelta import relativedelta +from odoo import api, fields, models +from odoo.tools.safe_eval import datetime + + +def get_period_start_date(period): + """Returns the start date for the given period""" + today = datetime.datetime.now() + + if period == 'month': + start_date = today.replace(day=1) + elif period == 'quarter': + current_month = today.month + start_month = ((current_month - 1) // 3) * 3 + 1 + start_date = today.replace(month=start_month, day=1) + elif period == 'year': + start_date = today.replace(month=1, day=1) + elif period == 'week': + start_date = today - datetime.timedelta(days=today.weekday()) + else: + raise ValueError("Invalid period specified") + + return start_date.date() + + +class CRMLead(models.Model): + """Extends crm.lead for adding more functions in it""" + _inherit = 'crm.lead' + + @api.model + def get_data(self, period): + """Returns data to the dashboard tiles""" + period_days = get_period_start_date(period) + + crm_model = self.search([('create_date', '>=', period_days)]) + + lead_count = 0 + opportunity_count = 0 + win_count = 0 + active_lead_count = 0 + active_opportunity_count = 0 + won_opportunity_count = 0 + total_seconds = 0 + expected_revenue = 0 + revenue = 0 + unassigned_leads = 0 + + for record in crm_model: + if record.type == 'lead': + lead_count += 1 + if not record.user_id: + unassigned_leads += 1 + + if record.type == 'opportunity': + opportunity_count += 1 + expected_revenue += record.expected_revenue + if record.active: + if record.probability == 0: + active_opportunity_count += 1 + elif record.probability == 100: + won_opportunity_count += 1 + if record.stage_id.is_won: + revenue += record.expected_revenue + + if record.active: + if record.probability == 0: + active_lead_count += 1 + elif record.probability == 100: + win_count += 1 + + if record.date_conversion: + total_seconds += ( + record.date_conversion - record.create_date).seconds + + win_ratio = win_count / active_lead_count if active_lead_count else 0 + opportunity_ratio = won_opportunity_count / active_opportunity_count if active_opportunity_count else 0 + avg_close_time = round(total_seconds / len(crm_model.filtered( + lambda l: l.date_conversion))) if total_seconds else 0 + + return { + 'leads': lead_count, + 'opportunities': opportunity_count, + 'exp_revenue': expected_revenue, + 'revenue': revenue, + 'win_ratio': win_ratio, + 'opportunity_ratio': opportunity_ratio, + 'avg_close_time': avg_close_time, + 'unassigned_leads': unassigned_leads, + } + + @api.model + def get_lead_stage_data(self, period): + """funnel chart""" + period_days = get_period_start_date(period) + crm_model = self.search([('create_date', '>=', period_days)]) + stage_lead_count = {} + + for lead in crm_model: + stage_name = lead.stage_id.name + if stage_name in stage_lead_count: + stage_lead_count[stage_name] += 1 + else: + stage_lead_count[stage_name] = 1 + + # Convert the dictionary into lists for stages and their counts + crm_stages = list(stage_lead_count.keys()) + lead_count = list(stage_lead_count.values()) + + # Return the data in the expected format + return [lead_count, crm_stages] + + @api.model + def get_lead_by_month(self): + """pie chart""" + month_count = [] + month_value = [] + for rec in self.search([]): + month = rec.create_date.month + if month not in month_value: + month_value.append(month) + month_count.append(month) + month_val = [{'label': calendar.month_name[month], + 'value': month_count.count(month)} for month in + month_value] + names = [record['label'] for record in month_val] + counts = [record['value'] for record in month_val] + month = [counts, names] + return month + + @api.model + def get_crm_activities(self, period): + """Sales Activity Pie""" + start_date = get_period_start_date(period) + self._cr.execute(''' + SELECT mail_activity_type.name, COUNT(*) + FROM mail_activity + INNER JOIN mail_activity_type + ON mail_activity.activity_type_id = mail_activity_type.id + INNER JOIN crm_lead + ON mail_activity.res_id = crm_lead.id + AND mail_activity.res_model = 'crm.lead' + WHERE crm_lead.create_date >= %s + GROUP BY mail_activity_type.name + ''', (start_date,)) + data = self._cr.dictfetchall() + names = [record['name']['en_US'] for record in data] + counts = [record['count'] for record in data] + return [counts, names] + + @api.model + def get_the_campaign_pie(self, period): + """Leads Group By Campaign Pie""" + start_date = get_period_start_date(period) + self._cr.execute('''SELECT campaign_id, COUNT(*), + (SELECT name FROM utm_campaign + WHERE utm_campaign.id = crm_lead.campaign_id) + FROM crm_lead WHERE create_date >= %s AND campaign_id IS NOT NULL GROUP BY + campaign_id''', (start_date,)) + data = self._cr.dictfetchall() + names = [record.get('name') for record in data] + counts = [record.get('count') for record in data] + final = [counts, names] + return final + + @api.model + def get_the_source_pie(self, period): + """Leads Group By Source Pie""" + start_date = get_period_start_date(period) + self._cr.execute('''SELECT source_id, COUNT(*), + (SELECT name FROM utm_source + WHERE utm_source.id = crm_lead.source_id) + FROM crm_lead WHERE create_date >= %s AND source_id IS NOT NULL GROUP BY + source_id''', (start_date,)) + data = self._cr.dictfetchall() + names = [record.get('name') for record in data] + counts = [record.get('count') for record in data] + final = [counts, names] + return final + + @api.model + def get_the_medium_pie(self, period): + """Leads Group By Medium Pie""" + start_date = get_period_start_date(period) + self._cr.execute('''SELECT medium_id, COUNT(*), + (SELECT name FROM utm_medium + WHERE utm_medium.id = crm_lead.medium_id) + FROM crm_lead WHERE create_date >= %s AND medium_id IS NOT NULL GROUP BY medium_id''', + (start_date,)) + data = self._cr.dictfetchall() + names = [record.get('name') for record in data] + counts = [record.get('count') for record in data] + final = [counts, names] + return final + + @api.model + def get_total_lost_crm(self, period): + """Lost Opportunity or Lead Graph""" + month_dict = {} + + # Format the start date to be used in the SQL query + start_date = get_period_start_date(period) + + if period == 'year': + num_months = 12 + elif period == 'quarter': + num_months = 3 + else: + num_months = 1 + + # Initialize the dictionary with month names and counts + for i in range(num_months): + current_month = start_date + relativedelta(months=i) + month_name = current_month.strftime('%B') + month_dict[month_name] = 0 + + # Execute the SQL query to count lost opportunities + self._cr.execute('''SELECT TO_CHAR(create_date, 'Month') AS month, + COUNT(id) + FROM crm_lead + WHERE probability = 0 + AND active = FALSE + AND create_date >= %s + GROUP BY TO_CHAR(create_date, 'Month') + ORDER BY TO_CHAR(create_date, 'Month')''', + (start_date,)) + + data = self._cr.dictfetchall() + + # Update month_dict with the results from the query + for rec in data: + month_name = rec[ + 'month'].strip() # Strip the month name to remove extra spaces + if month_name in month_dict: + month_dict[month_name] = rec['count'] + + result = { + 'month': list(month_dict.keys()), + 'count': list(month_dict.values()) + } + + return result + + @api.model + def get_upcoming_events(self): + """Upcoming Activities Table""" + today = fields.date.today() + session_user_id = self.env.uid + self._cr.execute('''select mail_activity.activity_type_id, + mail_activity.date_deadline, mail_activity.summary, + mail_activity.res_name,(SELECT mail_activity_type.name + FROM mail_activity_type WHERE mail_activity_type.id = + mail_activity.activity_type_id), mail_activity.user_id FROM + mail_activity WHERE res_model = 'crm.lead' AND + mail_activity.date_deadline >= '%s' and user_id = %s GROUP BY + mail_activity.activity_type_id, mail_activity.date_deadline, + mail_activity.summary,mail_activity.res_name,mail_activity.user_id + order by mail_activity.date_deadline asc''' % ( + today, session_user_id)) + data = self._cr.fetchall() + events = [[record[0], record[1], record[2], record[3], + record[4] if record[4] else '', + self.env['res.users'].browse(record[5]).name if record[ + 5] else '' + ] for record in data] + return { + 'event': events, + 'cur_lang': self.env.context.get('lang') + } + + @api.model + def total_revenue_by_sales(self, period): + """Total expected revenue and count Pie""" + session_user_id = self.env.uid + start_date = get_period_start_date(period) + # SQL query template + query_template = """ + SELECT sum(expected_revenue) as revenue + FROM crm_lead + WHERE user_id = %s + AND type = 'opportunity' + AND active = %s + {conditions} + """ + + # Query conditions for different cases + conditions = [ + "", # Active opportunities + "AND stage_id = '4'", # Won opportunities + "AND probability = '0'", # Lost opportunities + ] + + # Active status for each condition + active_status = ['true', 'false', 'false'] + + # Fetch total revenue for each condition + revenues = [] + for cond, active in zip(conditions, active_status): + self._cr.execute(query_template.format(conditions=cond), + (session_user_id, active)) + revenue = self._cr.fetchone()[0] or 0 + revenues.append(revenue) + + # Calculate expected revenue without won + exp_revenue_without_won = revenues[0] - revenues[1] + + # Prepare the data for the pie chart + revenue_pie_count = [exp_revenue_without_won, revenues[1], revenues[2]] + revenue_pie_title = ['Expected without Won', 'Won', 'Lost'] + + return [revenue_pie_count, revenue_pie_title] + + + @api.model + def get_top_sp_revenue(self,period): + """Top 10 Salesperson revenue Table""" + user = self.env.user + start_date = get_period_start_date(period) + self._cr.execute('''SELECT user_id, id, expected_revenue, name, company_id + FROM crm_lead + WHERE create_date >= '%s' AND expected_revenue IS NOT NULL AND user_id = %s + GROUP BY user_id, id + ORDER BY expected_revenue DESC + LIMIT 10''' % (start_date,user.id,)) + data1 = self._cr.fetchall() + top_revenue = [ + [self.env['res.users'].browse(rec[0]).name, rec[1], rec[2], + rec[3], self.env['res.company'].browse(rec[4]).currency_id.symbol] + for rec in data1] + return {'top_revenue': top_revenue} + + @api.model + def get_top_country_revenue(self, period): + """Top 10 Country Wise Revenue - Heat Map""" + company_id = self.env.company.id + self._cr.execute('''SELECT country_id, sum(expected_revenue) + FROM crm_lead + WHERE expected_revenue IS NOT NULL + AND country_id IS NOT NULL + GROUP BY country_id + ORDER BY sum(expected_revenue) DESC + LIMIT 10''') + data1 = self._cr.fetchall() + country_revenue = [[self.env['res.country'].browse(rec[0]).name, + rec[1], self.env['res.company'].browse( + company_id).currency_id.symbol] for rec in data1] + return {'country_revenue': country_revenue} + + @api.model + def get_top_country_count(self, period): + """Top 10 Country Wise Count - Heat Map""" + self._cr.execute('''SELECT country_id, COUNT(*) + FROM crm_lead + WHERE country_id IS NOT NULL + GROUP BY country_id + ORDER BY COUNT(*) DESC + LIMIT 10''') + data1 = self._cr.fetchall() + country_count = [[self.env['res.country'].browse(rec[0]).name, rec[1]] + for rec in data1] + return {'country_count': country_count} + + @api.model + def get_recent_activities(self, kwargs): + """Recent Activities Table""" + today = fields.Date.today() + recent_week = today - relativedelta(days=7) + current_user_id = self.env.user.id # Get the current logged-in user's ID + # Check if the current user is an administrator + is_admin = self.env.user.has_group('base.group_system') + # Build the SQL query with or without user filtering based on role + if is_admin: + self._cr.execute(''' + SELECT mail_activity.activity_type_id, + mail_activity.date_deadline, + mail_activity.summary, + mail_activity.res_name, + (SELECT mail_activity_type.name + FROM mail_activity_type + WHERE mail_activity_type.id = mail_activity.activity_type_id), + mail_activity.user_id + FROM mail_activity + WHERE res_model = 'crm.lead' + AND mail_activity.date_deadline BETWEEN %s AND %s + GROUP BY mail_activity.activity_type_id, + mail_activity.date_deadline, + mail_activity.summary, + mail_activity.res_name, + mail_activity.user_id + ORDER BY mail_activity.date_deadline DESC + ''', (recent_week, today)) + else: + self._cr.execute(''' + SELECT mail_activity.activity_type_id, + mail_activity.date_deadline, + mail_activity.summary, + mail_activity.res_name, + (SELECT mail_activity_type.name + FROM mail_activity_type + WHERE mail_activity_type.id = mail_activity.activity_type_id), + mail_activity.user_id + FROM mail_activity + WHERE res_model = 'crm.lead' + AND mail_activity.date_deadline BETWEEN %s AND %s + AND mail_activity.user_id = %s + GROUP BY mail_activity.activity_type_id, + mail_activity.date_deadline, + mail_activity.summary, + mail_activity.res_name, + mail_activity.user_id + ORDER BY mail_activity.date_deadline DESC + ''', (recent_week, today, current_user_id)) + + data = self._cr.fetchall() + activities = [ + [*record[:5], self.env['res.users'].browse(record[5]).name] for + record in data] + return {'activities': activities} diff --git a/crm_dashboard/models/crm_team.py b/crm_dashboard/models/crm_team.py new file mode 100644 index 000000000..c5330a8c2 --- /dev/null +++ b/crm_dashboard/models/crm_team.py @@ -0,0 +1,34 @@ +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2025-TODAY Cybrosys Technologies(). +# Author: Raneesha (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +################################################################################ +from odoo import fields, models + + +class CRMSalesTeam(models.Model): + """CRMSalesTeam model extends the base crm.team model to add a field, + crm_lead_state_id, which represents the default CRM Lead stage for + leads associated with this sales team. + """ + _inherit = 'crm.team' + + crm_lead_state_id = fields.Many2one("crm.stage", string="CRM Lead", + store=True, + help="CRM Lead stage for leads " + "associated with this sales team.") diff --git a/crm_dashboard/models/res_user.py b/crm_dashboard/models/res_user.py new file mode 100644 index 000000000..7b30c7f2b --- /dev/null +++ b/crm_dashboard/models/res_user.py @@ -0,0 +1,30 @@ +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2025-TODAY Cybrosys Technologies(). +# Author: Raneesha (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +################################################################################ +from odoo import fields, models + + +class ResUser(models.Model): + """ResUser model extends the base res. Users model to add a field 'sales' + that represents the target for the salesperson.""" + _inherit = 'res.users' + + sales = fields.Float(string="Target", help="The target value for the " + "salesperson.") diff --git a/crm_dashboard/models/sale_order.py b/crm_dashboard/models/sale_order.py new file mode 100644 index 000000000..3a04875fd --- /dev/null +++ b/crm_dashboard/models/sale_order.py @@ -0,0 +1,35 @@ +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2025-TODAY Cybrosys Technologies(). +# Author: Raneesha (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +################################################################################ +from odoo import models + + +class SalesOrder(models.Model): + """Extends sale order for overriding action confirm function""" + _inherit = 'sale.order' + + def action_confirm(self): + """Override the action_confirm method to change CRM Stage. + Returns: + dict: A dictionary containing the result of the original + action_confirm method.""" + res = super(SalesOrder, self).action_confirm() + self.opportunity_id.stage_id = self.team_id.crm_lead_state_id + return res diff --git a/crm_dashboard/models/utm_campaign.py b/crm_dashboard/models/utm_campaign.py new file mode 100644 index 000000000..cb7df1a1f --- /dev/null +++ b/crm_dashboard/models/utm_campaign.py @@ -0,0 +1,63 @@ +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2025-TODAY Cybrosys Technologies(). +# Author: Raneesha (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +################################################################################ +from odoo import fields, models + + +class CampaignSmartButton(models.Model): + """Extends the UTM Campaign model with a Smart Button to calculate and + display the Win Loss Ratio.""" + _inherit = 'utm.campaign' + + total_ratio = fields.Float(compute='_compute_ratio', + help="Total lead ratio") + + def get_ratio(self): + """Open the Win Loss Ratio window upon clicking the Smart Button. + Returns: + dict: A dictionary specifying the action to be taken upon button + click.""" + self.ensure_one() + return { + 'type': 'ir.actions.act_window', + 'name': 'Win Loss Ratio', + 'view_mode': 'kanban', + 'res_model': 'crm.lead', + 'domain': [['user_id', '=', self.env.uid], "|", + "&", ["active", "=", True], ["probability", '=', 100], + "&", ["active", "=", False], ["probability", '=', 0] + ], + 'context': "{'create': False,'records_draggable': False}" + } + + def _compute_ratio(self): + """Compute the Win Loss Ratio based on CRM lead statistics.""" + total_won = self.env['crm.lead'].search_count( + [('active', '=', True), ('probability', '=', 100), + ('user_id', '=', self.env.uid)]) + total_lose = self.env['crm.lead'].search_count( + [('active', '=', False), ('probability', '=', 0), + ('user_id', '=', self.env.uid)]) + + if total_lose == 0: + ratio = 0 + else: + ratio = round(total_won / total_lose, 2) + self.total_ratio = ratio diff --git a/crm_dashboard/static/description/assets/cybro-icon.png b/crm_dashboard/static/description/assets/cybro-icon.png new file mode 100755 index 000000000..06e73e11d Binary files /dev/null and b/crm_dashboard/static/description/assets/cybro-icon.png differ diff --git a/crm_dashboard/static/description/assets/cybro-odoo.png b/crm_dashboard/static/description/assets/cybro-odoo.png new file mode 100755 index 000000000..ed02e07a4 Binary files /dev/null and b/crm_dashboard/static/description/assets/cybro-odoo.png differ diff --git a/crm_dashboard/static/description/assets/h2.png b/crm_dashboard/static/description/assets/h2.png new file mode 100755 index 000000000..0bfc4707d Binary files /dev/null and b/crm_dashboard/static/description/assets/h2.png differ diff --git a/crm_dashboard/static/description/assets/icons/arrows-repeat.svg b/crm_dashboard/static/description/assets/icons/arrows-repeat.svg new file mode 100755 index 000000000..1d7efabc5 --- /dev/null +++ b/crm_dashboard/static/description/assets/icons/arrows-repeat.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/crm_dashboard/static/description/assets/icons/banner-1.png b/crm_dashboard/static/description/assets/icons/banner-1.png new file mode 100755 index 000000000..c180db172 Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/banner-1.png differ diff --git a/crm_dashboard/static/description/assets/icons/banner-2.svg b/crm_dashboard/static/description/assets/icons/banner-2.svg new file mode 100755 index 000000000..e606d97d9 --- /dev/null +++ b/crm_dashboard/static/description/assets/icons/banner-2.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/crm_dashboard/static/description/assets/icons/banner-bg.png b/crm_dashboard/static/description/assets/icons/banner-bg.png new file mode 100755 index 000000000..a8238d3c0 Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/banner-bg.png differ diff --git a/crm_dashboard/static/description/assets/icons/banner-bg.svg b/crm_dashboard/static/description/assets/icons/banner-bg.svg new file mode 100755 index 000000000..b1378103e --- /dev/null +++ b/crm_dashboard/static/description/assets/icons/banner-bg.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/crm_dashboard/static/description/assets/icons/banner-call.svg b/crm_dashboard/static/description/assets/icons/banner-call.svg new file mode 100755 index 000000000..96c687e81 --- /dev/null +++ b/crm_dashboard/static/description/assets/icons/banner-call.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/crm_dashboard/static/description/assets/icons/banner-mail.svg b/crm_dashboard/static/description/assets/icons/banner-mail.svg new file mode 100755 index 000000000..cbf0d158d --- /dev/null +++ b/crm_dashboard/static/description/assets/icons/banner-mail.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/crm_dashboard/static/description/assets/icons/banner-pattern.svg b/crm_dashboard/static/description/assets/icons/banner-pattern.svg new file mode 100755 index 000000000..9c1c7e101 --- /dev/null +++ b/crm_dashboard/static/description/assets/icons/banner-pattern.svg @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/crm_dashboard/static/description/assets/icons/banner-promo.svg b/crm_dashboard/static/description/assets/icons/banner-promo.svg new file mode 100755 index 000000000..d52791b11 --- /dev/null +++ b/crm_dashboard/static/description/assets/icons/banner-promo.svg @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/crm_dashboard/static/description/assets/icons/brand-pair.svg b/crm_dashboard/static/description/assets/icons/brand-pair.svg new file mode 100755 index 000000000..d8db7fc1e --- /dev/null +++ b/crm_dashboard/static/description/assets/icons/brand-pair.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/crm_dashboard/static/description/assets/icons/check.png b/crm_dashboard/static/description/assets/icons/check.png new file mode 100755 index 000000000..c8e85f51d Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/check.png differ diff --git a/crm_dashboard/static/description/assets/icons/chevron.png b/crm_dashboard/static/description/assets/icons/chevron.png new file mode 100755 index 000000000..2089293d6 Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/chevron.png differ diff --git a/crm_dashboard/static/description/assets/icons/close-icon.svg b/crm_dashboard/static/description/assets/icons/close-icon.svg new file mode 100755 index 000000000..df8cce37a --- /dev/null +++ b/crm_dashboard/static/description/assets/icons/close-icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/crm_dashboard/static/description/assets/icons/cogs.png b/crm_dashboard/static/description/assets/icons/cogs.png new file mode 100755 index 000000000..95d0bad62 Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/cogs.png differ diff --git a/crm_dashboard/static/description/assets/icons/collabarate-icon.svg b/crm_dashboard/static/description/assets/icons/collabarate-icon.svg new file mode 100755 index 000000000..dd4e10518 --- /dev/null +++ b/crm_dashboard/static/description/assets/icons/collabarate-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/crm_dashboard/static/description/assets/icons/consultation.png b/crm_dashboard/static/description/assets/icons/consultation.png new file mode 100755 index 000000000..8319d4baa Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/consultation.png differ diff --git a/crm_dashboard/static/description/assets/icons/cybro-logo.png b/crm_dashboard/static/description/assets/icons/cybro-logo.png new file mode 100755 index 000000000..ff4b78220 Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/cybro-logo.png differ diff --git a/crm_dashboard/static/description/assets/icons/down.svg b/crm_dashboard/static/description/assets/icons/down.svg new file mode 100755 index 000000000..f21c36271 --- /dev/null +++ b/crm_dashboard/static/description/assets/icons/down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/crm_dashboard/static/description/assets/icons/ecom-black.png b/crm_dashboard/static/description/assets/icons/ecom-black.png new file mode 100755 index 000000000..a9385ff13 Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/ecom-black.png differ diff --git a/crm_dashboard/static/description/assets/icons/education-black.png b/crm_dashboard/static/description/assets/icons/education-black.png new file mode 100755 index 000000000..3eb09b27b Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/education-black.png differ diff --git a/crm_dashboard/static/description/assets/icons/faq.png b/crm_dashboard/static/description/assets/icons/faq.png new file mode 100755 index 000000000..4250b5b81 Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/faq.png differ diff --git a/crm_dashboard/static/description/assets/icons/feature-icon.svg b/crm_dashboard/static/description/assets/icons/feature-icon.svg new file mode 100755 index 000000000..fa0ea6850 --- /dev/null +++ b/crm_dashboard/static/description/assets/icons/feature-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/crm_dashboard/static/description/assets/icons/feature.png b/crm_dashboard/static/description/assets/icons/feature.png new file mode 100755 index 000000000..ac7a785c0 Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/feature.png differ diff --git a/crm_dashboard/static/description/assets/icons/gear.svg b/crm_dashboard/static/description/assets/icons/gear.svg new file mode 100755 index 000000000..0cc66b6ea --- /dev/null +++ b/crm_dashboard/static/description/assets/icons/gear.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/crm_dashboard/static/description/assets/icons/hero.gif b/crm_dashboard/static/description/assets/icons/hero.gif new file mode 100755 index 000000000..380654dfe Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/hero.gif differ diff --git a/crm_dashboard/static/description/assets/icons/hire-odoo.svg b/crm_dashboard/static/description/assets/icons/hire-odoo.svg new file mode 100755 index 000000000..e1ac089b0 --- /dev/null +++ b/crm_dashboard/static/description/assets/icons/hire-odoo.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/crm_dashboard/static/description/assets/icons/hotel-black.png b/crm_dashboard/static/description/assets/icons/hotel-black.png new file mode 100755 index 000000000..130f613be Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/hotel-black.png differ diff --git a/crm_dashboard/static/description/assets/icons/license.png b/crm_dashboard/static/description/assets/icons/license.png new file mode 100755 index 000000000..a5869797e Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/license.png differ diff --git a/crm_dashboard/static/description/assets/icons/life-ring-icon.svg b/crm_dashboard/static/description/assets/icons/life-ring-icon.svg new file mode 100755 index 000000000..3ae6e1d89 --- /dev/null +++ b/crm_dashboard/static/description/assets/icons/life-ring-icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/crm_dashboard/static/description/assets/icons/lifebuoy.png b/crm_dashboard/static/description/assets/icons/lifebuoy.png new file mode 100755 index 000000000..658d56ccc Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/lifebuoy.png differ diff --git a/crm_dashboard/static/description/assets/icons/mail.svg b/crm_dashboard/static/description/assets/icons/mail.svg new file mode 100755 index 000000000..1eedde695 --- /dev/null +++ b/crm_dashboard/static/description/assets/icons/mail.svg @@ -0,0 +1,3 @@ + + + diff --git a/crm_dashboard/static/description/assets/icons/manufacturing-black.png b/crm_dashboard/static/description/assets/icons/manufacturing-black.png new file mode 100755 index 000000000..697eb0e9f Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/manufacturing-black.png differ diff --git a/crm_dashboard/static/description/assets/icons/notes.png b/crm_dashboard/static/description/assets/icons/notes.png new file mode 100755 index 000000000..ee5e95404 Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/notes.png differ diff --git a/crm_dashboard/static/description/assets/icons/notification icon.svg b/crm_dashboard/static/description/assets/icons/notification icon.svg new file mode 100755 index 000000000..053189973 --- /dev/null +++ b/crm_dashboard/static/description/assets/icons/notification icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/crm_dashboard/static/description/assets/icons/odoo-consultancy.svg b/crm_dashboard/static/description/assets/icons/odoo-consultancy.svg new file mode 100755 index 000000000..e05f65bde --- /dev/null +++ b/crm_dashboard/static/description/assets/icons/odoo-consultancy.svg @@ -0,0 +1,4 @@ + + + + diff --git a/crm_dashboard/static/description/assets/icons/odoo-licencing.svg b/crm_dashboard/static/description/assets/icons/odoo-licencing.svg new file mode 100755 index 000000000..2606c88b0 --- /dev/null +++ b/crm_dashboard/static/description/assets/icons/odoo-licencing.svg @@ -0,0 +1,3 @@ + + + diff --git a/crm_dashboard/static/description/assets/icons/odoo-logo.png b/crm_dashboard/static/description/assets/icons/odoo-logo.png new file mode 100755 index 000000000..0e4d0eb5a Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/odoo-logo.png differ diff --git a/crm_dashboard/static/description/assets/icons/patter.svg b/crm_dashboard/static/description/assets/icons/patter.svg new file mode 100755 index 000000000..25c9c0a8f --- /dev/null +++ b/crm_dashboard/static/description/assets/icons/patter.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/crm_dashboard/static/description/assets/icons/pattern1.png b/crm_dashboard/static/description/assets/icons/pattern1.png new file mode 100755 index 000000000..09ab0fb2d Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/pattern1.png differ diff --git a/crm_dashboard/static/description/assets/icons/pos-black.png b/crm_dashboard/static/description/assets/icons/pos-black.png new file mode 100755 index 000000000..97c0f90c1 Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/pos-black.png differ diff --git a/crm_dashboard/static/description/assets/icons/puzzle-piece-icon.svg b/crm_dashboard/static/description/assets/icons/puzzle-piece-icon.svg new file mode 100755 index 000000000..3e9ad9373 --- /dev/null +++ b/crm_dashboard/static/description/assets/icons/puzzle-piece-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/crm_dashboard/static/description/assets/icons/puzzle.png b/crm_dashboard/static/description/assets/icons/puzzle.png new file mode 100755 index 000000000..65cf854e7 Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/puzzle.png differ diff --git a/crm_dashboard/static/description/assets/icons/replace-icon.svg b/crm_dashboard/static/description/assets/icons/replace-icon.svg new file mode 100755 index 000000000..d0e3a7af1 --- /dev/null +++ b/crm_dashboard/static/description/assets/icons/replace-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/crm_dashboard/static/description/assets/icons/restaurant-black.png b/crm_dashboard/static/description/assets/icons/restaurant-black.png new file mode 100755 index 000000000..4a35eb939 Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/restaurant-black.png differ diff --git a/crm_dashboard/static/description/assets/icons/screenshot-main.png b/crm_dashboard/static/description/assets/icons/screenshot-main.png new file mode 100755 index 000000000..575f8e676 Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/screenshot-main.png differ diff --git a/crm_dashboard/static/description/assets/icons/screenshot.png b/crm_dashboard/static/description/assets/icons/screenshot.png new file mode 100755 index 000000000..cef272529 Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/screenshot.png differ diff --git a/crm_dashboard/static/description/assets/icons/service-black.png b/crm_dashboard/static/description/assets/icons/service-black.png new file mode 100755 index 000000000..301ab51cb Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/service-black.png differ diff --git a/crm_dashboard/static/description/assets/icons/skype-fill.svg b/crm_dashboard/static/description/assets/icons/skype-fill.svg new file mode 100755 index 000000000..c17423639 --- /dev/null +++ b/crm_dashboard/static/description/assets/icons/skype-fill.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/crm_dashboard/static/description/assets/icons/skype.png b/crm_dashboard/static/description/assets/icons/skype.png new file mode 100755 index 000000000..51b409fb3 Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/skype.png differ diff --git a/crm_dashboard/static/description/assets/icons/skype.svg b/crm_dashboard/static/description/assets/icons/skype.svg new file mode 100755 index 000000000..df3dad39b --- /dev/null +++ b/crm_dashboard/static/description/assets/icons/skype.svg @@ -0,0 +1,3 @@ + + + diff --git a/crm_dashboard/static/description/assets/icons/star-1.svg b/crm_dashboard/static/description/assets/icons/star-1.svg new file mode 100755 index 000000000..7e55ab162 --- /dev/null +++ b/crm_dashboard/static/description/assets/icons/star-1.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/crm_dashboard/static/description/assets/icons/star-2.svg b/crm_dashboard/static/description/assets/icons/star-2.svg new file mode 100755 index 000000000..5ae9f507a --- /dev/null +++ b/crm_dashboard/static/description/assets/icons/star-2.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/crm_dashboard/static/description/assets/icons/support.png b/crm_dashboard/static/description/assets/icons/support.png new file mode 100755 index 000000000..4f18b8b82 Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/support.png differ diff --git a/crm_dashboard/static/description/assets/icons/test-1 - Copy.png b/crm_dashboard/static/description/assets/icons/test-1 - Copy.png new file mode 100755 index 000000000..f6a902663 Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/test-1 - Copy.png differ diff --git a/crm_dashboard/static/description/assets/icons/test-1.png b/crm_dashboard/static/description/assets/icons/test-1.png new file mode 100755 index 000000000..0908add2b Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/test-1.png differ diff --git a/crm_dashboard/static/description/assets/icons/test-2.png b/crm_dashboard/static/description/assets/icons/test-2.png new file mode 100755 index 000000000..4671fe91e Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/test-2.png differ diff --git a/crm_dashboard/static/description/assets/icons/trading-black.png b/crm_dashboard/static/description/assets/icons/trading-black.png new file mode 100755 index 000000000..9398ba2f1 Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/trading-black.png differ diff --git a/crm_dashboard/static/description/assets/icons/training.png b/crm_dashboard/static/description/assets/icons/training.png new file mode 100755 index 000000000..884ca024d Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/training.png differ diff --git a/crm_dashboard/static/description/assets/icons/translate.svg b/crm_dashboard/static/description/assets/icons/translate.svg new file mode 100755 index 000000000..af9c8a1aa --- /dev/null +++ b/crm_dashboard/static/description/assets/icons/translate.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/crm_dashboard/static/description/assets/icons/update.png b/crm_dashboard/static/description/assets/icons/update.png new file mode 100755 index 000000000..ecbc5a01a Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/update.png differ diff --git a/crm_dashboard/static/description/assets/icons/user.png b/crm_dashboard/static/description/assets/icons/user.png new file mode 100755 index 000000000..6ffb23d9f Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/user.png differ diff --git a/crm_dashboard/static/description/assets/icons/video.png b/crm_dashboard/static/description/assets/icons/video.png new file mode 100755 index 000000000..576705b17 Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/video.png differ diff --git a/crm_dashboard/static/description/assets/icons/whatsapp.png b/crm_dashboard/static/description/assets/icons/whatsapp.png new file mode 100755 index 000000000..d513a5356 Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/whatsapp.png differ diff --git a/crm_dashboard/static/description/assets/icons/wrench-icon.svg b/crm_dashboard/static/description/assets/icons/wrench-icon.svg new file mode 100755 index 000000000..174b5a465 --- /dev/null +++ b/crm_dashboard/static/description/assets/icons/wrench-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/crm_dashboard/static/description/assets/icons/wrench.png b/crm_dashboard/static/description/assets/icons/wrench.png new file mode 100755 index 000000000..6c04dea0f Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/wrench.png differ diff --git a/crm_dashboard/static/description/assets/modules/1.jpg b/crm_dashboard/static/description/assets/modules/1.jpg new file mode 100644 index 000000000..3cb15fe01 Binary files /dev/null and b/crm_dashboard/static/description/assets/modules/1.jpg differ diff --git a/crm_dashboard/static/description/assets/modules/2.jpg b/crm_dashboard/static/description/assets/modules/2.jpg new file mode 100644 index 000000000..662cadcc3 Binary files /dev/null and b/crm_dashboard/static/description/assets/modules/2.jpg differ diff --git a/crm_dashboard/static/description/assets/modules/3.jpg b/crm_dashboard/static/description/assets/modules/3.jpg new file mode 100644 index 000000000..717a00443 Binary files /dev/null and b/crm_dashboard/static/description/assets/modules/3.jpg differ diff --git a/crm_dashboard/static/description/assets/modules/4.png b/crm_dashboard/static/description/assets/modules/4.png new file mode 100644 index 000000000..00ebf54ad Binary files /dev/null and b/crm_dashboard/static/description/assets/modules/4.png differ diff --git a/crm_dashboard/static/description/assets/modules/5.jpg b/crm_dashboard/static/description/assets/modules/5.jpg new file mode 100644 index 000000000..7c67e2eec Binary files /dev/null and b/crm_dashboard/static/description/assets/modules/5.jpg differ diff --git a/crm_dashboard/static/description/assets/modules/6.gif b/crm_dashboard/static/description/assets/modules/6.gif new file mode 100644 index 000000000..a35ece8df Binary files /dev/null and b/crm_dashboard/static/description/assets/modules/6.gif differ diff --git a/crm_dashboard/static/description/assets/screenshot.zip b/crm_dashboard/static/description/assets/screenshot.zip new file mode 100644 index 000000000..81266086d Binary files /dev/null and b/crm_dashboard/static/description/assets/screenshot.zip differ diff --git a/crm_dashboard/static/description/assets/screenshot/1.png b/crm_dashboard/static/description/assets/screenshot/1.png new file mode 100644 index 000000000..175252da0 Binary files /dev/null and b/crm_dashboard/static/description/assets/screenshot/1.png differ diff --git a/crm_dashboard/static/description/assets/screenshot/2.png b/crm_dashboard/static/description/assets/screenshot/2.png new file mode 100644 index 000000000..2e2a2f896 Binary files /dev/null and b/crm_dashboard/static/description/assets/screenshot/2.png differ diff --git a/crm_dashboard/static/description/assets/screenshot/3.png b/crm_dashboard/static/description/assets/screenshot/3.png new file mode 100644 index 000000000..4bf4f0600 Binary files /dev/null and b/crm_dashboard/static/description/assets/screenshot/3.png differ diff --git a/crm_dashboard/static/description/assets/screenshot/4.png b/crm_dashboard/static/description/assets/screenshot/4.png new file mode 100644 index 000000000..ff9463556 Binary files /dev/null and b/crm_dashboard/static/description/assets/screenshot/4.png differ diff --git a/crm_dashboard/static/description/assets/screenshot/5.png b/crm_dashboard/static/description/assets/screenshot/5.png new file mode 100644 index 000000000..7a656fbff Binary files /dev/null and b/crm_dashboard/static/description/assets/screenshot/5.png differ diff --git a/crm_dashboard/static/description/assets/screenshot/6.png b/crm_dashboard/static/description/assets/screenshot/6.png new file mode 100644 index 000000000..c458b18b4 Binary files /dev/null and b/crm_dashboard/static/description/assets/screenshot/6.png differ diff --git a/crm_dashboard/static/description/assets/screenshot/7.png b/crm_dashboard/static/description/assets/screenshot/7.png new file mode 100644 index 000000000..dedb72435 Binary files /dev/null and b/crm_dashboard/static/description/assets/screenshot/7.png differ diff --git a/crm_dashboard/static/description/assets/screenshot/8.png b/crm_dashboard/static/description/assets/screenshot/8.png new file mode 100644 index 000000000..e42c4e4d1 Binary files /dev/null and b/crm_dashboard/static/description/assets/screenshot/8.png differ diff --git a/crm_dashboard/static/description/assets/screenshot/hero.gif b/crm_dashboard/static/description/assets/screenshot/hero.gif new file mode 100644 index 000000000..37c9a06db Binary files /dev/null and b/crm_dashboard/static/description/assets/screenshot/hero.gif differ diff --git a/crm_dashboard/static/description/assets/y18.jpg b/crm_dashboard/static/description/assets/y18.jpg new file mode 100755 index 000000000..eea1714f2 Binary files /dev/null and b/crm_dashboard/static/description/assets/y18.jpg differ diff --git a/crm_dashboard/static/description/banner.png b/crm_dashboard/static/description/banner.png new file mode 100644 index 000000000..2b6f88ac4 Binary files /dev/null and b/crm_dashboard/static/description/banner.png differ diff --git a/crm_dashboard/static/description/icon.png b/crm_dashboard/static/description/icon.png new file mode 100644 index 000000000..71f627903 Binary files /dev/null and b/crm_dashboard/static/description/icon.png differ diff --git a/crm_dashboard/static/description/index.html b/crm_dashboard/static/description/index.html new file mode 100644 index 000000000..ca0483db7 --- /dev/null +++ b/crm_dashboard/static/description/index.html @@ -0,0 +1,1040 @@ + + + + + + CRM Dashboard + + + + + + + + + + +
+
+ + + +
+
+ Community +
+
+ Enterprise +
+ + + + +
+
+ +
+
+
+
+

+ Get a visual report of CRM through a Dashboard + in CRM. +

+

CRM Dashboard +

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

Key + Highlights

+
+
+
+
+ +
+
+ Different Types of Reports in the Form of + Graphs. +
+
+
+
+
+
+ +
+
+ Dedicated Views for Users and Admins. +
+
+
+
+
+
+ +
+
+ Top deals and Monthly revenue goals. +
+
+
+
+
+ +
+
+
+ CRM Dashboard +

+ Are you ready to make your business more + organized? +
Improve now! +

+ +
+
+ +
+
+
+ + + + +
+
+ +
+
+
+
+ acc_bg +
+ +
+
+
+
+

+ Clickable Dashboard Cards + +

+
+
+

+ You can click on the respective + Cards which will direct the + users to the respective + information and aspects of the + CRM operations with Odoo. +

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

+ Target, Lead and Activity analysis + +

+
+
+

+ A dedicated Chart provides you + with complete insight into the + Leads which are in operation. +

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

+ Upcoming Activities and Total Revenue. +

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

+ Recent Activities. + +

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

+ Top Salespersons as well as Top Country Revenues. + + +

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

+ UTM Campaign win-loss ratio. + + +

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

+ User Dashboard View. + + +

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

+ Activity monitoring.

+
+ +
+
+
+
+
+
+ +
+

+ The users will have different + authorization based on the + employment level.

+
+
+
+
+
+
+
+ +
+

+ Top deals and Monthly revenue + goals.

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

+ CRM dashboard module + brings a + multipurpose + graphical + dashboard for CRM + module and making + the relationship + management + better and easier +

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

+ Latest Release 18.0.1.0.0 +

+ + 26th September, 2024 + +
+
+
+
+
+ Add +
+
+
+
    +
  • + Initial Commit +
  • + +
+
+
+
+
+
+
+
+
+
+ + + +
+

+ Related Products +

+ +
+ + +
+

+ Our Services

+ +
+ +
+
+ .... +
+
+ +
+ + +
+
+ + + + + + diff --git a/crm_dashboard/static/src/css/style.css b/crm_dashboard/static/src/css/style.css new file mode 100644 index 000000000..1110d4ec9 --- /dev/null +++ b/crm_dashboard/static/src/css/style.css @@ -0,0 +1,295 @@ +/* Dashboard Main Section Styles */ +.dashboard_main_section { + padding-top: 2rem; + padding-bottom: 1rem; + background-color: #f8f9fa; +} + +.section-header { + font-size: 1.5rem; + font-weight: bold; + color: #343a40; +} + +/* Period Selection Styles */ +#period_selection { + margin-top: 1rem; + width: 100%; + height: 38px; + border: 1px solid #ced4da; + border-radius: 0.25rem; + background-color: #fff; + color: #495057; + font-size: 1rem; + line-height: 1.5; + padding: 0.375rem 1.75rem 0.375rem 0.75rem; + appearance: none; + -webkit-appearance: none; + -moz-appearance: none; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: right 0.75rem center; + background-size: 16px 12px; +} + +#period_selection:focus { + outline: none; + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +} + +/* Responsive Styles */ +@media (max-width: 767px) { + .section-header { + font-size: 1.25rem; + } + + #period_selection { + margin-top: 0.5rem; + height: 32px; + font-size: 0.875rem; + padding: 0.25rem 1.5rem 0.25rem 0.5rem; + } +} + +/* Dashboard Card Section Styles */ +.dashboard_card_section { + padding-top: 1rem; + padding-bottom: 2rem; +} + +/* Dashboard Card Styles */ +.dashboard-card { + position: relative; + margin-bottom: 1rem; + padding: 1rem; + border-radius: 0.5rem; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + background-color: #fff; + transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out; +} + +.dashboard-card:hover { + transform: translateY(-4px); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15); +} + +.dashboard-card__icon-container { + width: 3rem; + height: 3rem; + font-size: 1.5rem; + color: #797979; + display: flex; + align-items: center; + justify-content: center; + border-radius: 50%; + background-color: #f0f0f0; +} + +.dashboard-card__details { + display: flex; + align-items: center; + justify-content: space-between; + flex: 1; + padding-left: 1rem; +} + +.dashboard-card__details h3, +.dashboard-card__details h4 { + margin-bottom: 0; + color: #333; +} + +.dashboard-card__details h3 { + font-size: 1.25rem; +} + +.dashboard-card__details h4 { + font-size: 1rem; + color: #666; +} + +/* Specific Card Styles */ +.card-shadow { + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +.bg-mauve-light { + background-color: #f9f7ff; +} + +.text-mauve { + color: #7c4dff; +} + +/* Responsive Styles */ +@media (max-width: 767px) { + .dashboard-card { + padding: 0.75rem; + } + + .dashboard-card__icon-container { + width: 2.5rem; + height: 2.5rem; + font-size: 1.25rem; + } + + .dashboard-card__details h3 { + font-size: 1rem; + } + + .dashboard-card__details h4 { + font-size: 0.875rem; + } +} +/* Modern Minimalistic Kanban Card Style */ +/* Card Layout: Date as the Main Element */ +.upcoming_activities_div .chart-container { + padding: 20px; + background-color: #ffffff; + border-radius: 12px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); +} + +.upcoming_activities_div h3 { + margin-bottom: 20px; + font-weight: 600; + font-size: 18px; + color: #444; +} + +.recent_activity_div h3 { + margin-bottom: 20px; + font-weight: 600; + font-size: 18px; + color: #444; +} +.recent_activity_div .chart-container { + padding: 20px; + background-color: #ffffff; + border-radius: 12px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); +} + +.top_sp_revenue_div .chart-container { + padding: 20px; + background-color: #ffffff; + border-radius: 12px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); +} +.top_sp_revenue_div h3 { + margin-bottom: 20px; + font-weight: 600; + font-size: 18px; + color: #444; +} +.top_country_revenue_div .chart-container { + padding: 20px; + background-color: #ffffff; + border-radius: 12px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); +} +.top_country_revenue_div h3 { + margin-bottom: 20px; + font-weight: 600; + font-size: 18px; + color: #444; +} +.top_country_count_div .chart-container { + padding: 20px; + background-color: #ffffff; + border-radius: 12px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); +} +.top_country_count_div h3 { + margin-bottom: 20px; + font-weight: 600; + font-size: 18px; + color: #444; +} +.crm_scroll_table { + overflow-y: auto; + max-height: 530px; +} + +.items-table { + display: flex; + flex-direction: column; + gap: 15px; +} + +.item-container { + display: flex; + flex-direction: column; +} + +.item-header { + display: flex; + align-items: center; + padding: 15px; + background-color: #f7f7f7; + border-radius: 10px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08); + transition: box-shadow 0.3s ease; +} + +.item-header:hover { + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); +} + +.date-container { + flex-shrink: 0; + background-color: #4c8bf5; + color: #ffffff; + font-size: 16px; + font-weight: 700; + padding: 10px; + border-radius: 8px; + text-align: center; + margin-right: 20px; + min-width: 70px; + display: flex; + flex-direction: column; + align-items: center; +} + +.date-container .day { + font-size: 24px; + font-weight: 800; +} + +.date-container .month { + font-size: 14px; +} + +.item-content { + flex-grow: 1; + display: flex; + flex-direction: column; +} + +.item-content .item-title { + font-size: 18px; + font-weight: 600; + color: #333; + margin-bottom: 5px; +} + +.item-content .item-summary { + font-size: 14px; + color: #666; + margin-bottom: 3px; +} + +.item-content .item-extra { + font-size: 13px; + color: #888; +} +h2 { + padding: 8px; +} +canvas{ + padding-bottom: 9px; +} +#in_ex_body_hide{ + background: white; +} \ No newline at end of file diff --git a/crm_dashboard/static/src/js/crm_dashboard.js b/crm_dashboard/static/src/js/crm_dashboard.js new file mode 100644 index 000000000..58a6d3774 --- /dev/null +++ b/crm_dashboard/static/src/js/crm_dashboard.js @@ -0,0 +1,560 @@ +/** @odoo-module **/ +import {registry} from "@web/core/registry"; +import {Component} from "@odoo/owl"; +import {onWillStart, onMounted, useState, useRef, useEffect} from "@odoo/owl"; +import {useService} from "@web/core/utils/hooks"; + +export class CrmDashboard extends Component { + setup() { + super.setup(...arguments); + this.orm = useService("orm"); + this.action = useService("action"); + this.Leadstage = useRef('leads_stage') + this.LeadByMonth = useRef('leads_by_month') + this.CrmActivities = useRef('crm_activities') + this.LeadByCampaign = useRef('leads_campaign') + this.LeadByMedium = useRef('leads_medium') + this.LeadBySource = useRef('leads_source') + this.LostLead = useRef('leads_lost') + this.TotalRevenue = useRef('total_revenue') + this.state = useState({ + period: 'month', + leads: null, + opportunities: null, + exp_revenue: null, + revenue: null, + win_ratio: null, + avg_close_time: null, + opportunity_ratio: null, + unassigned_leads: null, + charts: [], + upcoming_events: [], + current_lang: [], + top_sp_revenue: [], + country_count: [], + country_revenue: [], + recent_activities:[], + + }) + onWillStart(async () => { + await this.fetch_data(); + await this.UpcomingEvents(); + await this.TopSpRevenue(); + await this.TopCountryRevenue(); + await this.TopCountryCount(); + await this.RecentActivities(); + // Destroy existing chart if it exists + + }); + + useEffect(() => { + if (this.state.charts.length > 0) { + this.state.charts.forEach(chart => { + chart.destroy(); + }); + } + if (this.state.period) { + this.fetch_data(); + this.render_leads_by_stage(); + this.render_leads_by_month(); + this.render_crm_activities(); + this.render_lead_by_campaign(); + this.render_lead_by_medium(); + this.render_lead_by_source(); + this.render_lost_lead(); + this.render_total_revenue(); + } + }, () => [this.state.period]); + } + + async fetch_data() { + var self = this + var result = await this.orm.call('crm.lead', "get_data", [this.state.period]) + this.state.leads = result['leads'] + this.state.opportunities = result['opportunities'] + this.state.exp_revenue = result['exp_revenue'] + this.state.revenue = result['revenue'] + this.state.win_ratio = result['win_ratio'] + this.state.opportunity_ratio = result['opportunity_ratio'] + this.state.avg_close_time = result['avg_close_time'] + this.state.unassigned_leads = result['unassigned_leads'] + + } + + async UpcomingEvents() { + var result = await this.orm.call('crm.lead', "get_upcoming_events", []) + this.state.upcoming_events = result['event'] + this.state.current_lang = result['cur_lang'] + } + + async TopSpRevenue() { + var result = await this.orm.call('crm.lead', "get_top_sp_revenue", [this.state.period]) + this.state.top_sp_revenue = result['top_revenue'] + // this.state.current_lang = result['cur_lang'] + } + + async TopCountryCount() { + var result = await this.orm.call('crm.lead', "get_top_country_count", [this.state.period]) + this.state.country_count = result['country_count'] + + } + + async TopCountryRevenue() { + var result = await this.orm.call('crm.lead', "get_top_country_revenue", [this.state.period]) + this.state.country_revenue = result['country_revenue'] + } + async RecentActivities() { + var result = await this.orm.call('crm.lead', "get_recent_activities", [this.state.period]) + this.state.recent_activities = result['activities'] + } + + + SetPeriods() { + var today = new Date(); + var start_date; + + if (this.state.period == 'month') { + start_date = new Date(today.getFullYear(), today.getMonth(), 1); // Start of the month + } else if (this.state.period == 'year') { + start_date = new Date(today.getFullYear(), 0, 1); // Start of the year + } else if (this.state.period == 'quarter') { + var startMonth = Math.floor(today.getMonth() / 3) * 3; // Start month of the quarter + start_date = new Date(today.getFullYear(), startMonth, 1); // Start of the quarter + } else if (this.state.period == 'week') { + var dayOfWeek = today.getDay(); + var diff = today.getDate() - dayOfWeek + (dayOfWeek === 0 ? -6 : 1); // Adjust when day is Sunday + start_date = new Date(today.setDate(diff)); // Start of the week (Monday) + } + + return start_date.getFullYear() + '-' + (start_date.getMonth() + 1).toString().padStart(2, '0') + '-' + start_date.getDate().toString().padStart(2, '0'); + } + + + OnChangePeriods() { + + } + + onClickLeads() { + var date = this.SetPeriods() + this.action.doAction({ + type: "ir.actions.act_window", + name: "Leads", + res_model: 'crm.lead', + views: [[false, "kanban"], [false, "form"]], + target: "current", + domain: [['type', '=', 'lead'], ['create_date', '>=', date]] + }); + } + + onClickOpportunities() { + var date = this.SetPeriods() + this.action.doAction({ + type: "ir.actions.act_window", + name: "Opportunities", + res_model: 'crm.lead', + views: [[false, "kanban"], [false, "form"]], + target: "current", + domain: [['type', '=', 'opportunity'], ['create_date', '>=', date]] + }); + } + + onClickExpRevenue() { + var date = this.SetPeriods() + this.action.doAction({ + type: "ir.actions.act_window", + name: "Expense Revenue", + res_model: 'crm.lead', + views: [[false, "list"], [false, "form"]], + target: "current", + domain: [['type', '=', 'opportunity'], ['active', '=', true], ['create_date', '>=', date]] + }); + } + + onClickRevenue() { + var date = this.SetPeriods() + this.action.doAction({ + type: "ir.actions.act_window", + name: "Revenue", + res_model: 'crm.lead', + views: [[false, "list"], [false, "form"]], + target: "current", + domain: [['type', '=', 'opportunity'], ['active', '=', true], ['stage_id', '=', 4], ['create_date', '>=', date]] + }); + } + + onClickUnAssignedLeads() { + var date = this.SetPeriods() + this.action.doAction({ + type: "ir.actions.act_window", + name: "Unassigned Leads", + res_model: 'crm.lead', + views: [[false, "list"], [false, "form"]], + target: "current", + domain: [['user_id', '=', false], ['type', '=', 'lead'], ['create_date', '>=', date]] + }); + } + + async render_leads_by_stage() { + + var self = this; + var ctx = this.Leadstage.el; + const arrays = await this.orm.call('crm.lead', "get_lead_stage_data", [this.state.period]); + const data = { + labels: arrays[1], + datasets: [{ + label: 'Leads', + data: arrays[0], + backgroundColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + borderColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + }] + }; + + //create Chart class object + var chart = new Chart(ctx, { + type: 'polarArea', + data: data, + + // options: options + }); + this.state.charts.push(chart) + } + + async render_leads_by_month() { + + var self = this; + var ctx = this.LeadByMonth.el; + const arrays = await this.orm.call('crm.lead', "get_lead_by_month", []); + const data = { + labels: arrays[1], + datasets: [{ + label: 'Leads', + data: arrays[0], + backgroundColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + borderColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + }] + }; + + + //create Chart class object + var chart = new Chart(ctx, { + type: 'doughnut', + data: data, + // options: options + }); + this.state.charts.push(chart) + } + + async render_crm_activities() { + + var self = this; + var ctx = this.CrmActivities.el; + const arrays = await this.orm.call('crm.lead', "get_crm_activities", [this.state.period]); + const data = { + labels: arrays[1], + datasets: [{ + label: 'Activity', + data: arrays[0], + backgroundColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + borderColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + }] + }; + + + //create Chart class object + var chart = new Chart(ctx, { + type: 'pie', + data: data, + // options: options + }); + this.state.charts.push(chart) + } + + async render_lead_by_campaign() { + + var self = this; + var ctx = this.LeadByCampaign.el; + const arrays = await this.orm.call('crm.lead', "get_the_campaign_pie", [this.state.period]); + const data = { + labels: arrays[1], + datasets: [{ + label: 'Activity', + data: arrays[0], + backgroundColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + borderColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + }] + }; + + + //create Chart class object + var chart = new Chart(ctx, { + type: 'pie', + data: data, + // options: options + }); + this.state.charts.push(chart) + } + + async render_lead_by_medium() { + + var self = this; + var ctx = this.LeadByMedium.el; + const arrays = await this.orm.call('crm.lead', "get_the_medium_pie", [this.state.period]); + const data = { + labels: arrays[1], + datasets: [{ + label: 'Activity', + data: arrays[0], + backgroundColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + borderColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + }] + }; + + + //create Chart class object + var chart = new Chart(ctx, { + type: 'pie', + data: data, + // options: options + }); + this.state.charts.push(chart) + } + + async render_lead_by_source() { + + var self = this; + var ctx = this.LeadBySource.el; + const arrays = await this.orm.call('crm.lead', "get_the_source_pie", [this.state.period]); + const data = { + labels: arrays[1], + datasets: [{ + label: 'Activity', + data: arrays[0], + backgroundColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + borderColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + }] + }; + + + //create Chart class object + var chart = new Chart(ctx, { + type: 'pie', + data: data, + // options: options + }); + this.state.charts.push(chart) + } + + async render_lost_lead() { + + var self = this; + var ctx = this.LostLead.el; + const arrays = await this.orm.call('crm.lead', "get_total_lost_crm", [this.state.period]); + const data = { + labels: arrays['month'], + datasets: [{ + label: 'Activity', + data: arrays['count'], + backgroundColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + borderColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + }] + }; + + + //create Chart class object + var chart = new Chart(ctx, { + type: 'bar', + data: data, + // options: options + }); + this.state.charts.push(chart) + } + + async render_total_revenue() { + + var self = this; + var ctx = this.TotalRevenue.el; + const arrays = await this.orm.call('crm.lead', "total_revenue_by_sales", [this.state.period]); + const data = { + labels: arrays[1], + datasets: [{ + label: 'Activity', + data: arrays[0], + backgroundColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + borderColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + }] + }; + + + //create Chart class object + var chart = new Chart(ctx, { + type: 'pie', + data: data, + // options: options + }); + this.state.charts.push(chart) + } +} + + +CrmDashboard.template = 'CrmDashboard' +registry.category("actions").add("crm_dashboard", CrmDashboard) diff --git a/crm_dashboard/static/src/xml/dashboard_templates.xml b/crm_dashboard/static/src/xml/dashboard_templates.xml new file mode 100644 index 000000000..00cb740ee --- /dev/null +++ b/crm_dashboard/static/src/xml/dashboard_templates.xml @@ -0,0 +1,502 @@ + + diff --git a/crm_dashboard/views/crm_dashboard_views.xml b/crm_dashboard/views/crm_dashboard_views.xml new file mode 100644 index 000000000..3aa0e6a54 --- /dev/null +++ b/crm_dashboard/views/crm_dashboard_views.xml @@ -0,0 +1,12 @@ + + + + + CRM + crm_dashboard + + + + diff --git a/crm_dashboard/views/crm_team_views.xml b/crm_dashboard/views/crm_team_views.xml new file mode 100644 index 000000000..e736d15f0 --- /dev/null +++ b/crm_dashboard/views/crm_team_views.xml @@ -0,0 +1,14 @@ + + + + + crm.team.view.form.inherit.crm.dashboard + crm.team + + + + + + + + diff --git a/crm_dashboard/views/res_users_views.xml b/crm_dashboard/views/res_users_views.xml new file mode 100644 index 000000000..9e2120ecd --- /dev/null +++ b/crm_dashboard/views/res_users_views.xml @@ -0,0 +1,18 @@ + + + + + res.users.view.form.inherit.crm.dashboard + res.users + + + + + + + + + + diff --git a/crm_dashboard/views/utm_campaign_views.xml b/crm_dashboard/views/utm_campaign_views.xml new file mode 100644 index 000000000..99664b547 --- /dev/null +++ b/crm_dashboard/views/utm_campaign_views.xml @@ -0,0 +1,18 @@ + + + + + utm.campaign.view.form.inherit.crm.dashboard + utm.campaign + + +
+ +
+
+
+