You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
461 lines
16 KiB
461 lines
16 KiB
# -*- coding: utf-8 -*-
|
|
#############################################################################
|
|
#
|
|
# Cybrosys Technologies Pvt. Ltd.
|
|
#
|
|
# Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
|
|
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
|
|
#
|
|
# You can modify it under the terms of the GNU LESSER
|
|
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
|
|
#
|
|
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
|
|
# (LGPL v3) along with this program.
|
|
# If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
#############################################################################
|
|
|
|
import calendar
|
|
import random
|
|
from datetime import datetime
|
|
|
|
from dateutil.relativedelta import relativedelta
|
|
|
|
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([])
|
|
report_project = self.env['project.profitability.report'].search([])
|
|
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
|
|
total_time = sum(analytic_project.mapped('unit_amount'))
|
|
employees = self.env['hr.employee'].search([])
|
|
|
|
task = self.env['project.task'].search_read([
|
|
('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_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),
|
|
'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
|
|
inner join hr_employee on hr_employee.id =account_analytic_line.employee_id
|
|
group by hr_employee.id ORDER
|
|
BY unit DESC Limit 10 '''
|
|
self._cr.execute(query)
|
|
top_product = self._cr.dictfetchall()
|
|
|
|
unit = []
|
|
for record in top_product:
|
|
unit.append(record.get('unit'))
|
|
employee = []
|
|
for record in top_product:
|
|
employee.append(record.get('employee'))
|
|
final = [unit, employee]
|
|
|
|
return final
|
|
|
|
@api.model
|
|
def get_details(self):
|
|
"""
|
|
|
|
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.
|
|
|
|
"""
|
|
query = '''select sum(amount_untaxed_invoiced) as invoiced,
|
|
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)
|
|
data = self._cr.dictfetchall()
|
|
invoiced = []
|
|
for record in data:
|
|
invoiced.append(record.get('invoiced'))
|
|
|
|
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'))
|
|
|
|
expen_cost = []
|
|
for record in data:
|
|
expen_cost.append(record.get('expen_cost'))
|
|
|
|
payment_details = []
|
|
for record in data:
|
|
payment_details.append(record.get('payment_details'))
|
|
return {
|
|
'invoiced': invoiced,
|
|
'to_invoice': to_invoice,
|
|
'time_cost': time_cost,
|
|
'expen_cost': expen_cost,
|
|
'payment_details': payment_details,
|
|
}
|
|
|
|
@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)
|
|
data = self._cr.dictfetchall()
|
|
hour_recorded = []
|
|
for record in data:
|
|
hour_recorded.append(record.get('hour_recorded'))
|
|
|
|
query = '''SELECT sum(unit_amount) as hour_recorde FROM account_analytic_line
|
|
WHERE timesheet_invoice_type='billable_time' '''
|
|
self._cr.execute(query)
|
|
data = self._cr.dictfetchall()
|
|
hour_recorde = []
|
|
for record in data:
|
|
hour_recorde.append(record.get('hour_recorde'))
|
|
|
|
query = '''SELECT sum(unit_amount) as billable_fix FROM account_analytic_line
|
|
WHERE timesheet_invoice_type='billable_fixed' '''
|
|
self._cr.execute(query)
|
|
data = self._cr.dictfetchall()
|
|
billable_fix = []
|
|
for record in data:
|
|
billable_fix.append(record.get('billable_fix'))
|
|
|
|
query = '''SELECT sum(unit_amount) as non_billable FROM account_analytic_line
|
|
WHERE timesheet_invoice_type='non_billable' '''
|
|
self._cr.execute(query)
|
|
data = self._cr.dictfetchall()
|
|
non_billable = []
|
|
for record in data:
|
|
non_billable.append(record.get('non_billable'))
|
|
|
|
query = '''SELECT sum(unit_amount) as total_hr FROM account_analytic_line
|
|
WHERE timesheet_invoice_type='non_billable_project' or timesheet_invoice_type='billable_time'
|
|
or timesheet_invoice_type='billable_fixed' or timesheet_invoice_type='non_billable' '''
|
|
self._cr.execute(query)
|
|
data = self._cr.dictfetchall()
|
|
total_hr = []
|
|
for record in data:
|
|
total_hr.append(record.get('total_hr'))
|
|
|
|
return {
|
|
'hour_recorded': hour_recorded,
|
|
'hour_recorde': hour_recorde,
|
|
'billable_fix': billable_fix,
|
|
'non_billable': non_billable,
|
|
'total_hr': total_hr,
|
|
}
|
|
|
|
@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):
|
|
l_month = datetime.now() - relativedelta(months=i)
|
|
text = format(l_month, '%B')
|
|
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
|
|
to_char(DATE(NOW()), 'YY') = to_char(project_profitability_report.line_date, 'YY')
|
|
%s group by month ''') % (states_arg))
|
|
record = self._cr.dictfetchall()
|
|
|
|
records = []
|
|
for month in month_list:
|
|
last_month_inc = list(
|
|
filter(lambda m: m['month'].strip() == month, record))
|
|
|
|
if not last_month_inc:
|
|
records.append({
|
|
'month': month,
|
|
'profit': 0.0,
|
|
})
|
|
|
|
else:
|
|
|
|
last_month_inc[0].update({
|
|
'profit': last_month_inc[0]['income']
|
|
})
|
|
records.append(last_month_inc[0])
|
|
|
|
month = []
|
|
profit = []
|
|
for rec in records:
|
|
month.append(rec['month'])
|
|
profit.append(rec['profit'])
|
|
return {
|
|
'profit': profit,
|
|
'month': month,
|
|
}
|
|
|
|
@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)
|
|
text = format(l_month, '%B')
|
|
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
|
|
%s group by month ''') % (states_arg))
|
|
record = self._cr.dictfetchall()
|
|
|
|
records = []
|
|
for month in month_list:
|
|
last_month_inc = list(
|
|
filter(lambda m: m['month'].strip() == month, record))
|
|
if not last_month_inc:
|
|
records.append({
|
|
'month': month,
|
|
'profit': 0.0,
|
|
|
|
})
|
|
|
|
else:
|
|
|
|
last_month_inc[0].update({
|
|
'profit': last_month_inc[0]['income']
|
|
})
|
|
records.append(last_month_inc[0])
|
|
|
|
month = []
|
|
profit = []
|
|
for rec in records:
|
|
month.append(rec['month'])
|
|
profit.append(rec['profit'])
|
|
return {
|
|
|
|
'month': month,
|
|
'profit': profit,
|
|
}
|
|
|
|
@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()
|
|
day = calendar.monthrange(now.year, now.month)[1]
|
|
for x in range(1, day + 1):
|
|
day_list.append(x)
|
|
self._cr.execute(('''select sum(margin) as income ,cast(to_char(project_profitability_report.line_date, 'DD')
|
|
as int) as date from project_profitability_report where
|
|
Extract(month FROM project_profitability_report.line_date) = Extract(month FROM DATE(NOW()))
|
|
AND Extract(YEAR FROM project_profitability_report.line_date) = Extract(YEAR FROM DATE(NOW()))
|
|
%s group by date ''') % (states_arg))
|
|
|
|
record = self._cr.dictfetchall()
|
|
|
|
records = []
|
|
for date in day_list:
|
|
last_month_inc = list(filter(lambda m: m['date'] == date, record))
|
|
if not last_month_inc:
|
|
records.append({
|
|
'date': date,
|
|
'income': 0.0,
|
|
'profit': 0.0
|
|
})
|
|
|
|
else:
|
|
|
|
last_month_inc[0].update({
|
|
'profit': last_month_inc[0]['income']
|
|
})
|
|
records.append(last_month_inc[0])
|
|
date = []
|
|
profit = []
|
|
for rec in records:
|
|
date.append(rec['date'])
|
|
profit.append(rec['profit'])
|
|
return {
|
|
'date': date,
|
|
'profit': profit
|
|
|
|
}
|
|
|
|
@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()
|
|
project_name = []
|
|
for rec in data:
|
|
b = list(rec)
|
|
project_name.append(b)
|
|
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
|
|
|