diff --git a/project_dashboard_odoo/README.rst b/project_dashboard_odoo/README.rst index 21a67ff5c..16e7a30ed 100644 --- a/project_dashboard_odoo/README.rst +++ b/project_dashboard_odoo/README.rst @@ -24,7 +24,8 @@ Company Credits ------- * Developers: odoo@cybrosys.com - V15 - Archana V, archana@cybrosys.info + V15 - Archana V, archana @ cybrosys + V16 - YadhuKrishnan K Yadhu @ cybrosys Contacts -------- diff --git a/project_dashboard_odoo/__init__.py b/project_dashboard_odoo/__init__.py index b5ec61ca5..d7026989b 100644 --- a/project_dashboard_odoo/__init__.py +++ b/project_dashboard_odoo/__init__.py @@ -20,4 +20,5 @@ # ############################################################################# -from .import models \ No newline at end of file +from .import models +from . import controllers diff --git a/project_dashboard_odoo/__manifest__.py b/project_dashboard_odoo/__manifest__.py index 9878c4639..408732b62 100644 --- a/project_dashboard_odoo/__manifest__.py +++ b/project_dashboard_odoo/__manifest__.py @@ -3,7 +3,7 @@ # # Cybrosys Technologies Pvt. Ltd. # -# Copyright (C) 2022-TODAY Cybrosys Technologies() +# Copyright (C) 2023-TODAY Cybrosys Technologies() # Author: Cybrosys Techno Solutions() # # You can modify it under the terms of the GNU LESSER @@ -25,7 +25,7 @@ 'category': 'Productivity', 'summary': 'Detailed Dashboard View for Project', 'description': 'Detailed Dashboard View for Project', - 'version': '15.0.1.0.0', + 'version': '15.0.2.0.1', 'author': 'Cybrosys Techno Solutions', 'company': 'Cybrosys Techno Solutions', 'maintainer': 'Cybrosys Techno Solutions', diff --git a/project_dashboard_odoo/controllers/__init__.py b/project_dashboard_odoo/controllers/__init__.py new file mode 100644 index 000000000..438486ad7 --- /dev/null +++ b/project_dashboard_odoo/controllers/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +from . import main diff --git a/project_dashboard_odoo/controllers/main.py b/project_dashboard_odoo/controllers/main.py new file mode 100644 index 000000000..368561300 --- /dev/null +++ b/project_dashboard_odoo/controllers/main.py @@ -0,0 +1,157 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +import datetime + +from odoo import http +from odoo.http import request + + +class ProjectFilter(http.Controller): + """ + The ProjectFilter class provides the filter option to the js. + When applying the filter return the corresponding data. + Methods: + project_filter(self): + when the page is loaded adding filter options to the selection + field. + return a list variable. + project_filter_apply(self,**kw): + after applying the filter receiving the values and return the + filtered data. + + """ + + @http.route('/project/filter', auth='public', type='json') + def project_filter(self): + """ + + Summery: + transferring data to the selection field that works as a filter + Returns: + type:list of lists , it contains the data for the corresponding + filter. + + + """ + project_list = [] + employee_list = [] + project_ids = request.env['project.project'].search([]) + employee_ids = request.env['hr.employee'].search([]) + # getting partner data + for employee_id in employee_ids: + dic = {'name': employee_id.name, + 'id': employee_id.id} + employee_list.append(dic) + for project_id in project_ids: + dic = {'name': project_id.name, + 'id': project_id.id} + project_list.append(dic) + return [project_list, employee_list] + + @http.route('/project/filter-apply', auth='public', type='json') + def project_filter_apply(self, **kw): + """ + Summery: + transferring data after filter 9is applied + Args: + kw(dict):This parameter contain value of selection field + Returns: + type:dict, it contains the data for the corresponding + filter. + + and transferring data to ui after filtration. + + + """ + data = kw['data'] + pro_selected = [] + emp_selected = [] + # checking tje employee selected or not + if data['employee'] == 'null': + emp_selected = [employee.id for employee in + request.env['hr.employee'].search([])] + else: + emp_selected = [int(data['employee'])] + start_date = data['start_date'] + end_date = data['end_date'] + pro_selected = False + # checking the dates are selected or not + if start_date != 'null' and end_date != 'null': + start_date = datetime.datetime.strptime(start_date, + "%Y-%m-%d").date() + end_date = datetime.datetime.strptime(end_date, "%Y-%m-%d").date() + if data['project'] == 'null': + pro_selected = [project.id for project in + request.env['project.project'].search( + [('date_start', '>', start_date), + ('date_start', '<', end_date)])] + else: + pro_selected = [int(data['project'])] + elif start_date == 'null' and end_date != 'null': + end_date = datetime.datetime.strptime(end_date, "%Y-%m-%d").date() + if data['project'] == 'null': + pro_selected = [project.id for project in + request.env['project.project'].search( + [('date_start', '<', end_date)])] + else: + pro_selected = [int(data['project'])] + + elif start_date != 'null' and end_date == 'null': + start_date = datetime.datetime.strptime(start_date, + "%Y-%m-%d").date() + if data['project'] == 'null': + pro_selected = [project.id for project in + request.env['project.project'].search( + [('date_start', '>', start_date)])] + else: + pro_selected = [int(data['project'])] + else: + if data['project'] == 'null': + pro_selected = [project.id for project in + request.env['project.project'].search([])] + else: + pro_selected = [int(data['project'])] + report_project = request.env['project.profitability.report'].search( + [('project_id', 'in', pro_selected)]) + to_invoice = sum(report_project.mapped('amount_untaxed_to_invoice')) + invoice = sum(report_project.mapped('amount_untaxed_invoiced')) + timesheet_cost = sum(report_project.mapped('timesheet_cost')) + other_cost = sum(report_project.mapped('expense_cost')) + profitability = to_invoice + invoice + timesheet_cost + other_cost + analytic_project = request.env['account.analytic.line'].search( + [('project_id', 'in', pro_selected), + ('employee_id', 'in', emp_selected)]) + sale_orders = [] + for rec in analytic_project: + if rec.order_id.id and rec.order_id.id not in sale_orders: + sale_orders.append(rec.order_id.id) + total_time = sum(analytic_project.mapped('unit_amount')) + return { + 'total_project': pro_selected, + 'total_emp': emp_selected, + 'total_task': [rec.id for rec in request.env['project.task'].search( + [('project_id', 'in', pro_selected)])], + 'hours_recorded': total_time, + 'list_hours_recorded': [rec.id for rec in analytic_project], + 'total_margin': profitability, + 'total_so': sale_orders + } diff --git a/project_dashboard_odoo/doc/RELEASE_NOTES.md b/project_dashboard_odoo/doc/RELEASE_NOTES.md index 8c37f1a28..89ba6b6a9 100644 --- a/project_dashboard_odoo/doc/RELEASE_NOTES.md +++ b/project_dashboard_odoo/doc/RELEASE_NOTES.md @@ -4,5 +4,11 @@ #### 26.05.2022 #### Version 15.0.1.0.0 ## Module - ##### Initial Commit for project_dashboard_odoo + + +#### 30.03.2023 +#### Version 15.0.2.0.1 +## Module +#### UPDT +#### Update the module with additional graph and filter, changed the UI. diff --git a/project_dashboard_odoo/models/pj_dashboard.py b/project_dashboard_odoo/models/pj_dashboard.py index 9de2308e5..79f25b522 100644 --- a/project_dashboard_odoo/models/pj_dashboard.py +++ b/project_dashboard_odoo/models/pj_dashboard.py @@ -20,18 +20,56 @@ # ############################################################################# -from odoo import models, api +import calendar +import random from datetime import datetime + from dateutil.relativedelta import relativedelta -import pandas as pd -import calendar + +from odoo import models, api class PosDashboard(models.Model): + """ + + The ProjectDashboard class provides the data to the js when the dashboard is loaded. + Methods: + get_tiles_data(self): + when the page is loaded get the data from different models and transfer to the js file. + return a dictionary variable. + get_top_timesheet_employees(model_ids): + getting data for the timesheet graph. + get_hours_data(self): + getting data for the hours table. + get_task_data(self): + getting data to project task table + get_project_task_count(self): + getting data to project task table + get_color_code(self): + getting dynamic color code for the graph + get_income_this_month(self): + getting data to profitable graph after month filter apply + get_income_last_year(self): + getting data to profitable graph after last year filter apply + get_income_this_year(self): + getting data to profitable graph after current year filter apply + get_details(self): + getting data for the profatable table + + """ _inherit = 'project.project' @api.model def get_tiles_data(self): + """ + + Summery: + when the page is loaded get the data from different models and transfer to the js file. + return a dictionary variable. + return: + type:It is a dictionary variable. This dictionary contain data that affecting the dashboard view. + + """ all_project = self.env['project.project'].search([]) all_task = self.env['project.task'].search([]) analytic_project = self.env['account.analytic.line'].search([]) @@ -48,18 +86,39 @@ class PosDashboard(models.Model): ('sale_order_id', '!=', False) ], ['sale_order_id']) task_so_ids = [o['sale_order_id'][0] for o in task] - sale_orders = self.mapped('sale_line_id.order_id') | self.env['sale.order'].browse(task_so_ids) + sale_orders = self.mapped('sale_line_id.order_id') | self.env[ + 'sale.order'].browse(task_so_ids) + sale_list = [rec.id for rec in sale_orders] + project_stage_ids = self.env['project.project.stage'].search([]) + project_stage_list = [] + for project_stage_id in project_stage_ids: + total_projects = self.env['project.project'].search_count( + [('stage_id', '=', project_stage_id.id)]) + project_stage_list.append({ + 'name': project_stage_id.name, + 'projects': total_projects, + }) return { 'total_projects': len(all_project), 'total_tasks': len(all_task), 'total_hours': total_time, 'total_profitability': profitability, 'total_employees': len(employees), - 'total_sale_orders': len(sale_orders) + 'total_sale_orders': len(sale_orders), + 'project_stage_list': project_stage_list, + 'sale_list': sale_list } @api.model def get_top_timesheet_employees(self): + """ + + Summery: + when the page is loaded get the data for the timesheet graph. + return: + type:It is a list. This list contain data that affecting the graph of employees. + + """ query = '''select hr_employee.name as employee,sum(unit_amount) as unit from account_analytic_line @@ -80,80 +139,19 @@ class PosDashboard(models.Model): return final @api.model - def get_project_task(self): - cr = self._cr - cr.execute("""select project_id, project_project.name,count(*) - from project_task join project_project on project_project.id=project_task.project_id - group by project_task.project_id,project_project.name""") - dat = cr.fetchall() - data = [] - for i in range(0, len(dat)): - data.append({'label': dat[i][1], 'value': dat[i][2]}) - return data - - @api.model - def project_profitability_trend(self): - leave_lines = [] - month_list = [] - graph_result = [] - for i in range(6, -2, -1): - last_month = datetime.now() - relativedelta(months=i) - text = format(last_month, '%B %Y') - month_list.append(text) - for month in month_list: - vals = { - 'l_month': month, - 'leave': 0 - } - - graph_result.append(vals) - - sql = """SELECT h.id,h.margin, - to_char(y, 'YYYY') as month_year - FROM (select * from project_profitability_report) h - ,date_trunc('year', line_date)y""" - - self.env.cr.execute(sql) - results = self.env.cr.dictfetchall() - for line in results: - days = line['margin'] - vals = { - 'l_month': line['month_year'], - 'days': days - } - leave_lines.append(vals) - if leave_lines: - df = pd.DataFrame(leave_lines) - rf = df.groupby(['l_month']).sum() - result_lines = rf.to_dict('index') - - for line in result_lines: - match = list(graph_result) - if match: - match[0]['leave'] = result_lines[line]['days'] - for result in graph_result: - result['l_month'] = result['l_month'].split(' ')[:1][0].strip()[:3] + " " + \ - result['l_month'].split(' ')[1:2][0] - - return graph_result - - @api.model - def get_profitability_details(self): - query = '''select sum(margin) as payment_details from project_profitability_report''' - self._cr.execute(query) - data = self._cr.dictfetchall() - payment_details = [] - for record in data: - payment_details.append(record.get('payment_details')) + def get_details(self): + """ - return { - 'payment_details': payment_details, - } + Summery: + when the page is loaded get the data for the profitable table. + return: + type:It is a dictionary variable. This dictionary contain data + that profitable table. - @api.model - def get_details(self): + """ query = '''select sum(amount_untaxed_invoiced) as invoiced, - sum(amount_untaxed_to_invoice) as to_invoice,sum(timesheet_cost) as time_cost, + sum(amount_untaxed_to_invoice) as to_invoice,sum(timesheet_cost) as + time_cost, sum(expense_cost) as expen_cost, sum(margin) as payment_details from project_profitability_report''' self._cr.execute(query) @@ -165,7 +163,7 @@ class PosDashboard(models.Model): to_invoice = [] for record in data: to_invoice.append(record.get('to_invoice')) - + record.get('to_invoice') time_cost = [] for record in data: time_cost.append(record.get('time_cost')) @@ -177,7 +175,6 @@ class PosDashboard(models.Model): payment_details = [] for record in data: payment_details.append(record.get('payment_details')) - return { 'invoiced': invoiced, 'to_invoice': to_invoice, @@ -188,6 +185,14 @@ class PosDashboard(models.Model): @api.model def get_hours_data(self): + """ + + Summery: + when the page is loaded get the data for the hours table. + return: + type:It is a dictionary variable. This dictionary contain data that hours table. + + """ query = '''SELECT sum(unit_amount) as hour_recorded FROM account_analytic_line WHERE timesheet_invoice_type='non_billable_project' ''' self._cr.execute(query) @@ -239,6 +244,14 @@ class PosDashboard(models.Model): @api.model def get_income_this_year(self): + """ + + Summery: + when the filter is applied get the data for the profitable graph. + return: + type:It is a dictionary variable. This dictionary contain data for profitable graph. + + """ month_list = [] for i in range(11, -1, -1): @@ -256,7 +269,8 @@ class PosDashboard(models.Model): records = [] for month in month_list: - last_month_inc = list(filter(lambda m: m['month'].strip() == month, record)) + last_month_inc = list( + filter(lambda m: m['month'].strip() == month, record)) if not last_month_inc: records.append({ @@ -283,6 +297,14 @@ class PosDashboard(models.Model): @api.model def get_income_last_year(self): + """ + + Summery: + when the filter is applied get the data for the profitable graph. + return: + type:It is a dictionary variable. This dictionary contain data for profitable graph. + + """ month_list = [] for i in range(11, -1, -1): l_month = datetime.now() - relativedelta(months=i) @@ -290,7 +312,6 @@ class PosDashboard(models.Model): month_list.append(text) states_arg = "" - self._cr.execute(('''select sum(margin) as income ,to_char(project_profitability_report.line_date, 'Month') as month from project_profitability_report where Extract(year FROM project_profitability_report.line_date) = Extract(year FROM DATE(NOW())) -1 @@ -299,7 +320,8 @@ class PosDashboard(models.Model): records = [] for month in month_list: - last_month_inc = list(filter(lambda m: m['month'].strip() == month, record)) + last_month_inc = list( + filter(lambda m: m['month'].strip() == month, record)) if not last_month_inc: records.append({ 'month': month, @@ -327,6 +349,14 @@ class PosDashboard(models.Model): @api.model def get_income_this_month(self): + """ + + Summery: + when the filter is applied get the data for the profitable graph. + return: + type:It is a dictionary variable. This dictionary contain data for profitable graph. + + """ states_arg = "" day_list = [] now = datetime.now() @@ -370,6 +400,15 @@ class PosDashboard(models.Model): @api.model def get_task_data(self): + """ + + Summery: + when the page is loaded get the data from different models and transfer to the js file. + return a dictionary variable. + return: + type:It is a dictionary variable. This dictionary contain data that affecting project task table. + + """ self._cr.execute('''select project_task.name as task_name,pro.name as project_name from project_task Inner join project_project as pro on project_task.project_id = pro.id ORDER BY project_name ASC''') data = self._cr.fetchall() @@ -380,3 +419,43 @@ class PosDashboard(models.Model): return { 'project': project_name } + + @api.model + def get_project_task_count(self): + """ + + Summery: + when the page is loaded get the data from different models and transfer to the js file. + return a dictionary variable. + return: + type:It is a dictionary variable. This dictionary contain data for the project task graph. + + """ + project_name = [] + total_task = [] + colors = [] + project_ids = self.env['project.project'].search([]) + for project_id in project_ids: + project_name.append(project_id.name) + task = self.env['project.task'].search_count( + [('project_id', '=', project_id.id)]) + total_task.append(task) + color_code = self.get_color_code() + colors.append(color_code) + return { + 'project': project_name, + 'task': total_task, + 'color': colors + } + + def get_color_code(self): + """ + + Summery: + the function is for creating the dynamic color code. + return: + type:variable containing color code. + + """ + color = "#{:06x}".format(random.randint(0, 0xFFFFFF)) + return color diff --git a/project_dashboard_odoo/static/description/assets/screenshots/Screenshot1.png b/project_dashboard_odoo/static/description/assets/screenshots/Screenshot1.png new file mode 100644 index 000000000..8266ce3ae Binary files /dev/null and b/project_dashboard_odoo/static/description/assets/screenshots/Screenshot1.png differ diff --git a/project_dashboard_odoo/static/description/assets/screenshots/Screenshot2.png b/project_dashboard_odoo/static/description/assets/screenshots/Screenshot2.png new file mode 100644 index 000000000..3e1a8d8b4 Binary files /dev/null and b/project_dashboard_odoo/static/description/assets/screenshots/Screenshot2.png differ diff --git a/project_dashboard_odoo/static/description/assets/screenshots/Screenshot3.png b/project_dashboard_odoo/static/description/assets/screenshots/Screenshot3.png new file mode 100644 index 000000000..bd9cae228 Binary files /dev/null and b/project_dashboard_odoo/static/description/assets/screenshots/Screenshot3.png differ diff --git a/project_dashboard_odoo/static/description/assets/screenshots/Screenshot4.png b/project_dashboard_odoo/static/description/assets/screenshots/Screenshot4.png new file mode 100644 index 000000000..f43ac3122 Binary files /dev/null and b/project_dashboard_odoo/static/description/assets/screenshots/Screenshot4.png differ diff --git a/project_dashboard_odoo/static/description/assets/screenshots/Screenshot5.png b/project_dashboard_odoo/static/description/assets/screenshots/Screenshot5.png new file mode 100644 index 000000000..53a068a29 Binary files /dev/null and b/project_dashboard_odoo/static/description/assets/screenshots/Screenshot5.png differ diff --git a/project_dashboard_odoo/static/description/assets/screenshots/Screenshot6.png b/project_dashboard_odoo/static/description/assets/screenshots/Screenshot6.png new file mode 100644 index 000000000..69b75de98 Binary files /dev/null and b/project_dashboard_odoo/static/description/assets/screenshots/Screenshot6.png differ diff --git a/project_dashboard_odoo/static/description/assets/screenshots/checked.png b/project_dashboard_odoo/static/description/assets/screenshots/checked.png deleted file mode 100644 index e6c63d582..000000000 Binary files a/project_dashboard_odoo/static/description/assets/screenshots/checked.png and /dev/null differ diff --git a/project_dashboard_odoo/static/description/assets/screenshots/hero.gif b/project_dashboard_odoo/static/description/assets/screenshots/hero.gif index df0f88cf3..7d16d565e 100644 Binary files a/project_dashboard_odoo/static/description/assets/screenshots/hero.gif and b/project_dashboard_odoo/static/description/assets/screenshots/hero.gif differ diff --git a/project_dashboard_odoo/static/description/assets/screenshots/hero.png b/project_dashboard_odoo/static/description/assets/screenshots/hero.png deleted file mode 100644 index 8cf6ddd39..000000000 Binary files a/project_dashboard_odoo/static/description/assets/screenshots/hero.png and /dev/null differ diff --git a/project_dashboard_odoo/static/description/assets/screenshots/logo.png b/project_dashboard_odoo/static/description/assets/screenshots/logo.png deleted file mode 100644 index 478462d3e..000000000 Binary files a/project_dashboard_odoo/static/description/assets/screenshots/logo.png and /dev/null differ diff --git a/project_dashboard_odoo/static/description/assets/screenshots/pd1.png b/project_dashboard_odoo/static/description/assets/screenshots/pd1.png deleted file mode 100644 index e009bbf9d..000000000 Binary files a/project_dashboard_odoo/static/description/assets/screenshots/pd1.png and /dev/null differ diff --git a/project_dashboard_odoo/static/description/assets/screenshots/pd2.png b/project_dashboard_odoo/static/description/assets/screenshots/pd2.png deleted file mode 100644 index cae8d7795..000000000 Binary files a/project_dashboard_odoo/static/description/assets/screenshots/pd2.png and /dev/null differ diff --git a/project_dashboard_odoo/static/description/assets/screenshots/pd3.png b/project_dashboard_odoo/static/description/assets/screenshots/pd3.png deleted file mode 100644 index cc0e3a73b..000000000 Binary files a/project_dashboard_odoo/static/description/assets/screenshots/pd3.png and /dev/null differ diff --git a/project_dashboard_odoo/static/description/assets/screenshots/pd4.png b/project_dashboard_odoo/static/description/assets/screenshots/pd4.png deleted file mode 100644 index 942174e85..000000000 Binary files a/project_dashboard_odoo/static/description/assets/screenshots/pd4.png and /dev/null differ diff --git a/project_dashboard_odoo/static/description/assets/screenshots/pd5.png b/project_dashboard_odoo/static/description/assets/screenshots/pd5.png deleted file mode 100644 index 44455d5ed..000000000 Binary files a/project_dashboard_odoo/static/description/assets/screenshots/pd5.png and /dev/null differ diff --git a/project_dashboard_odoo/static/description/assets/screenshots/prg_db.png b/project_dashboard_odoo/static/description/assets/screenshots/prg_db.png deleted file mode 100644 index a1d7fdef1..000000000 Binary files a/project_dashboard_odoo/static/description/assets/screenshots/prg_db.png and /dev/null differ diff --git a/project_dashboard_odoo/static/description/assets/screenshots/prg_db2.png b/project_dashboard_odoo/static/description/assets/screenshots/prg_db2.png deleted file mode 100644 index cf849c12e..000000000 Binary files a/project_dashboard_odoo/static/description/assets/screenshots/prg_db2.png and /dev/null differ diff --git a/project_dashboard_odoo/static/description/assets/screenshots/prg_db3.png b/project_dashboard_odoo/static/description/assets/screenshots/prg_db3.png deleted file mode 100644 index 823ad4586..000000000 Binary files a/project_dashboard_odoo/static/description/assets/screenshots/prg_db3.png and /dev/null differ diff --git a/project_dashboard_odoo/static/description/assets/screenshots/prg_db4.png b/project_dashboard_odoo/static/description/assets/screenshots/prg_db4.png deleted file mode 100644 index 8308bf6dc..000000000 Binary files a/project_dashboard_odoo/static/description/assets/screenshots/prg_db4.png and /dev/null differ diff --git a/project_dashboard_odoo/static/description/assets/screenshots/screenshot.png b/project_dashboard_odoo/static/description/assets/screenshots/screenshot.png new file mode 100644 index 000000000..bf8f82599 Binary files /dev/null and b/project_dashboard_odoo/static/description/assets/screenshots/screenshot.png differ diff --git a/project_dashboard_odoo/static/description/index.html b/project_dashboard_odoo/static/description/index.html index 157fb9b1b..187e6ca04 100644 --- a/project_dashboard_odoo/static/description/index.html +++ b/project_dashboard_odoo/static/description/index.html @@ -186,31 +186,39 @@

- Project Details

+ Use DIffrent Type of filters

+

+ +

+
+

+ Dynamic And Clickable Dashboard Tiles

- Display the Project related information likes Total Project, Total Employees, Total Tasks, - Hours Recorded, Total Profitability, Total Sale Orders.

- +

- Task Analysis

+ Different Types of Graphs

- Task analysis from various projects.

- +

- Employees Timesheet

- +
@@ -218,11 +226,24 @@

- Project Profitability

- + +
+
+

+ Diffrent Type Of Tables

+ +
+
+

+

+
- diff --git a/project_dashboard_odoo/static/src/css/dashboard.css b/project_dashboard_odoo/static/src/css/dashboard.css index 10df0849c..9839b20e6 100644 --- a/project_dashboard_odoo/static/src/css/dashboard.css +++ b/project_dashboard_odoo/static/src/css/dashboard.css @@ -13,28 +13,6 @@ overflow: auto !important; .breadcrumbs { margin-top: 0; } - -.buttons button { - margin: 2px 0; } - -/* Button Reset */ -.btn, .button { - display: inline-block; - font-weight: 400; - text-align: center; - white-space: nowrap; - vertical-align: middle; - transition: all .15s ease-in-out; - border-radius: 0; - cursor: pointer; } - - -/* Widget One ----------------------------*/ -.stat-content { - display: inline-block; - width: 66%; -} .stat-icon{ display: inline-block; } @@ -67,120 +45,6 @@ overflow: auto !important; .stat_count { font-size: 28px !important; } -.stat-count { - font-size: 28px; - text-align: center; - color: #00438b;} - -.stat-title { - font-size: 17px; - text-align: center; - color: #00438b; } - -.mb-0{ - font-size: 20px; - position: relative; - text-align: center; -} -.mb-0 .dash-title { - font-size: 20px; - text-align: center; - color: rgba(255, 255, 255, 0.81); -} -.hr_birthday { - font-size: 28px; - text-align: center; - padding: 20px 0; - color: #00438b; - font-weight: 600; -} -body .text-color { - color: #00438b; -} -.slice { - stroke: #fff; - stroke-width: 0px; -} - -/* Leave graph */ - -path { stroke: #fff; } -path:hover { opacity:0.9; } -rect:hover { fill:#934da5; } -.axis { font: 10px sans-serif; } -.legend tr{ border-bottom:1px solid grey; } -.legend tr:first-child{ border-top:1px solid grey; } - -.axis path, -.axis line { - fill: none; - stroke: #000; - shape-rendering: crispEdges; -} - -.x.axis path { display: none; } -.legend{ - border-collapse: collapse; - border-spacing: 0px; - display: inline-block; -} -.monthly_leave_graph_view .legend{ - height: 250px; - overflow: scroll; - margin-left: 112px; - margin-top: 77px; - margin-bottom: -97px - -} -.legend td, .legend .legend_col{ - padding:4px 5px; - vertical-align:bottom; -} -.legendFreq, .legendPerc{ - align:right; - width:50px; -} - -/* Leave broadfactor graph */ - -.broad_factor_graph .axis path, -.broad_factor_graph .axis line { - fill: none; - stroke: black; - shape-rendering: crispEdges; -} -.broad_factor_graph .axis text { - font-family: sans-serif; - font-size: 11px; -} - -.broad_factor_graph rect { - -moz-transition: all 0.3s; - -webkit-transition: all 0.3s; - -o-transition: all 0.3s; - transition: all 0.3s; -} -.broad_factor_graph rect:hover{ - fill: #ff618a; -} - -#broad_factor_pdf { - background-color: #ffffff; - border: 0; - color : #000000; - float: right; -} -#broad_factor_pdf i { - color: red; -} - -.leave_broad_factor{ - overflow-x: auto !important; - overflow-y: hidden !important; - height: auto; -} - -/*=====================New Dashboard===========================*/ .oh_dashboards { background-color: #f8faff !important; @@ -190,25 +54,6 @@ rect:hover { fill:#934da5; } .container-fluid.o_hr_dashboard { padding: 0px !important; } -.employee-prof { - - padding: 0px; - height: 100%; - background-color: #3e6282; - /*background-image: linear-gradient(180deg, #3e6282, #41666f);*/ - position: fixed; - /*z-index: 999;*/ -} -.employee-prof .oh-card:hover { - - transform:none !important; - box-shadow: none !important; - -} - -/*.dummy{ - height:130vh; -}*/ .oh-card { padding-top: 0px; @@ -227,116 +72,6 @@ rect:hover { fill:#934da5; } box-shadow: 0 10px 10px 0 rgba(62, 57, 107, 0.12), 0 0 0 transparent !important; } -.employee-prof .employee-icon { - - float: left; - padding-right: 0px; - width: 100%; - height: 185px; - overflow: hidden; - background: #999999; - -} -.employee-prof .employee-icon img{ - width: 100%; - background: #fff; -} - -.employee-prof .employee-name h2 { - - text-align: center; - font-weight: 300; - text-transform: uppercase; - font-size: 17px; - margin-top: 12px; - margin-bottom: 2px; - color: #fff; - -} -.media-body.employee-name { - - background: #466b8d; - float: left; - margin: 0; - width: 100% - -} -.employee-prof .employee-name p { - - margin: 0 0 9px; - text-align: center; - font-size: 12px; - color: #f3f3f3; - -} -.employee-prof p { - margin: 0 0 9px; - color: #fff; -} -.employee-gender { - width: 40%; - margin-left: 10%; - padding: 8% 10% 4%; - text-align: center; - border-right: 1px solid #4d769b; - margin-top: 14%; - float: left; - border-bottom: 1px solid #4d769b; -} -.employee-gender p { - margin: 0px 0 4px !important; - color: #fff; -} -.employee-age { - width: 40%; - margin-right: 10%; - padding: 4% 10% 7%; - text-align: center; - margin-top: 18%; - float: left; - border-bottom: 1px solid #4d769b; -} -.employee-age p { - margin: 0 0 1px; - color: #fff; -} -.employee-experience { - - width: 100%; - text-align: center; - padding-top: 8%; - float: left; - padding-bottom: 3%; - -} -.employee-country { - width: 40%; - margin-left: 10%; - padding: 9% 0% 4%; - text-align: center; - border-right: 1px solid #4d769b; - margin-top: 2%; - float: left; - border-top: 1px solid #4d769b; - -} -.employee-country p { - margin: 0px 0 1px !important; - color: #fff; -} -.employee-mobile { - width: 40%; - margin-right: 10%; - padding: 9% 0% 7%; - text-align: center; - margin-top: 2%; - float: left; - border-top: 1px solid #4d769b; -} -.employee-mobile p { - margin: 0 0 1px; - color: #fff; -} .oh-payslip { margin-top: 1.5%; @@ -348,7 +83,6 @@ rect:hover { fill:#934da5; } height: 85px; text-align: center; padding-top: 2%; - background: #ff8762; color: #fff; } @@ -362,7 +96,6 @@ rect:hover { fill:#934da5; } .stat-widget-one .stat-text { font-size: 14px; - color: #ff8762; margin-top: 2.3rem; margin-left: 1rem; @@ -380,7 +113,7 @@ rect:hover { fill:#934da5; } font-size: 42px; font-weight: 900; display: inline-block; - color: #fff; + color: #000; top: 16px; position: relative; } @@ -401,147 +134,7 @@ rect:hover { fill:#934da5; } padding-top: 2%; } -.oh-timesheets .stat-icon{ - background: #5ebade !important; -} -.oh-contracts .stat-icon{ - background: #b298e1 !important; -} -.oh-broad-factor .stat-icon{ - background: #70cac1 !important; -} -.oh-timesheets .stat-widget-one .stat-text { - color: #5ebade; -} -.oh-contracts .stat-widget-one .stat-text { - color: #b298e1; -} -.oh-broad-factor .stat-widget-one .stat-text { - color: #70cac1; -} -.leave-manager { - - background-color: #fff; - transition: transform 0.2s ease, box-shadow 0.2s ease; - will-change: transform, box-shadow; - box-shadow: 0 10px 40px 0 rgba(62,57,107,0.07), 0 2px 9px 0 rgba(62,57,107,0.06); - padding: 0px; - margin: 15px; - -} -.hr_leave_request_approve { - padding: 0; - padding-bottom: 0em; - padding-top: 0em; - transition: transform 0.2s ease, box-shadow 0.2s ease; - will-change: transform, box-shadow; -} -.leaves_request_month { - padding: 0; - padding-top: 0px; - padding-bottom: 0px; - padding-bottom: 0em; - padding-top: 0em; - transition: transform 0.2s ease, box-shadow 0.2s ease; - will-change: transform, box-shadow; - border-bottom: 1px solid #f1f1f133; -} -.leaves_request_today{ - padding: 0; - padding-bottom: 0em; - padding-top: 0em; - transition: transform 0.2s ease, box-shadow 0.2s ease; - will-change: transform, box-shadow; -} -.hr_leave_request_approve:hover, .leaves_request_month:hover, .leaves_request_today:hover{ - transform: translateY(-2px) translateZ(0) !important; - box-shadow: 0 10px 10px 0 rgba(62, 57, 107, 0.12), 0 0 0 transparent !important; -} -.hr_leave_request_approve p { - font-size: 14px; - color: #ff8762; - margin-left: 1rem; - margin-bottom: 0px; - text-align: left; - width: 64%; - font-weight: bold; - float: left; - text-align: center !important; -} -.leaves_request_today p { - font-size: 14px; - color: #5ebade; - margin-left: 1rem; - margin-bottom: 0px; - text-align: left; - width:64%; - float:left; - font-weight: bold; - text-align: center; - text-align: center !important; -} -.leaves_request_month p{ - font-size: 14px; - color: #b298e1; - margin-left: 1rem; - margin-bottom:0px; - text-align: left; - width:64%; - float:left; - font-weight: bold; - text-align: center !important; -} -h4 .stat-count { - font-size: 17px; - text-align: center; - color: #000 !important; - margin-top: 0px; - width: 100%; - float: left; - margin: 0; -} -.leave-manager h4 { - float: left; - width: 23%; - -} -.hr_leave_request_approve h4 { - - padding: 5.2rem 0; - margin: 0; - background: #ff8762; - color: #fff; - -} -.leaves_request_today h4 { - - padding: 2.2rem 0; - margin: 0 !important; - background: #5ebade; - color: #fff; - -} -.leaves_request_month h4 { - - padding: 2.1rem 0; - margin: 0 !important; - background: #b298e1; - color: #fff; - -} -.leaves_request_today h4 .stat-count ,.leaves_request_month h4 .stat-count , .hr_leave_request_approve h4 .stat-count -{ - color:#fff !important; -} -.graph_view .legend { - margin-bottom: -79px !important; - display: inline-block; - border-collapse: collapse; - border-spacing: 0px; - margin-left: 90px !important; - margin-top: 77px !important; -} .hr-chart-1{ margin: 15px 0px; background: #fff; @@ -568,223 +161,12 @@ h4 .stat-count { padding-bottom: 65px; text-align: center !important; } -.hr_leave_allocations_approve p { - font-size: 14px; - color: #ff8762; - margin-left: 1rem; - margin-bottom: 0px; - text-align: left; - width: 70%; - float: left; - font-weight: bold; - text-align: center !important; -} -.hr_leave_allocations_approve h4 { - - padding: 2.5rem 0; - margin: 0; - background: #ff8762; - color: #fff; - width: 26%; - float: left; -} -.hr_leave_allocations_approve .stat-count { - - font-size: 17px; - text-align: center; - color: #fff !important; - margin-top: 0px; - width: 100%; - float: left; - margin: 0; - -} -.hr_leave_allocations_approve { - - padding: 0; - padding-top: 0px; - padding-bottom: 0px; - padding-bottom: 0em; - padding-top: 0em; - box-shadow: 0 10px 40px 0 rgba(62,57,107,0.07), 0 2px 9px 0 rgba(62,57,107,0.06); - transition: transform 0.2s ease, box-shadow 0.2s ease; - will-change: transform, box-shadow; - background: #fff; - height: 80px; - -} -.hr_leave_allocations_approve:hover{ - transform: translateY(-2px) translateZ(0) !important; - box-shadow: 0 10px 10px 0 rgba(62, 57, 107, 0.12), 0 0 0 transparent !important; -} -.leave-manager { - - background-color: #fff; - transition: transform 0.2s ease, box-shadow 0.2s ease; - will-change: transform, box-shadow; - box-shadow: 0 10px 40px 0 rgba(62,57,107,0.07), 0 2px 9px 0 rgba(62,57,107,0.06); - padding: 0px; - margin: 15px; - margin-right: 15px; - margin-right: 0px; - width: 95% !important; - padding: 0; - -} -.hr_job_application_approve { - padding: 0; - padding-top: 0px; - padding-bottom: 0px; - padding-top: 0px; - padding-bottom: 0px; - padding-top: 0px; - padding-bottom: 0px; - padding-bottom: 0em; - padding-top: 0em; - box-shadow: 0 10px 40px 0 rgba(62,57,107,0.07), 0 2px 9px 0 rgba(62,57,107,0.06); - transition: transform 0.2s ease, box-shadow 0.2s ease; - will-change: transform, box-shadow; - background: #fff; - margin-top: 15px; - height: 80px; - -} -.hr_job_application_approve p { - font-size: 14px; - color: #70cac1; - margin-left: 1rem; - margin-bottom: 0px; - text-align: left; - width: 70%; - float: left; - font-weight: bold; - text-align: center !important; -} -.hr_job_application_approve h4 { - - padding: 2.5rem 0; - margin: 0; - background: #70cac1; - color: #fff; - width: 26%; - float: left; - -} -.hr_job_application_approve .stat-count { - - font-size: 17px !important; - color: #fff !important; - margin-top: 0px !important; - width: 100%; - float: left; - margin: 0; - margin: 0px !important; - text-align: center !important; - width: 100% !important; - -} -.hr_job_application_approve:hover{ - transform: translateY(-2px) translateZ(0) !important; - box-shadow: 0 10px 10px 0 rgba(62, 57, 107, 0.12), 0 0 0 transparent !important; -} -.hr_attendance_login .oh-card { - margin: 0; - margin-bottom: 0px; - margin-bottom: 0px; - background: #134c8a; - padding-bottom: 7px; - transition: transform 0.2s ease, box-shadow 0.2s ease; - will-change: transform, box-shadow; - box-shadow: 0 10px 40px 0 rgba(62,57,107,0.07), 0 2px 9px 0 rgba(62,57,107,0.06); -} -.hr_attendance_login .stat-widget-one { - background: none; -} -.hr_attendance_login .stat-widget-one .stat-icon { - text-align: center; - padding-top: 9px; -} -.hr_attendance_login .stat-content { - width: 100%; - color: #fff !important; -} -.hr_attendance_login .stat-widget-one .stat-text { - margin: 0; - text-align: center; - width: 100% !important; - padding: 0; - color: #fff; -} -.hr_attendance_login .stat-widget-one .stat-icon .fa { - font-size: 50px; -} -.hr_attendance_login .stat-widget-one .stat-icon .fa { - font-size: 50px; - margin: 0px; - box-shadow: none; -} -.hr_attendance_login { - margin-top: 1.5%; -} -.monthly_leave_graph_view .oh-card { - background: #fff; - transition: transform 0.2s ease, box-shadow 0.2s ease; - will-change: transform, box-shadow; - box-shadow: 0 10px 40px 0 rgba(62,57,107,0.07), 0 2px 9px 0 rgba(62,57,107,0.06); - padding: 15px; -} -.broad_factor_graph .oh-card { - padding: 15px !important; - background: #fff; - transition: transform 0.2s ease, box-shadow 0.2s ease; - will-change: transform, box-shadow; - box-shadow: 0 10px 40px 0 rgba(62,57,107,0.07), 0 2px 9px 0 rgba(62,57,107,0.06); - padding: 15px; -} -.leave_broad_factor { - overflow-x: auto !important; - overflow-y: hidden !important; - height: 336px; - padding: 0px; - padding-left: 0px; -} -#broad_factor_pdf { - - background-color: #ffffff; - float: right; - border-radius: 30px; - transition: transform 0.2s ease, box-shadow 0.2s ease; - will-change: transform, box-shadow; - box-shadow: 0 10px 40px 0 rgba(62,57,107,0.07), 0 2px 9px 0 rgba(62,57,107,0.06); - border: 1px solid #4ec3b7; - color: #757575; - padding-top: 9px; - color: #4ec3b7; - -} -#broad_factor_pdf:hover{ - transform: translateY(-2px) translateZ(0) !important; - box-shadow: 0 10px 10px 0 rgba(62, 57, 107, 0.12), 0 0 0 transparent !important; -} -.hr_birthday { - font-size: 17px; - text-align: center; - padding: 20px 0; - color: #00438b; - font-weight: 300; -} -.hr_notification img { - width: 40px; - height: 40px; - border-radius: 100%; -} .hr_notification { background: #fff; transition: transform 0.2s ease, box-shadow 0.2s ease; will-change: transform, box-shadow; box-shadow: 0 10px 40px 0 rgba(62,57,107,0.07), 0 2px 9px 0 rgba(62,57,107,0.06); - height: 316px; - overflow-y: auto; + height: 757pxpx; margin-bottom: 15px; } .hr_notification .media { @@ -810,32 +192,6 @@ h4 .stat-count { background: #5ebade; margin-bottom: 9px; } -.monthly_leave_trend .oh-card{ - background: #fff; - transition: none !important; - will-change: none !important; - box-shadow: none !important; - margin-bottom: 5px; -} - -.monthly_leave_trend path { - stroke: #70cac1; - stroke-width: 2; - fill: none; -} - -.monthly_leave_trend .axis path, -.monthly_leave_trend .axis line { - fill: none; - stroke: grey; - stroke-width: 1; - shape-rendering: crispEdges; -} -.monthly_leave_trend circle{ - fill: #ffffff; - stroke: #44b7ac; - stroke-width: 1.5; -} .hr-chart-1 { margin: 15px 0px; background: #fff; @@ -846,168 +202,57 @@ h4 .stat-count { box-shadow: 0 10px 40px 0 rgba(62,57,107,0.07), 0 2px 9px 0 rgba(62,57,107,0.06); padding-top: 3px !important; } -.monthly_leave_trend { - background: #fff; - transition: transform 0.2s ease, box-shadow 0.2s ease; - will-change: transform, box-shadow; - box-shadow: 0 10px 40px 0 rgba(62,57,107,0.07), 0 2px 9px 0 rgba(62,57,107,0.06); -} -.monthly_leave_trend:hover{ - transform: translateY(-2px) translateZ(0) !important; - box-shadow: 0 10px 10px 0 rgba(62, 57, 107, 0.12), 0 0 0 transparent !important; -} - - -/*----------------------*/ -.monthly_join_resign_trend{ - padding-right: 0px !important; -} - -.monthly_join_resign_trend .oh-card { - background: #fff; - transition: transform 0.2s ease, box-shadow 0.2s ease; - will-change: transform, box-shadow; - box-shadow: 0 10px 40px 0 rgba(62,57,107,0.07), 0 2px 9px 0 rgba(62,57,107,0.06); - padding: 15px; -} - -.monthly_join_resign_trend .axis path, -.monthly_join_resign_trend .axis line { - fill: none; - shape-rendering: crispEdges; - } - -.monthly_join_resign_trend .line { - fill: none; - stroke-width: 3px; - - } - -.monthly_join_resign_trend .area { - fill: steelblue; - opacity: 0.5; - } - -.monthly_join_resign_trend .dot { - fill: steelblue; - stroke: steelblue; - stroke-width: 1.5px; - } - -/*----------------------------------------*/ - - -.monthly_attrition_rate path { - stroke: #70cac1; - stroke-width: 2; - fill: none; -} - -.monthly_attrition_rate .axis path, -.monthly_attrition_rate .axis line { - fill: none; - stroke: grey; - stroke-width: 1; - shape-rendering: crispEdges; -} -.monthly_attrition_rate circle{ - fill: #ffffff; - stroke: #44b7ac; - stroke-width: 1.5; -} - -.monthly_attrition_rate .oh-card { - background: #fff; - transition: transform 0.2s ease, box-shadow 0.2s ease; - will-change: transform, box-shadow; - box-shadow: 0 10px 40px 0 rgba(62,57,107,0.07), 0 2px 9px 0 rgba(62,57,107,0.06); - padding: 15px; +.row.main-section { + margin-right: 0px; !important; } -.monthly_attrition_rate .oh-card:hover{ - transform: translateY(-2px) translateZ(0) !important; - box-shadow: 0 10px 10px 0 rgba(62, 57, 107, 0.12), 0 0 0 transparent !important; +.text-align { + margin-left: 17px; } - -.row.main-section { - margin-right: 0px; !important; +.chart { + width: 100% !important; + height: 400px !important; } -/* width */ -.hr_notification::-webkit-scrollbar { - width: 4px; +.inner_select { + min-width: 150px } -/* Track */ -.hr_notification::-webkit-scrollbar-track { - background: #f1f1f1; +#table_status { + width: 90%; + margin-left: 5%; + font-family: Arial, Helvetica, sans-serif; } -/* Handle */ -.hr_notification::-webkit-scrollbar-thumb { - background: #495057;; +#table_status tr:nth-child(even) { + background-color: #f2f2f2; } -/* Handle on hover */ -.hr_notification::-webkit-scrollbar-thumb:hover { - background: #598da1; +#table_status tr:hover { + background-color: #ddd; } -.oh-card-body { - display: flex; - justify-content: space-between; +.project-pill { align-items: center; -} - -.oh-ribbon { - position: absolute; - left: -5px; top: -5px; - z-index: 1; - overflow: hidden; - width: 150px; height: 150px; - text-align: right; -} -.oh-ribbon span { - font-size: 10px; + font-family: "Open Sans", Arial, Verdana, sans-serif; font-weight: bold; - color: #FFF; - text-transform: uppercase; - text-align: center; - line-height: 20px; - transform: rotate(-45deg); - -webkit-transform: rotate(-45deg); - width: 200px; - display: block; - background: #79A70A; - background: linear-gradient(#2989d8 0%, #1e5799 100%); - box-shadow: 0 3px 10px -5px rgba(0, 0, 0, 1); - position: absolute; - top: 56px; - left: -35px; -} -.oh-ribbon span::before { - content: ""; - position: absolute; left: 0px; top: 100%; - z-index: -1; - border-left: 3px solid #1e5799; - border-right: 3px solid transparent; - border-bottom: 3px solid transparent; - border-top: 3px solid #1e5799; -} -.oh-ribbon span::after { - content: ""; - position: absolute; right: 0px; top: 100%; - z-index: -1; - border-left: 3px solid transparent; - border-right: 3px solid #1e5799; - border-bottom: 3px solid transparent; - border-top: 3px solid #1e5799; -} -.text-align { - margin-left: 17px; + font-size: 11px; + display: inline-block; + height: 100%; + white-space: nowrap; + width: auto; + position: relative; + border-radius: 100px; + line-height: 1; + overflow: hidden; + padding: 0px 8px 0px 7px; + text-overflow: ellipsis; + line-height: 1.25rem; + color: #fff; + word-break: break-word; + background: #0253e8; } -.chart { - width: 100% !important; - height: 400px !important; +.inner_select p { + margin-left: 20px } diff --git a/project_dashboard_odoo/static/src/js/dashboard.js b/project_dashboard_odoo/static/src/js/dashboard.js index 8241ff9d2..e9ae33882 100644 --- a/project_dashboard_odoo/static/src/js/dashboard.js +++ b/project_dashboard_odoo/static/src/js/dashboard.js @@ -1,385 +1,526 @@ -odoo.define('pj_dashboard.Dashboard', function (require) { -"use strict"; - -var AbstractAction = require('web.AbstractAction'); -var core = require('web.core'); -var QWeb = core.qweb; -var ajax = require('web.ajax'); -var rpc = require('web.rpc'); -var _t = core._t; -var session = require('web.session'); -var web_client = require('web.web_client'); -var abstractView = require('web.AbstractView'); - - - - -var PjDashboard = AbstractAction.extend({ - template:'PjDashboard', - cssLibs: [ - '/project_dashboard_odoo/static/src/css/lib/nv.d3.css' - ], - jsLibs: [ - '/project_dashboard_odoo/static/src/js/lib/d3.min.js' - ], - - events: { - 'click .tot_projects':'tot_projects', - 'click .tot_tasks':'tot_tasks', - 'click .tot_profitability':'tot_profitability', - 'click .hr_recorded':'hr_recorded', - 'click .tot_sale':'tot_sale', - 'click .tot_emp':'tot_emp', - 'click #income_this_year': 'onclick_income_this_year', - 'click #income_last_year': 'onclick_income_last_year', - 'click #income_this_month': 'onclick_income_this_month', - +odoo.define('pj_dashboard.Dashboard', function(require) { + "use strict"; + + var AbstractAction = require('web.AbstractAction'); + var core = require('web.core'); + var QWeb = core.qweb; + var ajax = require('web.ajax'); + var rpc = require('web.rpc'); + var _t = core._t; + var session = require('web.session'); + var web_client = require('web.web_client'); + var abstractView = require('web.AbstractView'); + var flag = 0; + var tot_so = [] + var tot_project = [] + var tot_task = [] + var tot_employee = [] + var tot_hrs = [] + var tot_margin = [] + var PjDashboard = AbstractAction.extend({ + template: 'PjDashboard', + cssLibs: [ + '/project_dashboard_odoo/static/src/css/lib/nv.d3.css' + ], + jsLibs: [ + '/project_dashboard_odoo/static/src/js/lib/d3.min.js' + ], + + events: { + 'click .tot_projects': 'tot_projects', + 'click .tot_tasks': 'tot_tasks', + 'click .tot_profitability': 'tot_profitability', + 'click .hr_recorded': 'hr_recorded', + 'click .tot_sale': 'tot_sale', + 'click .tot_emp': 'tot_emp', + 'change #income_expense_values': 'onchange_profitability', + 'change #start_date': '_onchangeFilter', + 'change #end_date': '_onchangeFilter', + 'change #employee_selection': '_onchangeFilter', + 'change #project_selection': '_onchangeFilter', }, - init: function(parent, context) { - this._super(parent, context); - this.dashboards_templates = ['DashboardProject','DashboardChart']; - this.today_sale = []; - }, + init: function(parent, context) { + this._super(parent, context); + this.dashboards_templates = ['DashboardProject', 'DashboardChart']; + this.today_sale = []; + }, - willStart: function() { - var self = this; - return $.when(ajax.loadLibs(this), this._super()).then(function() { - return self.fetch_data(); - }); - }, + willStart: function() { + var self = this; + return $.when(ajax.loadLibs(this), this._super()).then(function() { + return self.fetch_data(); + }); + }, - start: function() { + start: function() { var self = this; this.set("title", 'Dashboard'); return this._super().then(function() { self.render_dashboards(); self.render_graphs(); + self.render_filter() }); }, - render_dashboards: function(){ - var self = this; - _.each(this.dashboards_templates, function(template) { - self.$('.o_pj_dashboard').append(QWeb.render(template, {widget: self})); + render_dashboards: function() { + var self = this; + _.each(this.dashboards_templates, function(template) { + self.$('.o_pj_dashboard').append(QWeb.render(template, { + widget: self + })); }); - }, - + }, + render_filter: function() { + ajax.rpc('/project/filter').then(function(data) { + var projects = data[0] + var employees = data[1] + $(projects).each(function(project) { + $('#project_selection').append(""); + }); + $(employees).each(function(employee) { + $('#employee_selection').append(""); + }); + }) + }, - render_graphs: function(){ - var self = this; + render_graphs: function() { + var self = this; self.render_project_task(); self.render_top_employees_graph(); - - }, - - on_reverse_breadcrumb: function() { - var self = this; - web_client.do_push_state({}); - this.fetch_data().then(function() { - self.$('.o_pj_dashboard').empty(); - self.render_dashboards(); - self.render_graphs(); - }); - }, - -// - onclick_toggle_two: function(ev) { - this.onclick_income_this_year(ev); - this.onclick_income_last_year(ev); - this.onclick_income_this_month(ev); - }, - - - - - render_project_task:function(){ - var self = this; - var w = 400; - var h = 400; - var r = h/2; - var elem = this.$('.emp_graph'); - var colors = ['#70cac1', '#659d4e', '#208cc2', '#4d6cb1', '#584999', '#8e559e', '#cf3650', '#f65337', '#fe7139', - '#ffa433', '#ffc25b', '#f8e54b']; - var color = d3.scale.ordinal().range(colors); - rpc.query({ - model: "project.project", - method: "get_project_task", - }).then(function (data) { - var segColor = {}; - var vis = d3.select(elem[0]).append("svg:svg").data([data]).attr("width", w).attr("height", h).append("svg:g").attr("transform", "translate(" + r + "," + r + ")"); - var pie = d3.layout.pie().value(function(d){return d.value;}); - var arc = d3.svg.arc().outerRadius(r); - var arcs = vis.selectAll("g.slice").data(pie).enter().append("svg:g").attr("class", "slice"); - arcs.append("svg:path") - .attr("fill", function(d, i){ - return color(i); - }) - .attr("d", function (d) { - return arc(d); + self.income_this_year(); + }, + render_project_task: function() { + var self = this + rpc.query({ + model: "project.project", + method: "get_project_task_count", + }).then(function(data) { + var ctx = self.$("#project_doughnut"); + new Chart(ctx, { + type: "doughnut", + data: { + labels: data.project, + datasets: [{ + backgroundColor: data.color, + data: data.task + }] + }, + options: { + legend: { + position: 'left' + }, + title: { + display: true, + position: "top", + text: " ProjectTask Analysis", + fontSize: 20, + fontColor: "#111" + }, + cutoutPercentage: 40, + responsive: true, + } }); + }) + }, - var legend = d3.select(elem[0]).append("table").attr('class','legend'); - - var tr = legend.append("tbody").selectAll("tr").data(data).enter().append("tr"); - - tr.append("td").append("svg").attr("width", '16').attr("height", '16').append("rect") - .attr("width", '16').attr("height", '16') - .attr("fill",function(d, i){ return color(i) }); - - tr.append("td").text(function(d){ return d.label;}); + on_reverse_breadcrumb: function() { + var self = this; + web_client.do_push_state({}); + this.fetch_data().then(function() { + self.$('.o_pj_dashboard').empty(); + self.render_dashboards(); + self.render_graphs(); + }); + }, + _onchangeFilter: function() { + flag = 1 + var start_date = $('#start_date').val(); + var end_date = $('#end_date').val(); + if (!start_date) { + start_date = "null" + } + if (!end_date) { + end_date = "null" + } + var employee_selection = $('#employee_selection').val(); + var project_selection = $('#project_selection').val(); + ajax.rpc('/project/filter-apply', { + 'data': { + 'start_date': start_date, + 'end_date': end_date, + 'project': project_selection, + 'employee': employee_selection + } + }).then(function(data) { + tot_hrs = data['list_hours_recorded'] + tot_employee = data['total_emp'] + tot_project = data['total_project'] + tot_task = data['total_task'] + tot_so = data['total_so'] + document.getElementById("tot_project").innerHTML = data['total_project'].length + document.getElementById("tot_employee").innerHTML = data['total_emp'].length + document.getElementById("tot_task").innerHTML = data['total_task'].length + document.getElementById("tot_hrs").innerHTML = data['hours_recorded'] + document.getElementById("tot_margin").innerHTML = data['total_margin'] + document.getElementById("tot_so").innerHTML = data['total_so'].length + }) + }, - tr.append("td").attr("class",'legendFreq') - .text(function(d){ return d.value;}); + onchange_profitability: function(ev) { + var selected_filter = $('#income_expense_values').val() + var self = this + if (selected_filter == 'income_last_year') { + self.income_last_year(ev) + } else if (selected_filter == 'income_this_year') { + self.income_this_year(ev) + } else { + self.income_this_month(ev) + } + }, + /** + for opening project view + */ + tot_projects: function(e) { + var self = this; + e.stopPropagation(); + e.preventDefault(); + var options = { + on_reverse_breadcrumb: this.on_reverse_breadcrumb, + }; + if (flag == 0) { + this.do_action({ + name: _t("Projects"), + type: 'ir.actions.act_window', + res_model: 'project.project', + view_mode: 'kanban,form', + views: [ + [false, 'kanban'], + [false, 'form'] + ], + target: 'current' + }, options) + } else { + if (tot_project) { + this.do_action({ + name: _t("Projects"), + type: 'ir.actions.act_window', + res_model: 'project.project', + domain: [ + ["id", "in", tot_project] + ], + view_mode: 'kanban,form', + views: [ + [false, 'kanban'], + [false, 'form'] + ], + target: 'current' + }, options) + } + } + }, + /** + for opening project task view + */ + tot_tasks: function(e) { + var self = this; + e.stopPropagation(); + e.preventDefault(); + var options = { + on_reverse_breadcrumb: this.on_reverse_breadcrumb, + }; + if (flag == 0) { + this.do_action({ + name: _t("Tasks"), + type: 'ir.actions.act_window', + res_model: 'project.task', + view_mode: 'tree,kanban,form', + views: [ + [false, 'list'], + [false, 'form'] + ], + target: 'current' + }, options) + } else { + if (tot_task) { + this.do_action({ + name: _t("Tasks"), + type: 'ir.actions.act_window', + res_model: 'project.task', + domain: [ + ["id", "in", tot_task] + ], + view_mode: 'tree,kanban,form', + views: [ + [false, 'list'], + [false, 'form'] + ], + target: 'current' + }, options) + } + } + }, + /** + for opening margin view + */ + tot_profitability: function(e) { + var self = this; + e.stopPropagation(); + e.preventDefault(); + var options = { + on_reverse_breadcrumb: this.on_reverse_breadcrumb, + }; + this.do_action({ + name: _t("Profitability"), + type: 'ir.actions.act_window', + res_model: 'project.project', + view_mode: 'pivot', + views: [ + [false, 'pivot'], + [false, 'graph'] + ], + target: 'current' + }, options) + }, - }); + /** + for opening account analytic line view + */ + hr_recorded: function(e) { + var self = this; + e.stopPropagation(); + e.preventDefault(); + var options = { + on_reverse_breadcrumb: this.on_reverse_breadcrumb, + }; + if (flag == 0) { + this.do_action({ + name: _t("Timesheets"), + type: 'ir.actions.act_window', + res_model: 'account.analytic.line', + view_mode: 'tree,form', + views: [ + [false, 'list'] + ], + target: 'current' + }, options) + } else { + if (tot_hrs) { + this.do_action({ + name: _t("Timesheets"), + type: 'ir.actions.act_window', + res_model: 'account.analytic.line', + domain: [ + ["id", "in", tot_hrs] + ], + view_mode: 'tree,form', + views: [ + [false, 'list'] + ], + target: 'current' + }, options) + } + } + }, - }, + /** + for opening sale order view + */ + tot_sale: function(e) { + var self = this; + e.stopPropagation(); + e.preventDefault(); + var options = { + on_reverse_breadcrumb: this.on_reverse_breadcrumb, + }; + if (flag == 0) { + this.do_action({ + name: _t("Sale Order"), + type: 'ir.actions.act_window', + res_model: 'sale.order', + view_mode: 'tree', + views: [ + [false, 'list'] + ], + domain: [ + ["id", "in", tot_so] + ], + target: 'current' + }, options) + } else { + if (tot_so) { + this.do_action({ + name: _t("Sale Order"), + type: 'ir.actions.act_window', + res_model: 'sale.order', + domain: [ + ["id", "in", tot_so] + ], + view_mode: 'tree', + views: [ + [false, 'list'] + ], + target: 'current' + }, options) + } + } + }, + /** + for opening hr employee view + */ + tot_emp: function(e) { + var self = this; + e.stopPropagation(); + e.preventDefault(); + var options = { + on_reverse_breadcrumb: this.on_reverse_breadcrumb, + }; + if (flag == 0) { + this.do_action({ + name: _t("Employees"), + type: 'ir.actions.act_window', + res_model: 'hr.employee', + view_mode: 'tree,form', + views: [ + [false, 'list'], + [false, 'form'] + ], + target: 'current' + }, options) + } else { + this.do_action({ + name: _t("Employees"), + type: 'ir.actions.act_window', + res_model: 'hr.employee', + domain: [ + ["id", "in", tot_employee] + ], + view_mode: 'tree,form', + views: [ + [false, 'list'], + [false, 'form'] + ], + target: 'current' + }, options) - //project - tot_projects: function(e) { - var self = this; - e.stopPropagation(); - e.preventDefault(); - var options = { - on_reverse_breadcrumb: this.on_reverse_breadcrumb, - }; - this.do_action({ - name: _t("Projects"), - type: 'ir.actions.act_window', - res_model: 'project.project', - view_mode: 'kanban,form', - views: [[false, 'list'],[false, 'form']], - target: 'current' - }, options) - }, - - //task - tot_tasks: function(e) { - var self = this; - e.stopPropagation(); - e.preventDefault(); - var options = { - on_reverse_breadcrumb: this.on_reverse_breadcrumb, - }; - this.do_action({ - name: _t("Tasks"), - type: 'ir.actions.act_window', - res_model: 'project.task', - view_mode: 'tree,kanban,form', - views: [[false, 'list'],[false, 'form']], - target: 'current' - }, options) - }, - - //task - tot_profitability: function(e) { - var self = this; - e.stopPropagation(); - e.preventDefault(); - var options = { - on_reverse_breadcrumb: this.on_reverse_breadcrumb, - }; - this.do_action({ - name: _t("Profitability"), - type: 'ir.actions.act_window', - res_model: 'project.profitability.report', - view_mode: 'pivot', - views: [[false, 'pivot'],[false, 'graph']], - target: 'current' - }, options) - }, - - //hr timesheets + } + }, - hr_recorded: function(e) { - var self = this; - e.stopPropagation(); - e.preventDefault(); - var options = { - on_reverse_breadcrumb: this.on_reverse_breadcrumb, - }; - this.do_action({ - name: _t("Timesheets"), - type: 'ir.actions.act_window', - res_model: 'account.analytic.line', - view_mode: 'tree,form', - views: [[false, 'list']], - target: 'current' - }, options) - }, - - //total saleorder - tot_sale: function(e) { - var self = this; - e.stopPropagation(); - e.preventDefault(); - var options = { - on_reverse_breadcrumb: this.on_reverse_breadcrumb, - }; - this.do_action({ - name: _t("Sale Order"), - type: 'ir.actions.act_window', - res_model: 'sale.order', - view_mode: 'tree', - views: [[false, 'list']], - domain: [['analytic_account_id', '!=',self.analytic_account_id ]], - target: 'current' - }, options) - }, - - //total emp + render_top_employees_graph: function() { + var self = this - tot_emp: function(e) { - var self = this; - e.stopPropagation(); - e.preventDefault(); - var options = { - on_reverse_breadcrumb: this.on_reverse_breadcrumb, - }; - this.do_action({ - name: _t("Employees"), - type: 'ir.actions.act_window', - res_model: 'hr.employee', - view_mode: 'tree,form', - views: [[false, 'list'],[false, 'form']], - target: 'current' - }, options) - }, - - - - render_top_employees_graph:function(){ - console.log('hhhh') - var self = this - console.log('bbb') - - var ctx = self.$(".top_selling_employees"); - console.log('vvv',ctx) + var ctx = self.$(".top_selling_employees"); rpc.query({ model: "project.project", method: 'get_top_timesheet_employees', - }).then(function (arrays) { - - - var data = { - labels: arrays[1], - datasets: [ - { - label: "Hours Spent", - data: arrays[0], - backgroundColor: [ - "rgba(190, 27, 75,1)", - "rgba(31, 241, 91,1)", - "rgba(103, 23, 252,1)", - "rgba(158, 106, 198,1)", - "rgba(250, 217, 105,1)", - "rgba(255, 98, 31,1)", - "rgba(255, 31, 188,1)", - "rgba(75, 192, 192,1)", - "rgba(153, 102, 255,1)", - "rgba(10,20,30,1)" - ], - borderColor: [ - "rgba(190, 27, 75, 0.2)", - "rgba(190, 223, 122, 0.2)", - "rgba(103, 23, 252, 0.2)", - "rgba(158, 106, 198, 0.2)", - "rgba(250, 217, 105, 0.2)", - "rgba(255, 98, 31, 0.2)", - "rgba(255, 31, 188, 0.2)", - "rgba(75, 192, 192, 0.2)", - "rgba(153, 102, 255, 0.2)", - "rgba(10,20,30,0.3)" - ], - borderWidth: 1 - }, - - ] - }; - console.log(data) - - //options - var options = { - responsive: true, - title: { - display: true, - position: "top", - text: " Time by Employees", - fontSize: 18, - fontColor: "#111" - }, - legend: { - display: true, - position: "bottom", - labels: { - fontColor: "#333", - fontSize: 16 - } - }, - scales: { - yAxes: [{ - ticks: { - min: 0 - } - }] - } - }; - console.log('lllll',data) - //create Chart class object - var chart = new Chart(ctx, { - type: 'bar', - data: data, - options: options - }); - - }); + }).then(function(arrays) { + + + var data = { + labels: arrays[1], + datasets: [{ + label: "Hours Spent", + data: arrays[0], + backgroundColor: [ + "rgba(190, 27, 75,1)", + "rgba(31, 241, 91,1)", + "rgba(103, 23, 252,1)", + "rgba(158, 106, 198,1)", + "rgba(250, 217, 105,1)", + "rgba(255, 98, 31,1)", + "rgba(255, 31, 188,1)", + "rgba(75, 192, 192,1)", + "rgba(153, 102, 255,1)", + "rgba(10,20,30,1)" + ], + borderColor: [ + "rgba(190, 27, 75, 0.2)", + "rgba(190, 223, 122, 0.2)", + "rgba(103, 23, 252, 0.2)", + "rgba(158, 106, 198, 0.2)", + "rgba(250, 217, 105, 0.2)", + "rgba(255, 98, 31, 0.2)", + "rgba(255, 31, 188, 0.2)", + "rgba(75, 192, 192, 0.2)", + "rgba(153, 102, 255, 0.2)", + "rgba(10,20,30,0.3)" + ], + borderWidth: 1 + }, + + ] + }; + + //options + var options = { + responsive: true, + title: { + display: true, + position: "top", + text: " Time by Employees", + fontSize: 18, + fontColor: "#111" + }, + scales: { + yAxes: [{ + ticks: { + min: 0 + } + }] + } + }; + //create Chart class object + var chart = new Chart(ctx, { + type: 'bar', + data: data, + options: options + }); + + }); }, - onclick_income_last_year: function(ev) { - ev.preventDefault(); - var selected = $('.btn.btn-tool.income'); - var data = $(selected[0]).data(); - var posted = 1; + income_last_year: function(ev) { + ev.preventDefault(); + var selected = $('.btn.btn-tool.income'); + var data = $(selected[0]).data(); + var posted = 1; - rpc.query({ - model: 'project.project', - method: 'get_income_last_year', - args: [], - }) - .then(function(result) { - - $('#net_profit_current_months').hide(); - $('#net_profit_last_year').show(); - $('#net_profit_this_year').hide(); + rpc.query({ + model: 'project.project', + method: 'get_income_last_year', + args: [], + }) + .then(function(result) { + $('#net_profit_current_months').hide(); + $('#net_profit_last_year').show(); + $('#net_profit_this_year').hide(); - var ctx = document.getElementById("canvas").getContext('2d'); + var ctx = document.getElementById("canvas").getContext('2d'); - // Define the data + // Define the data - var profit = result.profit; + var profit = result.profit; - var labels = result.month; // Add labels to array - // End Defining data + var labels = result.month; // Add labels to array + // End Defining data - // End Defining data - if (window.myCharts != undefined) - window.myCharts.destroy(); - window.myCharts = new Chart(ctx, { - //var myChart = new Chart(ctx, { - type: 'bar', - data: { - labels: labels, - datasets: [ - { + // End Defining data + if (window.myCharts != undefined) + window.myCharts.destroy(); + window.myCharts = new Chart(ctx, { + //var myChart = new Chart(ctx, { + type: 'bar', + data: { + labels: labels, + datasets: [{ label: 'Profitability', // Name the series data: profit, // Specify the data values array backgroundColor: '#0bd465', @@ -388,55 +529,48 @@ var PjDashboard = AbstractAction.extend({ borderWidth: 1, // Specify bar border width type: 'line', // Set this data to a line chart fill: false - } - ] - }, - options: { - responsive: true, // Instruct chart js to respond nicely. - maintainAspectRatio: false, // Add to prevent default behaviour of full-width/height - } - }); + }] + }, + options: { + responsive: true, // Instruct chart js to respond nicely. + maintainAspectRatio: false, // Add to prevent default behaviour of full-width/height + } + }); - }) - }, - - onclick_income_this_year: function(ev) { - ev.preventDefault(); - var selected = $('.btn.btn-tool.income'); - var data = $(selected[0]).data(); - var posted = false; + }) + }, - rpc.query({ - model: 'project.project', - method: 'get_income_this_year', - args: [], + income_this_year: function() { + var selected = $('.btn.btn-tool.income'); + var data = $(selected[0]).data(); + var posted = false; - }) - .then(function(result) { + rpc.query({ + model: 'project.project', + method: 'get_income_this_year', + args: [], - $('#net_profit_current_months').hide(); - $('#net_profit_last_year').hide(); - $('#net_profit_this_year').show(); + }) + .then(function(result) { - var ctx = document.getElementById("canvas").getContext('2d'); + var ctx = document.getElementById("canvas").getContext('2d'); - // Define the data - var income = result.income; // Add data values to array -// var expense = result.expense; - var profit = result.profit; + // Define the data + var income = result.income; // Add data values to array + // var expense = result.expense; + var profit = result.profit; - var labels = result.month; // Add labels to array + var labels = result.month; // Add labels to array - if (window.myCharts != undefined) - window.myCharts.destroy(); - window.myCharts = new Chart(ctx, { - //var myChart = new Chart(ctx, { - type: 'bar', - data: { - labels: labels, - datasets: [ - { + if (window.myCharts != undefined) + window.myCharts.destroy(); + window.myCharts = new Chart(ctx, { + //var myChart = new Chart(ctx, { + type: 'bar', + data: { + labels: labels, + datasets: [{ label: 'Profitability', // Name the series data: profit, // Specify the data values array backgroundColor: '#0bd465', @@ -445,128 +579,127 @@ var PjDashboard = AbstractAction.extend({ borderWidth: 1, // Specify bar border width type: 'line', // Set this data to a line chart fill: false - } - ] - }, - options: { - responsive: true, // Instruct chart js to respond nicely. - maintainAspectRatio: false, // Add to prevent default behaviour of full-width/height - } - }); - - }) - }, + }] + }, + options: { + responsive: true, // Instruct chart js to respond nicely. + maintainAspectRatio: false, // Add to prevent default behaviour of full-width/height + } + }); - onclick_income_this_month: function(ev) { - ev.preventDefault(); - var selected = $('.btn.btn-tool.income'); - var data = $(selected[0]).data(); - var posted = 1; + }) + }, - rpc.query({ - model: 'project.project', - method: 'get_income_this_month', - args: [], + income_this_month: function(ev) { - }) - .then(function(result) { + ev.preventDefault(); + var selected = $('.btn.btn-tool.income'); + var data = $(selected[0]).data(); + var posted = 1; + rpc.query({ + model: 'project.project', + method: 'get_income_this_month', + args: [], - var ctx = document.getElementById("canvas").getContext('2d'); + }) + .then(function(result) { + + + var ctx = document.getElementById("canvas").getContext('2d'); + + // Define the data + var profit = result.profit; + + var labels = result.date; // Add labels to array + // End Defining data + + // End Defining data + if (window.myCharts != undefined) + window.myCharts.destroy(); + window.myCharts = new Chart(ctx, { + //var myChart = new Chart(ctx, { + type: 'bar', + data: { + labels: labels, + datasets: [ + + { + label: 'Profitability', // Name the series + data: profit, // Specify the data values array + backgroundColor: '#0bd465', + borderColor: '#0bd465', + + borderWidth: 1, // Specify bar border width + type: 'line', // Set this data to a line chart + fill: false + } + ] + }, + options: { + responsive: true, // Instruct chart js to respond nicely. + maintainAspectRatio: false, // Add to prevent default behaviour of full-width/height + } + }); - // Define the data - var profit = result.profit; + }) + }, - var labels = result.date; // Add labels to array - // End Defining data - // End Defining data - if (window.myCharts != undefined) - window.myCharts.destroy(); - window.myCharts = new Chart(ctx, { - //var myChart = new Chart(ctx, { - type: 'bar', - data: { - labels: labels, - datasets: [ + fetch_data: function() { + var self = this; + var def1 = this._rpc({ + model: 'project.project', + method: 'get_tiles_data' + }).then(function(result) { + self.total_projects = result['total_projects'], + self.total_tasks = result['total_tasks'], + self.total_hours = result['total_hours'], + self.total_profitability = result['total_profitability'], + self.total_employees = result['total_employees'], + self.total_sale_orders = result['total_sale_orders'], + self.project_stage_list = result['project_stage_list'] + tot_so = result['sale_list'] + }); + var def2 = self._rpc({ + model: "project.project", + method: "get_details", + }) + .then(function(res) { + self.invoiced = res['invoiced']; + self.to_invoice = res['to_invoice']; + self.time_cost = res['time_cost']; + self.expen_cost = res['expen_cost']; + self.payment_details = res['payment_details']; + }); + var def3 = self._rpc({ + model: "project.project", + method: "get_hours_data", + }) + .then(function(res) { + self.hour_recorded = res['hour_recorded']; + self.hour_recorde = res['hour_recorde']; + self.billable_fix = res['billable_fix']; + self.non_billable = res['non_billable']; + self.total_hr = res['total_hr']; + }); - { - label: 'Profitability', // Name the series - data: profit, // Specify the data values array - backgroundColor: '#0bd465', - borderColor: '#0bd465', + var def4 = self._rpc({ + model: "project.project", + method: "get_task_data", + }) + .then(function(res) { + self.task_data = res['project']; - borderWidth: 1, // Specify bar border width - type: 'line', // Set this data to a line chart - fill: false - } - ] - }, - options: { - responsive: true, // Instruct chart js to respond nicely. - maintainAspectRatio: false, // Add to prevent default behaviour of full-width/height - } }); - }) - }, + return $.when(def1, def2, def3, def4); + }, + }); - fetch_data: function() { - var self = this; - var def1 = this._rpc({ - model: 'project.project', - method: 'get_tiles_data' - }).then(function(result) - { - self.total_projects = result['total_projects'], - self.total_tasks = result['total_tasks'], - self.total_hours = result['total_hours'], - self.total_profitability = result['total_profitability'], - self.total_employees = result['total_employees'], - self.total_sale_orders = result['total_sale_orders'] + core.action_registry.add('project_dashboard', PjDashboard); - }); - var def2 = self._rpc({ - model: "project.project", - method: "get_details", - }) - .then(function (res) { - self.invoiced = res['invoiced']; - self.to_invoice = res['to_invoice']; - self.time_cost = res['time_cost']; - self.expen_cost = res['expen_cost']; - self.payment_details = res['payment_details']; - }); - var def3 = self._rpc({ - model: "project.project", - method: "get_hours_data", - }) - .then(function (res) { - self.hour_recorded = res['hour_recorded']; - self.hour_recorde = res['hour_recorde']; - self.billable_fix = res['billable_fix']; - self.non_billable = res['non_billable']; - self.total_hr = res['total_hr']; - }); - - var def4 = self._rpc({ - model: "project.project", - method: "get_task_data", - }) - .then(function (res) { - self.task_data = res['project']; - - }); - - return $.when(def1,def2,def3,def4); - }, - -}); - -core.action_registry.add('project_dashboard', PjDashboard); - -return PjDashboard; - -}); + return PjDashboard; +}); \ No newline at end of file diff --git a/project_dashboard_odoo/static/src/xml/dashboard.xml b/project_dashboard_odoo/static/src/xml/dashboard.xml index 252121458..fcaa895ec 100644 --- a/project_dashboard_odoo/static/src/xml/dashboard.xml +++ b/project_dashboard_odoo/static/src/xml/dashboard.xml @@ -9,81 +9,105 @@
-
+
+

Start Date :

+

+ +

+

End Date :

+

+ +

+

Project :

+

+ +

+

Employees :

+

+ +

+
+
+
+
-
-
-
-
-
Total Project
-
+
+
+
+
Total Project
+
+
-
+
-
-
-
-
-
Total Employees
-
+
+
+
+
Total Employees
+
+
-
+
-
-
-
-
-
Total tasks
-
-
+
+
+
+
Total tasks
+
+ +
-
+
-
-
-
-
-
Hours Recorded
-
+
+
+
+
Hours Recorded
+
+
-
+
-
-
-
-
-
Total Profitability
-
+
+
+
+
Total Profitability
+
+
-
+
-
-
-
-
-
Total Sale Orders
-
+
+
+
+
Total Sale Orders
+
+
@@ -95,79 +119,87 @@
-
+
-
-

-

ProjectTask Analysis

+ +

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

Profitability

+
+
+
+ +
+
+
+
+

+
+ +
+
+
-
-
-
-
- ProjectTask Details +
+
+
+ Project Task Details
-
-
- - +
+
+
+ + + + + + + + - - + + - - - - - - - - - -
Project NameTask Name
Project NameTask Name + + + +
- - - -
-
+ + +
-
-
-
-
-
-
- -
-
-
-
-
-
-

-

-

Timesheet Analysis

-
-
- -
+
-
- Hours Recorded + height: 284px;margin-bottom: 15px;"> +
+ Hours Recorded
@@ -186,7 +218,7 @@

- +

@@ -200,15 +232,15 @@ - +

- +

-
+
@@ -219,13 +251,13 @@ - + @@ -240,207 +272,184 @@ - +

- +

- +

- - - - - - - - - +
Total:
+ + + - + + + - - - - - - -
Total:
-

+

-
-
-
-
-
-
-
-
+ +

-
-
-
-
-
-
-
-
- -

Profitability

-
-
-
- -
-
-
-
- -

-
- - -
- + +

+ + + + + +
-
-
- -
-
-
- Profitability
-
-
-
-
-
- - - - - - - - +
+
+ Profitability +
+
+
+
+
+
+
Invoiced
+ - + - - -
-

- -

-
Invoiced
- - - - - - - - + + + + + + + + +
To Invoice
+

+ +

+
+ + - + - - -
-

- - -

-
To Invoice
- - - - - - - - + + + + + + + + +
Timesheet costs
+

+ + +

+
+ + + + + + + + - + + + + + + +
Timesheet costs
-

+

+

- -

-
+ + + + - - -
Other costs
- - - - - - - - - - + + + - - - -
Other costs
-

+ +

+

- -

-
- - - - - - - - + + + + + + +
Total:
+ + + + + + + + - - - - -
Total:
-

+

+

- -

-
+ + + + + + + +
+
+
+ Stage Wise Total Projects +
+ + + + + + + + + +
+ +
+

+

+

+

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