odoo-2-flectra-converter/odoo/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py

3000 lines
172 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
import datetime as dt
import pytz
import json
from dateutil import relativedelta
import dateutil
from datetime import datetime
from collections import defaultdict
import re
import babel
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT, DEFAULT_SERVER_DATE_FORMAT, \
frozendict, lazy_classproperty, lazy_property, ormcache, \
Collector, LastOrderedSet, OrderedSet, pycompat
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError, AccessError, UserError
from ast import literal_eval
from odoo.tools.safe_eval import safe_eval
from ..lib.ks_date_filter_selections import ks_get_date
# TODO : Check all imports if needed
aggregate_fun= {
'array_agg', 'count', 'count_distinct',
'bool_and', 'bool_or', 'max', 'min', 'avg', 'sum',
}
regex_field_agg = re.compile(r'(\w+)(?::(\w+)(?:\((\w+)\))?)?')
read = fields.Many2one.read
def ks_read(self, records):
if self.name == 'ks_list_view_fields' or self.name == 'ks_list_view_group_fields':
comodel = records.env[self.comodel_name]
# String domains are supposed to be dynamic and evaluated on client-side
# only (thus ignored here).
domain = self.domain if isinstance(self.domain, list) else []
wquery = comodel._where_calc(domain)
comodel._apply_ir_rules(wquery, 'read')
from_c, where_c, where_params = wquery.get_sql()
query = """ SELECT {rel}.{id1}, {rel}.{id2} FROM {rel}, {from_c}
WHERE {where_c} AND {rel}.{id1} IN %s AND {rel}.{id2} = {tbl}.id
""".format(rel=self.relation, id1=self.column1, id2=self.column2,
tbl=comodel._table, from_c=from_c, where_c=where_c or '1=1',
limit=(' LIMIT %d' % self.limit) if self.limit else '',
)
where_params.append(tuple(records.ids))
# retrieve lines and group them by record
group = defaultdict(list)
records._cr.execute(query, where_params)
rec_list = records._cr.fetchall()
for row in rec_list:
group[row[0]].append(row[1])
# store result in cache
cache = records.env.cache
for record in records:
if self.name == 'ks_list_view_fields':
field = 'ks_list_view_fields'
else:
field = 'ks_list_view_group_fields'
order = False
if record.ks_many2many_field_ordering:
order = json.loads(record.ks_many2many_field_ordering).get(field, False)
if order:
group[record.id].sort(key=lambda x: order.index(x))
cache.set(record, self, tuple(group[record.id]))
else:
comodel = records.env[self.comodel_name]
# String domains are supposed to be dynamic and evaluated on client-side
# only (thus ignored here).
domain = self.domain if isinstance(self.domain, list) else []
wquery = comodel._where_calc(domain)
comodel._apply_ir_rules(wquery, 'read')
order_by = comodel._generate_order_by(None, wquery)
from_c, where_c, where_params = wquery.get_sql()
query = """ SELECT {rel}.{id1}, {rel}.{id2} FROM {rel}, {from_c}
WHERE {where_c} AND {rel}.{id1} IN %s AND {rel}.{id2} = {tbl}.id
{order_by} {limit} OFFSET {offset}
""".format(rel=self.relation, id1=self.column1, id2=self.column2,
tbl=comodel._table, from_c=from_c, where_c=where_c or '1=1',
limit=(' LIMIT %d' % self.limit) if self.limit else '',
offset=0, order_by=order_by)
where_params.append(tuple(records.ids))
# retrieve lines and group them by record
group = defaultdict(list)
records._cr.execute(query, where_params)
for row in records._cr.fetchall():
group[row[0]].append(row[1])
# store result in cache
cache = records.env.cache
for record in records:
cache.set(record, self, tuple(group[record.id]))
fields.Many2many.read = ks_read
read_group = models.BaseModel._read_group_process_groupby
def ks_time_addition(self, gb, query):
split = gb.split(':')
field_type = self._fields[split[0]].type
gb_function = split[1] if len(split) == 2 else None
if gb_function == 'month_year':
gb_function = 'month'
temporal = field_type in ('date', 'datetime')
tz_convert = field_type == 'datetime' and self._context.get('tz') in pytz.all_timezones
qualified_field = self._inherits_join_calc(self._table, split[0], query)
if temporal:
display_formats = {
# Careful with week/year formats:
# - yyyy (lower) must always be used, *except* for week+year formats
# - YYYY (upper) must always be used for week+year format
# e.g. 2006-01-01 is W52 2005 in some locales (de_DE),
# and W1 2006 for others
#
# Mixing both formats, e.g. 'MMM YYYY' would yield wrong results,
# such as 2006-01-01 being formatted as "January 2005" in some locales.
# Cfr: http://babel.pocoo.org/docs/dates/#date-fields
'minute': 'hh:mm dd MMM',
'hour': 'hh:00 dd MMM',
'day': 'dd MMM yyyy', # yyyy = normal year
'week': "'W'w YYYY", # w YYYY = ISO week-year
'month': 'MMMM yyyy',
'quarter': 'QQQ yyyy',
'year': 'yyyy',
}
time_intervals = {
'minute': dateutil.relativedelta.relativedelta(minutes=1),
'hour': dateutil.relativedelta.relativedelta(hours=1),
'day': dateutil.relativedelta.relativedelta(days=1),
'week': dt.timedelta(days=7),
'month': dateutil.relativedelta.relativedelta(months=1),
'month_year': dateutil.relativedelta.relativedelta(months=1),
'quarter': dateutil.relativedelta.relativedelta(months=3),
'year': dateutil.relativedelta.relativedelta(years=1)
}
if tz_convert:
qualified_field = "timezone('%s', timezone('UTC',%s))" % (self._context.get('tz', 'UTC'), qualified_field)
qualified_field = "date_trunc('%s', %s)" % (gb_function or 'month', qualified_field)
if field_type == 'boolean':
qualified_field = "coalesce(%s,false)" % qualified_field
return {
'field': split[0],
'groupby': gb,
'type': field_type,
'display_format': display_formats[gb_function or 'month'] if temporal else None,
'interval': time_intervals[gb_function or 'month'] if temporal else None,
'tz_convert': tz_convert,
'qualified_field': qualified_field
}
def ks_read_group_raw(self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True):
self.check_access_rights('read')
query = self._where_calc(domain)
fields = fields or [f.name for f in self._fields.values() if f.store]
groupby = [groupby] if isinstance(groupby, pycompat.string_types) else list(OrderedSet(groupby))
groupby_list = groupby[:1] if lazy else groupby
annotated_groupbys = [self._read_group_process_groupby(gb, query) for gb in groupby_list]
groupby_fields = [g['field'] for g in annotated_groupbys]
order = orderby or ','.join([g for g in groupby_list])
groupby_dict = {gb['groupby']: gb for gb in annotated_groupbys}
self._apply_ir_rules(query, 'read')
for gb in groupby_fields:
assert gb in fields, "Fields in 'groupby' must appear in the list of fields to read (perhaps it's missing in the list view?)"
assert gb in self._fields, "Unknown field %r in 'groupby'" % gb
gb_field = self._fields[gb].base_field
assert gb_field.store and gb_field.column_type, "Fields in 'groupby' must be regular database-persisted fields (no function or related fields), or function fields with store=True"
aggregated_fields = []
select_terms = []
for field in fields:
if field == 'sequence':
continue
match = regex_field_agg.match(field)
if not match:
raise UserError(_("Invalid field specification %r.") % field)
name, func, fname = match.groups()
if func:
fname = fname or name
field = self._fields[fname]
if not (field.base_field.store and field.base_field.column_type):
raise UserError(_("Cannot aggregate field %r.") % fname)
if func not in aggregate_fun:
raise UserError(_("Invalid aggregation function %r.") % func)
else:
field = self._fields.get(name)
if not (field and field.base_field.store and
field.base_field.column_type and field.group_operator):
continue
func, fname = field.group_operator, name
if fname in groupby_fields:
continue
if name in aggregated_fields:
raise UserError(_("Output name %r is used twice.") % name)
aggregated_fields.append(name)
expr = self._inherits_join_calc(self._table, fname, query)
if func.lower() == 'count_distinct':
term = 'COUNT(DISTINCT %s) AS "%s"' % (expr, name)
else:
term = '%s(%s) AS "%s"' % (func, expr, name)
select_terms.append(term)
for gb in annotated_groupbys:
select_terms.append('%s as "%s" ' % (gb['qualified_field'], gb['groupby']))
for gb in annotated_groupbys:
select_terms.append('%s as "%s" ' % (gb['qualified_field'], gb['groupby']))
groupby_terms, orderby_terms = self._read_group_prepare(order, aggregated_fields, annotated_groupbys, query)
from_clause, where_clause, where_clause_params = query.get_sql()
if lazy and (len(groupby_fields) >= 2 or not self._context.get('group_by_no_leaf')):
count_field = groupby_fields[0] if len(groupby_fields) >= 1 else '_'
else:
count_field = '_'
count_field += '_count'
prefix_terms = lambda prefix, terms: (prefix + " " + ",".join(terms)) if terms else ''
prefix_term = lambda prefix, term: ('%s %s' % (prefix, term)) if term else ''
query = """
SELECT min("%(table)s".id) AS id, count("%(table)s".id) AS "%(count_field)s" %(extra_fields)s
FROM %(from)s
%(where)s
%(groupby)s
%(orderby)s
%(limit)s
%(offset)s
""" % {
'table': self._table,
'count_field': count_field,
'extra_fields': prefix_terms(',', select_terms),
'from': from_clause,
'where': prefix_term('WHERE', where_clause),
'groupby': prefix_terms('GROUP BY', groupby_terms),
'orderby': prefix_terms('ORDER BY', orderby_terms),
'limit': prefix_term('LIMIT', int(limit) if limit else None),
'offset': prefix_term('OFFSET', int(offset) if limit else None),
}
self._cr.execute(query, where_clause_params)
fetched_data = self._cr.dictfetchall()
if not groupby_fields:
return fetched_data
self._read_group_resolve_many2one_fields(fetched_data, annotated_groupbys)
data = ({k: self._read_group_prepare_data(k,v, groupby_dict) for k,v in r.items()} for r in fetched_data)
result = [self._read_group_format_result(d, annotated_groupbys, groupby, domain) for d in data]
if lazy:
result = self._read_group_fill_results(
domain, groupby_fields[0], groupby[len(annotated_groupbys):],
aggregated_fields, count_field, result, read_group_order=order,
)
return result
models.BaseModel._read_group_process_groupby = ks_time_addition
models.BaseModel._read_group_raw = ks_read_group_raw
class KsDashboardNinjaItems(models.Model):
_name = 'ks_dashboard_ninja.item'
_description = 'Dashboard Ninja items'
name = fields.Char(string="Name", size=256)
ks_model_id = fields.Many2one('ir.model', string='Model', required=True,
domain="[('access_ids','!=',False),('transient','=',False),"
"('model','not ilike','base_import%'),'|',('model','not ilike','ir.%'),('model','=ilike','_%ir.%'),"
"('model','not ilike','web_editor.%'),('model','not ilike','web_tour.%'),"
"('model','!=','mail.thread'),('model','not ilike','ks_dash%')]")
ks_domain = fields.Char(string="Domain")
ks_model_id_2 = fields.Many2one('ir.model', string='Kpi Model',
domain="[('access_ids','!=',False),('transient','=',False),"
"('model','not ilike','base_import%'),'|',('model','not ilike','ir.%'),('model','=ilike','_%ir.%'),"
"('model','not ilike','web_editor.%'),('model','not ilike','web_tour.%'),"
"('model','!=','mail.thread'),('model','not ilike','ks_dash%')]")
ks_model_name_2 = fields.Char(related='ks_model_id_2.model', readonly=True)
ks_record_field_2 = fields.Many2one('ir.model.fields',
domain="[('model_id','=',ks_model_id_2),('name','!=','id'),('name','!=','sequence'),('store','=',"
"True),'|','|',('ttype','=','integer'),('ttype','=','float'),('ttype',"
"'=','monetary')]",
string="Record Field")
ks_record_count_type_2 = fields.Selection([('count', 'Count'),
('sum', 'Sum'),
('average', 'Average')], string="Record Type", default="count")
ks_domain_2_temp = fields.Char(string="KPI Domain Substitute")
ks_domain_temp = fields.Char(string="Domain Substitute")
ks_background_color = fields.Char(default="#337ab7,0.99", string="Background Color")
ks_icon = fields.Binary(string="Icon", attachment=True)
ks_default_icon = fields.Char(string="Icon", default="bar-chart")
ks_default_icon_color = fields.Char(default="#ffffff,0.99", string="Icon Color")
ks_icon_select = fields.Char(string="Icon Option", default="Default")
ks_font_color = fields.Char(default="#ffffff,0.99", string="Font Color")
ks_dashboard_item_theme = fields.Char(default="white", string="Theme")
ks_layout = fields.Selection([('layout1', 'Layout 1'),
('layout2', 'Layout 2'),
('layout3', 'Layout 3'),
('layout4', 'Layout 4'),
('layout5', 'Layout 5'),
('layout6', 'Layout 6'),
], default=('layout1'), required=True, string="Layout")
ks_preview = fields.Integer(default=1, string="Preview")
ks_model_name = fields.Char(related='ks_model_id.model', readonly=True)
ks_many2many_field_ordering = fields.Char()
ks_record_count_type = fields.Selection([('count', 'Count'),
('sum', 'Sum'),
('average', 'Average')], string="Record Count Type", default="count")
ks_record_count = fields.Float(string="Record Count", compute='ks_get_record_count', readonly=True)
ks_record_field = fields.Many2one('ir.model.fields',
domain="[('model_id','=',ks_model_id),('name','!=','id'),('name','!=','sequence'),('store','=',True),"
"'|','|',('ttype','=','integer'),('ttype','=','float'),('ttype','=',"
"'monetary')]",
string="Record Field")
ks_date_filter_selection = fields.Selection([
('l_none', 'None'),
('l_day', 'Today'),
('t_week', 'This Week'),
('t_month', 'This Month'),
('t_quarter', 'This Quarter'),
('t_year', 'This Year'),
('n_day', 'Next Day'),
('n_week', 'Next Week'),
('n_month', 'Next Month'),
('n_quarter', 'Next Quarter'),
('n_year', 'Next Year'),
('ls_day', 'Last Day'),
('ls_week', 'Last Week'),
('ls_month', 'Last Month'),
('ls_quarter', 'Last Quarter'),
('ls_year', 'Last Year'),
('l_week', 'Last 7 days'),
('l_month', 'Last 30 days'),
('l_quarter', 'Last 90 days'),
('l_year', 'Last 365 days'),
('ls_past_until_now', 'Past Till Now'),
('ls_pastwithout_now', ' Past Excluding Today'),
('n_future_starting_now', 'Future Starting Now'),
('n_futurestarting_tomorrow', 'Future Starting Tomorrow'),
('l_custom', 'Custom Filter'),
], string="Date Filter Selection", default="l_none", required=True)
ks_date_filter_field = fields.Many2one('ir.model.fields',
domain="[('model_id','=',ks_model_id),('store','=',True),'|',('ttype','=','date'),"
"('ttype','=','datetime')]",
string="Date Filter Field")
ks_item_start_date = fields.Datetime(string="Start Date")
ks_item_end_date = fields.Datetime(string="End Date")
ks_date_filter_field_2 = fields.Many2one('ir.model.fields',
domain="[('model_id','=',ks_model_id_2),('store','=',True),'|',('ttype','=','date'),"
"('ttype','=','datetime')]",
string="Date Filter Field")
ks_item_start_date_2 = fields.Datetime(string="Start Date")
ks_item_end_date_2 = fields.Datetime(string="End Date")
ks_domain_2 = fields.Char(string="Domain")
ks_date_filter_selection_2 = fields.Selection([
('l_none', "None"),
('l_day', 'Today'),
('t_week', 'This Week'),
('t_month', 'This Month'),
('t_quarter', 'This Quarter'),
('t_year', 'This Year'),
('n_day', 'Next Day'),
('n_week', 'Next Week'),
('n_month', 'Next Month'),
('n_quarter', 'Next Quarter'),
('n_year', 'Next Year'),
('ls_day', 'Last Day'),
('ls_week', 'Last Week'),
('ls_month', 'Last Month'),
('ls_quarter', 'Last Quarter'),
('ls_year', 'Last Year'),
('l_week', 'Last 7 days'),
('l_month', 'Last 30 days'),
('l_quarter', 'Last 90 days'),
('l_year', 'Last 365 days'),
('ls_past_until_now', 'Past Till Now'),
('ls_pastwithout_now', ' Past Excluding Today'),
('n_future_starting_now', 'Future Starting Now'),
('n_futurestarting_tomorrow', 'Future Starting Tomorrow'),
('l_custom', 'Custom Filter'),
], string="Date Filter Selection", required=True, default='l_none')
ks_previous_period = fields.Boolean(string="Previous Period")
# Pro Fields
ks_dashboard_ninja_board_id = fields.Many2one('ks_dashboard_ninja.board',
default=lambda self: self._context[
'ks_dashboard_id'] if 'ks_dashboard_id' in self._context else False)
# Chart related fields
ks_dashboard_item_type = fields.Selection([('ks_tile', 'Tile'),
('ks_bar_chart', 'Bar Chart'),
('ks_horizontalBar_chart', 'Horizontal Bar Chart'),
('ks_line_chart', 'Line Chart'),
('ks_area_chart', 'Area Chart'),
('ks_pie_chart', 'Pie Chart'),
('ks_doughnut_chart', 'Doughnut Chart'),
('ks_polarArea_chart', 'Polar Area Chart'),
('ks_list_view', 'List View'),
('ks_kpi', 'KPI'),
], default=lambda self: self._context.get('ks_dashboard_item_type',
'ks_tile'), required=True,
string="Dashboard Item Type")
ks_chart_groupby_type = fields.Char(compute='get_chart_groupby_type')
ks_chart_relation_groupby = fields.Many2one('ir.model.fields',
domain="[('model_id','=',ks_model_id),('name','!=','id'),('name','!=','sequence'),('store','=',True),"
"('ttype','!=','binary'),('ttype','!=','many2many'), ('ttype','!=','one2many')]",
string="Group By")
ks_chart_relation_sub_groupby = fields.Many2one('ir.model.fields',
domain="[('model_id','=',ks_model_id),('name','!=','id'),('name','!=','sequence'),('store','=',True),"
"('ttype','!=','binary'),('ttype','!=','many2many'), ('ttype','!=','one2many')]",
string=" Sub Group By")
ks_chart_date_sub_groupby = fields.Selection([('minute', 'Minute'),
('hour', 'Hour'),
('day', 'Day'),
('week', 'Week'),
('month', 'Month'),
('quarter', 'Quarter'),
('year', 'Year'),
], string="Sub Group By Date")
ks_chart_date_groupby = fields.Selection([('minute', 'Minute'),
('hour', 'Hour'),
('day', 'Day'),
('week', 'Week'),
('month', 'Month'),
('quarter', 'Quarter'),
('year', 'Year'),
('month_year', 'Month-Year'),
], string=" Group By Date")
ks_graph_preview = fields.Char(string="Preview", default="Graph Preview")
ks_chart_data = fields.Char(string="Chart Data in string form", compute='ks_get_chart_data')
ks_chart_data_count_type = fields.Selection([('count', 'Count'), ('sum', 'Sum'), ('average', 'Average')],
string="Data Type", default="sum")
ks_chart_sub_groupby_type = fields.Char(compute='get_chart_sub_groupby_type')
ks_chart_measure_field = fields.Many2many('ir.model.fields', 'ks_dn_measure_field_rel', 'measure_field_id',
'field_id',
domain="[('model_id','=',ks_model_id),('name','!=','id'),('name','!=','sequence'),('store','=',"
"True),'|','|', "
"('ttype','=','integer'),('ttype','=','float'),"
"('ttype','=','monetary')]",
string="Measures")
ks_chart_measure_field_2 = fields.Many2many('ir.model.fields', 'ks_dn_measure_field_rel_2', 'measure_field_id_2',
'field_id',
domain="[('model_id','=',ks_model_id),('name','!=','id'),('name','!=','sequence'),('store',"
"'=',True),'|','|', "
"('ttype','=','integer'),('ttype','=','float'),"
"('ttype','=','monetary')]",
string="Line Measure")
ks_bar_chart_stacked = fields.Boolean(string="Stacked Bar Chart")
ks_sort_by_field = fields.Many2one('ir.model.fields',
domain="[('model_id','=',ks_model_id),('name','!=','id'),('name','!=','sequence'),('store','=',True),"
"('ttype','!=','one2many'),('ttype','!=','binary')]",
string="Sort By Field")
ks_sort_by_order = fields.Selection([('ASC', 'Ascending'), ('DESC', 'Descending')],
string="Sort Order")
ks_record_data_limit = fields.Integer(string="Record Limit")
ks_list_view_preview = fields.Char(string="List View Preview", default="List View Preview")
ks_kpi_preview = fields.Char(string="Preview", default="KPI Preview")
ks_kpi_type = fields.Selection([
('layout_1', 'KPI With Target'),
('layout_2', 'Data Comparison'),
], string="Layout", default="layout_1")
ks_target_view = fields.Char(string="View", default="Number")
ks_data_comparison = fields.Char(string="Data Type", default="None")
ks_kpi_data = fields.Char(string="KPI Data", compute="ks_get_kpi_data")
ks_chart_item_color = fields.Selection(
[('default', 'Default'), ('cool', 'Cool'), ('warm', 'Warm'), ('neon', 'Neon')],
string="Chart Color Palette", default="default")
# ------------------------ List View Fields ------------------------------
ks_list_view_type = fields.Selection([('ungrouped', 'Un-Grouped'), ('grouped', 'Grouped')], default="ungrouped",
string="List View Type", required=True)
ks_list_view_fields = fields.Many2many('ir.model.fields', 'ks_dn_list_field_rel', 'list_field_id', 'field_id',
domain="[('model_id','=',ks_model_id),('store','=',True),"
"('ttype','!=','one2many'),('ttype','!=','many2many'),('ttype',"
"'!=','binary')]",
string="Fields to show in list")
ks_list_view_group_fields = fields.Many2many('ir.model.fields', 'ks_dn_list_group_field_rel', 'list_field_id',
'field_id',
domain="[('model_id','=',ks_model_id),('name','!=','id'),('name','!=','sequence'),('store',"
"'=',True),'|','|', "
"('ttype','=','integer'),('ttype','=','float'),"
"('ttype','=','monetary')]",
string="List View Grouped Fields")
ks_list_view_data = fields.Char(string="List View Data in JSon", compute='ks_get_list_view_data')
# -------------------- Multi Company Feature ---------------------
ks_company_id = fields.Many2one('res.company', string='Company', default=lambda self: self.env.user.company_id)
ks_semi_circle_chart = fields.Boolean(string='Semi Circle Chart')
# -------------------- Target Company Feature ---------------------
ks_goal_enable = fields.Boolean(string="Enable Target")
ks_goal_bar_line = fields.Boolean(string="Show Target As Line")
ks_standard_goal_value = fields.Float(string="Standard Target")
ks_goal_lines = fields.One2many('ks_dashboard_ninja.item_goal', 'ks_dashboard_item', string="Target Lines")
ks_list_target_deviation_field = fields.Many2one('ir.model.fields', 'list_field_id',
domain="[('model_id','=',ks_model_id),('name','!=','id'),('name','!=','sequence'),"
"('store','=',True),'|','|',"
"('ttype','=','integer'),('ttype','=','float'),"
"('ttype','=','monetary')]", )
ks_compare_period = fields.Integer(string="Include Period")
ks_year_period = fields.Integer(string="Same Period Previous Years")
ks_compare_period_2 = fields.Integer(string="KPI Include Period")
ks_year_period_2 = fields.Integer(string="KPI Same Period Previous Years")
# ------------------------------------ Chart display props. TODO : Merge all these fields into one and show a widget to get output for these fields from JS
ks_show_data_value = fields.Boolean(string="Show Data Value")
ks_action_lines = fields.One2many('ks_dashboard_ninja.item_action', 'ks_dashboard_item_id', string="Action Lines")
ks_actions = fields.Many2one('ir.actions.act_window', domain="[('res_model','=',ks_model_name)]",
string="Actions")
ks_record_count_2 = fields.Float(string="KPI Record Count", readonly=True)
# Adding refresh per item override global update interval
ks_update_items_data = fields.Selection([
(15000, '15 Seconds'),
(30000, '30 Seconds'),
(45000, '45 Seconds'),
(60000, '1 minute'),
(120000, '2 minute'),
(300000, '5 minute'),
(600000, '10 minute'),
], string="Set Update Interval", default=lambda self: self._context.get('ks_set_interval', False))
@api.multi
def copy_data(self, default=None):
if default is None:
default = {}
if 'ks_action_lines' not in default:
default['ks_action_lines'] = [(0, 0, line.copy_data()[0]) for line in self.ks_action_lines]
if 'ks_goal_lines' not in default:
default['ks_goal_lines'] = [(0, 0, line.copy_data()[0]) for line in self.ks_goal_lines]
return super(KsDashboardNinjaItems, self).copy_data(default)
@api.model
def create(self, values):
""" Override to save list view fields ordering """
if values.get('ks_list_view_fields', False) and values.get('ks_list_view_group_fields', False):
ks_many2many_field_ordering = {
'ks_list_view_fields': values['ks_list_view_fields'][0][2],
'ks_list_view_group_fields': values['ks_list_view_group_fields'][0][2],
}
values['ks_many2many_field_ordering'] = json.dumps(ks_many2many_field_ordering)
return super(KsDashboardNinjaItems, self).create(
values)
# User can select custom units for measure
ks_unit = fields.Boolean(string="Show Custom Unit", default=False)
ks_unit_selection = fields.Selection([
('monetary', 'Monetary'),
('custom', 'Custom'),
], string="Select Unit Type")
ks_chart_unit = fields.Char(string="Enter Unit", size=5, default="",
help="Maximum limit 5 characters, for ex: km, m")
# User can stop propagation of the tile item
ks_show_records = fields.Boolean(string="Show Records", default=True, help="""This field Enable the click on
Dashboard Items to view the Odoo
default view of records""")
# Domain Extension field
ks_domain_extension = fields.Char('Domain Extension')
ks_domain_extension_2 = fields.Char('KPI Domain Extension')
# hide legend
ks_hide_legend = fields.Boolean('Show Legend', help="Hide all legend from the chart item", default=True)
@api.multi
def copy_data(self, default=None):
if default is None:
default = {}
if 'ks_action_lines' not in default:
default['ks_action_lines'] = [(0, 0, line.copy_data()[0]) for line in self.ks_action_lines]
if 'ks_goal_lines' not in default:
default['ks_goal_lines'] = [(0, 0, line.copy_data()[0]) for line in self.ks_goal_lines]
return super(KsDashboardNinjaItems, self).copy_data(default)
@api.model
def create(self, values):
""" Override to save list view fields ordering """
if values.get('ks_list_view_fields', False) and values.get('ks_list_view_group_fields', False):
ks_many2many_field_ordering = {
'ks_list_view_fields': values['ks_list_view_fields'][0][2],
'ks_list_view_group_fields': values['ks_list_view_group_fields'][0][2],
}
values['ks_many2many_field_ordering'] = json.dumps(ks_many2many_field_ordering)
return super(KsDashboardNinjaItems, self).create(
values)
@api.multi
def write(self, values):
for rec in self:
if rec['ks_many2many_field_ordering']:
ks_many2many_field_ordering = json.loads(rec['ks_many2many_field_ordering'])
else:
ks_many2many_field_ordering = {}
if values.get('ks_list_view_fields', False):
ks_many2many_field_ordering['ks_list_view_fields'] = values['ks_list_view_fields'][0][2]
if values.get('ks_list_view_group_fields', False):
ks_many2many_field_ordering['ks_list_view_group_fields'] = values['ks_list_view_group_fields'][0][2]
values['ks_many2many_field_ordering'] = json.dumps(ks_many2many_field_ordering)
return super(KsDashboardNinjaItems, self).write(
values)
@api.multi
def write(self, values):
for rec in self:
if rec['ks_many2many_field_ordering']:
ks_many2many_field_ordering = json.loads(rec['ks_many2many_field_ordering'])
else:
ks_many2many_field_ordering = {}
if values.get('ks_list_view_fields', False):
ks_many2many_field_ordering['ks_list_view_fields'] = values['ks_list_view_fields'][0][2]
if values.get('ks_list_view_group_fields', False):
ks_many2many_field_ordering['ks_list_view_group_fields'] = values['ks_list_view_group_fields'][0][2]
values['ks_many2many_field_ordering'] = json.dumps(ks_many2many_field_ordering)
return super(KsDashboardNinjaItems, self).write(
values)
@api.multi
@api.onchange('ks_goal_lines')
def ks_date_target_line(self):
for rec in self:
if rec.ks_chart_date_groupby in ('minute', 'hour') or rec.ks_chart_date_sub_groupby in ('minute', 'hour'):
rec.ks_goal_lines = False
return {'warning': {
'title': _('Groupby Field aggregation'),
'message': _('Cannot create target lines when Group By Date field is set to have aggregation in '
'Minute and Hour case.')
}}
@api.multi
@api.onchange('ks_chart_date_groupby', 'ks_chart_date_sub_groupby')
def ks_date_target(self):
for rec in self:
if (rec.ks_chart_date_groupby in ('minute', 'hour') or rec.ks_chart_date_sub_groupby in ('minute', 'hour')) \
and rec.ks_goal_enable and rec.ks_goal_lines:
raise ValidationError(_("Cannot set aggregation having Date time (Hour, Minute) when target lines are "
"being used. "
" To proceed this, first delete target lines"))
@api.multi
def name_get(self):
res = []
for rec in self:
name = rec.name
if not name:
name = rec.ks_model_id.name
res.append((rec.id, name))
return res
@api.onchange('ks_layout')
def layout_four_font_change(self):
if self.ks_dashboard_item_theme != "white":
if self.ks_layout == 'layout4':
self.ks_font_color = self.ks_background_color
self.ks_default_icon_color = "#ffffff,0.99"
elif self.ks_layout == 'layout6':
self.ks_font_color = "#ffffff,0.99"
self.ks_default_icon_color = self.ks_get_dark_color(self.ks_background_color.split(',')[0],
self.ks_background_color.split(',')[1])
else:
self.ks_default_icon_color = "#ffffff,0.99"
self.ks_font_color = "#ffffff,0.99"
else:
if self.ks_layout == 'layout4':
self.ks_background_color = "#00000,0.99"
self.ks_font_color = self.ks_background_color
self.ks_default_icon_color = "#ffffff,0.99"
else:
self.ks_background_color = "#ffffff,0.99"
self.ks_font_color = "#00000,0.99"
self.ks_default_icon_color = "#00000,0.99"
# To convert color into 10% darker. Percentage amount is hardcoded. Change amt if want to change percentage.
def ks_get_dark_color(self, color, opacity):
num = int(color[1:], 16)
amt = -25
R = (num >> 16) + amt
R = (255 if R > 255 else 0 if R < 0 else R) * 0x10000
G = (num >> 8 & 0x00FF) + amt
G = (255 if G > 255 else 0 if G < 0 else G) * 0x100
B = (num & 0x0000FF) + amt
B = (255 if B > 255 else 0 if B < 0 else B)
return "#" + hex(0x1000000 + R + G + B).split('x')[1][1:] + "," + opacity
@api.onchange('ks_model_id')
def make_record_field_empty(self):
for rec in self:
rec.ks_record_field = False
rec.ks_domain = False
rec.ks_date_filter_field = False
# To show "created on" by default on date filter field on model select.
if rec.ks_model_id:
datetime_field_list = rec.ks_date_filter_field.search(
[('model_id', '=', rec.ks_model_id.id), '|', ('ttype', '=', 'date'),
('ttype', '=', 'datetime')]).read(['id', 'name'])
for field in datetime_field_list:
if field['name'] == 'create_date':
rec.ks_date_filter_field = field['id']
else:
rec.ks_date_filter_field = False
# Pro
rec.ks_record_field = False
rec.ks_chart_measure_field = False
rec.ks_chart_measure_field_2 = False
rec.ks_chart_relation_sub_groupby = False
rec.ks_chart_relation_groupby = False
rec.ks_chart_date_sub_groupby = False
rec.ks_chart_date_groupby = False
rec.ks_sort_by_field = False
rec.ks_sort_by_order = False
rec.ks_record_data_limit = False
rec.ks_list_view_fields = False
rec.ks_list_view_group_fields = False
rec.ks_action_lines = False
rec.ks_actions = False
rec.ks_domain_extension = False
@api.onchange('ks_record_count', 'ks_layout', 'name', 'ks_model_id', 'ks_domain', 'ks_icon_select',
'ks_default_icon', 'ks_icon',
'ks_background_color', 'ks_font_color', 'ks_default_icon_color')
def ks_preview_update(self):
self.ks_preview += 1
@api.onchange('ks_dashboard_item_theme')
def change_dashboard_item_theme(self):
if self.ks_dashboard_item_theme == "red":
self.ks_background_color = "#d9534f,0.99"
self.ks_default_icon_color = "#ffffff,0.99"
self.ks_font_color = "#ffffff,0.99"
elif self.ks_dashboard_item_theme == "blue":
self.ks_background_color = "#337ab7,0.99"
self.ks_default_icon_color = "#ffffff,0.99"
self.ks_font_color = "#ffffff,0.99"
elif self.ks_dashboard_item_theme == "yellow":
self.ks_background_color = "#f0ad4e,0.99"
self.ks_default_icon_color = "#ffffff,0.99"
self.ks_font_color = "#ffffff,0.99"
elif self.ks_dashboard_item_theme == "green":
self.ks_background_color = "#5cb85c,0.99"
self.ks_default_icon_color = "#ffffff,0.99"
self.ks_font_color = "#ffffff,0.99"
elif self.ks_dashboard_item_theme == "white":
if self.ks_layout == 'layout4':
self.ks_background_color = "#00000,0.99"
self.ks_default_icon_color = "#ffffff,0.99"
else:
self.ks_background_color = "#ffffff,0.99"
self.ks_default_icon_color = "#000000,0.99"
self.ks_font_color = "#000000,0.99"
if self.ks_layout == 'layout4':
self.ks_font_color = self.ks_background_color
elif self.ks_layout == 'layout6':
self.ks_default_icon_color = self.ks_get_dark_color(self.ks_background_color.split(',')[0],
self.ks_background_color.split(',')[1])
if self.ks_dashboard_item_theme == "white":
self.ks_default_icon_color = "#000000,0.99"
@api.multi
@api.depends('ks_record_count_type', 'ks_model_id', 'ks_domain', 'ks_record_field', 'ks_date_filter_field',
'ks_item_end_date', 'ks_item_start_date', 'ks_compare_period', 'ks_year_period',
'ks_dashboard_item_type', 'ks_domain_extension', 'ks_record_data_limit')
def ks_get_record_count(self):
for rec in self:
if rec.ks_record_count_type == 'count' or rec.ks_dashboard_item_type == 'ks_list_view':
rec.ks_record_count = rec.ks_fetch_model_data(rec.ks_model_name, rec.ks_domain, 'search_count', rec)
elif rec.ks_record_count_type in ['sum', 'average'] and \
rec.ks_record_field and rec.ks_dashboard_item_type != 'ks_list_view':
ks_records_grouped_data = rec.ks_fetch_model_data(rec.ks_model_name, rec.ks_domain, 'read_group', rec)
if ks_records_grouped_data and len(ks_records_grouped_data) > 0:
ks_records_grouped_data = ks_records_grouped_data[0]
if rec.ks_record_count_type == 'sum' and ks_records_grouped_data.get('__count', False) and (
ks_records_grouped_data.get(rec.ks_record_field.name)):
rec.ks_record_count = ks_records_grouped_data.get(rec.ks_record_field.name, 0)
elif rec.ks_record_count_type == 'average' and ks_records_grouped_data.get(
'__count', False) and (ks_records_grouped_data.get(rec.ks_record_field.name)):
rec.ks_record_count = ks_records_grouped_data.get(rec.ks_record_field.name,
0) / ks_records_grouped_data.get('__count',
1)
else:
rec.ks_record_count = 0
else:
rec.ks_record_count = 0
else:
rec.ks_record_count = 0
# Writing separate function to fetch dashboard item data
def ks_fetch_model_data(self, ks_model_name, ks_domain, ks_func, rec):
data = 0
try:
if ks_domain and ks_domain != '[]' and ks_model_name:
proper_domain = self.ks_convert_into_proper_domain(ks_domain, rec)
if ks_func == 'search_count':
if rec.ks_dashboard_item_type == "ks_list_view" and rec.ks_record_data_limit:
data = self.env[ks_model_name].search_count(proper_domain, limit=rec.ks_record_data_limit)
else:
data = self.env[ks_model_name].search_count(proper_domain)
elif ks_func == 'read_group':
data = self.env[ks_model_name].read_group(proper_domain, [rec.ks_record_field.name], [])
elif ks_model_name:
# Have to put extra if condition here because on load,model giving False value
proper_domain = self.ks_convert_into_proper_domain(False, rec)
if ks_func == 'search_count':
if rec.ks_dashboard_item_type == "ks_list_view" and rec.ks_record_data_limit:
data = self.env[ks_model_name].search_count(proper_domain, limit=rec.ks_record_data_limit)
else:
data = self.env[ks_model_name].search_count(proper_domain)
elif ks_func == 'read_group':
data = self.env[ks_model_name].read_group(proper_domain, [rec.ks_record_field.name], [])
else:
return []
except Exception as e:
return []
return data
def ks_convert_into_proper_domain(self, ks_domain, rec):
if ks_domain and "%UID" in ks_domain:
ks_domain = ks_domain.replace('"%UID"', str(self.env.user.id))
if ks_domain and "%MYCOMPANY" in ks_domain:
ks_domain = ks_domain.replace('"%MYCOMPANY"', str(self.env.user.company_id.id))
ks_date_domain = False
if rec.ks_date_filter_field:
if not rec.ks_date_filter_selection or rec.ks_date_filter_selection == "l_none":
selected_start_date = self._context.get('ksDateFilterStartDate', False)
selected_end_date = self._context.get('ksDateFilterEndDate', False)
if selected_end_date and not selected_start_date:
ks_date_domain = [
(rec.ks_date_filter_field.name, "<=",
selected_end_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT))]
elif selected_start_date and not selected_end_date:
ks_date_domain = [
(rec.ks_date_filter_field.name, ">=",
selected_start_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT))]
else:
if selected_end_date and selected_start_date:
ks_date_domain = [
(rec.ks_date_filter_field.name, ">=",
selected_start_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT)),
(rec.ks_date_filter_field.name, "<=",
selected_end_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT))]
else:
if rec.ks_date_filter_selection and rec.ks_date_filter_selection != 'l_custom':
ks_date_data = ks_get_date(rec.ks_date_filter_selection, self)
selected_start_date = ks_date_data["selected_start_date"]
selected_end_date = ks_date_data["selected_end_date"]
else:
selected_start_date = rec.ks_item_start_date
selected_end_date = rec.ks_item_end_date
if selected_start_date and selected_end_date:
if rec.ks_compare_period:
selected_start_date = fields.datetime.strptime(rec.ks_item_start_date,
DEFAULT_SERVER_DATETIME_FORMAT)
selected_end_date = fields.datetime.strptime(rec.ks_item_end_date,
DEFAULT_SERVER_DATETIME_FORMAT)
ks_compare_period = abs(rec.ks_compare_period)
if ks_compare_period > 100:
ks_compare_period = 100
if rec.ks_compare_period > 0:
selected_end_date = selected_end_date + (
selected_end_date - selected_start_date) * ks_compare_period
elif rec.ks_compare_period < 0:
selected_start_date = selected_start_date - (
selected_end_date - selected_start_date) * ks_compare_period
if rec.ks_year_period and rec.ks_year_period != 0 and rec.ks_dashboard_item_type:
abs_year_period = abs(rec.ks_year_period)
sign_yp = rec.ks_year_period / abs_year_period
if abs_year_period > 100:
abs_year_period = 100
date_field_name = rec.ks_date_filter_field.name
ks_date_domain = ['&', (date_field_name, ">=",
fields.datetime.strftime(selected_start_date,
DEFAULT_SERVER_DATETIME_FORMAT)),
(date_field_name, "<=",
fields.datetime.strftime(selected_end_date, DEFAULT_SERVER_DATETIME_FORMAT))]
for p in range(1, abs_year_period + 1):
ks_date_domain.insert(0, '|')
ks_date_domain.extend(['&', (date_field_name, ">=", fields.datetime.strftime(
selected_start_date - relativedelta.relativedelta(years=p) * sign_yp,
DEFAULT_SERVER_DATETIME_FORMAT)),
(date_field_name, "<=", fields.datetime.strftime(
selected_end_date - relativedelta.relativedelta(years=p)
* sign_yp, DEFAULT_SERVER_DATETIME_FORMAT))])
else:
selected_start_date = fields.datetime.strftime(selected_start_date,
DEFAULT_SERVER_DATETIME_FORMAT) if \
type(selected_start_date).__name__ == 'datetime' else selected_start_date
selected_end_date = fields.datetime.strftime(selected_end_date, DEFAULT_SERVER_DATETIME_FORMAT) \
if type(selected_end_date).__name__ == 'datetime' else selected_end_date
ks_date_domain = [(rec.ks_date_filter_field.name, ">=", selected_start_date),
(rec.ks_date_filter_field.name, "<=", selected_end_date)]
elif selected_start_date and not selected_end_date:
selected_start_date = fields.datetime.strftime(selected_start_date, DEFAULT_SERVER_DATETIME_FORMAT) \
if type(selected_start_date).__name__ == 'datetime' else selected_start_date
ks_date_domain = [(rec.ks_date_filter_field.name, ">=", selected_start_date)]
elif selected_end_date and not selected_start_date:
selected_end_date = fields.datetime.strftime(selected_end_date, DEFAULT_SERVER_DATETIME_FORMAT) \
if type(selected_end_date).__name__ == 'datetime' else selected_end_date
ks_date_domain = [(rec.ks_date_filter_field.name, "<=", selected_end_date)]
else:
ks_date_domain = []
proper_domain = safe_eval(ks_domain) if ks_domain else []
if ks_date_domain:
proper_domain.extend(ks_date_domain)
if rec.ks_domain_extension:
ks_domain_extension = rec.ks_convert_domain_extension(rec.ks_domain_extension, rec)
proper_domain.extend(ks_domain_extension)
return proper_domain
def ks_convert_domain_extension(self, ks_extensiom_domain, rec):
if ks_extensiom_domain and "%UID" in ks_extensiom_domain:
ks_extensiom_domain = ks_extensiom_domain.replace("%UID", str(self.env.user.id))
if ks_extensiom_domain and "%MYCOMPANY" in ks_extensiom_domain:
ks_extensiom_domain = ks_extensiom_domain.replace("%MYCOMPANY",
str(self.env.user.company_id.id))
ks_domain = safe_eval(ks_extensiom_domain)
return ks_domain
@api.onchange('ks_domain_extension')
def ks_onchange_domain_extension(self):
if self.ks_domain_extension:
proper_domain = []
try:
ks_domain_extension = self.ks_domain_extension
if "%UID" in ks_domain_extension:
ks_domain_extension = ks_domain_extension.replace("%UID", str(self.env.user.id))
if "%MYCOMPANY" in ks_domain_extension:
ks_domain_extension = ks_domain_extension.replace("%MYCOMPANY", str(self.env.user.company_id.id))
self.env[self.ks_model_name].search_count(safe_eval(ks_domain_extension))
except Exception:
raise ValidationError(
"Domain Extension Syntax is wrong. \nProper Syntax Example :[['<field_name'>,'<operator>',"
"'<value_to_compare>']]")
@api.constrains('ks_domain_extension')
def ks_check_domain_extension(self):
if self.ks_domain_extension:
proper_domain = []
try:
ks_domain_extension = self.ks_domain_extension
if "%UID" in ks_domain_extension:
ks_domain_extension = ks_domain_extension.replace("%UID", str(self.env.user.id))
if "%MYCOMPANY" in ks_domain_extension:
ks_domain_extension = ks_domain_extension.replace("%MYCOMPANY", str(self.env.user.company_id.id))
self.env[self.ks_model_name].search_count(safe_eval(ks_domain_extension))
except Exception:
raise ValidationError(
"Domain Extension Syntax is wrong. \nProper Syntax Example :[['<field_name'>,'<operator>',"
"'<value_to_compare>']]")
@api.onchange('ks_domain_extension_2')
def ks_onchange_domain_extension_2(self):
if self.ks_domain_extension_2:
proper_domain = []
try:
ks_domain_extension = self.ks_domain_extension_2
if "%UID" in ks_domain_extension:
ks_domain_extension = ks_domain_extension.replace("%UID", str(self.env.user.id))
if "%MYCOMPANY" in ks_domain_extension:
ks_domain_extension = ks_domain_extension.replace("%MYCOMPANY", str(self.env.user.company_id.id))
self.env[self.ks_model_name].search_count(safe_eval(ks_domain_extension))
except Exception:
raise ValidationError(
"Domain Extension Syntax is wrong. \nProper Syntax Example :[['<field_name'>,'<operator>',"
"'<value_to_compare>']]")
@api.constrains('ks_domain_extension_2')
def ks_check_domain_extension_2(self):
if self.ks_domain_extension:
proper_domain = []
try:
ks_domain_extension = self.ks_domain_extension
if "%UID" in ks_domain_extension:
ks_domain_extension = ks_domain_extension.replace("%UID", str(self.env.user.id))
if "%MYCOMPANY" in ks_domain_extension:
ks_domain_extension = ks_domain_extension.replace("%MYCOMPANY", str(self.env.user.company_id.id))
self.env[self.ks_model_name].search_count(safe_eval(ks_domain_extension))
except Exception:
raise ValidationError(
"Domain Extension Syntax is wrong. \nProper Syntax Example :[['<field_name'>,'<operator>',"
"'<value_to_compare>']]")
@api.onchange('ks_list_view_fields')
def ks_set_list_view_fields_order(self):
for rec in self:
order = [res.id for res in rec.ks_list_view_fields]
if rec.ks_many2many_field_ordering:
ks_many2many_field_ordering = json.loads(rec.ks_many2many_field_ordering)
else:
ks_many2many_field_ordering = {}
ks_many2many_field_ordering['ks_list_view_fields'] = order
rec.ks_many2many_field_ordering = json.dumps(ks_many2many_field_ordering)
@api.onchange('ks_list_view_group_fields')
def ks_set_list_view_group_fields_order(self):
for rec in self:
order = [res.id for res in rec.ks_list_view_group_fields]
if rec.ks_many2many_field_ordering:
ks_many2many_field_ordering = json.loads(rec.ks_many2many_field_ordering)
else:
ks_many2many_field_ordering = {}
ks_many2many_field_ordering['ks_list_view_group_fields'] = order
rec.ks_many2many_field_ordering = json.dumps(ks_many2many_field_ordering)
@api.multi
@api.onchange('ks_chart_relation_groupby')
def get_chart_groupby_type(self):
for rec in self:
if rec.ks_chart_relation_groupby.ttype == 'datetime' or rec.ks_chart_relation_groupby.ttype == 'date':
rec.ks_chart_groupby_type = 'date_type'
elif rec.ks_chart_relation_groupby.ttype == 'many2one':
rec.ks_chart_groupby_type = 'relational_type'
rec.ks_chart_date_groupby = False
elif rec.ks_chart_relation_groupby.ttype == 'selection':
rec.ks_chart_groupby_type = 'selection'
rec.ks_chart_date_groupby = False
else:
rec.ks_chart_groupby_type = 'other'
@api.onchange('ks_chart_relation_groupby')
def ks_empty_sub_group_by(self):
for rec in self:
if not rec.ks_chart_relation_groupby or rec.ks_chart_groupby_type == "date_type" \
and not rec.ks_chart_date_groupby:
rec.ks_chart_relation_sub_groupby = False
rec.ks_chart_date_sub_groupby = False
@api.depends('ks_chart_relation_sub_groupby')
def get_chart_sub_groupby_type(self):
for rec in self:
if rec.ks_chart_relation_sub_groupby.ttype == 'datetime' or \
rec.ks_chart_relation_sub_groupby.ttype == 'date':
rec.ks_chart_sub_groupby_type = 'date_type'
elif rec.ks_chart_relation_sub_groupby.ttype == 'many2one':
rec.ks_chart_sub_groupby_type = 'relational_type'
elif rec.ks_chart_relation_sub_groupby.ttype == 'selection':
rec.ks_chart_sub_groupby_type = 'selection'
else:
rec.ks_chart_sub_groupby_type = 'other'
# Using this function just to let js call rpc to load some data later
@api.model
def ks_chart_load(self):
return True
@api.multi
@api.depends('ks_chart_measure_field', 'ks_chart_relation_groupby', 'ks_chart_date_groupby', 'ks_domain',
'ks_dashboard_item_type', 'ks_model_id', 'ks_sort_by_field', 'ks_sort_by_order',
'ks_record_data_limit', 'ks_chart_data_count_type', 'ks_chart_measure_field_2', 'ks_goal_enable',
'ks_standard_goal_value', 'ks_goal_bar_line', 'ks_chart_relation_sub_groupby',
'ks_chart_date_sub_groupby', 'ks_date_filter_field', 'ks_item_start_date', 'ks_item_end_date',
'ks_compare_period', 'ks_year_period', 'ks_unit', 'ks_unit_selection', 'ks_chart_unit',
'ks_domain_extension')
def ks_get_chart_data(self):
for rec in self:
if rec.ks_dashboard_item_type and rec.ks_dashboard_item_type != 'ks_tile' and \
rec.ks_dashboard_item_type != 'ks_list_view' and rec.ks_model_id and rec.ks_chart_data_count_type:
ks_chart_data = {'labels': [], 'datasets': [], 'ks_currency': 0, 'ks_field': "", 'ks_selection': "",
'ks_show_second_y_scale': False, 'domains': [], }
ks_chart_measure_field = []
ks_chart_measure_field_with_type = []
ks_chart_measure_field_ids = []
ks_chart_measure_field_2 = []
ks_chart_measure_field_with_type_2 = []
ks_chart_measure_field_2_ids = []
if rec.ks_unit and rec.ks_unit_selection == 'monetary':
ks_chart_data['ks_selection'] += rec.ks_unit_selection
ks_chart_data['ks_currency'] += rec.env.user.company_id.currency_id.id
elif rec.ks_unit and rec.ks_unit_selection == 'custom':
ks_chart_data['ks_selection'] += rec.ks_unit_selection
if rec.ks_chart_unit:
ks_chart_data['ks_field'] += rec.ks_chart_unit
# If count chart data type:
if rec.ks_chart_data_count_type == "count":
rec.ks_chart_measure_field = False
rec.ks_chart_measure_field_2 = False
ks_chart_measure_field_with_type.append('count:count(id)')
ks_chart_data['datasets'].append({'data': [], 'label': "Count"})
else:
if rec.ks_dashboard_item_type == 'ks_bar_chart':
if rec.ks_chart_measure_field_2:
ks_chart_data['ks_show_second_y_scale'] = True
for res in rec.ks_chart_measure_field_2:
if rec.ks_chart_data_count_type == 'sum':
ks_data_count_type = 'sum'
elif rec.ks_chart_data_count_type == 'average':
ks_data_count_type = 'avg'
else:
raise ValidationError(_('Please chose any Data Type!'))
ks_chart_measure_field_2.append(res.name)
ks_chart_measure_field_with_type_2.append(res.name + ':' + ks_data_count_type)
ks_chart_measure_field_2_ids.append(res.id)
ks_chart_data['datasets'].append(
{'data': [], 'label': res.field_description, 'type': 'line', 'yAxisID': 'y-axis-1'})
for res in rec.ks_chart_measure_field:
if rec.ks_chart_data_count_type == 'sum':
ks_data_count_type = 'sum'
elif rec.ks_chart_data_count_type == 'average':
ks_data_count_type = 'avg'
else:
raise ValidationError(_('Please chose any Data Type!'))
ks_chart_measure_field_with_type.append(res.name + ':' + ks_data_count_type)
ks_chart_measure_field.append(res.name)
ks_chart_measure_field_ids.append(res.id)
ks_chart_data['datasets'].append({'data': [], 'label': res.field_description})
# ks_chart_measure_field = [res.name for res in rec.ks_chart_measure_field]
ks_chart_groupby_relation_field = rec.ks_chart_relation_groupby.name
ks_chart_domain = self.ks_convert_into_proper_domain(rec.ks_domain, rec)
ks_chart_data['previous_domain'] = ks_chart_domain
if rec.ks_chart_data_count_type == "count":
orderby = 'count'
else:
orderby = rec.ks_sort_by_field.name if rec.ks_sort_by_field else "id"
if rec.ks_sort_by_order:
orderby = orderby + " " + rec.ks_sort_by_order
limit = rec.ks_record_data_limit if rec.ks_record_data_limit and rec.ks_record_data_limit > 0 else False
if ((rec.ks_chart_data_count_type != "count" and ks_chart_measure_field) or (
rec.ks_chart_data_count_type == "count" and not ks_chart_measure_field)) and \
not rec.ks_chart_relation_sub_groupby:
if rec.ks_chart_relation_groupby.ttype == 'date' and rec.ks_chart_date_groupby in (
'minute', 'hour'):
raise ValidationError(_('Groupby field: {} cannot be aggregated by {}').format(
rec.ks_chart_relation_groupby.display_name, rec.ks_chart_date_groupby))
ks_chart_date_groupby = 'day' # when date_type doesn't have time
else:
if rec.ks_chart_date_groupby == 'month_year':
ks_chart_date_groupby = 'month'
else:
ks_chart_date_groupby = rec.ks_chart_date_groupby
if (rec.ks_chart_groupby_type == 'date_type' and rec.ks_chart_date_groupby) or\
rec.ks_chart_groupby_type != 'date_type':
ks_chart_data = rec.ks_fetch_chart_data(rec.ks_model_name, ks_chart_domain, ks_chart_measure_field_with_type, ks_chart_measure_field_with_type_2,
ks_chart_measure_field,
ks_chart_measure_field_2,
ks_chart_groupby_relation_field,
ks_chart_date_groupby,
rec.ks_chart_groupby_type, orderby, limit,
rec.ks_chart_data_count_type,
ks_chart_measure_field_ids,
ks_chart_measure_field_2_ids,
rec.ks_chart_relation_groupby.id, ks_chart_data)
if rec.ks_chart_groupby_type == 'date_type' and rec.ks_goal_enable and rec.ks_dashboard_item_type in [
'ks_bar_chart', 'ks_horizontalBar_chart', 'ks_line_chart',
'ks_area_chart'] and rec.ks_chart_groupby_type == "date_type":
ks_goal_labels = []
ks_goal_dataset = []
goal_dataset = []
if rec.ks_goal_lines and len(rec.ks_goal_lines) != 0:
if rec._context.get('current_id', False):
ks_item_id = rec._context['current_id']
else:
ks_item_id = rec.id
if rec.ks_date_filter_selection == "l_none":
selected_start_date = rec._context.get('ksDateFilterStartDate', False)
selected_end_date = rec._context.get('ksDateFilterEndDate', False)
else:
if rec.ks_date_filter_selection == "l_custom":
selected_start_date = rec.ks_item_start_date
selected_end_date = rec.ks_item_start_date
else:
ks_date_data = ks_get_date(rec.ks_date_filter_selection, self)
selected_start_date = ks_date_data["selected_start_date"]
selected_end_date = ks_date_data["selected_end_date"]
if selected_start_date and selected_end_date:
selected_start_date = selected_start_date.strftime('%Y-%m-%d')
selected_end_date = selected_end_date.strftime('%Y-%m-%d')
ks_goal_domain = [('ks_dashboard_item', '=', ks_item_id)]
if selected_start_date and selected_end_date:
ks_goal_domain.extend([('ks_goal_date', '>=', str(selected_start_date).split(" ")[0]),
('ks_goal_date', '<=', str(selected_end_date).split(" ")[0])])
ks_date_data = rec.ks_get_start_end_date(rec.ks_model_name,
ks_chart_groupby_relation_field,
rec.ks_chart_relation_groupby.ttype,
ks_chart_domain,
ks_goal_domain)
labels = []
if rec.ks_chart_date_groupby == 'month_year':
ks_chart_date_groupby = 'month'
else:
ks_chart_date_groupby = rec.ks_chart_date_groupby
if ks_date_data['start_date'] and ks_date_data['end_date']:
labels = self.generate_timeserise(ks_date_data['start_date'],
ks_date_data['end_date'],
ks_chart_date_groupby)
ks_goal_records = self.env['ks_dashboard_ninja.item_goal'].read_group(
ks_goal_domain, ['ks_goal_value', 'ks_goal_date'],
['ks_goal_date' + ":" + ks_chart_date_groupby])
ks_goal_domains = {}
for res in ks_goal_records:
if res['ks_goal_date' + ":" + ks_chart_date_groupby]:
label = res['ks_goal_date' + ":" + ks_chart_date_groupby]
ks_goal_labels.append(label)
ks_goal_dataset.append(res['ks_goal_value'])
ks_goal_domains[label] = res['__domain']
for goal_domain in ks_goal_domains.keys():
ks_goal_doamins = []
for item in ks_goal_domains[goal_domain]:
if 'ks_goal_date' in item:
domain = list(item)
domain[0] = ks_chart_groupby_relation_field
domain = tuple(domain)
ks_goal_doamins.append(domain)
ks_goal_doamins.insert(0, '&')
ks_goal_domains[goal_domain] = ks_goal_doamins
domains = {}
counter = 0
for label in ks_chart_data['labels']:
domains[label] = ks_chart_data['domains'][counter]
counter += 1
ks_chart_records_dates = ks_chart_data['labels'] + list(
set(ks_goal_labels) - set(ks_chart_data['labels']))
ks_chart_records = []
for label in labels:
if label in ks_chart_records_dates:
ks_chart_records.append(label)
ks_chart_data['domains'].clear()
datasets = []
for dataset in ks_chart_data['datasets']:
datasets.append(dataset['data'].copy())
for dataset in ks_chart_data['datasets']:
dataset['data'].clear()
for label in ks_chart_records:
counterr = 0
domain = domains.get(label, False)
if domain:
ks_chart_data['domains'].append(domain)
else:
ks_chart_data['domains'].append(ks_goal_domains.get(label, []))
if label in ks_chart_data['labels']:
index = ks_chart_data['labels'].index(label)
for dataset in ks_chart_data['datasets']:
dataset['data'].append(datasets[counterr][index])
counterr += 1
else:
for dataset in ks_chart_data['datasets']:
dataset['data'].append(0.00)
if label in ks_goal_labels:
index = ks_goal_labels.index(label)
goal_dataset.append(ks_goal_dataset[index])
else:
goal_dataset.append(0.00)
ks_chart_data['labels'] = ks_chart_records
else:
if rec.ks_standard_goal_value:
length = len(ks_chart_data['datasets'][0]['data'])
for i in range(length):
goal_dataset.append(rec.ks_standard_goal_value)
ks_goal_datasets = {
'label': 'Target',
'data': goal_dataset,
}
if rec.ks_goal_bar_line:
ks_goal_datasets['type'] = 'line'
ks_chart_data['datasets'].insert(0, ks_goal_datasets)
else:
ks_chart_data['datasets'].append(ks_goal_datasets)
elif rec.ks_chart_relation_sub_groupby and ((rec.ks_chart_sub_groupby_type == 'relational_type') or
(rec.ks_chart_sub_groupby_type == 'selection') or
(rec.ks_chart_sub_groupby_type == 'date_type' and
rec.ks_chart_date_sub_groupby) or
(rec.ks_chart_sub_groupby_type == 'other')):
if rec.ks_chart_relation_sub_groupby.ttype == 'date':
if rec.ks_chart_date_sub_groupby in ('minute', 'hour'):
raise ValidationError(_('Sub Groupby field: {} cannot be aggregated by {}').format(
rec.ks_chart_relation_sub_groupby.display_name, rec.ks_chart_date_sub_groupby))
if rec.ks_chart_date_groupby in ('minute', 'hour'):
raise ValidationError(_('Groupby field: {} cannot be aggregated by {}').format(
rec.ks_chart_relation_sub_groupby.display_name, rec.ks_chart_date_groupby))
# doesn't have time in date
ks_chart_date_sub_groupby = rec.ks_chart_date_sub_groupby
ks_chart_date_groupby = rec.ks_chart_date_groupby
else:
ks_chart_date_sub_groupby = rec.ks_chart_date_sub_groupby
if rec.ks_chart_date_groupby == 'month_year':
ks_chart_date_groupby = 'month'
else:
ks_chart_date_groupby = rec.ks_chart_date_groupby
if len(ks_chart_measure_field) != 0 or rec.ks_chart_data_count_type == 'count':
if rec.ks_chart_groupby_type == 'date_type' and ks_chart_date_groupby:
ks_chart_group = rec.ks_chart_relation_groupby.name + ":" + ks_chart_date_groupby
else:
ks_chart_group = rec.ks_chart_relation_groupby.name
if rec.ks_chart_sub_groupby_type == 'date_type' and rec.ks_chart_date_sub_groupby:
ks_chart_sub_groupby_field = rec.ks_chart_relation_sub_groupby.name + ":" + \
ks_chart_date_sub_groupby
else:
ks_chart_sub_groupby_field = rec.ks_chart_relation_sub_groupby.name
ks_chart_groupby_relation_fields = [ks_chart_group, ks_chart_sub_groupby_field]
ks_chart_record = False
try:
ks_chart_record = self.env[rec.ks_model_name].read_group(ks_chart_domain,
list(set(ks_chart_measure_field_with_type +
ks_chart_measure_field_with_type_2 +
[ks_chart_groupby_relation_field,
rec.ks_chart_relation_sub_groupby.name ])),
ks_chart_groupby_relation_fields,
orderby=orderby, limit=limit,
lazy=False)
except Exception:
ks_chart_record = {}
chart_data = []
chart_sub_data = []
for res in ks_chart_record:
domain = res.get('__domain', [])
if all(measure_field in res for measure_field in ks_chart_measure_field) and all(
measure_field in res for measure_field in ks_chart_measure_field_2):
if res[ks_chart_groupby_relation_fields[0]] is not False:
if rec.ks_chart_groupby_type == 'date_type':
# x-axis modification
if rec.ks_chart_date_groupby == "day" and rec.ks_chart_date_sub_groupby in [ \
"quarter", "year"]:
label = " ".join(res[ks_chart_groupby_relation_fields[0]].split(" ")[0:2])
elif rec.ks_chart_date_groupby in ["minute",
"hour"] and rec.ks_chart_date_sub_groupby in \
["month", "week", "quarter", "year"]:
label = " ".join(res[ks_chart_groupby_relation_fields[0]].split(" ")[0:3])
elif rec.ks_chart_date_groupby == 'month_year':
label = res[ks_chart_groupby_relation_fields[0]]
else:
label = res[ks_chart_groupby_relation_fields[0]].split(" ")[0]
elif rec.ks_chart_groupby_type == 'selection':
selection = res[ks_chart_groupby_relation_fields[0]]
label = dict(self.env[rec.ks_model_name].fields_get(
allfields=[ks_chart_groupby_relation_fields[0]])
[ks_chart_groupby_relation_fields[0]]['selection'])[selection]
elif rec.ks_chart_groupby_type == 'relational_type':
label = res[ks_chart_groupby_relation_fields[0]][1]
else:
label = res[ks_chart_groupby_relation_fields[0]]
labels = []
value = []
value_2 = []
labels_2 = []
if rec.ks_chart_data_count_type != 'count':
for ress in rec.ks_chart_measure_field:
if rec.ks_chart_sub_groupby_type == 'date_type':
# Labels Name modification
if res[ks_chart_groupby_relation_fields[1]] is not False:
labels.append(res[ks_chart_groupby_relation_fields[1]].split(" ")[
0] + " " + ress.field_description)
else:
labels.append(str(res[ks_chart_groupby_relation_fields[1]])
+ " " + ress.field_description)
elif rec.ks_chart_sub_groupby_type == 'selection':
if res[ks_chart_groupby_relation_fields[1]] is not False:
selection = res[ks_chart_groupby_relation_fields[1]]
labels.append(dict(self.env[rec.ks_model_name].fields_get(
allfields=[ks_chart_groupby_relation_fields[1]])
[ks_chart_groupby_relation_fields[1]][
'selection'])[
selection]
+ " " + ress.field_description)
else:
labels.append(str(res[ks_chart_groupby_relation_fields[1]])
+ ' ' + ress.field_description)
elif rec.ks_chart_sub_groupby_type == 'relational_type':
if res[ks_chart_groupby_relation_fields[1]] is not False:
labels.append(res[ks_chart_groupby_relation_fields[1]][1]
+ " " + ress.field_description)
else:
labels.append(str(res[ks_chart_groupby_relation_fields[1]]) +
' ' + ress.field_description)
else:
if res[ks_chart_groupby_relation_fields[1]]:
labels.append(str(res[ks_chart_groupby_relation_fields[1]])
+ "\'s " + ress.field_description)
else:
labels.append(str(res[ks_chart_groupby_relation_fields[1]])
+ ' ' + ress.field_description)
value.append(res.get(
ress.name) if rec.ks_chart_data_count_type == 'sum' else res.get(
ress.name) / res.get('__count'))
if rec.ks_chart_measure_field_2 and rec.ks_dashboard_item_type == 'ks_bar_chart':
for ress in rec.ks_chart_measure_field_2:
if rec.ks_chart_sub_groupby_type == 'date_type':
# line in bar chart case
if res[ks_chart_groupby_relation_fields[1]] is not False:
labels_2.append(
res[ks_chart_groupby_relation_fields[1]].split(" ")[0] + " "
+ ress.field_description)
else:
labels_2.append(str(res[ks_chart_groupby_relation_fields[1]])
+ ' ' + ress.field_description)
elif rec.ks_chart_sub_groupby_type == 'selection':
if res[ks_chart_groupby_relation_fields[1]] is not False:
selection = res[ks_chart_groupby_relation_fields[1]]
labels_2.append(dict(self.env[rec.ks_model_name].fields_get(
allfields=[ks_chart_groupby_relation_fields[1]])
[ks_chart_groupby_relation_fields[1]][
'selection'])[
selection] + " " + ress.field_description)
else:
labels_2.append(str(res[ks_chart_groupby_relation_fields[1]])
+ '' + ress.field_description)
elif rec.ks_chart_sub_groupby_type == 'relational_type':
if res[ks_chart_groupby_relation_fields[1]] is not False:
labels_2.append(
res[ks_chart_groupby_relation_fields[1]][1] + " " +
ress.field_description)
else:
labels_2.append(str(res[ks_chart_groupby_relation_fields[1]])
+ ' ' + ress.field_description)
else:
if res[ks_chart_groupby_relation_fields[1]] is not False:
labels_2.append(str(
res[ks_chart_groupby_relation_fields[1]]) + " " +
ress.field_description)
else:
labels_2.append(str(res[ks_chart_groupby_relation_fields[1]])
+ ' ' + ress.field_description)
value_2.append(res.get(
ress.name) if rec.ks_chart_data_count_type == 'sum' else res.get(
ress.name) / res.get('__count'))
chart_sub_data.append({
'value': value_2,
'labels': label,
'series': labels_2,
'domain': domain,
})
else:
if res[ks_chart_groupby_relation_fields[1]] and rec.ks_chart_sub_groupby_type == \
'date_type':
# Labels
labels.append(res[ks_chart_groupby_relation_fields[1]].split(" ")[0])
elif res[ks_chart_groupby_relation_fields[1]] and rec.ks_chart_sub_groupby_type == 'selection':
selection = res[ks_chart_groupby_relation_fields[1]]
labels.append(dict(self.env[rec.ks_model_name].fields_get(
allfields=[ks_chart_groupby_relation_fields[1]])
[ks_chart_groupby_relation_fields[1]]['selection'])[
selection])
elif res[ks_chart_groupby_relation_fields[1]] and rec.ks_chart_sub_groupby_type == 'relational_type':
labels.append(res[ks_chart_groupby_relation_fields[1]][1])
else:
labels.append(res[ks_chart_groupby_relation_fields[1]])
value.append(res['__count'])
chart_data.append({
'value': value,
'labels': label,
'series': labels,
'domain': domain,
})
xlabels = []
series = []
values = {}
domains = {}
for data in chart_data:
label = data['labels']
serie = data['series']
domain = data['domain']
if (len(xlabels) == 0) or (label not in xlabels):
xlabels.append(label)
if (label not in domains):
domains[label] = domain
else:
domains[label].insert(0, '|')
domains[label] = domains[label] + domain
series = series + serie
value = data['value']
counter = 0
for seri in serie:
if seri not in values:
values[seri] = {}
if label in values[seri]:
values[seri][label] = values[seri][label] + value[counter]
else:
values[seri][label] = value[counter]
counter += 1
final_datasets = []
for serie in series:
if serie not in final_datasets:
final_datasets.append(serie)
ks_data = []
for dataset in final_datasets:
ks_dataset = {
'value': [],
'key': dataset
}
for label in xlabels:
ks_dataset['value'].append({
'domain': domains[label],
'x': label,
'y': values[dataset][label] if label in values[dataset] else 0
})
ks_data.append(ks_dataset)
if rec.ks_chart_relation_sub_groupby.name == rec.ks_chart_relation_groupby.name == rec.ks_sort_by_field.name:
ks_data = rec.ks_sort_sub_group_by_records(ks_data, rec.ks_chart_groupby_type,
rec.ks_chart_date_groupby, rec.ks_sort_by_order,
rec.ks_chart_date_sub_groupby)
ks_chart_data = {
'labels': [],
'datasets': [],
'domains': [],
'ks_selection': "",
'ks_currency': 0,
'ks_field': "",
'previous_domain': ks_chart_domain
}
if rec.ks_unit and rec.ks_unit_selection == 'monetary':
ks_chart_data['ks_selection'] += rec.ks_unit_selection
ks_chart_data['ks_currency'] += rec.env.user.company_id.currency_id.id
elif rec.ks_unit and rec.ks_unit_selection == 'custom':
ks_chart_data['ks_selection'] += rec.ks_unit_selection
if rec.ks_chart_unit:
ks_chart_data['ks_field'] += rec.ks_chart_unit
if len(ks_data) != 0:
for res in ks_data[0]['value']:
ks_chart_data['labels'].append(res['x'])
ks_chart_data['domains'].append(res['domain'])
if rec.ks_chart_measure_field_2 and rec.ks_dashboard_item_type == 'ks_bar_chart':
ks_chart_data['ks_show_second_y_scale'] = True
values_2 = {}
series_2 = []
for data in chart_sub_data:
label = data['labels']
serie = data['series']
series_2 = series_2 + serie
value = data['value']
counter = 0
for seri in serie:
if seri not in values_2:
values_2[seri] = {}
if label in values_2[seri]:
values_2[seri][label] = values_2[seri][label] + value[counter]
else:
values_2[seri][label] = value[counter]
counter += 1
final_datasets_2 = []
for serie in series_2:
if serie not in final_datasets_2:
final_datasets_2.append(serie)
ks_data_2 = []
for dataset in final_datasets_2:
ks_dataset = {
'value': [],
'key': dataset
}
for label in xlabels:
ks_dataset['value'].append({
'x': label,
'y': values_2[dataset][label] if label in values_2[dataset] else 0
})
ks_data_2.append(ks_dataset)
for ks_dat in ks_data_2:
dataset = {
'label': ks_dat['key'],
'data': [],
'type': 'line',
'yAxisID': 'y-axis-1',
}
for res in ks_dat['value']:
dataset['data'].append(res['y'])
ks_chart_data['datasets'].append(dataset)
for ks_dat in ks_data:
dataset = {
'label': ks_dat['key'],
'data': []
}
for res in ks_dat['value']:
dataset['data'].append(res['y'])
ks_chart_data['datasets'].append(dataset)
if rec.ks_goal_enable and rec.ks_standard_goal_value and rec.ks_dashboard_item_type in [
'ks_bar_chart', 'ks_line_chart', 'ks_area_chart', 'ks_horizontalBar_chart']:
goal_dataset = []
length = len(ks_chart_data['datasets'][0]['data'])
for i in range(length):
goal_dataset.append(rec.ks_standard_goal_value)
ks_goal_datasets = {
'label': 'Target',
'data': goal_dataset,
}
if rec.ks_goal_bar_line and rec.ks_dashboard_item_type != 'ks_horizontalBar_chart':
ks_goal_datasets['type'] = 'line'
ks_chart_data['datasets'].insert(0, ks_goal_datasets)
else:
ks_chart_data['datasets'].append(ks_goal_datasets)
else:
ks_chart_data = False
rec.ks_chart_data = json.dumps(ks_chart_data)
elif not rec.ks_dashboard_item_type or rec.ks_dashboard_item_type == 'ks_tile':
rec.ks_chart_measure_field = False
rec.ks_chart_measure_field_2 = False
rec.ks_chart_relation_groupby = False
@api.multi
@api.depends('ks_domain', 'ks_dashboard_item_type', 'ks_model_id', 'ks_sort_by_field', 'ks_sort_by_order',
'ks_record_data_limit', 'ks_list_view_fields', 'ks_list_view_type', 'ks_list_view_group_fields',
'ks_chart_groupby_type', 'ks_chart_date_groupby', 'ks_date_filter_field', 'ks_item_end_date',
'ks_item_start_date', 'ks_compare_period', 'ks_year_period', 'ks_list_target_deviation_field',
'ks_goal_enable', 'ks_standard_goal_value', 'ks_goal_lines', 'ks_domain_extension')
def ks_get_list_view_data(self):
for rec in self:
if rec.ks_list_view_type and rec.ks_dashboard_item_type and rec.ks_dashboard_item_type == 'ks_list_view' and \
rec.ks_model_id:
ks_list_view_data = {'label': [],
'data_rows': [], 'model': rec.ks_model_name, 'fields_type': []}
ks_chart_domain = self.ks_convert_into_proper_domain(rec.ks_domain, rec)
orderby = rec.ks_sort_by_field.name if rec.ks_sort_by_field else "id"
if rec.ks_sort_by_order:
orderby = orderby + " " + rec.ks_sort_by_order
limit = rec.ks_record_data_limit if rec.ks_record_data_limit and rec.ks_record_data_limit > 0 else False
if rec.ks_list_view_type == "ungrouped":
if rec.ks_list_view_fields:
ks_list_view_data = rec.ks_fetch_list_view_data(rec)
elif rec.ks_list_view_type == "grouped" and rec.ks_list_view_group_fields and rec.ks_chart_relation_groupby:
ks_list_fields = []
if rec.ks_chart_groupby_type == 'relational_type':
ks_list_view_data['list_view_type'] = 'relational_type'
ks_list_view_data['groupby'] = rec.ks_chart_relation_groupby.name
ks_list_fields.append(rec.ks_chart_relation_groupby.name)
ks_list_view_data['label'].append(rec.ks_chart_relation_groupby.field_description)
ks_list_view_data['fields_type'].append(self.ks_chart_relation_groupby.ttype)
for res in rec.ks_list_view_group_fields:
ks_list_fields.append(res.name)
ks_list_view_data['label'].append(res.field_description)
ks_list_view_data['fields_type'].append(res.ttype)
ks_list_view_records = self.env[rec.ks_model_name].read_group(ks_chart_domain, ks_list_fields,
[
rec.ks_chart_relation_groupby.name],
orderby=orderby, limit=limit)
for res in ks_list_view_records:
if all(list_fields in res for list_fields in ks_list_fields) and res[
rec.ks_chart_relation_groupby.name]:
counter = 0
data_row = {'id': res[rec.ks_chart_relation_groupby.name][0], 'data': [],
'domain': json.dumps(res['__domain'])}
for field_rec in ks_list_fields:
if counter == 0:
data_row['data'].append(res[field_rec][1])
else:
data_row['data'].append(res[field_rec])
counter += 1
ks_list_view_data['data_rows'].append(data_row)
elif rec.ks_chart_groupby_type == 'date_type' and rec.ks_chart_date_groupby:
ks_chart_date_groupby = rec.ks_chart_date_groupby
if rec.ks_chart_date_groupby == 'month_year':
ks_chart_date_groupby = 'month'
ks_list_view_data['list_view_type'] = 'date_type'
ks_list_field = []
ks_list_view_data[
'groupby'] = rec.ks_chart_relation_groupby.name + ':' + ks_chart_date_groupby
ks_list_field.append(rec.ks_chart_relation_groupby.name)
ks_list_fields.append(rec.ks_chart_relation_groupby.name + ':' + ks_chart_date_groupby)
ks_list_view_data['label'].append(
rec.ks_chart_relation_groupby.field_description + ' : ' + ks_chart_date_groupby.capitalize())
ks_list_view_data['fields_type'].append(self.ks_chart_relation_groupby.ttype)
for res in rec.ks_list_view_group_fields:
ks_list_fields.append(res.name)
ks_list_field.append(res.name)
ks_list_view_data['label'].append(res.field_description)
ks_list_view_data['fields_type'].append(res.ttype)
list_target_deviation_field = []
if rec.ks_goal_enable and rec.ks_list_target_deviation_field:
list_target_deviation_field.append(rec.ks_list_target_deviation_field.name)
if rec.ks_list_target_deviation_field.name in ks_list_field:
ks_list_field.remove(rec.ks_list_target_deviation_field.name)
ks_list_fields.remove(rec.ks_list_target_deviation_field.name)
ks_list_view_data['label'].remove(rec.ks_list_target_deviation_field.field_description)
ks_list_view_records = self.env[rec.ks_model_name].read_group(ks_chart_domain,
ks_list_field
+ list_target_deviation_field,
[
rec.ks_chart_relation_groupby.name + ':'
+ ks_chart_date_groupby],
orderby=orderby, limit=limit)
if all(list_fields in res for res in ks_list_view_records for list_fields in
ks_list_fields + list_target_deviation_field):
for res in ks_list_view_records:
counter = 0
data_row = {'id': 0, 'data': []}
for field_rec in ks_list_fields:
data_row['data'].append(res[field_rec])
ks_list_view_data['data_rows'].append(data_row)
if rec.ks_goal_enable:
ks_list_labels = []
ks_list_view_data['label'].append("Target")
if rec.ks_list_target_deviation_field:
ks_list_view_data['label'].append(
rec.ks_list_target_deviation_field.field_description)
ks_list_view_data['label'].append("Achievement")
ks_list_view_data['label'].append("Deviation")
for res in ks_list_view_records:
ks_list_labels.append(res[ks_list_view_data['groupby']])
ks_list_view_data2 = rec.get_target_list_view_data(ks_list_view_records, rec,
ks_list_fields,
ks_list_view_data['groupby'],
list_target_deviation_field,
ks_chart_domain)
ks_list_view_data['data_rows'] = ks_list_view_data2['data_rows']
elif rec.ks_chart_groupby_type == 'selection':
ks_list_view_data['list_view_type'] = 'selection'
ks_list_view_data['groupby'] = rec.ks_chart_relation_groupby.name
ks_selection_field = rec.ks_chart_relation_groupby.name
ks_list_fields.append(rec.ks_chart_relation_groupby.name)
ks_list_view_data['label'].append(rec.ks_chart_relation_groupby.field_description)
ks_list_view_data['fields_type'].append(self.ks_chart_relation_groupby.ttype)
for res in rec.ks_list_view_group_fields:
ks_list_fields.append(res.name)
ks_list_view_data['label'].append(res.field_description)
ks_list_view_data['fields_type'].append(res.ttype)
ks_list_view_records = self.env[rec.ks_model_name].read_group(ks_chart_domain, ks_list_fields,
[
rec.ks_chart_relation_groupby.name],
orderby=orderby, limit=limit)
for res in ks_list_view_records:
if all(list_fields in res for list_fields in ks_list_fields):
counter = 0
data_row = {'id': 0, 'data': [], 'domain': json.dumps(res['__domain'])}
if res[ks_selection_field]:
data_row['data'].append(dict(
self.env[rec.ks_model_name].fields_get(allfields=ks_selection_field)
[ks_selection_field]['selection'])[res[ks_selection_field]])
else:
data_row['data'].append(" ")
for field_rec in ks_list_fields:
data_row['data'].append(res[field_rec])
ks_list_view_data['data_rows'].append(data_row)
elif rec.ks_chart_groupby_type == 'other':
ks_list_view_data['list_view_type'] = 'other'
ks_list_view_data['groupby'] = rec.ks_chart_relation_groupby.name
ks_list_fields.append(rec.ks_chart_relation_groupby.name)
ks_list_view_data['label'].append(rec.ks_chart_relation_groupby.field_description)
ks_list_view_data['fields_type'].append(self.ks_chart_relation_groupby.ttype)
for res in rec.ks_list_view_group_fields:
if rec.ks_chart_relation_groupby.name != res.name:
ks_list_fields.append(res.name)
ks_list_view_data['label'].append(res.field_description)
ks_list_view_data['fields_type'].append(res.ttype)
ks_list_view_records = self.env[rec.ks_model_name].read_group(ks_chart_domain, ks_list_fields,
[
rec.ks_chart_relation_groupby.name],
orderby=orderby, limit=limit)
for res in ks_list_view_records:
if all(list_fields in res for list_fields in ks_list_fields):
counter = 0
data_row = {'id': 0, 'data': [], 'domain': json.dumps(res['__domain'])}
for field_rec in ks_list_fields:
if counter == 0:
data_row['data'].append(res[field_rec])
else:
if rec.ks_chart_relation_groupby.name == field_rec:
data_row['data'].append(res[field_rec] * res[field_rec + '_count'])
else:
data_row['data'].append(res[field_rec])
counter += 1
ks_list_view_data['data_rows'].append(data_row)
rec.ks_list_view_data = json.dumps(ks_list_view_data)
else:
rec.ks_list_view_data = False
def get_target_list_view_data(self, ks_list_view_records, rec, ks_list_fields, ks_group_by,
target_deviation_field, ks_chart_domain):
ks_list_view_data = {}
ks_list_labels = []
ks_list_records = {}
ks_domains = {}
for res in ks_list_view_records:
ks_list_labels.append(res[ks_group_by])
ks_domains[res[ks_group_by]] = res['__domain']
ks_list_records[res[ks_group_by]] = {'measure_field': [], 'deviation_value': 0.0}
ks_list_records[res[ks_group_by]]['measure_field'] = []
for fields in ks_list_fields[1:]:
ks_list_records[res[ks_group_by]]['measure_field'].append(res[fields])
for field in target_deviation_field:
ks_list_records[res[ks_group_by]]['deviation'] = res[field]
if rec._context.get('current_id', False):
ks_item_id = rec._context['current_id']
else:
ks_item_id = rec.id
if rec.ks_date_filter_selection_2 == "l_none":
selected_start_date = rec._context.get('ksDateFilterStartDate', False)
selected_end_date = rec._context.get('ksDateFilterEndDate', False)
else:
selected_start_date = rec.ks_item_start_date
selected_end_date = rec.ks_item_end_date
ks_goal_domain = [('ks_dashboard_item', '=', ks_item_id)]
if selected_start_date and selected_end_date:
ks_goal_domain.extend([('ks_goal_date', '>=', selected_start_date.strftime("%Y-%m-%d")),
('ks_goal_date', '<=', selected_end_date.strftime("%Y-%m-%d"))])
ks_date_data = rec.ks_get_start_end_date(rec.ks_model_name, rec.ks_chart_relation_groupby.name,
rec.ks_chart_relation_groupby.ttype,
ks_chart_domain,
ks_goal_domain)
labels = []
ks_chart_date_groupby = rec.ks_chart_date_groupby
if rec.ks_chart_date_groupby == 'month_year':
ks_chart_date_groupby = 'month'
if ks_date_data['start_date'] and ks_date_data['end_date'] and rec.ks_goal_lines:
labels = self.generate_timeserise(ks_date_data['start_date'], ks_date_data['end_date'],
ks_chart_date_groupby)
ks_goal_records = self.env['ks_dashboard_ninja.item_goal'].read_group(
ks_goal_domain, ['ks_goal_value', 'ks_goal_date'],
['ks_goal_date' + ":" + ks_chart_date_groupby], )
ks_goal_labels = []
ks_goal_dataset = {}
ks_list_view_data['data_rows'] = []
if rec.ks_goal_lines and len(rec.ks_goal_lines) != 0:
ks_goal_domains = {}
for res in ks_goal_records:
if res['ks_goal_date' + ":" + ks_chart_date_groupby]:
ks_goal_labels.append(res['ks_goal_date' + ":" + ks_chart_date_groupby])
ks_goal_dataset[res['ks_goal_date' + ":" + ks_chart_date_groupby]] = res['ks_goal_value']
ks_goal_domains[res['ks_goal_date' + ":" + ks_chart_date_groupby]] = res.get('__domain')
for goal_domain in ks_goal_domains.keys():
ks_goal_doamins = []
for item in ks_goal_domains[goal_domain]:
if 'ks_goal_date' in item:
domain = list(item)
domain[0] = ks_group_by.split(":")[0]
domain = tuple(domain)
ks_goal_doamins.append(domain)
ks_goal_doamins.insert(0, '&')
ks_goal_domains[goal_domain] = ks_goal_doamins
ks_chart_records_dates = ks_list_labels + list(
set(ks_goal_labels) - set(ks_list_labels))
ks_list_labels_dates = []
for label in labels:
if label in ks_chart_records_dates:
ks_list_labels_dates.append(label)
for label in ks_list_labels_dates:
data_rows = {'data': [label]}
data = ks_list_records.get(label, False)
if data:
data_rows['data'] = data_rows['data'] + data['measure_field']
data_rows['domain'] = json.dumps(ks_domains[label])
else:
for fields in ks_list_fields[1:]:
data_rows['data'].append(0.0)
data_rows['domain'] = json.dumps(ks_goal_domains[label])
target_value = (ks_goal_dataset.get(label, 0.0))
data_rows['data'].append(target_value)
for field in target_deviation_field:
if data:
data_rows['data'].append(data['deviation'])
value = data['deviation']
else:
data_rows['data'].append(0.0)
value = 0
if target_value:
acheivement = round(((value) / target_value) * 100)
acheivement = str(acheivement) + "%"
else:
acheivement = ""
deviation = (value - target_value)
data_rows['data'].append(acheivement)
data_rows['data'].append(deviation)
ks_list_view_data['data_rows'].append(data_rows)
else:
for res in ks_list_view_records:
if all(list_fields in res for list_fields in ks_list_fields):
counter = 0
data_row = {'id': 0, 'data': [], }
for field_rec in ks_list_fields:
data_row['data'].append(res[field_rec])
data_row['data'].append(rec.ks_standard_goal_value)
data_row['domain'] = json.dumps(res['__domain'])
for field in target_deviation_field:
value = res[field]
data_row['data'].append(res[field])
target_value = rec.ks_standard_goal_value
if target_value:
acheivement = round(((value) / target_value) * 100)
acheivement = str(acheivement) + "%"
else:
acheivement = ""
deviation = (value - target_value)
data_row['data'].append(acheivement)
data_row['data'].append(deviation)
ks_list_view_data['data_rows'].append(data_row)
return ks_list_view_data
@api.model
def ks_fetch_list_view_data(self, rec, limit=15, offset=0):
ks_list_view_data = {'label': [],
'data_rows': [], 'model': rec.ks_model_name, 'fields_type': []}
ks_chart_domain = rec.ks_convert_into_proper_domain(rec.ks_domain, rec)
orderby = rec.ks_sort_by_field.name if rec.ks_sort_by_field else "id"
if rec.ks_sort_by_order:
orderby = orderby + " " + rec.ks_sort_by_order
ks_limit = rec.ks_record_data_limit if rec.ks_record_data_limit and rec.ks_record_data_limit > 0 else False
if ks_limit:
ks_limit = ks_limit - offset
if ks_limit < 15:
limit = ks_limit
else:
limit = 15
if rec.ks_list_view_fields:
ks_list_view_data['list_view_type'] = 'other'
ks_list_view_data['groupby'] = False
ks_list_view_data['label'] = []
ks_list_view_data['date_index'] = []
for res in rec.ks_list_view_fields:
if (res.ttype == "datetime" or res.ttype == "date"):
index = len(ks_list_view_data['label'])
ks_list_view_data['label'].append(res.field_description)
ks_list_view_data['date_index'].append(index)
ks_list_view_data['fields_type'].append(res.ttype)
else:
ks_list_view_data['label'].append(res.field_description)
ks_list_view_data['fields_type'].append(res.ttype)
ks_list_view_fields = [res.name for res in rec.ks_list_view_fields]
ks_list_view_field_type = [res.ttype for res in rec.ks_list_view_fields]
try:
ks_list_view_records = self.env[rec.ks_model_name].search_read(ks_chart_domain,
ks_list_view_fields,
order=orderby, limit=limit, offset=offset)
except Exception as e:
ks_list_view_data = False
return ks_list_view_data
for res in ks_list_view_records:
counter = 0
data_row = {'id': res['id'], 'data': []}
for field_rec in ks_list_view_fields:
if type(res[field_rec]) == fields.datetime or type(res[field_rec]) == fields.date:
res[field_rec] = res[field_rec].strftime("%D %T")
elif ks_list_view_field_type[counter] == "many2one":
if res[field_rec]:
res[field_rec] = res[field_rec][1]
data_row['data'].append(res[field_rec])
counter += 1
ks_list_view_data['data_rows'].append(data_row)
return ks_list_view_data
@api.onchange('ks_dashboard_item_type')
def set_color_palette(self):
for rec in self:
if rec.ks_dashboard_item_type == "ks_bar_chart" or rec.ks_dashboard_item_type == "ks_horizontalBar_chart" or rec.ks_dashboard_item_type == "ks_line_chart" or rec.ks_dashboard_item_type == "ks_area_chart":
rec.ks_chart_item_color = "cool"
else:
rec.ks_chart_item_color = "default"
# Time Filter Calculation
@api.multi
@api.onchange('ks_date_filter_selection')
def ks_set_date_filter(self):
for rec in self:
if (not rec.ks_date_filter_selection) or rec.ks_date_filter_selection == "l_none":
rec.ks_item_start_date = rec.ks_item_end_date = False
elif rec.ks_date_filter_selection != 'l_custom':
ks_date_data = ks_get_date(rec.ks_date_filter_selection, self)
rec.ks_item_start_date = ks_date_data["selected_start_date"]
rec.ks_item_end_date = ks_date_data["selected_end_date"]
@api.multi
@api.depends('ks_dashboard_item_type', 'ks_model_id', 'ks_model_id_2', 'ks_record_field', 'ks_goal_enable',
'ks_standard_goal_value', 'ks_record_field_2', 'ks_record_count_type_2', 'ks_domain', 'ks_domain_2',
'ks_date_filter_selection', 'ks_item_start_date', 'ks_record_count_type', 'ks_date_filter_selection_2',
'ks_item_end_date', 'ks_previous_period', 'ks_item_start_date_2', 'ks_item_end_date',
'ks_compare_period', 'ks_year_period', 'ks_date_filter_field', 'ks_date_filter_field_2',
'ks_compare_period_2', 'ks_year_period_2', 'ks_domain_extension_2')
def ks_get_kpi_data(self):
for rec in self:
if rec.ks_dashboard_item_type and rec.ks_dashboard_item_type == 'ks_kpi' and rec.ks_model_id:
ks_kpi_data = []
ks_record_count = 0.0
ks_kpi_data_model_1 = {}
if rec.ks_record_count_type == 'count':
ks_record_count = rec.ks_fetch_model_data(rec.ks_model_name, rec.ks_domain, 'search_count', rec)
elif rec.ks_record_count_type in ['sum', 'average'] and rec.ks_record_field:
ks_records_grouped_data = rec.ks_fetch_model_data(rec.ks_model_name, rec.ks_domain, 'read_group',
rec)
if len(ks_records_grouped_data) > 0:
ks_records_grouped_data = ks_records_grouped_data[0]
if rec.ks_record_count_type == 'sum' and ks_records_grouped_data.get('__count', False) and (
ks_records_grouped_data.get(rec.ks_record_field.name)):
ks_record_count = ks_records_grouped_data.get(rec.ks_record_field.name, 0)
elif rec.ks_record_count_type == 'average' and ks_records_grouped_data.get(
'__count', False) and (ks_records_grouped_data.get(rec.ks_record_field.name)):
ks_record_count = ks_records_grouped_data.get(rec.ks_record_field.name,
0) / ks_records_grouped_data.get(
'__count', 1)
else:
ks_record_count = 0
else:
ks_record_count = 0
else:
ks_record_count = 0
ks_kpi_data_model_1['model'] = rec.ks_model_name
ks_kpi_data_model_1['record_field'] = rec.ks_record_field.field_description
ks_kpi_data_model_1['record_data'] = ks_record_count
if rec.ks_goal_enable:
ks_kpi_data_model_1['target'] = rec.ks_standard_goal_value
ks_kpi_data.append(ks_kpi_data_model_1)
if rec.ks_previous_period:
ks_previous_period_data = rec.ks_get_previous_period_data(rec)
ks_kpi_data_model_1['previous_period'] = ks_previous_period_data
if rec.ks_model_id_2 and rec.ks_record_count_type_2:
ks_kpi_data_model_2 = rec.ks_get_model_2_data(rec.ks_model_name_2, rec.ks_record_count_type_2,
rec.ks_record_field_2, rec.ks_domain_2, rec)
ks_kpi_data.append(ks_kpi_data_model_2)
rec.ks_kpi_data = json.dumps(ks_kpi_data)
def ks_get_model_2_data(self, ks_model_name_2, ks_record_count_type_2, ks_record_field_2, ks_domain, rec):
if rec.ks_record_count_type_2 == 'count':
ks_record_count = rec.ks_fetch_model_data_2(ks_model_name_2, ks_domain, 'search_count', rec)
elif rec.ks_record_count_type_2 in ['sum', 'average'] and ks_record_field_2:
ks_records_grouped_data = rec.ks_fetch_model_data_2(ks_model_name_2, ks_domain, 'read_group', rec)
if len(ks_records_grouped_data) > 0:
ks_records_grouped_data = ks_records_grouped_data[0]
if rec.ks_record_count_type_2 == 'sum' and ks_records_grouped_data.get('__count', False) and (
ks_records_grouped_data.get(ks_record_field_2.name)):
ks_record_count = ks_records_grouped_data.get(ks_record_field_2.name, 0)
elif rec.ks_record_count_type_2 == 'average' and ks_records_grouped_data.get(
'__count', False) and (ks_records_grouped_data.get(ks_record_field_2.name)):
ks_record_count = ks_records_grouped_data.get(ks_record_field_2.name,
0) / ks_records_grouped_data.get('__count',
1)
else:
ks_record_count = 0
else:
ks_record_count = 0
else:
ks_record_count = 0
rec.ks_record_count_2 = ks_record_count
ks_kpi_data_model_2 = {}
ks_kpi_data_model_2['model'] = rec.ks_model_name_2
ks_kpi_data_model_2[
'record_field'] = 'count' if ks_record_count_type_2 == 'count' else ks_record_field_2.field_description
ks_kpi_data_model_2['record_data'] = ks_record_count
return ks_kpi_data_model_2
# writing separate function for fetching previous period data
def ks_get_previous_period_data(self, rec):
switcher = {
'l_day': 'ls_day',
't_week': 'ls_week',
't_month': 'ls_month',
't_quarter': 'ls_quarter',
't_year': 'ls_year',
}
ks_previous_period = False
ks_date_data = False
if rec.ks_date_filter_selection == "l_none":
date_filter_selection = rec.ks_dashboard_ninja_board_id.ks_date_filter_selection
else:
date_filter_selection = rec.ks_date_filter_selection
ks_previous_period = switcher.get(date_filter_selection, False)
if ks_previous_period:
ks_date_data = ks_get_date(ks_previous_period, self)
if (ks_date_data):
previous_period_start_date = ks_date_data["selected_start_date"]
previous_period_end_date = ks_date_data["selected_end_date"]
proper_domain = rec.ks_get_previous_period_domain(rec.ks_domain, previous_period_start_date,
previous_period_end_date, rec.ks_date_filter_field)
ks_record_count = 0.0
if rec.ks_record_count_type == 'count':
try:
ks_record_count = self.env[rec.ks_model_name].search_count(proper_domain)
except Exception as e:
ks_record_count = 0.0
return ks_record_count
elif rec.ks_record_field:
try:
data = self.env[rec.ks_model_name].read_group(proper_domain, [rec.ks_record_field.name], [])[0]
except Exception as e:
data = {}
pass
if rec.ks_record_count_type == 'sum':
return data.get(rec.ks_record_field.name, 0) if data.get('__count', False) and (
data.get(rec.ks_record_field.name)) else 0
else:
return data.get(rec.ks_record_field.name, 0) / data.get('__count', 1) if data.get('__count',
False) and (
data.get(
rec.ks_record_field.name)) else 0
else:
return False
else:
return False
def ks_get_previous_period_domain(self, ks_domain, ks_start_date, ks_end_date, date_filter_field):
if ks_domain and "%UID" in ks_domain:
ks_domain = ks_domain.replace('"%UID"', str(self.env.user.id))
if ks_domain:
# try:
proper_domain = safe_eval(ks_domain)
if ks_start_date and ks_end_date and date_filter_field:
proper_domain.extend([(date_filter_field.name, ">=", str(ks_start_date)),
(date_filter_field.name, "<=", str(ks_end_date))])
else:
if ks_start_date and ks_end_date and date_filter_field:
proper_domain = ([(date_filter_field.name, ">=", str(ks_start_date)),
(date_filter_field.name, "<=", str(ks_end_date))])
else:
proper_domain = []
return proper_domain
@api.depends('ks_domain_2', 'ks_model_id_2', 'ks_record_field_2', 'ks_record_count_type_2', 'ks_item_start_date_2',
'ks_date_filter_selection_2', 'ks_record_count_type_2', 'ks_compare_period_2', 'ks_year_period_2')
def ks_get_record_count_2(self):
for rec in self:
if rec.ks_record_count_type_2 == 'count':
ks_record_count = rec.ks_fetch_model_data_2(rec.ks_model_name_2, rec.ks_domain_2, 'search_count', rec)
elif rec.ks_record_count_type_2 in ['sum', 'average'] and rec.ks_record_field_2:
ks_records_grouped_data = rec.ks_fetch_model_data_2(rec.ks_model_name_2, rec.ks_domain_2, 'read_group',
rec)
if ks_records_grouped_data and len(ks_records_grouped_data) > 0:
ks_records_grouped_data = ks_records_grouped_data[0]
if rec.ks_record_count_type_2 == 'sum' and ks_records_grouped_data.get('__count', False) and (
ks_records_grouped_data.get(rec.ks_record_field_2.name)):
ks_record_count = ks_records_grouped_data.get(rec.ks_record_field_2.name, 0)
elif rec.ks_record_count_type_2 == 'average' and ks_records_grouped_data.get(
'__count', False) and (ks_records_grouped_data.get(rec.ks_record_field_2.name)):
ks_record_count = ks_records_grouped_data.get(rec.ks_record_field_2.name,
0) / ks_records_grouped_data.get('__count',
1)
else:
ks_record_count = 0
else:
ks_record_count = 0
else:
ks_record_count = False
rec.ks_record_count_2 = ks_record_count
@api.onchange('ks_model_id_2')
def make_record_field_empty_2(self):
for rec in self:
rec.ks_record_field_2 = False
rec.ks_domain_2 = False
rec.ks_date_filter_field_2 = False
# To show "created on" by default on date filter field on model select.
if rec.ks_model_id:
datetime_field_list = rec.ks_date_filter_field_2.search(
[('model_id', '=', rec.ks_model_id.id), '|', ('ttype', '=', 'date'),
('ttype', '=', 'datetime')]).read(['id', 'name'])
for field in datetime_field_list:
if field['name'] == 'create_date':
rec.ks_date_filter_field_2 = field['id']
else:
rec.ks_date_filter_field_2 = False
# Writing separate function to fetch dashboard item data
def ks_fetch_model_data_2(self, ks_model_name, ks_domain, ks_func, rec):
data = 0
try:
if ks_domain and ks_domain != '[]' and ks_model_name:
proper_domain = self.ks_convert_into_proper_domain_2(ks_domain, rec)
if ks_func == 'search_count':
data = self.env[ks_model_name].search_count(proper_domain)
elif ks_func == 'read_group':
data = self.env[ks_model_name].read_group(proper_domain, [rec.ks_record_field_2.name], [])
elif ks_model_name:
# Have to put extra if condition here because on load,model giving False value
proper_domain = self.ks_convert_into_proper_domain_2(False, rec)
if ks_func == 'search_count':
data = self.env[ks_model_name].search_count(proper_domain)
elif ks_func == 'read_group':
data = self.env[ks_model_name].read_group(proper_domain, [rec.ks_record_field_2.name], [])
else:
return []
except Exception as e:
return []
return data
@api.multi
@api.onchange('ks_date_filter_selection_2')
def ks_set_date_filter_2(self):
for rec in self:
if (not rec.ks_date_filter_selection_2) or rec.ks_date_filter_selection_2 == "l_none":
rec.ks_item_start_date_2 = rec.ks_item_end_date = False
elif rec.ks_date_filter_selection_2 != 'l_custom':
ks_date_data = ks_get_date(rec.ks_date_filter_selection_2, self)
rec.ks_item_start_date_2 = ks_date_data["selected_start_date"]
rec.ks_item_end_date_2 = ks_date_data["selected_end_date"]
def ks_convert_into_proper_domain_2(self, ks_domain_2, rec):
if ks_domain_2 and "%UID" in ks_domain_2:
ks_domain_2 = ks_domain_2.replace("%UID", str(self.env.user.id))
if ks_domain_2 and "%MYCOMPANY" in ks_domain_2:
ks_domain_2 = str(safe_eval(ks_domain_2)).replace("'%MYCOMPANY'", str(self.env.user.company_id.id))
ks_date_domain = False
if not rec.ks_date_filter_selection_2 or rec.ks_date_filter_selection_2 == "l_none":
selected_start_date = self._context.get('ksDateFilterStartDate', False)
selected_end_date = self._context.get('ksDateFilterEndDate', False)
if selected_end_date and not selected_start_date:
ks_date_domain = [
(rec.ks_date_filter_field.name, "<=",
selected_end_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT))]
elif selected_start_date and not selected_end_date:
ks_date_domain = [
(rec.ks_date_filter_field.name, ">=",
selected_start_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT))]
else:
if selected_end_date and selected_start_date:
ks_date_domain = [
(rec.ks_date_filter_field.name, ">=",
selected_start_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT)),
(rec.ks_date_filter_field.name, "<=",
selected_end_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT))]
else:
if rec.ks_date_filter_selection_2 and rec.ks_date_filter_selection_2 != 'l_custom':
ks_date_data = ks_get_date(rec.ks_date_filter_selection_2, self)
selected_start_date = ks_date_data["selected_start_date"]
selected_end_date = ks_date_data["selected_end_date"]
else:
if rec.ks_item_start_date_2 and rec.ks_item_end_date_2:
selected_start_date = fields.datetime.strptime(rec.ks_item_start_date_2,
DEFAULT_SERVER_DATETIME_FORMAT)
selected_end_date = fields.datetime.strptime(rec.ks_item_end_date_2, DEFAULT_SERVER_DATETIME_FORMAT)
else:
selected_start_date = False
selected_end_date = False
if selected_start_date and selected_end_date:
if rec.ks_compare_period_2:
ks_compare_period_2 = abs(rec.ks_compare_period_2)
if ks_compare_period_2 > 100:
ks_compare_period_2 = 100
if rec.ks_compare_period_2 > 0:
selected_end_date = selected_end_date + (
selected_end_date - selected_start_date) * ks_compare_period_2
elif rec.ks_compare_period_2 < 0:
selected_start_date = selected_start_date - (
selected_end_date - selected_start_date) * ks_compare_period_2
if rec.ks_year_period_2 and rec.ks_year_period_2 != 0:
abs_year_period_2 = abs(rec.ks_year_period_2)
sign_yp = rec.ks_year_period / abs_year_period_2
if abs_year_period_2 > 100:
abs_year_period_2 = 100
date_field_name = rec.ks_date_filter_field_2.name
ks_date_domain = ['&', (date_field_name, ">=", fields.datetime.strftime(selected_start_date,
DEFAULT_SERVER_DATETIME_FORMAT)),
(date_field_name, "<=",
fields.datetime.strftime(selected_end_date, DEFAULT_SERVER_DATETIME_FORMAT))]
for p in range(1, abs_year_period_2 + 1):
ks_date_domain.insert(0, '|')
ks_date_domain.extend(['&', (date_field_name, ">=", fields.datetime.strftime(
selected_start_date - dateutil.relativedelta.relativedelta(years=p) * sign_yp,
DEFAULT_SERVER_DATETIME_FORMAT)),
(date_field_name, "<=", fields.datetime.strftime(
selected_end_date - dateutil.relativedelta.relativedelta(
years=p) * sign_yp,
DEFAULT_SERVER_DATETIME_FORMAT))])
else:
if rec.ks_date_filter_field_2:
selected_start_date = fields.datetime.strftime(selected_start_date,
DEFAULT_SERVER_DATETIME_FORMAT)
selected_end_date = fields.datetime.strftime(selected_end_date,
DEFAULT_SERVER_DATETIME_FORMAT)
ks_date_domain = [(rec.ks_date_filter_field_2.name, ">=", selected_start_date),
(rec.ks_date_filter_field_2.name, "<=", selected_end_date)]
else:
ks_date_domain = []
elif selected_start_date and rec.ks_date_filter_field_2:
selected_start_date = fields.datetime.strftime(selected_start_date, DEFAULT_SERVER_DATETIME_FORMAT)
ks_date_domain = [(rec.ks_date_filter_field_2.name, ">=", selected_start_date)]
elif selected_end_date and rec.ks_date_filter_field_2:
selected_end_date = fields.datetime.strftime(selected_end_date, DEFAULT_SERVER_DATETIME_FORMAT)
ks_date_domain = [(rec.ks_date_filter_field_2.name, "<=", selected_end_date)]
proper_domain = safe_eval(ks_domain_2) if ks_domain_2 else []
if ks_date_domain:
proper_domain.extend(ks_date_domain)
if rec.ks_domain_extension_2:
ks_domain_extension = rec.ks_convert_domain_extension(rec.ks_domain_extension_2, rec)
proper_domain.extend(ks_domain_extension)
return proper_domain
def ks_fetch_chart_data(self, ks_model_name, ks_chart_domain,ks_chart_measure_field_with_type,
ks_chart_measure_field_with_type_2,
ks_chart_measure_field, ks_chart_measure_field_2,
ks_chart_groupby_relation_field, ks_chart_date_groupby, ks_chart_groupby_type, orderby,
limit, chart_count, ks_chart_measure_field_ids, ks_chart_measure_field_2_ids,
ks_chart_groupby_relation_field_id, ks_chart_data):
if ks_chart_groupby_type == "date_type":
ks_chart_groupby_field = ks_chart_groupby_relation_field + ":" + ks_chart_date_groupby
else:
ks_chart_groupby_field = ks_chart_groupby_relation_field
try:
ks_chart_records = self.env[ks_model_name].read_group(ks_chart_domain,
set(
ks_chart_measure_field_with_type +
ks_chart_measure_field_with_type_2
+ [ks_chart_groupby_relation_field]),
[ks_chart_groupby_field],
orderby=orderby,
limit=limit)
except Exception as e:
ks_chart_records = []
pass
if ks_chart_groupby_type == "relational_type":
ks_chart_data['groupByIds'] = []
for res in ks_chart_records:
if all(measure_field in res for measure_field in ks_chart_measure_field):
if ks_chart_groupby_type == "relational_type":
label = res.get(ks_chart_groupby_field)
if label:
ks_chart_data['labels'].append(label[1])
ks_chart_data['groupByIds'].append(res[ks_chart_groupby_field][0])
else:
ks_chart_data['labels'].append(label)
elif ks_chart_groupby_type == "selection":
selection = res[ks_chart_groupby_field]
if selection:
ks_chart_data['labels'].append(
dict(self.env[ks_model_name].fields_get(allfields=[ks_chart_groupby_field])
[ks_chart_groupby_field]['selection'])[selection])
else:
ks_chart_data['labels'].append(selection)
else:
ks_chart_data['labels'].append(res[ks_chart_groupby_field])
ks_chart_data['domains'].append(res.get('__domain', []))
counter = 0
if ks_chart_measure_field:
if ks_chart_measure_field_2:
index = 0
for field_rec in ks_chart_measure_field_2:
ks_groupby_equal_measures = res[ks_chart_groupby_relation_field + "_count"] \
if ks_chart_measure_field_2_ids[index] == ks_chart_groupby_relation_field_id \
else 1
data = res[field_rec] * ks_groupby_equal_measures
ks_chart_data['datasets'][counter]['data'].append(data)
counter += 1
index += 1
index = 0
for field_rec in ks_chart_measure_field:
ks_groupby_equal_measures = res[ks_chart_groupby_relation_field + "_count"] \
if ks_chart_measure_field_ids[index] == ks_chart_groupby_relation_field_id \
else 1
data = res[field_rec] * ks_groupby_equal_measures
ks_chart_data['datasets'][counter]['data'].append(data)
counter += 1
index += 1
else:
data = res[ks_chart_groupby_relation_field + "_count"]
ks_chart_data['datasets'][0]['data'].append(data)
return ks_chart_data
@api.model
def ks_fetch_drill_down_data(self, item_id, domain, sequence):
record = self.browse(int(item_id))
ks_chart_data = {'labels': [], 'datasets': [], 'ks_show_second_y_scale': False, 'domains': [],
'previous_domain': domain, 'ks_currency': 0, 'ks_field': "", 'ks_selection': ""}
if record.ks_unit and record.ks_unit_selection == 'monetary':
ks_chart_data['ks_selection'] += record.ks_unit_selection
ks_chart_data['ks_currency'] += record.env.user.company_id.currency_id.id
elif record.ks_unit and record.ks_unit_selection == 'custom':
ks_chart_data['ks_selection'] += record.ks_unit_selection
if record.ks_chart_unit:
ks_chart_data['ks_field'] += record.ks_chart_unit
# If count chart data type:
action_lines = record.ks_action_lines.sorted(key=lambda r: r.sequence)
action_line = action_lines[sequence]
ks_chart_type = action_line.ks_chart_type if action_line.ks_chart_type else record.ks_dashboard_item_type
ks_list_view_data = {'label': [],
'data_rows': [], 'model': record.ks_model_name, 'previous_domain': domain, }
if action_line.ks_chart_type == 'ks_list_view':
if record.ks_dashboard_item_type == 'ks_list_view':
ks_chart_list_measure = record.ks_list_view_group_fields
else:
ks_chart_list_measure = record.ks_chart_measure_field
ks_list_fields = []
orderby = action_line.ks_sort_by_field.name if action_line.ks_sort_by_field else "id"
if action_line.ks_sort_by_order:
orderby = orderby + " " + action_line.ks_sort_by_order
limit = action_line.ks_record_limit if action_line.ks_record_limit \
and action_line.ks_record_limit > 0 else False
ks_count = 0
for ks in record.ks_action_lines:
ks_count += 1
if action_line.ks_item_action_field.ttype == 'many2one':
ks_list_view_data['groupby'] = action_line.ks_item_action_field.name
ks_list_fields.append(action_line.ks_item_action_field.name)
ks_list_view_data['label'].append(action_line.ks_item_action_field.field_description)
for res in ks_chart_list_measure:
ks_list_fields.append(res.name)
ks_list_view_data['label'].append(res.field_description)
ks_list_view_records = self.env[record.ks_model_name].read_group(domain, ks_list_fields,
[
action_line.ks_item_action_field.name],
orderby=orderby, limit=limit)
for res in ks_list_view_records:
counter = 0
data_row = {'id': res[action_line.ks_item_action_field.name][0], 'data': [],
'domain': json.dumps(res['__domain']), 'sequence': sequence + 1,
'last_seq': ks_count}
for field_rec in ks_list_fields:
if counter == 0:
data_row['data'].append(res[field_rec][1])
else:
data_row['data'].append(res[field_rec])
counter += 1
ks_list_view_data['data_rows'].append(data_row)
elif action_line.ks_item_action_field.ttype == 'date' or \
action_line.ks_item_action_field.ttype == 'datetime':
ks_list_view_data['list_view_type'] = 'date_type'
ks_list_field = []
ks_list_view_data['groupby'] = action_line.ks_item_action_field.name
ks_list_field.append(
action_line.ks_item_action_field.name + ':' + action_line.ks_item_action_date_groupby)
ks_list_fields.append(action_line.ks_item_action_field.name)
ks_list_view_data['label'].append(
action_line.ks_item_action_field.field_description)
for res in ks_chart_list_measure:
ks_list_fields.append(res.name)
ks_list_field.append(res.name)
ks_list_view_data['label'].append(res.field_description)
ks_list_view_records = self.env[record.ks_model_name].read_group(domain, ks_list_fields,
[action_line.ks_item_action_field.name
+ ':' + action_line.ks_item_action_date_groupby],
orderby=orderby, limit=limit)
for res in ks_list_view_records:
counter = 0
data_row = {'data': [],
'domain': json.dumps(res['__domain']), 'sequence': sequence + 1,
'last_seq': ks_count}
for field_rec in ks_list_field:
data_row['data'].append(res[field_rec])
ks_list_view_data['data_rows'].append(data_row)
elif action_line.ks_item_action_field.ttype == 'selection':
ks_list_view_data['list_view_type'] = 'selection'
ks_list_view_data['groupby'] = action_line.ks_item_action_field.name
ks_list_fields.append(action_line.ks_item_action_field.name)
ks_selection_field = action_line.ks_item_action_field.name
ks_list_view_data['label'].append(action_line.ks_item_action_field.field_description)
for res in ks_chart_list_measure:
ks_list_fields.append(res.name)
ks_list_view_data['label'].append(res.field_description)
ks_list_view_records = self.env[record.ks_model_name].read_group(domain, ks_list_fields,
[
action_line.ks_item_action_field.name],
orderby=orderby, limit=limit)
for res in ks_list_view_records:
counter = 0
data_row = {'data': [],
'domain': json.dumps(res['__domain']), 'sequence': sequence + 1,
'last_seq': ks_count}
if res[ks_selection_field]:
data_row['data'].append(dict(
self.env[record.ks_model_name].fields_get(allfields=ks_selection_field)
[ks_selection_field]['selection'])[res[ks_selection_field]])
else:
data_row['data'].append(" ")
for field_rec in ks_list_fields:
data_row['data'].append(res[field_rec])
ks_list_view_data['data_rows'].append(data_row)
else:
ks_list_view_data['list_view_type'] = 'other'
ks_list_view_data['groupby'] = action_line.ks_item_action_field.name
ks_list_fields.append(action_line.ks_item_action_field.name)
ks_list_view_data['label'].append(action_line.ks_item_action_field.field_description)
for res in ks_chart_list_measure:
ks_list_fields.append(res.name)
ks_list_view_data['label'].append(res.field_description)
ks_list_view_records = self.env[record.ks_model_name].read_group(domain, ks_list_fields,
[
action_line.ks_item_action_field.name],
orderby=orderby, limit=limit)
for res in ks_list_view_records:
if all(list_fields in res for list_fields in ks_list_fields):
counter = 0
data_row = {'id': action_line.ks_item_action_field.name, 'data': [],
'domain': json.dumps(res['__domain']), 'sequence': sequence + 1,
'last_seq': ks_count}
for field_rec in ks_list_fields:
if counter == 0:
data_row['data'].append(res[field_rec])
else:
if action_line.ks_item_action_field.name == field_rec:
data_row['data'].append(res[field_rec] * res[field_rec + '_count'])
else:
data_row['data'].append(res[field_rec])
counter += 1
ks_list_view_data['data_rows'].append(data_row)
return {"ks_list_view_data": json.dumps(ks_list_view_data), "ks_list_view_type": "grouped",
'sequence': sequence + 1, }
else:
ks_chart_measure_field = []
ks_chart_measure_field_with_type = []
ks_chart_measure_field_ids = []
ks_chart_measure_field_2 = []
ks_chart_measure_field_with_type_2 = []
ks_chart_measure_field_2_ids = []
if record.ks_chart_data_count_type == "count":
ks_chart_measure_field_with_type.append('count:count(id)')
ks_chart_data['datasets'].append({'data': [], 'label': "Count"})
else:
if ks_chart_type == 'ks_bar_chart':
if record.ks_chart_measure_field_2:
ks_chart_data['ks_show_second_y_scale'] = True
for res in record.ks_chart_measure_field_2:
if record.ks_chart_data_count_type == 'sum':
ks_data_count_type = 'sum'
elif record.ks_chart_data_count_type == 'average':
ks_data_count_type = 'avg'
else:
raise ValidationError(_('Please chose any Data Type!'))
ks_chart_measure_field_2.append(res.name)
ks_chart_measure_field_with_type_2.append(res.name + ':' + ks_data_count_type)
ks_chart_measure_field_2_ids.append(res.id)
ks_chart_data['datasets'].append(
{'data': [], 'label': res.field_description, 'type': 'line', 'yAxisID': 'y-axis-1'})
if record.ks_dashboard_item_type == 'ks_list_view':
for res in record.ks_list_view_group_fields:
ks_chart_measure_field.append(res.name)
ks_chart_measure_field_with_type.append(res.name + ':' + 'sum')
ks_chart_measure_field_ids.append(res.id)
ks_chart_data['datasets'].append({'data': [], 'label': res.field_description})
else:
for res in record.ks_chart_measure_field:
if record.ks_chart_data_count_type == 'sum':
ks_data_count_type = 'sum'
elif record.ks_chart_data_count_type == 'average':
ks_data_count_type = 'avg'
else:
raise ValidationError(_('Please chose any Data Type!'))
ks_chart_measure_field.append(res.name)
ks_chart_measure_field_with_type.append(res.name + ':' + ks_data_count_type)
ks_chart_measure_field_ids.append(res.id)
ks_chart_data['datasets'].append({'data': [], 'label': res.field_description})
ks_chart_groupby_relation_field = action_line.ks_item_action_field.name
ks_chart_relation_type = action_line.ks_item_action_field_type
ks_chart_date_group_by = action_line.ks_item_action_date_groupby
ks_chart_groupby_relation_field_id = action_line.ks_item_action_field.id
orderby = action_line.ks_sort_by_field.name if action_line.ks_sort_by_field else "id"
if record.ks_chart_data_count_type == "count":
orderby = 'count'
if action_line.ks_sort_by_order:
orderby = orderby + " " + action_line.ks_sort_by_order
limit = action_line.ks_record_limit if action_line.ks_record_limit and action_line.ks_record_limit > 0 else False
if ks_chart_type != "ks_bar_chart":
ks_chart_measure_field_2 = []
ks_chart_measure_field_2_ids = []
ks_chart_data = record.ks_fetch_chart_data(record.ks_model_name, domain,
ks_chart_measure_field_with_type,
ks_chart_measure_field_with_type_2,
ks_chart_measure_field,
ks_chart_measure_field_2,
ks_chart_groupby_relation_field, ks_chart_date_group_by,
ks_chart_relation_type,
orderby, limit, record.ks_chart_data_count_type,
ks_chart_measure_field_ids,
ks_chart_measure_field_2_ids, ks_chart_groupby_relation_field_id,
ks_chart_data)
return {
'ks_chart_data': json.dumps(ks_chart_data),
'ks_chart_type': ks_chart_type,
'sequence': sequence + 1,
}
def ks_sort_sub_group_by_records(self, ks_data, field_type, ks_chart_date_groupby, ks_sort_by_order,
ks_chart_date_sub_groupby):
if ks_data:
reverse = False
if ks_sort_by_order == 'DESC':
reverse = True
for data in ks_data:
if field_type == 'date_type':
if ks_chart_date_groupby in ['minute', 'hour']:
if ks_chart_date_sub_groupby in ["month", "week", "quarter", "year"]:
ks_sorted_months = self.get_sorted_month("MMM")
data['value'].sort(key=lambda x: int(
str(ks_sorted_months.index(x['x'].split(" ")[2]) + 1) + x['x'].split(" ")[1] +
x['x'].split(" ")[0].replace(":", "")), reverse=reverse)
else:
data['value'].sort(key=lambda x: int(x['x'].replace(":", "")), reverse=reverse)
elif ks_chart_date_groupby == 'day' and ks_chart_date_sub_groupby in ["quarter", "year"]:
ks_sorted_days = self.generate_timeserise("2020-01-01 00:00:00", "2020-12-31 00:00:00",
'day', "date")
b = [" ".join(x.split(" ")[0:2]) for x in ks_sorted_days]
data['value'].sort(key=lambda x: b.index(x['x']), reverse=reverse)
elif ks_chart_date_groupby == 'day' and ks_chart_date_sub_groupby not in ["quarter", "year"]:
data['value'].sort(key=lambda i: int(i['x']), reverse=reverse)
elif ks_chart_date_groupby == 'week':
data['value'].sort(key=lambda i: int(i['x'][1:]), reverse=reverse)
elif ks_chart_date_groupby == 'month':
ks_sorted_months = self.generate_timeserise("2020-01-01 00:00:00", "2020-12-31 00:00:00",
'month', "date")
b = [" ".join(x.split(" ")[0:1]) for x in ks_sorted_months]
data['value'].sort(key=lambda x: b.index(x['x']), reverse=reverse)
elif ks_chart_date_groupby == 'quarter':
data['value'].sort(key=lambda i: int(i['x'][1:]), reverse=reverse)
elif ks_chart_date_groupby == 'year':
data['value'].sort(key=lambda i: int(i['x']), reverse=reverse)
else:
data['value'].sort(key=lambda i: i['x'], reverse=reverse)
return ks_data
@api.model
def ks_get_next_offset(self, ks_item_id, offset):
record = self.browse(ks_item_id)
ks_offset = offset['offset']
ks_list_view_data = self.ks_fetch_list_view_data(record, offset=int(ks_offset))
return {
'ks_list_view_data': json.dumps(ks_list_view_data),
'offset': int(ks_offset) + 1,
'next_offset': int(ks_offset) + len(ks_list_view_data['data_rows']),
'limit': record.ks_record_data_limit if record.ks_record_data_limit else 0,
}
@api.model
def get_sorted_month(self, display_format, ftype='date'):
query = """
with d as (SELECT date_trunc(%(aggr)s, generate_series) AS timestamp FROM generate_series(%(timestamp_begin)s::TIMESTAMP , %(timestamp_end)s::TIMESTAMP , %(aggr1)s::interval )) select timestamp from d group by timestamp order by timestamp
"""
self.env.cr.execute(query, {
'timestamp_begin': "2020-01-01 00:00:00",
'timestamp_end': "2020-12-31 00:00:00",
'aggr': 'month',
'aggr1': '1 month'
})
dates = self.env.cr.fetchall()
locale = self._context.get('lang') or 'en_US'
tz_convert = self._context.get('tz')
return [self.format_label(d[0], ftype, display_format, tz_convert, locale) for d in dates]
@api.model
def generate_timeserise(self, date_begin, date_end, aggr, ftype='date'):
query = """
with d as (SELECT date_trunc(%(aggr)s, generate_series) AS timestamp FROM generate_series(%(timestamp_begin)s::TIMESTAMP , %(timestamp_end)s::TIMESTAMP , '1 hour'::interval )) select timestamp from d group by timestamp order by timestamp
"""
self.env.cr.execute(query, {
'timestamp_begin': date_begin,
'timestamp_end': date_end,
'aggr': aggr
})
dates = self.env.cr.fetchall()
display_formats = {
# Careful with week/year formats:
# - yyyy (lower) must always be used, except for week+year formats
# - YYYY (upper) must always be used for week+year format
# e.g. 2006-01-01 is W52 2005 in some locales (de_DE),
# and W1 2006 for others
#
# Mixing both formats, e.g. 'MMM YYYY' would yield wrong results,
# such as 2006-01-01 being formatted as "January 2005" in some locales.
# Cfr: http://babel.pocoo.org/en/latest/dates.html#date-fields
'minute': 'hh:mm dd MMM',
'hour': 'hh:00 dd MMM',
'day': 'dd MMM yyyy', # yyyy = normal year
'week': "'W'w YYYY", # w YYYY = ISO week-year
'month': 'MMMM yyyy',
'quarter': 'QQQ yyyy',
'year': 'yyyy',
}
display_format = display_formats[aggr]
locale = self._context.get('lang') or 'en_US'
tz_convert = self._context.get('tz')
return [self.format_label(d[0], ftype, display_format, tz_convert, locale) for d in dates]
@api.model
def format_label(self, value, ftype, display_format, tz_convert, locale):
dt_format = '%Y-%m-%d %H:%M:%S'
tzinfo = None
if ftype == 'datetime':
value = fields.datetime.strptime(value, dt_format)
if tz_convert:
value = pytz.timezone(self._context['tz']).localize(value)
tzinfo = value.tzinfo
return babel.dates.format_datetime(value, format=display_format, tzinfo=tzinfo, locale=locale)
else:
value = fields.datetime.strptime(value, dt_format)
if tz_convert:
value = pytz.timezone(self._context['tz']).localize(value)
tzinfo = value.tzinfo
return babel.dates.format_date(value, format=display_format, locale=locale)
@api.model
def ks_get_start_end_date(self, model_name, ks_chart_groupby_relation_field, ttype, ks_chart_domain,
ks_goal_domain):
ks_start_end_date = {}
try:
model_field_start_date = \
self.env[model_name].search(ks_chart_domain + [(ks_chart_groupby_relation_field, '!=', False)], limit=1,
order=ks_chart_groupby_relation_field + " ASC")[
ks_chart_groupby_relation_field]
model_field_end_date = \
self.env[model_name].search(ks_chart_domain + [(ks_chart_groupby_relation_field, '!=', False)], limit=1,
order=ks_chart_groupby_relation_field + " DESC")[
ks_chart_groupby_relation_field]
except Exception as e:
model_field_start_date = model_field_end_date = False
pass
goal_model_start_date = \
self.env['ks_dashboard_ninja.item_goal'].search(ks_goal_domain, limit=1,
order='ks_goal_date ASC')['ks_goal_date']
goal_model_end_date = \
self.env['ks_dashboard_ninja.item_goal'].search(ks_goal_domain, limit=1,
order='ks_goal_date DESC')['ks_goal_date']
if model_field_start_date and ttype == "date":
model_field_end_date = model_field_end_date + " 23:59:59"
model_field_start_date = model_field_start_date + " 00:00:00"
if model_field_start_date and goal_model_start_date:
goal_model_start_date = goal_model_start_date + " 00:00:00"
goal_model_end_date = goal_model_end_date + " 23:59:59"
if fields.datetime.strptime(model_field_start_date, '%Y-%m-%d %H:%M:%S') < fields.datetime.strptime(
goal_model_start_date, '%Y-%m-%d %H:%M:%S'):
ks_start_end_date['start_date'] = model_field_start_date
else:
ks_start_end_date['start_date'] = goal_model_start_date
if fields.datetime.strptime(model_field_end_date, '%Y-%m-%d %H:%M:%S') > fields.datetime.strptime(
goal_model_end_date, '%Y-%m-%d %H:%M:%S'):
ks_start_end_date['end_date'] = model_field_end_date
else:
ks_start_end_date['end_date'] = goal_model_end_date
elif model_field_start_date and not goal_model_start_date:
ks_start_end_date['start_date'] = model_field_start_date
ks_start_end_date['end_date'] = model_field_end_date
elif goal_model_start_date and not model_field_start_date:
ks_start_end_date['start_date'] = goal_model_start_date
ks_start_end_date['end_date'] = goal_model_start_date
else:
ks_start_end_date['start_date'] = False
ks_start_end_date['end_date'] = False
return ks_start_end_date
class KsDashboardItemsGoal(models.Model):
_name = 'ks_dashboard_ninja.item_goal'
_description = 'Dashboard Ninja Items Goal Lines'
ks_goal_date = fields.Date(string="Date")
ks_goal_value = fields.Float(string="Value")
ks_dashboard_item = fields.Many2one('ks_dashboard_ninja.item', string="Dashboard Item")
class KsDashboardItemsActions(models.Model):
_name = 'ks_dashboard_ninja.item_action'
_description = 'Dashboard Ninja Items Action Lines'
ks_item_action_field = fields.Many2one('ir.model.fields',
domain="[('model_id','=',ks_model_id),('name','!=','id'),('store','=',True),"
"('ttype','!=','binary'),('ttype','!=','many2many'), ('ttype','!=','one2many')]",
string="Action Group By")
ks_item_action_field_type = fields.Char(compute="ks_get_item_action_type")
ks_item_action_date_groupby = fields.Selection([('minute', 'Minute'),
('hour', 'Hour'),
('day', 'Day'),
('week', 'Week'),
('month', 'Month'),
('quarter', 'Quarter'),
('year', 'Year'),
], string="Group By Date")
ks_chart_type = fields.Selection([('ks_bar_chart', 'Bar Chart'),
('ks_horizontalBar_chart', 'Horizontal Bar Chart'),
('ks_line_chart', 'Line Chart'),
('ks_area_chart', 'Area Chart'),
('ks_pie_chart', 'Pie Chart'),
('ks_doughnut_chart', 'Doughnut Chart'),
('ks_polarArea_chart', 'Polar Area Chart'),
('ks_list_view', 'List View')],
string="Item Type")
ks_dashboard_item_id = fields.Many2one('ks_dashboard_ninja.item', string="Dashboard Item")
ks_model_id = fields.Many2one('ir.model', related='ks_dashboard_item_id.ks_model_id')
sequence = fields.Integer(string="Sequence")
# For sorting and record limit
ks_record_limit = fields.Integer(string="Record Limit")
ks_sort_by_field = fields.Many2one('ir.model.fields',
domain="[('model_id','=',ks_model_id),('name','!=','id'),('store','=',True),"
"('ttype','!=','one2many'),('ttype','!=','binary')]",
string="Sort By Field")
ks_sort_by_order = fields.Selection([('ASC', 'Ascending'), ('DESC', 'Descending')],
string="Sort Order")
@api.depends('ks_item_action_field')
def ks_get_item_action_type(self):
for rec in self:
if rec.ks_item_action_field.ttype == 'datetime' or rec.ks_item_action_field.ttype == 'date':
rec.ks_item_action_field_type = 'date_type'
elif rec.ks_item_action_field.ttype == 'many2one':
rec.ks_item_action_field_type = 'relational_type'
rec.ks_item_action_date_groupby = False
elif rec.ks_item_action_field.ttype == 'selection':
rec.ks_item_action_field_type = 'selection'
rec.ks_item_action_date_groupby = False
else:
rec.ks_item_action_field_type = 'none'
rec.ks_item_action_date_groupby = False
@api.onchange('ks_item_action_date_groupby')
def ks_check_date_group_by(self):
for rec in self:
if rec.ks_item_action_field.ttype == 'date' and rec.ks_item_action_date_groupby in ['hour', 'minute']:
raise ValidationError(_('Action field: {} cannot be aggregated by {}').format(
rec.ks_item_action_field.display_name, rec.ks_item_action_date_groupby))
@api.onchange('ks_item_action_field')
def ks_onchange_item_action(self):
for rec in self:
if not (rec.ks_item_action_field.ttype == 'datetime' or rec.ks_item_action_field.ttype == 'date'):
rec.ks_item_action_date_groupby = False