diff --git a/ks_dashboard_ninja/__init__.py b/ks_dashboard_ninja/__init__.py
new file mode 100644
index 000000000..728ad5dac
--- /dev/null
+++ b/ks_dashboard_ninja/__init__.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from . import models
+from . import controllers
+from . import common_lib
+from . import wizard
+
+from odoo.api import Environment, SUPERUSER_ID
+
+
+def uninstall_hook(env):
+ # env = Environment(cr, SUPERUSER_ID, {})
+ for rec in env['ks_dashboard_ninja.board'].search([]):
+ rec.ks_dashboard_client_action_id.unlink()
+ rec.ks_dashboard_menu_id.unlink()
diff --git a/ks_dashboard_ninja/__manifest__.py b/ks_dashboard_ninja/__manifest__.py
new file mode 100644
index 000000000..59df7103d
--- /dev/null
+++ b/ks_dashboard_ninja/__manifest__.py
@@ -0,0 +1,76 @@
+# -*- coding: utf-8 -*-
+{
+ 'name': 'Dashboard Ninja',
+
+ 'summary': """
+ KS Dashboard Ninja
+ """,
+
+ 'description': """
+ Dashboard Ninja v17
+""",
+
+ 'author': 'Ksolves India Ltd.',
+
+ 'license': 'OPL-1',
+
+
+ 'website': 'https://store.ksolves.com/',
+
+ 'maintainer': 'Ksolves India Ltd.',
+
+ 'category': 'public_pur',
+ 'version': '17.0.1.8.3',
+
+ 'support': 'sales@ksolves.com',
+
+ 'images': ['static/description/Independence_sale.jpg'],
+
+ 'depends': ['base', 'web', 'base_setup', 'bus', 'base_geolocalize'],
+
+ 'data': [
+ 'security/ir.model.access.csv',
+ 'security/ks_security_groups.xml',
+ 'data/ks_default_data.xml',
+ 'data/ks_mail_cron.xml',
+ 'data/dn_data.xml',
+ 'data/sequence.xml',
+ 'views/res_settings.xml',
+ 'views/ks_dashboard_ninja_view.xml',
+ 'views/ks_dashboard_ninja_item_view.xml',
+ 'views/ks_dashboard_group_by.xml',
+ 'views/ks_dashboard_csv_group_by.xml',
+ 'views/ks_dashboard_action.xml',
+ 'views/ks_import_dashboard_view.xml',
+ 'wizard/ks_create_dashboard_wiz_view.xml',
+ 'wizard/ks_duplicate_dashboard_wiz_view.xml',
+ 'views/ks_ai_dashboard.xml',
+ 'views/ks_whole_ai_dashboard.xml',
+ 'views/ks_key_fetch.xml'
+ ],
+
+ 'demo': ['demo/ks_dashboard_ninja_demo.xml'],
+
+ 'assets': {
+ 'web.assets_backend':[
+ 'ks_dashboard_ninja/static/lib/css/Chart.css',
+ 'ks_dashboard_ninja/static/lib/css/gridstack.min.css',
+ 'ks_dashboard_ninja/static/lib/js/gridstack-h5.js',
+ 'ks_dashboard_ninja/static/lib/js/Chart.bundle.min.js',
+ 'ks_dashboard_ninja/static/src/css/*',
+ 'ks_dashboard_ninja/static/src/scss/*',
+ 'ks_dashboard_ninja/static/src/dashboard/*',
+ 'ks_dashboard_ninja/static/src/items/*',
+ 'ks_dashboard_ninja/static/src/items/**/*',
+ 'ks_dashboard_ninja/static/src/preview/**/*',
+ 'ks_dashboard_ninja/static/src/tools/*',
+ # 'ks_dashboard_ninja/static/src/**/**/*',
+ ],
+ },
+
+ 'external_dependencies': {
+ 'python': ['pandas','xlrd']
+ },
+
+ 'uninstall_hook': 'uninstall_hook',
+}
diff --git a/ks_dashboard_ninja/common_lib/__init__.py b/ks_dashboard_ninja/common_lib/__init__.py
new file mode 100644
index 000000000..7f95402fc
--- /dev/null
+++ b/ks_dashboard_ninja/common_lib/__init__.py
@@ -0,0 +1 @@
+from . import ks_date_filter_selections
diff --git a/ks_dashboard_ninja/common_lib/ks_date_filter_selections.py b/ks_dashboard_ninja/common_lib/ks_date_filter_selections.py
new file mode 100644
index 000000000..e0971409d
--- /dev/null
+++ b/ks_dashboard_ninja/common_lib/ks_date_filter_selections.py
@@ -0,0 +1,342 @@
+# -*- coding: utf-8 -*-
+
+from odoo.fields import datetime
+from odoo import _
+from odoo.exceptions import ValidationError
+from datetime import timedelta
+import pytz
+import os
+import os.path
+from dateutil import rrule
+from dateutil.relativedelta import relativedelta
+
+
+
+def ks_get_date(ks_date_filter_selection, self, type):
+ try:
+ timezone = self._context.get('tz')
+ except Exception as e:
+ timezone = self.env.user.tz
+
+ if not timezone:
+ ks_tzone = os.environ.get('TZ')
+ if ks_tzone:
+ timezone = ks_tzone
+ elif os.path.exists('/etc/timezone'):
+ ks_tzone = open('/etc/timezone').read()
+ timezone = ks_tzone[0:-1]
+ try:
+ datetime.now(pytz.timezone(timezone))
+ except Exception as e:
+ raise ValidationError(_("Please set the local timezone."))
+
+ else:
+ raise ValidationError(_("Please set the local timezone."))
+
+ series = ks_date_filter_selection
+ if ks_date_filter_selection in ['t_fiscal_year', 'n_fiscal_year', 'ls_fiscal_year']:
+ function_name = globals()["ks_date_series_" + series.split("_")[0]]
+ return function_name(series.split("_")[1], timezone, type, self)
+ else:
+ function_name = globals()["ks_date_series_" + series.split("_")[0]]
+ return function_name(series.split("_")[1], timezone, type, self)
+
+
+def ks_date_series_td(ks_date_selection, timezone, type, self=None):
+ ks_function_name = globals()["ks_get_date_range_from_td_" + ks_date_selection]
+ return ks_function_name(timezone, type, self)
+
+def ks_get_date_range_from_td_year(timezone, type,self):
+ ks_date_data = {}
+ date = datetime.now(pytz.timezone(timezone))
+ year = date.year
+ start_date = datetime(year, 1, 1)
+ end_date = date
+ if type == 'date':
+ ks_date_data["selected_start_date"] = datetime.strptime(start_date.strftime("%Y-%m-%d"), '%Y-%m-%d')
+ ks_date_data["selected_end_date"] = datetime.strptime(end_date.strftime("%Y-%m-%d"), '%Y-%m-%d')
+ else:
+ ks_date_data["selected_start_date"] = ks_convert_into_utc(start_date, timezone)
+ ks_date_data["selected_end_date"] = ks_convert_into_utc(end_date, timezone)
+ return ks_date_data
+
+def ks_get_date_range_from_td_month(timezone, type,self):
+ ks_date_data = {}
+
+ date = datetime.now(pytz.timezone(timezone))
+ year = date.year
+ month = date.month
+ start_date = datetime(year, month, 1)
+ end_date = date
+ if type == 'date':
+ ks_date_data["selected_start_date"] = datetime.strptime(start_date.strftime("%Y-%m-%d"), '%Y-%m-%d')
+ ks_date_data["selected_end_date"] = datetime.strptime(end_date.strftime("%Y-%m-%d"), '%Y-%m-%d')
+ else:
+ ks_date_data["selected_start_date"] = ks_convert_into_utc(start_date, timezone)
+ ks_date_data["selected_end_date"] = ks_convert_into_utc(end_date, timezone)
+ return ks_date_data
+def ks_get_date_range_from_td_week(timezone, type,self):
+ ks_date_data = {}
+ lang = self.env['res.lang']._lang_get(self.env.user.lang)
+ week_start = lang.week_start
+ start_Date = rrule.weekday(int(week_start) - 1)
+ start_date = datetime.today() + relativedelta(weekday=start_Date(-1))
+ end_date = datetime.now(pytz.timezone(timezone))
+ start_date = datetime.strptime(start_date.strftime("%Y-%m-%d"), '%Y-%m-%d')
+ if type == 'date':
+ ks_date_data["selected_start_date"] = start_date
+ end_date = datetime.strptime(end_date.strftime("%Y-%m-%d"), '%Y-%m-%d')
+ ks_date_data["selected_end_date"] = end_date
+ else:
+ ks_date_data["selected_start_date"] = ks_convert_into_utc(start_date, timezone)
+ ks_date_data["selected_end_date"] = ks_convert_into_utc(end_date, timezone)
+ return ks_date_data
+def ks_get_date_range_from_td_quarter(timezone, type,self):
+ ks_date_data = {}
+ date = datetime.now(pytz.timezone(timezone))
+ year = date.year
+ quarter = int((date.month - 1) / 3) + 1
+ start_date = datetime(year, 3 * quarter - 2, 1)
+ end_date = date
+ if type == 'date':
+ ks_date_data["selected_start_date"] = datetime.strptime(start_date.strftime("%Y-%m-%d"), '%Y-%m-%d')
+ ks_date_data["selected_end_date"] = datetime.strptime(end_date.strftime("%Y-%m-%d"), '%Y-%m-%d')
+ else:
+ ks_date_data["selected_start_date"] = ks_convert_into_utc(start_date, timezone)
+ ks_date_data["selected_end_date"] = ks_convert_into_utc(end_date, timezone)
+ return ks_date_data
+
+
+# Last Specific Days Ranges : 7, 30, 90, 365
+def ks_date_series_l(ks_date_selection, timezone, type, self=None):
+ ks_date_data = {}
+ date_filter_options = {
+ 'day': 0,
+ 'week': 7,
+ 'month': 30,
+ 'quarter': 90,
+ 'year': 365,
+ 'past': False,
+ 'future': False
+ }
+ end_time = datetime.strptime(datetime.now(pytz.timezone(timezone)).strftime("%Y-%m-%d 23:59:59"),
+ '%Y-%m-%d %H:%M:%S')
+ start_time = datetime.strptime((datetime.now(pytz.timezone(timezone)) - timedelta(
+ days=date_filter_options[ks_date_selection])).strftime("%Y-%m-%d 00:00:00"), '%Y-%m-%d %H:%M:%S')
+ if type == 'date':
+ ks_date_data["selected_end_date"] = datetime.strptime(end_time.strftime("%Y-%m-%d"), '%Y-%m-%d')
+ ks_date_data["selected_start_date"] = datetime.strptime(start_time.strftime("%Y-%m-%d"), '%Y-%m-%d')
+ else:
+ ks_date_data["selected_end_date"] = ks_convert_into_utc(end_time, timezone)
+ ks_date_data["selected_start_date"] = ks_convert_into_utc(start_time, timezone)
+
+ return ks_date_data
+
+
+# Current Date Ranges : Week, Month, Quarter, year
+def ks_date_series_t(ks_date_selection, timezone, type, self=None):
+ ks_function_name = globals()["ks_get_date_range_from_" + ks_date_selection]
+ return ks_function_name("current", timezone, type,self)
+
+
+# Previous Date Ranges : Week, Month, Quarter, year
+def ks_date_series_ls(ks_date_selection, timezone, type,self=None):
+ ks_function_name = globals()["ks_get_date_range_from_" + ks_date_selection]
+ return ks_function_name("previous", timezone, type,self)
+
+
+# Next Date Ranges : Day, Week, Month, Quarter, year
+def ks_date_series_n(ks_date_selection, timezone, type,self=None):
+ ks_function_name = globals()["ks_get_date_range_from_" + ks_date_selection]
+ return ks_function_name("next", timezone, type, self)
+
+
+def ks_get_date_range_from_day(date_state, timezone, type,self):
+ ks_date_data = {}
+
+ date = datetime.now(pytz.timezone(timezone))
+
+ if date_state == "previous":
+ date = date - timedelta(days=1)
+ elif date_state == "next":
+ date = date + timedelta(days=1)
+ start_date = datetime(date.year, date.month, date.day)
+ end_date = datetime(date.year, date.month, date.day) + timedelta(days=1, seconds=-1)
+ if type == 'date':
+ ks_date_data["selected_start_date"] = datetime.strptime(start_date.strftime("%Y-%m-%d"), '%Y-%m-%d')
+ ks_date_data["selected_end_date"] = datetime.strptime(end_date.strftime("%Y-%m-%d"), '%Y-%m-%d')
+ else:
+ ks_date_data["selected_start_date"] = ks_convert_into_utc(start_date,timezone)
+ ks_date_data["selected_end_date"] = ks_convert_into_utc(end_date,timezone)
+ return ks_date_data
+
+
+def ks_get_date_range_from_week(date_state, timezone, type,self):
+ ks_date_data = {}
+
+ # date = datetime.now(pytz.timezone(timezone))
+ # ks_week = 0
+ lang = self.env['res.lang']._lang_get(self.env.user.lang)
+ week_start = lang.week_start
+ start_Date = rrule.weekday(int(week_start) - 1)
+ start_date = datetime.today() + relativedelta(weekday=start_Date(-1))
+ if date_state == "previous":
+ start_date = datetime.today() - relativedelta(weeks=1, weekday=start_Date(-1))
+ elif date_state == "next":
+ start_date = datetime.today() - relativedelta(weeks=-1, weekday=start_Date(-1))
+
+ start_date = datetime.strptime(start_date.strftime("%Y-%m-%d"), '%Y-%m-%d')
+ if type == 'date':
+ ks_date_data["selected_start_date"] = start_date
+ end_date = start_date + timedelta(days=6, hours=23, minutes=59, seconds=59, milliseconds=59)
+ ks_date_data["selected_end_date"] = end_date
+ else:
+ ks_date_data["selected_start_date"] = ks_convert_into_utc(start_date, timezone)
+ end_date = start_date + timedelta(days=6, hours=23, minutes=59, seconds=59, milliseconds=59)
+ ks_date_data["selected_end_date"] = ks_convert_into_utc(end_date, timezone)
+ return ks_date_data
+
+def ks_get_date_range_from_month(date_state, timezone, type,self):
+ ks_date_data = {}
+
+ date = datetime.now(pytz.timezone(timezone))
+ year = date.year
+ month = date.month
+
+ if date_state == "previous":
+ month -= 1
+ if month == 0:
+ month = 12
+ year -= 1
+ elif date_state == "next":
+ month += 1
+ if month == 13:
+ month = 1
+ year += 1
+
+ end_year = year
+ end_month = month
+ if month == 12:
+ end_year += 1
+ end_month = 1
+ else:
+ end_month += 1
+ start_date = datetime(year, month, 1)
+ end_date = datetime(end_year, end_month, 1) - timedelta(seconds=1)
+ if type == 'date':
+ ks_date_data["selected_start_date"] = datetime.strptime(start_date.strftime("%Y-%m-%d"), '%Y-%m-%d')
+ ks_date_data["selected_end_date"] = datetime.strptime(end_date.strftime("%Y-%m-%d"), '%Y-%m-%d')
+ else:
+ ks_date_data["selected_start_date"] = ks_convert_into_utc(start_date, timezone)
+ ks_date_data["selected_end_date"] = ks_convert_into_utc(end_date, timezone)
+ return ks_date_data
+
+
+def ks_get_date_range_from_quarter(date_state, timezone, type,self):
+ ks_date_data = {}
+
+ date = datetime.now(pytz.timezone(timezone))
+ year = date.year
+ quarter = int((date.month - 1) / 3) + 1
+
+ if date_state == "previous":
+ quarter -= 1
+ if quarter == 0:
+ quarter = 4
+ year -= 1
+ elif date_state == "next":
+ quarter += 1
+ if quarter == 5:
+ quarter = 1
+ year += 1
+
+ start_date = datetime(year, 3 * quarter - 2, 1)
+
+ month = 3 * quarter
+ remaining = int(month / 12)
+ end_date = datetime(year + remaining, month % 12 + 1, 1) - timedelta(seconds=1)
+ if type == 'date':
+ ks_date_data["selected_start_date"] = datetime.strptime(start_date.strftime("%Y-%m-%d"), '%Y-%m-%d')
+ ks_date_data["selected_end_date"] = datetime.strptime(end_date.strftime("%Y-%m-%d"), '%Y-%m-%d')
+ else:
+ ks_date_data["selected_start_date"] = ks_convert_into_utc(start_date, timezone)
+ ks_date_data["selected_end_date"] = ks_convert_into_utc(end_date, timezone)
+ return ks_date_data
+
+
+def ks_get_date_range_from_year(date_state, timezone, type,self):
+ ks_date_data = {}
+
+ date = datetime.now(pytz.timezone(timezone))
+ year = date.year
+
+ if date_state == "previous":
+ year -= 1
+ elif date_state == "next":
+ year += 1
+ start_date = datetime(year, 1, 1)
+ end_date = datetime(year + 1, 1, 1) - timedelta(seconds=1)
+ if type == 'date':
+ ks_date_data["selected_start_date"] = datetime.strptime(start_date.strftime("%Y-%m-%d"), '%Y-%m-%d')
+ ks_date_data["selected_end_date"] = datetime.strptime(end_date.strftime("%Y-%m-%d"), '%Y-%m-%d')
+ else:
+ ks_date_data["selected_start_date"] = ks_convert_into_utc(start_date, timezone)
+ ks_date_data["selected_end_date"] = ks_convert_into_utc(end_date, timezone)
+ return ks_date_data
+
+def ks_get_date_range_from_past(date_state, self_tz, type, self):
+ ks_date_data = {}
+ date = datetime.now(pytz.timezone(self_tz))
+ if type == 'date':
+ ks_date_data["selected_end_date"] = datetime.strptime(date.strftime("%Y-%m-%d"), '%Y-%m-%d')
+ else:
+ ks_date_data["selected_end_date"] = ks_convert_into_utc(date, self_tz)
+ ks_date_data["selected_start_date"] = False
+ return ks_date_data
+
+
+def ks_get_date_range_from_pastwithout(date_state, self_tz, type,self):
+ ks_date_data = {}
+ date = datetime.now(pytz.timezone(self_tz))
+ hour = date.hour + 1
+ date = date - timedelta(hours=hour)
+ date = datetime.strptime(date.strftime("%Y-%m-%d 23:59:59"), '%Y-%m-%d %H:%M:%S')
+ ks_date_data["selected_start_date"] = False
+ if type == 'date':
+ ks_date_data["selected_end_date"] = datetime.strptime(date.strftime("%Y-%m-%d"), '%Y-%m-%d')
+ else:
+ ks_date_data["selected_end_date"] = ks_convert_into_utc(date, self_tz)
+ return ks_date_data
+
+
+def ks_get_date_range_from_future(date_state, self_tz, type,self):
+ ks_date_data = {}
+ date = datetime.now(pytz.timezone(self_tz))
+ ks_date_data["selected_end_date"] = False
+ if type == 'date':
+ ks_date_data["selected_start_date"] = date.strptime(date.strftime("%Y-%m-%d"), '%Y-%m-%d')
+ else:
+ ks_date_data["selected_start_date"] = ks_convert_into_utc(date,self_tz)
+ return ks_date_data
+
+
+def ks_get_date_range_from_futurestarting(date_state, self_tz, type,self):
+ ks_date_data = {}
+ date = datetime.now(pytz.timezone(self_tz))
+ date = date + timedelta(days=1)
+ start_date = datetime.strptime(date.strftime("%Y-%m-%d 00:00:00"), '%Y-%m-%d %H:%M:%S')
+ if type == 'date':
+ ks_date_data["selected_start_date"] = datetime.strptime(start_date.strftime("%Y-%m-%d"), '%Y-%m-%d')
+ ks_date_data["selected_end_date"] = False
+ else:
+ ks_date_data["selected_start_date"] = ks_convert_into_utc(start_date, self_tz)
+ ks_date_data["selected_end_date"] = False
+ return ks_date_data
+
+def ks_convert_into_utc(datetime, timezone):
+ ks_tz = timezone and pytz.timezone(timezone) or pytz.UTC
+ return ks_tz.localize(datetime.replace(tzinfo=None), is_dst=False).astimezone(pytz.UTC).replace(tzinfo=None)
+
+def ks_convert_into_local(datetime, timezone):
+ ks_tz = timezone and pytz.timezone(timezone) or pytz.UTC
+ return pytz.UTC.localize(datetime.replace(tzinfo=None), is_dst=False).astimezone(ks_tz).replace(tzinfo=None)
\ No newline at end of file
diff --git a/ks_dashboard_ninja/controllers/__init__.py b/ks_dashboard_ninja/controllers/__init__.py
new file mode 100644
index 000000000..fa2f9cbfd
--- /dev/null
+++ b/ks_dashboard_ninja/controllers/__init__.py
@@ -0,0 +1,3 @@
+from . import ks_chart_export
+from . import ks_list_export
+from . import ks_dashboard_export
\ No newline at end of file
diff --git a/ks_dashboard_ninja/controllers/ks_chart_export.py b/ks_dashboard_ninja/controllers/ks_chart_export.py
new file mode 100644
index 000000000..dbd400b6b
--- /dev/null
+++ b/ks_dashboard_ninja/controllers/ks_chart_export.py
@@ -0,0 +1,115 @@
+
+import re
+import datetime
+import io
+import json
+import operator
+import logging
+
+from odoo.addons.web.controllers.main import ExportFormat, ExportXlsxWriter
+from odoo.tools.translate import _
+from werkzeug.exceptions import InternalServerError
+from odoo import http
+from odoo.http import content_disposition, request
+from odoo.tools.misc import xlwt
+from odoo.exceptions import UserError
+from odoo.tools import pycompat
+_logger = logging.getLogger(__name__)
+
+class KsChartExport(http.Controller):
+
+ def base(self, data):
+ params = json.loads(data)
+ header,chart_data = operator.itemgetter('header','chart_data')(params)
+ chart_data = json.loads(chart_data)
+ chart_data['labels'].insert(0,'Measure')
+ columns_headers = chart_data['labels']
+ import_data = []
+
+ for dataset in chart_data['datasets']:
+ dataset['data'].insert(0, dataset['label'])
+ import_data.append(dataset['data'])
+
+ return request.make_response(self.from_data(columns_headers, import_data),
+ headers=[('Content-Disposition',
+ content_disposition(self.filename(header))),
+ ('Content-Type', self.content_type)],
+ # cookies={'fileToken': token}
+ )
+
+
+
+
+class KsChartExcelExport(KsChartExport, http.Controller):
+
+ # Excel needs raw data to correctly handle numbers and date values
+ raw_data = True
+
+ @http.route('/ks_dashboard_ninja/export/chart_xls', type='http', auth="user")
+ def index(self, data):
+ try:
+ return self.base(data)
+ except Exception as exc:
+ _logger.exception("Exception during request handling.")
+ payload = json.dumps({
+ 'code': 200,
+ 'message': "Odoo Server Error",
+ 'data': http.serialize_exception(exc)
+ })
+ raise InternalServerError(payload) from exc
+
+ @property
+ def content_type(self):
+ return 'application/vnd.ms-excel'
+
+ def filename(self, base):
+ return base + '.xlsx'
+
+ def from_data(self, fields, rows):
+ with ExportXlsxWriter(fields, len(rows)) as xlsx_writer:
+ for row_index, row in enumerate(rows):
+ for cell_index, cell_value in enumerate(row):
+ xlsx_writer.write_cell(row_index + 1, cell_index, cell_value)
+
+ return xlsx_writer.value
+
+
+class KsChartCsvExport(KsChartExport, http.Controller):
+
+ @http.route('/ks_dashboard_ninja/export/chart_csv', type='http', auth="user")
+ def index(self, data):
+ try:
+ return self.base(data)
+ except Exception as exc:
+ _logger.exception("Exception during request handling.")
+ payload = json.dumps({
+ 'code': 200,
+ 'message': "Odoo Server Error",
+ 'data': http.serialize_exception(exc)
+ })
+ raise InternalServerError(payload) from exc
+
+ @property
+ def content_type(self):
+ return 'text/csv;charset=utf8'
+
+ def filename(self, base):
+ return base + '.csv'
+
+ def from_data(self, fields, rows):
+ fp = io.BytesIO()
+ writer = pycompat.csv_writer(fp, quoting=1)
+
+ writer.writerow(fields)
+
+ for data in rows:
+ row = []
+ for d in data:
+ # Spreadsheet apps tend to detect formulas on leading =, + and -
+ if isinstance(d, str) and d.startswith(('=', '-', '+')):
+ d = "'" + d
+
+ row.append(pycompat.to_text(d))
+ writer.writerow(row)
+
+ return fp.getvalue()
diff --git a/ks_dashboard_ninja/controllers/ks_dashboard_export.py b/ks_dashboard_ninja/controllers/ks_dashboard_export.py
new file mode 100644
index 000000000..85f37ca6a
--- /dev/null
+++ b/ks_dashboard_ninja/controllers/ks_dashboard_export.py
@@ -0,0 +1,87 @@
+import io
+import json
+import operator
+import logging
+
+from odoo.addons.web.controllers.main import ExportFormat
+
+from odoo import http
+from odoo.http import request
+from odoo.http import content_disposition,request
+from werkzeug.exceptions import InternalServerError
+_logger = logging.getLogger(__name__)
+
+
+class KsDashboardExport(http.Controller):
+
+ def base(self, data):
+ params = json.loads(data)
+ header, dashboard_data = operator.itemgetter('header', 'dashboard_data')(params)
+ return request.make_response(self.from_data(dashboard_data),
+ headers=[('Content-Disposition',
+ content_disposition(self.filename(header))),
+ ('Content-Type', self.content_type)],
+ # cookies={'fileToken': token}
+ )
+
+
+class KsDashboardJsonExport(KsDashboardExport, http.Controller):
+
+ @http.route('/ks_dashboard_ninja/export/dashboard_json', type='http', auth="user")
+ def index(self, data):
+ try:
+ return self.base(data)
+ except Exception as exc:
+ _logger.exception("Exception during request handling.")
+ payload = json.dumps({
+ 'code': 200,
+ 'message': "Odoo Server Error",
+ 'data': http.serialize_exception(exc)
+ })
+ raise InternalServerError(payload) from exc
+
+ @property
+ def content_type(self):
+ return 'text/csv;charset=utf8'
+
+ def filename(self, base):
+ return base + '.json'
+
+ def from_data(self, dashboard_data):
+ fp = io.StringIO()
+ fp.write(json.dumps(dashboard_data))
+
+ return fp.getvalue()
+
+class KsItemJsonExport(KsDashboardExport, http.Controller):
+
+ @http.route('/ks_dashboard_ninja/export/item_json', type='http', auth="user")
+ def index(self, data):
+ try:
+ data = json.loads(data)
+ item_id = data["item_id"]
+ data['dashboard_data'] = request.env['ks_dashboard_ninja.board'].ks_export_item(item_id)
+ data = json.dumps(data)
+ return self.base(data)
+ except Exception as exc:
+ _logger.exception("Exception during request handling.")
+ payload = json.dumps({
+ 'code': 200,
+ 'message': "Odoo Server Error",
+ 'data': http.serialize_exception(exc)
+ })
+ raise InternalServerError(payload) from exc
+
+
+ @property
+ def content_type(self):
+ return 'text/csv;charset=utf8'
+
+ def filename(self, base):
+ return base + '.json'
+
+ def from_data(self, dashboard_data):
+ fp = io.StringIO()
+ fp.write(json.dumps(dashboard_data))
+
+ return fp.getvalue()
diff --git a/ks_dashboard_ninja/controllers/ks_list_export.py b/ks_dashboard_ninja/controllers/ks_list_export.py
new file mode 100644
index 000000000..6802a8217
--- /dev/null
+++ b/ks_dashboard_ninja/controllers/ks_list_export.py
@@ -0,0 +1,204 @@
+
+import re
+import io
+import json
+import operator
+import logging
+from odoo.addons.web.controllers.main import ExportFormat, ExportXlsxWriter
+from odoo.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT, DEFAULT_SERVER_DATE_FORMAT
+import datetime
+from odoo import http
+from odoo.http import content_disposition, request
+from odoo.tools import pycompat
+from ..common_lib.ks_date_filter_selections import ks_get_date, ks_convert_into_utc, ks_convert_into_local
+import os
+import pytz
+from werkzeug.exceptions import InternalServerError
+_logger = logging.getLogger(__name__)
+
+
+class KsListExport(http.Controller):
+
+ def base(self, data):
+ params = json.loads(data)
+ # header,list_data = operator.itemgetter('header','chart_data')(params)
+ header, list_data, item_id, ks_export_boolean, context, params = operator.itemgetter('header', 'chart_data',
+ 'ks_item_id',
+ 'ks_export_boolean',
+ 'context', 'params')(
+ params)
+ list_data = json.loads(list_data)
+ if ks_export_boolean:
+ item = request.env['ks_dashboard_ninja.item'].browse(int(item_id))
+ ks_timezone = item._context.get('tz') or item.env.user.tz
+ if not ks_timezone:
+ ks_tzone = os.environ.get('TZ')
+ if ks_tzone:
+ ks_timezone = ks_tzone
+ elif os.path.exists('/etc/timezone'):
+ ks_tzone = open('/etc/timezone').read()
+ ks_timezone = ks_tzone[0:-1]
+ try:
+ datetime.now(pytz.timezone(ks_timezone))
+ except Exception as e:
+ _logger.info('Please set the local timezone')
+
+ else:
+ _logger.info('Please set the local timezone')
+ orderby = item.ks_sort_by_field.id
+ sort_order = item.ks_sort_by_order
+ ks_start_date = context.get('ksDateFilterStartDate', False)
+ ks_end_date = context.get('ksDateFilterEndDate', False)
+ ksDateFilterSelection = context.get('ksDateFilterSelection', False)
+ if context.get('allowed_company_ids', False):
+ item = item.with_context(allowed_company_ids=context.get('allowed_company_ids'))
+ if item.ks_data_calculation_type == 'query':
+ query_start_date = item.ks_query_start_date
+ query_end_date = item.ks_query_end_date
+ ks_query = str(item.ks_custom_query)
+ if ks_start_date and ks_end_date:
+ ks_start_date = datetime.datetime.strptime(ks_start_date,DEFAULT_SERVER_DATETIME_FORMAT)
+ ks_end_date = datetime.datetime.strptime(ks_end_date,DEFAULT_SERVER_DATETIME_FORMAT)
+ item = item.with_context(ksDateFilterStartDate=ks_start_date)
+ item = item.with_context(ksDateFilterEndDate=ks_end_date)
+ item = item.with_context(ksDateFilterSelection=ksDateFilterSelection)
+
+ if item._context.get('ksDateFilterSelection', False):
+ ks_date_filter_selection = item._context['ksDateFilterSelection']
+ if ks_date_filter_selection == 'l_custom':
+ item = item.with_context(ksDateFilterStartDate=ks_start_date)
+ item = item.with_context(ksDateFilterEndDate=ks_end_date)
+ item = item.with_context(ksIsDefultCustomDateFilter=False)
+
+ else:
+ ks_date_filter_selection = item.ks_dashboard_ninja_board_id.ks_date_filter_selection
+ item = item.with_context(ksDateFilterStartDate=item.ks_dashboard_ninja_board_id.ks_dashboard_start_date)
+ item = item.with_context(ksDateFilterEndDate=item.ks_dashboard_ninja_board_id.ks_dashboard_end_date)
+ item = item.with_context(ksDateFilterSelection=ks_date_filter_selection)
+ item = item.with_context(ksIsDefultCustomDateFilter=True)
+
+ if ks_date_filter_selection not in ['l_custom', 'l_none']:
+ ks_date_data = ks_get_date(ks_date_filter_selection, request, 'datetime')
+ item = item.with_context(ksDateFilterStartDate=ks_date_data["selected_start_date"])
+ item = item.with_context(ksDateFilterEndDate=ks_date_data["selected_end_date"])
+
+ item_domain = params.get('ks_domain_1', [])
+ ks_chart_domain = item.ks_convert_into_proper_domain(item.ks_domain, item,item_domain)
+ # list_data = item.ks_fetch_list_view_data(item,ks_chart_domain, ks_export_all=
+ if list_data['type'] == 'ungrouped':
+ list_data = item.ks_fetch_list_view_data(item, ks_chart_domain, ks_export_all=True)
+ elif list_data['type'] == 'grouped':
+ list_data = item.get_list_view_record(orderby, sort_order, ks_chart_domain, ks_export_all=True)
+ elif item.ks_data_calculation_type == 'query':
+ if ks_start_date or ks_end_date:
+ query_start_date = ks_start_date
+ query_end_date = ks_end_date
+ ks_query_result = item.ks_get_list_query_result(ks_query, query_start_date, query_end_date, ks_offset=0,
+ ks_export_all=True)
+ list_data = item.ks_format_query_result(ks_query_result)
+
+ # chart_data['labels'].insert(0,'Measure')
+ columns_headers = list_data['label']
+ import_data = []
+
+ for dataset in list_data['data_rows']:
+ if not list_data['type'] == 'grouped':
+ for count, index in enumerate(dataset['ks_column_type']):
+ if index == 'datetime':
+ ks_converted_date = False
+ date_string = dataset['data'][count]
+ if dataset['data'][count]:
+ ks_converted_date = ks_convert_into_local(datetime.datetime.strptime(date_string, '%m/%d/%y %H:%M:%S'),ks_timezone)
+ dataset['data'][count] = ks_converted_date
+ for ks_count, val in enumerate(dataset['data']):
+ if isinstance(val, (float, int)):
+ if val >= 0:
+ try:
+ ks_precision = item.sudo().env.ref('ks_dashboard_ninja.ks_dashboard_ninja_precision').digits
+ except Exception as e:
+ ks_precision = 2
+ dataset['data'][ks_count] = item.env['ir.qweb.field.float'].sudo().value_to_html(val,
+ {'precision': ks_precision})
+ import_data.append(dataset['data'])
+
+ return request.make_response(self.from_data(columns_headers, import_data),
+ headers=[('Content-Disposition',
+ content_disposition(self.filename(header))),
+ ('Content-Type', self.content_type)],
+ # cookies={'fileToken': token}
+ )
+
+
+class KsListExcelExport(KsListExport, http.Controller):
+
+ # Excel needs raw data to correctly handle numbers and date values
+ raw_data = True
+
+ @http.route('/ks_dashboard_ninja/export/list_xls', type='http', auth="user")
+ def index(self, data):
+ try:
+ return self.base(data)
+ except Exception as exc:
+ _logger.exception("Exception during request handling.")
+ payload = json.dumps({
+ 'code': 200,
+ 'message': "Odoo Server Error",
+ 'data': http.serialize_exception(exc)
+ })
+ raise InternalServerError(payload) from exc
+
+ @property
+ def content_type(self):
+ return 'application/vnd.ms-excel'
+
+ def filename(self, base):
+ return base + '.xlsx'
+
+ def from_data(self, fields, rows):
+ with ExportXlsxWriter(fields, len(rows)) as xlsx_writer:
+ for row_index, row in enumerate(rows):
+ for cell_index, cell_value in enumerate(row):
+ xlsx_writer.write_cell(row_index + 1, cell_index, cell_value)
+
+ return xlsx_writer.value
+
+
+class KsListCsvExport(KsListExport, http.Controller):
+
+ @http.route('/ks_dashboard_ninja/export/list_csv', type='http', auth="user")
+ def index(self, data):
+ try:
+ return self.base(data)
+ except Exception as exc:
+ _logger.exception("Exception during request handling.")
+ payload = json.dumps({
+ 'code': 200,
+ 'message': "Odoo Server Error",
+ 'data': http.serialize_exception(exc)
+ })
+ raise InternalServerError(payload) from exc
+
+ @property
+ def content_type(self):
+ return 'text/csv;charset=utf8'
+
+ def filename(self, base):
+ return base + '.csv'
+
+ def from_data(self, fields, rows):
+ fp = io.BytesIO()
+ writer = pycompat.csv_writer(fp, quoting=1)
+
+ writer.writerow(fields)
+
+ for data in rows:
+ row = []
+ for d in data:
+ # Spreadsheet apps tend to detect formulas on leading =, + and -
+ if isinstance(d, str) and d.startswith(('=', '-', '+')):
+ d = "'" + d
+
+ row.append(pycompat.to_text(d))
+ writer.writerow(row)
+
+ return fp.getvalue()
diff --git a/ks_dashboard_ninja/data/dn_data.xml b/ks_dashboard_ninja/data/dn_data.xml
new file mode 100644
index 000000000..040edcef7
--- /dev/null
+++ b/ks_dashboard_ninja/data/dn_data.xml
@@ -0,0 +1,9 @@
+
+
\n" +" You can find all items related to Dashboard Here.
\n" +" " +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_ninja_dashboard_item_action__ks_action +msgid "Action" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__ks_item_action_field +msgid "Action Group By" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_action_lines +msgid "Action Lines" +msgstr "" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py:0 +#, python-format +msgid "Action field: {} cannot be aggregated by {}" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_actions +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Actions" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_active +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__ks_is_active +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Active" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_description__ks_active +msgid "Active Description" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Add" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Add Item" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Add a Line" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Add a Section" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dn_global_filter.xml:0 +#, python-format +msgid "Add a condition" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.board_form +msgid "Add a filter" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.board_form +msgid "Add a separator" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Add button" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Advance Configuration" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "" +"All Target Lines Changes Will be reflected on Chart after saving the record " +"and pagination will be ignore ." +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__l_none +#, python-format +msgid "All Time" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_import_dashboard.js:0 +#, python-format +msgid "All items can not be Imported" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dn_global_filter.xml:0 +#, python-format +msgid "Apply" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_import_dashboard.js:0 +#: code:addons/ks_dashboard_ninja/static/src/js/ks_import_dashboard.js:0 +#, python-format +msgid "Archive" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_import_dashboard.js:0 +#: code:addons/ks_dashboard_ninja/static/src/js/ks_import_dashboard.js:0 +#, python-format +msgid "Are you sure that you want to archive all the selected records?" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#, python-format +msgid "Are you sure you want to remove this item?" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_to_do_dashboard.js:0 +#, python-format +msgid "Are you sure you want to remove this task?" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_dashboard_item_type__ks_area_chart +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_chart_type__ks_area_chart +#, python-format +msgid "Area Chart" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_sort_by_order__asc +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_sort_by_order__asc +msgid "Ascending" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Auto Update" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_auto_update_type +msgid "Auto Update Type" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_data_count_type__average +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_record_count_type_2__average +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_record_count_type__average +msgid "Average" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_background_color +msgid "Background Color" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_dashboard_item_type__ks_bar_chart +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_chart_type__ks_bar_chart +#, python-format +msgid "Bar Chart" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model,name:ks_dashboard_ninja.model_base +msgid "Base" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Below action will be performed at the end of the Drill Down Action" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.ks_dashboard_ninja_action +msgid "Cancel" +msgstr "" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py:0 +#, python-format +msgid "" +"Cannot create target lines when Group By Date field is set to have " +"aggregation in Minute and Hour case." +msgstr "" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py:0 +#, python-format +msgid "" +"Cannot set aggregation having Date time (Hour, Minute) when target lines per" +" date are being used. To proceed this, first delete target lines" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#, python-format +msgid "" +"Changing Layout midway will set the default icon colour and font colour for " +"selected layout." +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_item_color +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Chart Color Palette" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_data +msgid "Chart Data in string form" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_show_live_pop_up +msgid "Checkbox to enable notification after every update. " +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_previous_period +msgid "" +"Checkbox to show comparison between the data of present day and the previous" +" selected period. " +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_icon_select +msgid "Choose the Icon option. " +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Clear" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_is_client_action +msgid "Client Action" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_client_action +msgid "Client Item Action" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_to_do_dashboard.js:0 +#: code:addons/ks_dashboard_ninja/static/src/js/ks_to_do_dashboard.js:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#, python-format +msgid "Close" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_data_format__colombian +msgid "Colombian Peso Format" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#, python-format +msgid "Color Palette" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#, python-format +msgid "Coming Soon in Future :)" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_company_id +msgid "Company" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.ui.menu,name:ks_dashboard_ninja.configuration_menu +msgid "Configuration" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_item_color__cool +msgid "Cool" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_data_count_type__count +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_record_count_type_2__count +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_record_count_type__count +msgid "Count" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_quick_edit_form_view +msgid "Count..." +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__create_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_custom_filters__create_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__create_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_template__create_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_child_board__create_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__create_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__create_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_goal__create_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_ninja_dashboard_item_action__create_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_description__create_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_headers__create_uid +msgid "Created by" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__create_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_custom_filters__create_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__create_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_template__create_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_child_board__create_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__create_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__create_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_goal__create_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_ninja_dashboard_item_action__create_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_description__create_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_headers__create_date +msgid "Created on" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_cumulative +msgid "Cumulative As Line" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_cumulative_field +msgid "Cumulative Field" +msgstr "" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja.py:0 +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja.py:0 +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja.py:0 +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja.py:0 +#, python-format +msgid "" +"Current Json File is not properly formatted according to Dashboard Ninja " +"Model." +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board_template__ks_template_type__ks_custom +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_unit_selection__custom +msgid "Custom" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dn_global_filter.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__l_custom +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__l_custom +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__l_custom +#, python-format +msgid "Custom Filter" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.board_form +msgid "Custom Filters" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_data_calculation_type__query +msgid "Custom Query" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Customize Dashboard" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#, python-format +msgid "Customize Item" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_custom_filters__ks_dashboard_board_id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__ks_dashboard_board_id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_template__ks_dashboard_board_id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_dashboard_ninja_board_id +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.child_board_tree +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item +msgid "Dashboard" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_custom_filters_ids +msgid "Dashboard Custom Filters" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.board_defined_filters +msgid "Dashboard Defined Filter" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__ks_dashboard_item_id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_goal__ks_dashboard_item +msgid "Dashboard Item" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.ks_dashboard_ninja_action +msgid "Dashboard Item Action" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_date_groupby +msgid "Dashboard Item Chart Group By Type" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_date_sub_groupby +msgid "Dashboard Item Chart Sub Group By Type" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_dashboard_item_type +msgid "Dashboard Item Type" +msgstr "" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja.py:0 +#: model:ir.actions.act_window,name:ks_dashboard_ninja.item_action_window +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_items_ids +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_ninja_dashboard_item_action__ks_dashboard_item_ids +#, python-format +msgid "Dashboard Items" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.child_board_tree +msgid "Dashboard Layout" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.ui.menu,name:ks_dashboard_ninja.dashboard_layout_menu +msgid "Dashboard Layouts" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.actions.act_window,name:ks_dashboard_ninja.board_form_tree_action_window +msgid "Dashboard Manager" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__name +msgid "Dashboard Name" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model,name:ks_dashboard_ninja.model_ks_dashboard_ninja_board +msgid "Dashboard Ninja" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model,name:ks_dashboard_ninja.model_ks_dashboard_ninja_child_board +msgid "Dashboard Ninja Child Board" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model,name:ks_dashboard_ninja.model_ks_dashboard_ninja_board_custom_filters +msgid "Dashboard Ninja Custom Filters" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model,name:ks_dashboard_ninja.model_ks_dashboard_ninja_board_defined_filters +msgid "Dashboard Ninja Defined Filters" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model,name:ks_dashboard_ninja.model_ks_ninja_dashboard_item_action +msgid "Dashboard Ninja Item Actions" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model,name:ks_dashboard_ninja.model_ks_dashboard_ninja_item_action +msgid "Dashboard Ninja Items Action Lines" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model,name:ks_dashboard_ninja.model_ks_dashboard_ninja_item_goal +msgid "Dashboard Ninja Items Goal Lines" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.module.category,name:ks_dashboard_ninja.ks_dashboard_ninja_security_groups +msgid "Dashboard Ninja Rights" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model,name:ks_dashboard_ninja.model_ks_dashboard_ninja_board_template +msgid "Dashboard Ninja Template" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model,name:ks_dashboard_ninja.model_ks_dashboard_ninja_item +msgid "Dashboard Ninja items" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_defined_filters_ids +msgid "Dashboard Predefined Filters" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.actions.act_window,name:ks_dashboard_ninja.template_tree_action_window +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_default_template +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_dashboard_board_template_id +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.board_template_form +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.board_template_tree +msgid "Dashboard Template" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.actions.act_window,name:ks_dashboard_ninja.layout_tree_action_window +msgid "Dashboard layout" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.ui.menu,name:ks_dashboard_ninja.dashboard_menu +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.board_form +msgid "Dashboards" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Data" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Data #2" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Data Calculation" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_data_calculation_type +msgid "Data Calculation Type" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_kpi_type__layout_2 +msgid "Data Comparison" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_measure_field_2 +msgid "Data Points displayed with a line in the graph. " +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_data_count_type +msgid "Data Type" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_cumulative_field +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_measure_field +msgid "Data points to be selected." +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_board_custom_filters__ks_model_id +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__ks_model_id +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_model_id +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__ks_model_id +msgid "" +"Data source to fetch and read the data for the creation of dashboard items. " +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_goal__ks_goal_date +msgid "Date" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#, python-format +msgid "Date Filter" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_date_filter_field +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Date Filter Field" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_date_filter_selection +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Date Filter Selection" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_groupby__day +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_sub_groupby__day +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_item_action_date_groupby__day +msgid "Day" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_item_color__default +msgid "Default" +msgstr "" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja.py:0 +#, python-format +msgid "Default Dashboard can't be deleted." +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_date_filter_selection +msgid "Default Date Filter" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_widget_toggle.xml:0 +#, python-format +msgid "Default Icons" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_data_calculation_type__custom +msgid "Default Query" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_set_interval +msgid "Default Update Interval" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_domain_extension +msgid "Define conditions for filter to write manually" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__ks_domain +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_domain +msgid "Define conditions for filter. " +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_import_dashboard.js:0 +#: code:addons/ks_dashboard_ninja/static/src/js/ks_import_dashboard.js:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dn_global_filter.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dn_global_filter.xml:0 +#, python-format +msgid "Delete" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_sort_by_order__desc +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_sort_by_order__desc +msgid "Descending" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_description__ks_description +msgid "Description" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Deviation Field" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_quick_edit_view.xml:0 +#, python-format +msgid "Discard" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Discard Changes" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Display" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__display_name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_custom_filters__display_name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__display_name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_template__display_name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_child_board__display_name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__display_name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__display_name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_goal__display_name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_ninja_dashboard_item_action__display_name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_description__display_name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_headers__display_name +msgid "Display Name" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__display_type +msgid "Display Type" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_unit +msgid "Display the unit of the data." +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__ks_domain +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_domain +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Domain" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_domain_extension +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Domain Extension" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_custom_filters__ks_domain_field_id +msgid "Domain Field" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__ks_domain_temp +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_domain_temp +msgid "Domain Substitute" +msgstr "" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_filters.py:0 +#, python-format +msgid "Domain can not be empty" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_dashboard_item_type__ks_doughnut_chart +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_chart_type__ks_doughnut_chart +#, python-format +msgid "Doughnut Chart" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#, python-format +msgid "Drill Up" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#: model:ir.actions.server,name:ks_dashboard_ninja.ks_duplicate_dashboard +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_ninja_dashboard_item_action__ks_action__duplicate +#, python-format +msgid "Duplicate" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Edit Layout" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_to_do_dashboard.js:0 +#, python-format +msgid "Edit Task" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_goal_enable +msgid "Enable Target" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_end_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_item_end_date +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "End Date" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_data_format__global +msgid "English Format" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_unit +msgid "Enter Unit" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_data_formatting__exact +msgid "Exact" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_data_format__exact +msgid "Exact Value" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_import_dashboard.js:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#, python-format +msgid "Export" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_export_all_records +msgid "Export All Records" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#, python-format +msgid "Export Chart" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_import_dashboard.js:0 +#, python-format +msgid "Export Dashboard" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#, python-format +msgid "Export Item" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#, python-format +msgid "Export List" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#, python-format +msgid "Export to CSV" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#, python-format +msgid "Export to Excel" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#, python-format +msgid "Fields Required : Name, Model, Icon (Default or Custom Upload), Layout" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_list_view_fields +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_quick_edit_form_view +msgid "Fields to show in list" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_fill_temporal +msgid "Fill Temporal Value" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dn_global_filter.xml:0 +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +#, python-format +msgid "Filter" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_custom_filters__name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__name +msgid "Filter Label" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#, python-format +msgid "Font Awesome 4.7.0" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_font_color +msgid "Font Color" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_data_formatting +msgid "Format" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_quick_edit_view.xml:0 +#, python-format +msgid "Full Settings" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__n_future_starting_now +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__n_future_starting_now +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__n_future_starting_now +#, python-format +msgid "Future Starting Now" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__n_futurestarting_tomorrow +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__n_futurestarting_tomorrow +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__n_futurestarting_tomorrow +#, python-format +msgid "Future Starting Tomorrow" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__sequence +msgid "" +"Gives the sequence order when displaying a list of payment terms lines." +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_data_formatting__global +msgid "Global" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Goal Lines" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_graph_preview +msgid "Graph Preview" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_group_access +msgid "Group Access" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_relation_groupby +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_quick_edit_form_view +msgid "Group By" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__ks_item_action_date_groupby +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_quick_edit_form_view +msgid "Group By Date" +msgstr "" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py:0 +#, python-format +msgid "Groupby Field aggregation" +msgstr "" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py:0 +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py:0 +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py:0 +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py:0 +#, python-format +msgid "Groupby field: {} cannot be aggregated by {}" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_list_view_type__grouped +msgid "Grouped" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Groups/Dimensions" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_headers__ks_to_do_header +msgid "Header" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_header_bg_color +msgid "Header Background Color" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_hide_legend +msgid "Hide all legend from the chart item" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_dashboard_item_type__ks_horizontalbar_chart +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_chart_type__ks_horizontalbar_chart +#, python-format +msgid "Horizontal Bar Chart" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_groupby__hour +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_sub_groupby__hour +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_item_action_date_groupby__hour +msgid "Hour" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_custom_filters__id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_template__id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_child_board__id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_goal__id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_ninja_dashboard_item_action__id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_description__id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_headers__id +msgid "ID" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_default_icon +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Icon" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_default_icon_color +msgid "Icon Color" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_icon_select +msgid "Icon Option" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_import_list_view_template.xml:0 +#, python-format +msgid "Import Dashboard" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Import Item" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_compare_period +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Include Period" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_data_formatting__indian +msgid "Indian" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_data_format__indian +msgid "Indian Format" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#, python-format +msgid "Invalid Date" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_child_board__ks_active +msgid "Is Selected" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Item Action" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_gridstack_config +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_child_board__ks_gridstack_config +msgid "Item Configurations" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#, python-format +msgid "Item Duplicated" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#, python-format +msgid "Item Moved" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__ks_chart_type +msgid "Item Type" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_update_items_data +msgid "Item Update Interval" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_quick_edit_form_view +msgid "Item Update Interval.." +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_dashboard_item_type__ks_kpi +#, python-format +msgid "KPI" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_kpi_data +msgid "KPI Data" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_domain_extension_2 +msgid "KPI Domain Extension" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_compare_period_2 +msgid "KPI Include Period" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_record_count_2 +msgid "KPI Record Count" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_year_period_2 +msgid "KPI Same Period Previous Years" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_kpi_type__layout_1 +msgid "KPI With Target" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_data_comparison +msgid "Kpi Data Type" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_date_filter_field_2 +msgid "Kpi Date Filter Field" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_date_filter_selection_2 +msgid "Kpi Date Filter Selection" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_domain_2 +msgid "Kpi Domain" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_domain_2_temp +msgid "Kpi Domain Substitute" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_item_end_date_2 +msgid "Kpi End Date" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_kpi_type +msgid "Kpi Layout" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_model_id_2 +msgid "Kpi Model" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_model_name_2 +msgid "Kpi Model Name" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_kpi_preview +msgid "Kpi Preview" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_record_field_2 +msgid "Kpi Record Field" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_record_count_type_2 +msgid "Kpi Record Type" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_item_start_date_2 +msgid "Kpi Start Date" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_groupby_type +msgid "Ks Chart Groupby Type" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_sub_groupby_type +msgid "Ks Chart Sub Groupby Type" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_child_dashboard_ids +msgid "Ks Child Dashboard" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_client_action_id +msgid "Ks Dashboard Client Action" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_menu_id +msgid "Ks Dashboard Menu" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_state +msgid "Ks Dashboard State" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_dn_header_lines +msgid "Ks Dn Header Lines" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_headers__ks_dn_item_id +msgid "Ks Dn Item" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_template__ks_gridstack_config +msgid "Ks Gridstack Config" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_isDateFilterApplied +msgid "Ks Isdatefilterapplied" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__ks_item_action_field_type +msgid "Ks Item Action Field Type" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_template__ks_item_count +msgid "Ks Item Count" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_many2many_field_ordering +msgid "Ks Many2Many Field Ordering" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_headers__ks_to_do_description_lines +msgid "Ks To Do Description Lines" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_description__ks_to_do_header_id +msgid "Ks To Do Header" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__l_month +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__l_month +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__l_month +#, python-format +msgid "Last 30 days" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__l_year +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__l_year +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__l_year +#, python-format +msgid "Last 365 days" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__l_week +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__l_week +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__l_week +#, python-format +msgid "Last 7 days" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__l_quarter +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__l_quarter +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__l_quarter +#, python-format +msgid "Last 90 days" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__ls_day +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__ls_day +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__ls_day +#, python-format +msgid "Last Day" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board____last_update +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_custom_filters____last_update +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters____last_update +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_template____last_update +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_child_board____last_update +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item____last_update +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action____last_update +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_goal____last_update +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_ninja_dashboard_item_action____last_update +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_description____last_update +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_headers____last_update +msgid "Last Modified on" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__ls_month +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__ls_month +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__ls_month +#, python-format +msgid "Last Month" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__ls_quarter +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__ls_quarter +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__ls_quarter +#, python-format +msgid "Last Quarter" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__write_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_custom_filters__write_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__write_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_template__write_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_child_board__write_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__write_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__write_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_goal__write_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_ninja_dashboard_item_action__write_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_description__write_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_headers__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__write_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_custom_filters__write_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__write_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_template__write_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_child_board__write_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__write_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__write_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_goal__write_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_ninja_dashboard_item_action__write_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_description__write_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_headers__write_date +msgid "Last Updated on" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__ls_week +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__ls_week +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__ls_week +#, python-format +msgid "Last Week" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__ls_year +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__ls_year +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__ls_year +#, python-format +msgid "Last Year" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_layout +msgid "Layout" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_layout__layout1 +msgid "Layout 1" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_layout__layout2 +msgid "Layout 2" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_layout__layout3 +msgid "Layout 3" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_layout__layout4 +msgid "Layout 4" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_layout__layout5 +msgid "Layout 5" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_layout__layout6 +msgid "Layout 6" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Layout Coming Soon" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_quick_edit_form_view +msgid "Layout..." +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_dashboard_item_type__ks_line_chart +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_chart_type__ks_line_chart +#, python-format +msgid "Line Chart" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_measure_field_2 +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_quick_edit_form_view +msgid "Line Measure" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_dashboard_item_type__ks_list_view +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_chart_type__ks_list_view +#, python-format +msgid "List View" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_list_view_data +msgid "List View Data in JSon" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_list_view_group_fields +msgid "List View Grouped Fields" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_list_view_preview +msgid "List View Preview" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_list_view_type +msgid "List View Type" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_unit +msgid "Maximum limit 5 characters, for ex: km, m" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_measure_field +msgid "Measure 1" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_quick_edit_form_view +msgid "Measures" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_menu_name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_child_board__ks_dashboard_menu_name +msgid "Menu Name" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_menu_sequence +msgid "Menu Sequence" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_groupby__minute +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_sub_groupby__minute +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_item_action_date_groupby__minute +msgid "Minute" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_custom_filters__ks_model_id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__ks_model_id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_model_id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__ks_model_id +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Model" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__ks_model_name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_model_name +msgid "Model Name" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_quick_edit_form_view +msgid "Model..." +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_unit_selection__monetary +msgid "Monetary" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_groupby__month +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_sub_groupby__month +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_item_action_date_groupby__month +msgid "Month" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_groupby__month_year +msgid "Month-Year" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#, python-format +msgid "More Info" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#: model:ir.actions.server,name:ks_dashboard_ninja.ks_move_dashboard +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_ninja_dashboard_item_action__ks_action__move +#, python-format +msgid "Move" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#, python-format +msgid "Move/Duplicate" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.actions.client,name:ks_dashboard_ninja.board_dashboard_action_window +#: model:ir.ui.menu,name:ks_dashboard_ninja.board_menu_root +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.board_tree +msgid "My Dashboard" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_template__name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_child_board__name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_ninja_dashboard_item_action__name +msgid "Name" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_company_id +msgid "" +"Name of the company for which analytics will be displayed in the dashboard. " +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_quick_edit_form_view +msgid "Name..." +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_item_color__neon +msgid "Neon" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_to_do_dashboard.js:0 +#, python-format +msgid "New Task" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#, python-format +msgid "Next" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__n_day +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__n_day +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__n_day +#, python-format +msgid "Next Day" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__n_month +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__n_month +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__n_month +#, python-format +msgid "Next Month" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__n_quarter +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__n_quarter +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__n_quarter +#, python-format +msgid "Next Quarter" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__n_week +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__n_week +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__n_week +#, python-format +msgid "Next Week" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__n_year +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__n_year +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__n_year +#, python-format +msgid "Next Year" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#, python-format +msgid "No Data Present" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#, python-format +msgid "No Section Available." +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#, python-format +msgid "No Tasks Available" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_widget_toggle.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__l_none +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__l_none +#, python-format +msgid "None" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#, python-format +msgid "Note :" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#, python-format +msgid "Note:" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_widget_toggle.xml:0 +#, python-format +msgid "Number" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_data_format +msgid "Number System" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_pagination_limit +msgid "Pagination Limit" +msgstr "" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py:0 +#, python-format +msgid "Pagination limit value cannot be Negative or Zero" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#, python-format +msgid "Past Excluding Today" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__ls_past_until_now +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__ls_past_until_now +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__ls_past_until_now +#, python-format +msgid "Past Till Now" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_widget_toggle.xml:0 +#, python-format +msgid "Percentage" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_dashboard_item_type__ks_pie_chart +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_chart_type__ks_pie_chart +#, python-format +msgid "Pie Chart" +msgstr "" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja.py:0 +#, python-format +msgid "" +"Please Install the Module which contains the following Model : %s " +"ks_model_id" +msgstr "" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py:0 +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py:0 +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py:0 +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py:0 +#, python-format +msgid "Please chose any Data Type!" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#, python-format +msgid "Please enter start date and end date" +msgstr "" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/lib/ks_date_filter_selections.py:0 +#: code:addons/ks_dashboard_ninja/lib/ks_date_filter_selections.py:0 +#, python-format +msgid "Please set the local timezone." +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#, python-format +msgid "" +"Please use Font Awesome 4.7.0 icons only. E.g. 'fa-bell' or 'bell'.\n" +" For more information visit" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_dashboard_item_type__ks_polararea_chart +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_chart_type__ks_polararea_chart +#, python-format +msgid "Polar Area Chart" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.board_form +msgid "Pre Defined Filters" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board_template__ks_template_type__ks_default +msgid "Predefined" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_preview +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Preview" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#, python-format +msgid "Previous" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Print" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_widget_toggle.xml:0 +#, python-format +msgid "Progress Bar" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_groupby__quarter +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_sub_groupby__quarter +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_item_action_date_groupby__quarter +msgid "Quarter" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#, python-format +msgid "Quick Customize" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_widget_toggle.xml:0 +#, python-format +msgid "Ratio" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_record_count +msgid "Record Count" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_record_field +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Record Field" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_quick_edit_form_view +msgid "Record Field..." +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_record_data_limit +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__ks_record_limit +msgid "Record Limit" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_record_data_limit_visibility +msgid "Record Limit Data Visibility" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_record_count_type +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Record Type" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_quick_edit_form_view +msgid "Record Value" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_actions +msgid "Redirects you to the selected view. " +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dn_global_filter.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dn_global_filter.xml:0 +#, python-format +msgid "Remove" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#, python-format +msgid "Remove Item" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_year_period +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Same Period Previous Years" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_quick_edit_view.xml:0 +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.ks_dashboard_ninja_action +#, python-format +msgid "Save" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Save Changes" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Save Changes as a New Layout" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#, python-format +msgid "Save as Image" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Save as New Layout" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#, python-format +msgid "Save as PDF" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.ks_item_search_view +msgid "Search Items" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#, python-format +msgid "Search fa-icon.." +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#, python-format +msgid "Search through site content" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board_defined_filters__display_type__line_section +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Section" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Sections" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#, python-format +msgid "Select" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_child_board__ks_dashboard_ninja_id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_ninja_dashboard_item_action__ks_dashboard_ninja_id +#, python-format +msgid "Select Dashboard" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_ninja_dashboard_item_action__ks_dashboard_ninja_ids +msgid "Select Dashboards" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#, python-format +msgid "Select Icon" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#, python-format +msgid "Select Icons" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_unit_selection +msgid "Select Unit Type" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_date_filter_selection +msgid "Select interval of the records to be displayed. " +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_dashboard_item_theme +msgid "Select the color theme for the display. " +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_list_view_type +msgid "Select the desired list view type. " +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_sort_by_field +msgid "Select the desired sorting preference. " +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_item_color +msgid "Select the display preference. " +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_date_filter_field +msgid "Select the field for which Date Filter should be applicable." +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_font_color +msgid "Select the font color. " +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_default_icon +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_default_icon_color +msgid "Select the icon to be displayed. " +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_dashboard_item_type +msgid "Select the required type of dashboard to display. " +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_relation_sub_groupby +msgid "Select the second level of grouping. " +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_data_calculation_type +msgid "Select the type of calculation you want to perform on the data." +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_unit_selection +msgid "Select the unit to be assigned to the value. " +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_auto_update_type +msgid "Select the update type." +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#, python-format +msgid "Selected item is duplicated to ." +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#, python-format +msgid "Selected item is moved to ." +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_domain_fix.js:0 +#, python-format +msgid "Selected records" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_semi_circle_chart +msgid "Semi Circle Chart" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.board_defined_filters +msgid "Separator Name (eg. Order States, Deadlines)" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__sequence +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__sequence +msgid "Sequence" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Set Current Layout" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Set Update Interval" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_unit +msgid "Show Custom Unit" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_show_data_value +msgid "Show Data Value" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:res.groups,name:ks_dashboard_ninja.ks_dashboard_ninja_group_manager +msgid "Show Full Dashboard Features" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_hide_legend +msgid "Show Legend" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_show_live_pop_up +msgid "Show Live Update Pop Up" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_show_records +msgid "Show Records" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_goal_bar_line +msgid "Show Target As Line" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_top_menu_id +msgid "Show Under Menu" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_standard_goal_value +msgid "Show the set target" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_goal_enable +msgid "Show the set target." +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_menu_sequence +msgid "" +"Smallest sequence give high priority and Highest sequence give low priority" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_import_dashboard.js:0 +#, python-format +msgid "Some Items can not be imported Need Dashboard Ninja pro " +msgstr "" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_filters.py:0 +#, python-format +msgid "" +"Something went wrong . Possibly it is due to wrong input type for domain" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_sort_by_field +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__ks_sort_by_field +msgid "Sort By Field" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_sort_by_order +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__ks_sort_by_order +msgid "Sort Order" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_bar_chart_stacked +msgid "Stack the columns of the same record. " +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_bar_chart_stacked +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Stacked Bar Chart" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_standard_goal_value +msgid "Standard Target" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_start_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_item_start_date +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Start Date" +msgstr "" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja.py:0 +#, python-format +msgid "Start date must be less than end date" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#, python-format +msgid "Start date should be less than end date" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Sub Group By Date" +msgstr "" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py:0 +#, python-format +msgid "Sub Groupby field: {} cannot be aggregated by {}" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_widget_toggle.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_data_count_type__sum +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_record_count_type_2__sum +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_record_count_type__sum +#, python-format +msgid "Sum" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Target" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_goal_lines +msgid "Target Lines" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Task Lines" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Tasks" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__display_type +msgid "Technical field for UX purpose." +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_template__ks_template_type +msgid "Template Format" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_template__ks_dashboard_item_ids +msgid "Template Type" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__name +msgid "The item will be represented by this unique name." +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_dashboard_item_theme +msgid "Theme" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_client_action +msgid "This Action will be Performed at the end of Drill Down Action" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__t_month +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__t_month +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__t_month +#, python-format +msgid "This Month" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__t_quarter +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__t_quarter +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__t_quarter +#, python-format +msgid "This Quarter" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__t_week +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__t_week +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__t_week +#, python-format +msgid "This Week" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__t_year +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__t_year +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__t_year +#, python-format +msgid "This Year" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_show_records +msgid "" +"This field Enable the click on \n" +" Dashboard Items to view the Odoo \n" +" default view of records" +msgstr "" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja.py:0 +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja.py:0 +#, python-format +msgid "This file is not supported" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_dashboard_item_type__ks_tile +#, python-format +msgid "Tile" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_data_format +msgid "To Change the number format showing in chart to given option" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_dashboard_item_type__ks_to_do +#, python-format +msgid "To Do" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_to_do_data +msgid "To Do Data in JSon" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_to_do_preview +msgid "To Do Preview" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "To add dashboard item, use" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_record_data_limit_visibility +msgid "To enable the record data limit field" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__l_day +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__l_day +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__l_day +#, python-format +msgid "Today" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_button_color +msgid "Top Button Color" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Type" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_record_count_type +msgid "" +"Type of record how record will show as count,sum and average of the record" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_list_view_type__ungrouped +msgid "Un-Grouped" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_import_dashboard.js:0 +#: code:addons/ks_dashboard_ninja/static/src/js/ks_import_dashboard.js:0 +#, python-format +msgid "Unarchive" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_set_interval +msgid "Update Interval for new items only" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_auto_update_type__ks_live_update +msgid "Update at every instance." +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_widget_toggle.xml:0 +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_icon +#, python-format +msgid "Upload Icon" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#, python-format +msgid "Uploading..." +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_goal__ks_goal_value +msgid "Value" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_target_view +msgid "View" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.board_tree +msgid "View Items" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_item_color__warm +msgid "Warm" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_groupby__week +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_sub_groupby__week +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_item_action_date_groupby__week +msgid "Week" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_groupby__year +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_sub_groupby__year +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_item_action_date_groupby__year +msgid "Year" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Your personal dashboard is empty" +msgstr "" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py:0 +#, python-format +msgid "if target lines is selected then cannot be set pagination value" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_list_target_deviation_field +msgid "list_field_id" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "on top right corner." +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dn_global_filter.xml:0 +#, python-format +msgid "or" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model,name:ks_dashboard_ninja.model_ks_to_do_description +msgid "to do description" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model,name:ks_dashboard_ninja.model_ks_to_do_headers +msgid "to do headers" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "vs Prev" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "vs Target" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_export_all_records +msgid "" +"when click on boolean button, all the records will be downloaded which are " +"present in entire list" +msgstr "" diff --git a/ks_dashboard_ninja/i18n/zh_CN.po b/ks_dashboard_ninja/i18n/zh_CN.po new file mode 100644 index 000000000..5d1cc699e --- /dev/null +++ b/ks_dashboard_ninja/i18n/zh_CN.po @@ -0,0 +1,2920 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * ks_dashboard_ninja +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-05-26 14:51+0000\n" +"PO-Revision-Date: 2024-08-22 15:49+0800\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Poedit 3.4.1\n" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_board_template__ks_dashboard_board_id +msgid "" +"\n" +" Items Configuration and their position in the dashboard will be copied from the selected " +"dashboard \n" +" and will be saved as template.\n" +" " +msgstr "" +"\n" +" 项目配置及其在仪表板中的位置将从所选仪表板中复制,并保存为模板。\n" +" 并保存为模板。\n" +" " + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_previous_period +msgid " Compare With Previous Period " +msgstr "与前期比较" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_update_items_data +msgid " Data will be refreshed after the selected interval." +msgstr "数据将在所选时间间隔后刷新。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_relation_groupby +msgid " Define the x-axis of the graph. " +msgstr "定义图形的 x 轴。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_year_period +msgid " Display the record for the same Date field for the last year. " +msgstr "显示去年同一日期字段的记录。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_show_data_value +msgid " Display value on the graph. . " +msgstr "在图表上显示数值.." + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__ls_pastwithout_now +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__ls_pastwithout_now +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__ls_pastwithout_now +msgid " Past Excluding Today" +msgstr "过去(不包括今日)" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_compare_period +msgid " Provide the number of Date Filter Selection you want to include while displaying the record." +msgstr "提供您希望在显示记录时包含的日期筛选器选择数量。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_record_data_limit +msgid " Records to be displayed on the graph" +msgstr "图表上要显示的记录" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_background_color +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_header_bg_color +msgid " Select the background color with transparency. " +msgstr "选择透明背景色。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_list_view_fields +msgid " Select the fields you want to display in the list. " +msgstr "选择要在列表中显示的字段。 " + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_layout +msgid " Select the layout to display records. " +msgstr "选择显示记录的布局。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_sort_by_order +msgid " Select the order of the sorting. " +msgstr "选择排序顺序。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_target_view +msgid " Select the view to compare target with data." +msgstr "选择视图,将目标与数据进行比较。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_relation_sub_groupby +msgid " Sub Group By" +msgstr "次级分组" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_auto_update_type__ks_update_interval +msgid " Update after the selected interval" +msgstr "选定时间间隔后更新" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_set_interval__60000 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_update_items_data__60000 +msgid "1 minute" +msgstr "1分钟" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_set_interval__600000 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_update_items_data__600000 +msgid "10 minute" +msgstr "10分钟" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_set_interval__15000 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_update_items_data__15000 +msgid "15 Seconds" +msgstr "15秒" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_set_interval__120000 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_update_items_data__120000 +msgid "2 minute" +msgstr "2分钟" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_set_interval__30000 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_update_items_data__30000 +msgid "30 Seconds" +msgstr "30秒" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_set_interval__45000 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_update_items_data__45000 +msgid "45 Seconds" +msgstr "45秒" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_set_interval__300000 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_update_items_data__300000 +msgid "5 minute" +msgstr "5分钟" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja.py:0 +#, python-format +msgid "" +"\n" +" You can find all items related to Dashboard Here.
\n" +" " +msgstr "" +"\n" +" 您可以在这里找到与“仪表板”相关的所有项目。
\n" +" " + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_ninja_dashboard_item_action__ks_action +msgid "Action" +msgstr "行动" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__ks_item_action_field +msgid "Action Group By" +msgstr "操作分组" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_action_lines +msgid "Action Lines" +msgstr "操作明细" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py:0 +#, python-format +msgid "Action field: {} cannot be aggregated by {}" +msgstr "操作字段: {} 不能按{} 生成" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_actions +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Actions" +msgstr "操作" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_active +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__ks_is_active +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Active" +msgstr "" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_description__ks_active +msgid "Active Description" +msgstr "" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Add" +msgstr "添加" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Add Item" +msgstr "添加物料" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Add a Line" +msgstr "添加一行" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Add a Section" +msgstr "添加区块" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dn_global_filter.xml:0 +#, python-format +msgid "Add a condition" +msgstr "添加条件" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.board_form +msgid "Add a filter" +msgstr "添加过滤器" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.board_form +msgid "Add a separator" +msgstr "添加分隔符" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Add button" +msgstr "添加按钮" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Advance Configuration" +msgstr "" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "" +"All Target Lines Changes Will be reflected on Chart after saving the record and pagination will be " +"ignore ." +msgstr "保存记录后,所有目标行更改都将反映在图表上,分页将被忽略。" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__l_none +#, python-format +msgid "All Time" +msgstr "所有时间" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_import_dashboard.js:0 +#, python-format +msgid "All items can not be Imported" +msgstr "所有不能导入的项目" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dn_global_filter.xml:0 +#, python-format +msgid "Apply" +msgstr "应用" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_import_dashboard.js:0 +#, python-format +msgid "Archive" +msgstr "存档" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_import_dashboard.js:0 +#, python-format +msgid "Are you sure that you want to archive all the selected records?" +msgstr "您确定要存档所有选定的记录吗?" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#, python-format +msgid "Are you sure you want to remove this item?" +msgstr "您确定要删除此项吗?" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_to_do_dashboard.js:0 +#, python-format +msgid "Are you sure you want to remove this task?" +msgstr "您确定要删除这项任务吗?" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_dashboard_item_type__ks_area_chart +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_chart_type__ks_area_chart +#, python-format +msgid "Area Chart" +msgstr "面积图" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_sort_by_order__asc +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_sort_by_order__asc +msgid "Ascending" +msgstr "升序" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Auto Update" +msgstr "自动更新" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_auto_update_type +msgid "Auto Update Type" +msgstr "自动更新类型" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_data_count_type__average +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_record_count_type_2__average +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_record_count_type__average +msgid "Average" +msgstr "一般" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_background_color +msgid "Background Color" +msgstr "背景颜色" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_dashboard_item_type__ks_bar_chart +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_chart_type__ks_bar_chart +#, python-format +msgid "Bar Chart" +msgstr "条形图" + +#. module: ks_dashboard_ninja +#: model:ir.model,name:ks_dashboard_ninja.model_base +msgid "Base" +msgstr "基础" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Below action will be performed at the end of the Drill Down Action" +msgstr "向下钻取动作结束时将执行以下动作" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.ks_dashboard_ninja_action +msgid "Cancel" +msgstr "取消" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py:0 +#, python-format +msgid "" +"Cannot create target lines when Group By Date field is set to have aggregation in Minute and Hour case." +msgstr "当“按日期分组”字段设置为在“分钟和小时”情况下具有聚合时,无法创建目标行。" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py:0 +#, python-format +msgid "" +"Cannot set aggregation having Date time (Hour, Minute) when target lines per date are being used. To " +"proceed this, first delete target lines" +msgstr "使用每个日期的目标行时,无法设置具有日期时间(小时,分钟)的聚合。 为此,请先删除目标行" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#, python-format +msgid "Changing Layout midway will set the default icon colour and font colour for selected layout." +msgstr "中途更改布局将为所选布局设置默认的图标颜色和字体颜色。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_item_color +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Chart Color Palette" +msgstr "图表调色板" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_data +msgid "Chart Data in string form" +msgstr "字符串形式的图表数据" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_show_live_pop_up +msgid "Checkbox to enable notification after every update. " +msgstr "复选框用于启用每次更新后的通知。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_previous_period +msgid "Checkbox to show comparison between the data of present day and the previous selected period. " +msgstr "复选框,用于显示当前数据与上一选定时段数据的比较。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_icon_select +msgid "Choose the Icon option. " +msgstr "选择图标选项。" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Clear" +msgstr "清除" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_is_client_action +msgid "Client Action" +msgstr "按钮" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_client_action +msgid "Client Item Action" +msgstr "客户端动作" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_to_do_dashboard.js:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#, python-format +msgid "Close" +msgstr "关闭" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_data_format__colombian +msgid "Colombian Peso Format" +msgstr "哥伦比亚比索格式" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#, python-format +msgid "Color Palette" +msgstr "调色板" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#, python-format +msgid "Coming Soon in Future :)" +msgstr " 即将推出:)" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_company_id +msgid "Company" +msgstr "公司" + +#. module: ks_dashboard_ninja +#: model:ir.ui.menu,name:ks_dashboard_ninja.configuration_menu +msgid "Configuration" +msgstr "配置" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_item_color__cool +msgid "Cool" +msgstr "很酷" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_data_count_type__count +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_record_count_type_2__count +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_record_count_type__count +msgid "Count" +msgstr "计数" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_quick_edit_form_view +msgid "Count..." +msgstr "总计..." + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__create_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_custom_filters__create_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__create_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_template__create_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_child_board__create_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__create_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__create_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_goal__create_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_ninja_dashboard_item_action__create_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_description__create_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_headers__create_uid +msgid "Created by" +msgstr "创建人" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__create_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_custom_filters__create_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__create_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_template__create_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_child_board__create_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__create_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__create_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_goal__create_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_ninja_dashboard_item_action__create_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_description__create_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_headers__create_date +msgid "Created on" +msgstr "创建时间" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_cumulative +msgid "Cumulative As Line" +msgstr "累计折线图" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_cumulative_field +msgid "Cumulative Field" +msgstr "累计字段" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja.py:0 +#, python-format +msgid "Current Json File is not properly formatted according to Dashboard Ninja Model." +msgstr "根据仪表板模型,当前的Json文件格式不正确。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board_template__ks_template_type__ks_custom +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_unit_selection__custom +msgid "Custom" +msgstr "自定义" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dn_global_filter.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__l_custom +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__l_custom +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__l_custom +#, python-format +msgid "Custom Filter" +msgstr "自定义筛选" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.board_form +msgid "Custom Filters" +msgstr "定制过滤器" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_data_calculation_type__query +msgid "Custom Query" +msgstr "自定义查询" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Customize Dashboard" +msgstr "自定义仪表板" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#, python-format +msgid "Customize Item" +msgstr "自定义项目" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_custom_filters__ks_dashboard_board_id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__ks_dashboard_board_id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_template__ks_dashboard_board_id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_dashboard_ninja_board_id +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.child_board_tree +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item +msgid "Dashboard" +msgstr "仪表盘" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_custom_filters_ids +msgid "Dashboard Custom Filters" +msgstr "仪表板自定义过滤器" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.board_defined_filters +msgid "Dashboard Defined Filter" +msgstr "筛选" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__ks_dashboard_item_id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_goal__ks_dashboard_item +msgid "Dashboard Item" +msgstr "仪表板项目" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.ks_dashboard_ninja_action +msgid "Dashboard Item Action" +msgstr "仪表板项目动作" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_date_groupby +msgid "Dashboard Item Chart Group By Type" +msgstr "仪表板项目图表按类型分组" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_date_sub_groupby +msgid "Dashboard Item Chart Sub Group By Type" +msgstr "仪表板项目图表子类型分组" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_dashboard_item_type +msgid "Dashboard Item Type" +msgstr "仪表板项目类型" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja.py:0 +#: model:ir.actions.act_window,name:ks_dashboard_ninja.item_action_window +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_items_ids +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_ninja_dashboard_item_action__ks_dashboard_item_ids +#, python-format +msgid "Dashboard Items" +msgstr "仪表板项目" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.child_board_tree +msgid "Dashboard Layout" +msgstr "仪表盘布局" + +#. module: ks_dashboard_ninja +#: model:ir.ui.menu,name:ks_dashboard_ninja.dashboard_layout_menu +msgid "Dashboard Layouts" +msgstr "仪表板布局" + +#. module: ks_dashboard_ninja +#: model:ir.actions.act_window,name:ks_dashboard_ninja.board_form_tree_action_window +msgid "Dashboard Manager" +msgstr "仪表板管理" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__name +msgid "Dashboard Name" +msgstr "仪表板名称" + +#. module: ks_dashboard_ninja +#: model:ir.model,name:ks_dashboard_ninja.model_ks_dashboard_ninja_board +msgid "Dashboard Ninja" +msgstr "忍者仪表板" + +#. module: ks_dashboard_ninja +#: model:ir.model,name:ks_dashboard_ninja.model_ks_dashboard_ninja_child_board +msgid "Dashboard Ninja Child Board" +msgstr "仪表板子面板" + +#. module: ks_dashboard_ninja +#: model:ir.model,name:ks_dashboard_ninja.model_ks_dashboard_ninja_board_custom_filters +msgid "Dashboard Ninja Custom Filters" +msgstr "仪表板忍者自定义过滤器" + +#. module: ks_dashboard_ninja +#: model:ir.model,name:ks_dashboard_ninja.model_ks_dashboard_ninja_board_defined_filters +msgid "Dashboard Ninja Defined Filters" +msgstr "仪表板忍者定义的过滤器" + +#. module: ks_dashboard_ninja +#: model:ir.model,name:ks_dashboard_ninja.model_ks_ninja_dashboard_item_action +msgid "Dashboard Ninja Item Actions" +msgstr "仪表板项目操作" + +#. module: ks_dashboard_ninja +#: model:ir.model,name:ks_dashboard_ninja.model_ks_dashboard_ninja_item_action +msgid "Dashboard Ninja Items Action Lines" +msgstr "仪表板忍者物品动作线" + +#. module: ks_dashboard_ninja +#: model:ir.model,name:ks_dashboard_ninja.model_ks_dashboard_ninja_item_goal +msgid "Dashboard Ninja Items Goal Lines" +msgstr "仪表盘项目目标线" + +#. module: ks_dashboard_ninja +#: model:ir.module.category,name:ks_dashboard_ninja.ks_dashboard_ninja_security_groups +msgid "Dashboard Ninja Rights" +msgstr "仪表盘权限" + +#. module: ks_dashboard_ninja +#: model:ir.model,name:ks_dashboard_ninja.model_ks_dashboard_ninja_board_template +msgid "Dashboard Ninja Template" +msgstr "仪表板模板" + +#. module: ks_dashboard_ninja +#: model:ir.model,name:ks_dashboard_ninja.model_ks_dashboard_ninja_item +msgid "Dashboard Ninja items" +msgstr "仪表板项目" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_defined_filters_ids +msgid "Dashboard Predefined Filters" +msgstr "仪表板预定义过滤器" + +#. module: ks_dashboard_ninja +#: model:ir.actions.act_window,name:ks_dashboard_ninja.template_tree_action_window +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_default_template +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_dashboard_board_template_id +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.board_template_form +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.board_template_tree +msgid "Dashboard Template" +msgstr "仪表板模板" + +#. module: ks_dashboard_ninja +#: model:ir.actions.act_window,name:ks_dashboard_ninja.layout_tree_action_window +msgid "Dashboard layout" +msgstr "仪表板布局" + +#. module: ks_dashboard_ninja +#: model:ir.ui.menu,name:ks_dashboard_ninja.dashboard_menu +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.board_form +msgid "Dashboards" +msgstr "仪表盘" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Data" +msgstr "日期" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Data #2" +msgstr "数据 #2" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Data Calculation" +msgstr "数据计算" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_data_calculation_type +msgid "Data Calculation Type" +msgstr "数据计算类型" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_kpi_type__layout_2 +msgid "Data Comparison" +msgstr "数据比较" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_measure_field_2 +msgid "Data Points displayed with a line in the graph. " +msgstr "数据点在图表中以直线显示。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_data_count_type +msgid "Data Type" +msgstr "数据类型" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_cumulative_field +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_measure_field +msgid "Data points to be selected." +msgstr "要选择的数据点。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_board_custom_filters__ks_model_id +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__ks_model_id +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_model_id +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__ks_model_id +msgid "Data source to fetch and read the data for the creation of dashboard items. " +msgstr "数据源,用于获取和读取数据以创建仪表板项目。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_goal__ks_goal_date +msgid "Date" +msgstr "日期" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#, python-format +msgid "Date Filter" +msgstr "日期筛选" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_date_filter_field +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Date Filter Field" +msgstr "日期过滤字段" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_date_filter_selection +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Date Filter Selection" +msgstr "日期筛选选项" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_groupby__day +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_sub_groupby__day +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_item_action_date_groupby__day +msgid "Day" +msgstr "天" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_item_color__default +msgid "Default" +msgstr "默认" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja.py:0 +#, python-format +msgid "Default Dashboard can't be deleted." +msgstr "无法删除默认仪表板。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_date_filter_selection +msgid "Default Date Filter" +msgstr "默认日期过滤器" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_widget_toggle.xml:0 +#, python-format +msgid "Default Icons" +msgstr "默认图标" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_data_calculation_type__custom +msgid "Default Query" +msgstr "默认查询" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_set_interval +msgid "Default Update Interval" +msgstr "默认更新间隔" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_domain_extension +msgid "Define conditions for filter to write manually" +msgstr "定义过滤器手动写入的条件" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__ks_domain +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_domain +msgid "Define conditions for filter. " +msgstr "定义过滤器的条件。" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_import_dashboard.js:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dn_global_filter.xml:0 +#, python-format +msgid "Delete" +msgstr "删除" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_sort_by_order__desc +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_sort_by_order__desc +msgid "Descending" +msgstr "降序" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_description__ks_description +msgid "Description" +msgstr "描述" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Deviation Field" +msgstr "误差字段" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_quick_edit_view.xml:0 +#, python-format +msgid "Discard" +msgstr "丢弃" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Discard Changes" +msgstr "放弃更改" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Display" +msgstr "显示" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__display_name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_custom_filters__display_name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__display_name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_template__display_name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_child_board__display_name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__display_name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__display_name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_goal__display_name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_ninja_dashboard_item_action__display_name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_description__display_name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_headers__display_name +msgid "Display Name" +msgstr "显示名称" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__display_type +msgid "Display Type" +msgstr "显示类型" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_unit +msgid "Display the unit of the data." +msgstr "显示数据的单位。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__ks_domain +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_domain +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Domain" +msgstr "域名" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_domain_extension +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Domain Extension" +msgstr "Domain拓展" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_custom_filters__ks_domain_field_id +msgid "Domain Field" +msgstr "领域" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__ks_domain_temp +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_domain_temp +msgid "Domain Substitute" +msgstr "替代域" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_filters.py:0 +#, python-format +msgid "Domain can not be empty" +msgstr "域不能为空" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_dashboard_item_type__ks_doughnut_chart +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_chart_type__ks_doughnut_chart +#, python-format +msgid "Doughnut Chart" +msgstr "环形图" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#, python-format +msgid "Drill Up" +msgstr "向上钻" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#: model:ir.actions.server,name:ks_dashboard_ninja.ks_duplicate_dashboard +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_ninja_dashboard_item_action__ks_action__duplicate +#, python-format +msgid "Duplicate" +msgstr "复制" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Edit Layout" +msgstr "编辑布局" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_to_do_dashboard.js:0 +#, python-format +msgid "Edit Task" +msgstr "编辑任务" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_goal_enable +msgid "Enable Target" +msgstr "启用目标" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_end_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_item_end_date +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "End Date" +msgstr "完工日" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_data_format__global +msgid "English Format" +msgstr "英文格式" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_unit +msgid "Enter Unit" +msgstr "输入单位" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_data_formatting__exact +msgid "Exact" +msgstr "精确" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_data_format__exact +msgid "Exact Value" +msgstr "精确值" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_import_dashboard.js:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#, python-format +msgid "Export" +msgstr "导出" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_export_all_records +msgid "Export All Records" +msgstr "导出所有记录" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#, python-format +msgid "Export Chart" +msgstr "导出图表" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_import_dashboard.js:0 +#, python-format +msgid "Export Dashboard" +msgstr "导出仪表板" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#, python-format +msgid "Export Item" +msgstr "导出项目" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#, python-format +msgid "Export List" +msgstr "导出列表" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#, python-format +msgid "Export to CSV" +msgstr "导出CSV" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#, python-format +msgid "Export to Excel" +msgstr "导出Excel" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#, python-format +msgid "Fields Required : Name, Model, Icon (Default or Custom Upload), Layout" +msgstr "必填字段:名称,模型,图标(默认或自定义上传),布局" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_list_view_fields +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_quick_edit_form_view +msgid "Fields to show in list" +msgstr "列表中显示的字段" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_fill_temporal +msgid "Fill Temporal Value" +msgstr "填写时间值" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dn_global_filter.xml:0 +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +#, python-format +msgid "Filter" +msgstr "筛选" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_custom_filters__name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__name +msgid "Filter Label" +msgstr "筛选标签" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#, python-format +msgid "Font Awesome 4.7.0" +msgstr "Font Awesome 4.7.0" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_font_color +msgid "Font Color" +msgstr "字体颜色" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_data_formatting +msgid "Format" +msgstr "格式" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_quick_edit_view.xml:0 +#, python-format +msgid "Full Settings" +msgstr "所有设置" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__n_future_starting_now +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__n_future_starting_now +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__n_future_starting_now +#, python-format +msgid "Future Starting Now" +msgstr "今日起" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__n_futurestarting_tomorrow +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__n_futurestarting_tomorrow +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__n_futurestarting_tomorrow +#, python-format +msgid "Future Starting Tomorrow" +msgstr "明日起" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__sequence +msgid "Gives the sequence order when displaying a list of payment terms lines." +msgstr "提供显示付款列表的序列。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_data_formatting__global +msgid "Global" +msgstr "全局" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Goal Lines" +msgstr "目标明细" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_graph_preview +msgid "Graph Preview" +msgstr "图形预览" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_group_access +msgid "Group Access" +msgstr "组访问权限" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_relation_groupby +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_quick_edit_form_view +msgid "Group By" +msgstr "分组方式" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__ks_item_action_date_groupby +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_quick_edit_form_view +msgid "Group By Date" +msgstr "按日期分组" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py:0 +#, python-format +msgid "Groupby Field aggregation" +msgstr "按字段分组" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py:0 +#, python-format +msgid "Groupby field: {} cannot be aggregated by {}" +msgstr "分组字段: {} 不能按 {} 聚合" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_list_view_type__grouped +msgid "Grouped" +msgstr "分组" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Groups/Dimensions" +msgstr "组/维度" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_headers__ks_to_do_header +msgid "Header" +msgstr "页眉" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_header_bg_color +msgid "Header Background Color" +msgstr "页眉背景颜色" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_hide_legend +msgid "Hide all legend from the chart item" +msgstr "隐藏所有图表项图例" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_dashboard_item_type__ks_horizontalbar_chart +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_chart_type__ks_horizontalbar_chart +#, python-format +msgid "Horizontal Bar Chart" +msgstr "水平条形图" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_groupby__hour +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_sub_groupby__hour +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_item_action_date_groupby__hour +msgid "Hour" +msgstr "小时" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_custom_filters__id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_template__id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_child_board__id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_goal__id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_ninja_dashboard_item_action__id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_description__id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_headers__id +msgid "ID" +msgstr "ID" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_default_icon +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Icon" +msgstr "图标" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_default_icon_color +msgid "Icon Color" +msgstr "图标颜色" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_icon_select +msgid "Icon Option" +msgstr "图标选项" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_import_list_view_template.xml:0 +#, python-format +msgid "Import Dashboard" +msgstr "导入仪表板" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Import Item" +msgstr "导入项目" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_compare_period +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Include Period" +msgstr "包含周期" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_data_formatting__indian +msgid "Indian" +msgstr "印度" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_data_format__indian +msgid "Indian Format" +msgstr "印度格式" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#, python-format +msgid "Invalid Date" +msgstr "无效的日期范围" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_child_board__ks_active +msgid "Is Selected" +msgstr "已选择" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Item Action" +msgstr "项目动作" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_gridstack_config +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_child_board__ks_gridstack_config +msgid "Item Configurations" +msgstr "项目配置" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#, python-format +msgid "Item Duplicated" +msgstr "项目复制" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#, python-format +msgid "Item Moved" +msgstr "项目移动" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__ks_chart_type +msgid "Item Type" +msgstr "项目类型" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_update_items_data +msgid "Item Update Interval" +msgstr "项目更新间隔" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_quick_edit_form_view +msgid "Item Update Interval.." +msgstr "项目更新间隔.." + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_dashboard_item_type__ks_kpi +#, python-format +msgid "KPI" +msgstr "KPI" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_kpi_data +msgid "KPI Data" +msgstr "KPI 数据" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_domain_extension_2 +msgid "KPI Domain Extension" +msgstr "KPI 域名后缀" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_compare_period_2 +msgid "KPI Include Period" +msgstr "关键绩效指标包括期间" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_record_count_2 +msgid "KPI Record Count" +msgstr "KPI 记录计数" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_year_period_2 +msgid "KPI Same Period Previous Years" +msgstr "关键绩效指标 往年同期" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_kpi_type__layout_1 +msgid "KPI With Target" +msgstr "目标KPI" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_data_comparison +msgid "Kpi Data Type" +msgstr "Kpi 数据类型" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_date_filter_field_2 +msgid "Kpi Date Filter Field" +msgstr "Kpi 日期过滤字段" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_date_filter_selection_2 +msgid "Kpi Date Filter Selection" +msgstr "Kpi 日期过滤器选择" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_domain_2 +msgid "Kpi Domain" +msgstr "Kpi 领域" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_domain_2_temp +msgid "Kpi Domain Substitute" +msgstr "Kpi Domain替代" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_item_end_date_2 +msgid "Kpi End Date" +msgstr "Kpi 结束日期" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_kpi_type +msgid "Kpi Layout" +msgstr "Kpi 布局" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_model_id_2 +msgid "Kpi Model" +msgstr "Kpi 模型" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_model_name_2 +msgid "Kpi Model Name" +msgstr "Kpi 模型名称" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_kpi_preview +msgid "Kpi Preview" +msgstr "Kpi 预览" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_record_field_2 +msgid "Kpi Record Field" +msgstr "Kpi 记录字段" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_record_count_type_2 +msgid "Kpi Record Type" +msgstr "Kpi 记录类型" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_item_start_date_2 +msgid "Kpi Start Date" +msgstr "Kpi 开始日期" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_groupby_type +msgid "Ks Chart Groupby Type" +msgstr "图表分组类型" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_sub_groupby_type +msgid "Ks Chart Sub Groupby Type" +msgstr "图表子级分组类型" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_child_dashboard_ids +msgid "Ks Child Dashboard" +msgstr "Ks 儿童仪表板" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_client_action_id +msgid "Ks Dashboard Client Action" +msgstr "仪表板客户端动作" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_menu_id +msgid "Ks Dashboard Menu" +msgstr "仪表板菜单" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_state +msgid "Ks Dashboard State" +msgstr "仪表板状态" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_dn_header_lines +msgid "Ks Dn Header Lines" +msgstr "Ks Dn 标题行" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_headers__ks_dn_item_id +msgid "Ks Dn Item" +msgstr "Ks Dn 项目" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_template__ks_gridstack_config +msgid "Ks Gridstack Config" +msgstr "网格堆栈配置" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_isDateFilterApplied +msgid "Ks Isdatefilterapplied" +msgstr "日期过滤已启用" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__ks_item_action_field_type +msgid "Ks Item Action Field Type" +msgstr "项目行动领域类型" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_template__ks_item_count +msgid "Ks Item Count" +msgstr "项目计数" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_many2many_field_ordering +msgid "Ks Many2Many Field Ordering" +msgstr "KS多对多字段排序" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_headers__ks_to_do_description_lines +msgid "Ks To Do Description Lines" +msgstr "Ks 待办事项说明行" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_description__ks_to_do_header_id +msgid "Ks To Do Header" +msgstr "Ks 待办事项标题" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__l_month +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__l_month +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__l_month +#, python-format +msgid "Last 30 days" +msgstr "最近30天" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__l_year +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__l_year +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__l_year +#, python-format +msgid "Last 365 days" +msgstr "最近365天" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__l_week +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__l_week +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__l_week +#, python-format +msgid "Last 7 days" +msgstr "最近 7 天" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__l_quarter +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__l_quarter +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__l_quarter +#, python-format +msgid "Last 90 days" +msgstr "最近90天" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__ls_day +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__ls_day +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__ls_day +#, python-format +msgid "Last Day" +msgstr "最后一天" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board____last_update +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_custom_filters____last_update +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters____last_update +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_template____last_update +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_child_board____last_update +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item____last_update +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action____last_update +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_goal____last_update +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_ninja_dashboard_item_action____last_update +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_description____last_update +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_headers____last_update +msgid "Last Modified on" +msgstr "最后修改日期" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__ls_month +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__ls_month +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__ls_month +#, python-format +msgid "Last Month" +msgstr "上个月" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__ls_quarter +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__ls_quarter +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__ls_quarter +#, python-format +msgid "Last Quarter" +msgstr "上个季度" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__write_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_custom_filters__write_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__write_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_template__write_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_child_board__write_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__write_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__write_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_goal__write_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_ninja_dashboard_item_action__write_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_description__write_uid +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_headers__write_uid +msgid "Last Updated by" +msgstr "最后修改人" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__write_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_custom_filters__write_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__write_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_template__write_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_child_board__write_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__write_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__write_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_goal__write_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_ninja_dashboard_item_action__write_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_description__write_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_to_do_headers__write_date +msgid "Last Updated on" +msgstr "最后更新时间" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__ls_week +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__ls_week +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__ls_week +#, python-format +msgid "Last Week" +msgstr "上周" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__ls_year +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__ls_year +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__ls_year +#, python-format +msgid "Last Year" +msgstr "去年" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_layout +msgid "Layout" +msgstr "布局" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_layout__layout1 +msgid "Layout 1" +msgstr "布局 1" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_layout__layout2 +msgid "Layout 2" +msgstr "布局 2" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_layout__layout3 +msgid "Layout 3" +msgstr "布局 3" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_layout__layout4 +msgid "Layout 4" +msgstr "布局 4" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_layout__layout5 +msgid "Layout 5" +msgstr "布局 5" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_layout__layout6 +msgid "Layout 6" +msgstr "布局 6" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Layout Coming Soon" +msgstr "布局即将推出" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_quick_edit_form_view +msgid "Layout..." +msgstr "布局..." + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_dashboard_item_type__ks_line_chart +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_chart_type__ks_line_chart +#, python-format +msgid "Line Chart" +msgstr "折线图" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_measure_field_2 +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_quick_edit_form_view +msgid "Line Measure" +msgstr "拆线维度" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_dashboard_item_type__ks_list_view +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_chart_type__ks_list_view +#, python-format +msgid "List View" +msgstr "列表视图" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_list_view_data +msgid "List View Data in JSon" +msgstr "Json数据列表视图" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_list_view_group_fields +msgid "List View Grouped Fields" +msgstr "列表视图分组字段" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_list_view_preview +msgid "List View Preview" +msgstr "列表预览" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_list_view_type +msgid "List View Type" +msgstr "列表视图类型" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_unit +msgid "Maximum limit 5 characters, for ex: km, m" +msgstr "最大限制5个字符,例如:km, m" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_measure_field +msgid "Measure 1" +msgstr "维度1" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_quick_edit_form_view +msgid "Measures" +msgstr "度量" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_menu_name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_child_board__ks_dashboard_menu_name +msgid "Menu Name" +msgstr "菜单名称" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_menu_sequence +msgid "Menu Sequence" +msgstr "菜单序列号" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_groupby__minute +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_sub_groupby__minute +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_item_action_date_groupby__minute +msgid "Minute" +msgstr "分钟" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_custom_filters__ks_model_id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__ks_model_id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_model_id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__ks_model_id +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Model" +msgstr "模型" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__ks_model_name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_model_name +msgid "Model Name" +msgstr "模型名称" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_quick_edit_form_view +msgid "Model..." +msgstr "模型..." + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_unit_selection__monetary +msgid "Monetary" +msgstr "币种" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_groupby__month +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_sub_groupby__month +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_item_action_date_groupby__month +msgid "Month" +msgstr "月" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_groupby__month_year +msgid "Month-Year" +msgstr "月-年" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#, python-format +msgid "More Info" +msgstr "更多信息" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#: model:ir.actions.server,name:ks_dashboard_ninja.ks_move_dashboard +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_ninja_dashboard_item_action__ks_action__move +#, python-format +msgid "Move" +msgstr "移动" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#, python-format +msgid "Move/Duplicate" +msgstr "移动/复制" + +#. module: ks_dashboard_ninja +#: model:ir.actions.client,name:ks_dashboard_ninja.board_dashboard_action_window +#: model:ir.ui.menu,name:ks_dashboard_ninja.board_menu_root +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.board_tree +msgid "My Dashboard" +msgstr "我的仪表板" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_template__name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_child_board__name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__name +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_ninja_dashboard_item_action__name +msgid "Name" +msgstr "名称" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_company_id +msgid "Name of the company for which analytics will be displayed in the dashboard. " +msgstr "将在仪表板中显示分析结果的公司名称。" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_quick_edit_form_view +msgid "Name..." +msgstr "名称..." + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_item_color__neon +msgid "Neon" +msgstr "霓虹灯" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_to_do_dashboard.js:0 +#, python-format +msgid "New Task" +msgstr "新任务" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#, python-format +msgid "Next" +msgstr "下一页" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__n_day +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__n_day +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__n_day +#, python-format +msgid "Next Day" +msgstr "明天" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__n_month +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__n_month +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__n_month +#, python-format +msgid "Next Month" +msgstr "下个月" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__n_quarter +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__n_quarter +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__n_quarter +#, python-format +msgid "Next Quarter" +msgstr "下个季度" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__n_week +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__n_week +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__n_week +#, python-format +msgid "Next Week" +msgstr "下周" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__n_year +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__n_year +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__n_year +#, python-format +msgid "Next Year" +msgstr "明年" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#, python-format +msgid "No Data Present" +msgstr "没有可呈现的数据" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#, python-format +msgid "No Section Available." +msgstr "没有部分可用。" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#, python-format +msgid "No Tasks Available" +msgstr "无任务可用" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_widget_toggle.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__l_none +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__l_none +#, python-format +msgid "None" +msgstr "无" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#, python-format +msgid "Note :" +msgstr "备注:" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#, python-format +msgid "Note:" +msgstr "注意:" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_widget_toggle.xml:0 +#, python-format +msgid "Number" +msgstr "数量" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_data_format +msgid "Number System" +msgstr "数字系统" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_pagination_limit +msgid "Pagination Limit" +msgstr "分页限制" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py:0 +#, python-format +msgid "Pagination limit value cannot be Negative or Zero" +msgstr "分页限制值不能为负或零" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#, python-format +msgid "Past Excluding Today" +msgstr "过去(不包括今天)" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__ls_past_until_now +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__ls_past_until_now +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__ls_past_until_now +#, python-format +msgid "Past Till Now" +msgstr "截止到现在" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_widget_toggle.xml:0 +#, python-format +msgid "Percentage" +msgstr "百分比" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_dashboard_item_type__ks_pie_chart +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_chart_type__ks_pie_chart +#, python-format +msgid "Pie Chart" +msgstr "饼图" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja.py:0 +#, python-format +msgid "Please Install the Module which contains the following Model : %s ks_model_id" +msgstr "请安装包含以下模组的模块 : %s ks_model_id" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py:0 +#, python-format +msgid "Please chose any Data Type!" +msgstr "请选择任何数据类型!" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#, python-format +msgid "Please enter start date and end date" +msgstr "请设置开始日期和结束日期" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/lib/ks_date_filter_selections.py:0 +#, python-format +msgid "Please set the local timezone." +msgstr "请设置当地时区。" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#, python-format +msgid "" +"Please use Font Awesome 4.7.0 icons only. E.g. 'fa-bell' or 'bell'.\n" +" For more information visit" +msgstr "" +"请仅使用Font Awesome 4.7.0图标。例如。 “ fa-bell”或“ bell”。\n" +" 欲了解更多信息,请访问" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_dashboard_item_type__ks_polararea_chart +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_chart_type__ks_polararea_chart +#, python-format +msgid "Polar Area Chart" +msgstr "极地面积图" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.board_form +msgid "Pre Defined Filters" +msgstr "预设过滤器" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board_template__ks_template_type__ks_default +msgid "Predefined" +msgstr "预定义" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_preview +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Preview" +msgstr "预览" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#, python-format +msgid "Previous" +msgstr "上一个" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Print" +msgstr "打印" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_widget_toggle.xml:0 +#, python-format +msgid "Progress Bar" +msgstr "进度条" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_groupby__quarter +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_sub_groupby__quarter +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_item_action_date_groupby__quarter +msgid "Quarter" +msgstr "季度" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#, python-format +msgid "Quick Customize" +msgstr "快速定制" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_widget_toggle.xml:0 +#, python-format +msgid "Ratio" +msgstr "比率" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_record_count +msgid "Record Count" +msgstr "记录计数" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_record_field +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Record Field" +msgstr "记录字段" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_quick_edit_form_view +msgid "Record Field..." +msgstr "记录字段..." + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_record_data_limit +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__ks_record_limit +msgid "Record Limit" +msgstr "记录限制" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_record_data_limit_visibility +msgid "Record Limit Data Visibility" +msgstr "记录限制数据可见性" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_record_count_type +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Record Type" +msgstr "记录类型" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_quick_edit_form_view +msgid "Record Value" +msgstr "记录值" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_actions +msgid "Redirects you to the selected view. " +msgstr "将您重定向到所选视图。" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dn_global_filter.xml:0 +#, python-format +msgid "Remove" +msgstr "删除" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#, python-format +msgid "Remove Item" +msgstr "删除项目" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_year_period +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Same Period Previous Years" +msgstr "去年同一时期" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_quick_edit_view.xml:0 +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.ks_dashboard_ninja_action +#, python-format +msgid "Save" +msgstr "保存" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Save Changes" +msgstr "保存更改" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Save Changes as a New Layout" +msgstr "将更改保存为新布局" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#, python-format +msgid "Save as Image" +msgstr "保存为图像" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Save as New Layout" +msgstr "保存为新布局" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#, python-format +msgid "Save as PDF" +msgstr "保存为PDF" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.ks_item_search_view +msgid "Search Items" +msgstr "搜索项目" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#, python-format +msgid "Search fa-icon.." +msgstr "搜索 fa-icon.." + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#, python-format +msgid "Search through site content" +msgstr "搜索网站内容" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board_defined_filters__display_type__line_section +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Section" +msgstr "部分" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Sections" +msgstr "部分" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#, python-format +msgid "Select" +msgstr "选择" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_pro.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_to_do_template.xml:0 +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_child_board__ks_dashboard_ninja_id +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_ninja_dashboard_item_action__ks_dashboard_ninja_id +#, python-format +msgid "Select Dashboard" +msgstr "选择仪表板" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_ninja_dashboard_item_action__ks_dashboard_ninja_ids +msgid "Select Dashboards" +msgstr "选择仪表板" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#, python-format +msgid "Select Icon" +msgstr "选择图标" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#, python-format +msgid "Select Icons" +msgstr "选择图标" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_unit_selection +msgid "Select Unit Type" +msgstr "选择单位类型" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_date_filter_selection +msgid "Select interval of the records to be displayed. " +msgstr "选择要显示的记录时间间隔。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_dashboard_item_theme +msgid "Select the color theme for the display. " +msgstr "选择显示屏的颜色主题。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_list_view_type +msgid "Select the desired list view type. " +msgstr "选择所需的列表视图类型。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_sort_by_field +msgid "Select the desired sorting preference. " +msgstr "选择所需的排序偏好。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_item_color +msgid "Select the display preference. " +msgstr "选择显示偏好。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_date_filter_field +msgid "Select the field for which Date Filter should be applicable." +msgstr "选择适用日期筛选器的字段。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_font_color +msgid "Select the font color. " +msgstr "选择字体颜色。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_default_icon +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_default_icon_color +msgid "Select the icon to be displayed. " +msgstr "选择要显示的图标。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_dashboard_item_type +msgid "Select the required type of dashboard to display. " +msgstr "选择要显示的所需仪表盘类型。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_chart_relation_sub_groupby +msgid "Select the second level of grouping. " +msgstr "选择第二级分组。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_data_calculation_type +msgid "Select the type of calculation you want to perform on the data." +msgstr "选择要对数据进行计算的类型。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_unit_selection +msgid "Select the unit to be assigned to the value. " +msgstr "选择要分配给数值的单位。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_auto_update_type +msgid "Select the update type." +msgstr "选择更新类型。" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#, python-format +msgid "Selected item is duplicated to ." +msgstr "选择项目复制到." + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#, python-format +msgid "Selected item is moved to ." +msgstr "选择项目移动到 ." + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_domain_fix.js:0 +#, python-format +msgid "Selected records" +msgstr "已选记录" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_semi_circle_chart +msgid "Semi Circle Chart" +msgstr "半圆图" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.board_defined_filters +msgid "Separator Name (eg. Order States, Deadlines)" +msgstr "分隔符名称(如订购国、截止日期)" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__sequence +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__sequence +msgid "Sequence" +msgstr "序列" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Set Current Layout" +msgstr "设置当前布局" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Set Update Interval" +msgstr "设置更新间隔" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_unit +msgid "Show Custom Unit" +msgstr "显示自定义单位" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_show_data_value +msgid "Show Data Value" +msgstr "显示数据值" + +#. module: ks_dashboard_ninja +#: model:res.groups,name:ks_dashboard_ninja.ks_dashboard_ninja_group_manager +msgid "Show Full Dashboard Features" +msgstr "显示全部仪表板功能" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_hide_legend +msgid "Show Legend" +msgstr "显示图例" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_show_live_pop_up +msgid "Show Live Update Pop Up" +msgstr "显示实时更新弹出窗口" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_show_records +msgid "Show Records" +msgstr "显示记录" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_goal_bar_line +msgid "Show Target As Line" +msgstr "显示目标线" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_top_menu_id +msgid "Show Under Menu" +msgstr "显示在顶层菜单" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_standard_goal_value +msgid "Show the set target" +msgstr "显示既定目标" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_goal_enable +msgid "Show the set target." +msgstr "显示既定目标。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_menu_sequence +msgid "Smallest sequence give high priority and Highest sequence give low priority" +msgstr "序列号越小,优先级越高;序列越大,优先级越低" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_import_dashboard.js:0 +#, python-format +msgid "Some Items can not be imported Need Dashboard Ninja pro " +msgstr "有些项目不能导入,需要高级版仪表盘" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_filters.py:0 +#, python-format +msgid "Something went wrong . Possibly it is due to wrong input type for domain" +msgstr "出了点问题。可能是由于条件的输入类型错误。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_sort_by_field +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__ks_sort_by_field +msgid "Sort By Field" +msgstr "字段排序" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_sort_by_order +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_action__ks_sort_by_order +msgid "Sort Order" +msgstr "排序" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_bar_chart_stacked +msgid "Stack the columns of the same record. " +msgstr "堆叠同一记录的列。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_bar_chart_stacked +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Stacked Bar Chart" +msgstr "堆叠条形图" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_standard_goal_value +msgid "Standard Target" +msgstr "标准目标" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_dashboard_start_date +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_item_start_date +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Start Date" +msgstr "开始日期" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja.py:0 +#, python-format +msgid "Start date must be less than end date" +msgstr "开始日期必须小于结束日期" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#, python-format +msgid "Start date should be less than end date" +msgstr "开始日期应小于结束日期" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Sub Group By Date" +msgstr "日期子级分组" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py:0 +#, python-format +msgid "Sub Groupby field: {} cannot be aggregated by {}" +msgstr "子级分组字段: {} 不能按 {} 聚合" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_widget_toggle.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_data_count_type__sum +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_record_count_type_2__sum +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_record_count_type__sum +#, python-format +msgid "Sum" +msgstr "总计" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Target" +msgstr "目标" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_goal_lines +msgid "Target Lines" +msgstr "目标明细" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Task Lines" +msgstr "任务明细" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Tasks" +msgstr "任务" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_board_defined_filters__display_type +msgid "Technical field for UX purpose." +msgstr "用户体验技术领域。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_template__ks_template_type +msgid "Template Format" +msgstr "模板格式" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_board_template__ks_dashboard_item_ids +msgid "Template Type" +msgstr "模板类型" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__name +msgid "The item will be represented by this unique name." +msgstr "项目将由这个唯一的名称表示。" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_dashboard_item_theme +msgid "Theme" +msgstr "主题" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_client_action +msgid "This Action will be Performed at the end of Drill Down Action" +msgstr "此操作将在向下分解操作结束时执行" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__t_month +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__t_month +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__t_month +#, python-format +msgid "This Month" +msgstr "本月" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__t_quarter +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__t_quarter +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__t_quarter +#, python-format +msgid "This Quarter" +msgstr "本季度" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__t_week +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__t_week +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__t_week +#, python-format +msgid "This Week" +msgstr "本周" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__t_year +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__t_year +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__t_year +#, python-format +msgid "This Year" +msgstr "今年" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_show_records +msgid "" +"This field Enable the click on \n" +" Dashboard Items to " +"view the Odoo \n" +" default view of records" +msgstr "" +"此字段启用单击以 \n" +" 查看系统的仪表板 \n" +" 默认记录视图" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja.py:0 +#, python-format +msgid "This file is not supported" +msgstr "不支持此文件" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_dashboard_item_type__ks_tile +#, python-format +msgid "Tile" +msgstr "瓦片" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_data_format +msgid "To Change the number format showing in chart to given option" +msgstr "将图表中显示的数字格式更改为给定选项" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_dashboard_item_type__ks_to_do +#, python-format +msgid "To Do" +msgstr "待办" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_to_do_data +msgid "To Do Data in JSon" +msgstr "JSon 中的待办事项数据" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_to_do_preview +msgid "To Do Preview" +msgstr "待办事项预览" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "To add dashboard item, use" +msgstr "要添加仪表板项目,请使用" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_record_data_limit_visibility +msgid "To enable the record data limit field" +msgstr "启用记录数据限制字段" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js:0 +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_board__ks_date_filter_selection__l_day +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection_2__l_day +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_date_filter_selection__l_day +#, python-format +msgid "Today" +msgstr "今天" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_button_color +msgid "Top Button Color" +msgstr "顶部按钮颜色" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.item_form_view +msgid "Type" +msgstr "类型" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_record_count_type +msgid "Type of record how record will show as count,sum and average of the record" +msgstr "记录类型 如何显示记录的计数、总和和平均值" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_list_view_type__ungrouped +msgid "Un-Grouped" +msgstr "未分组" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/js/ks_import_dashboard.js:0 +#, python-format +msgid "Unarchive" +msgstr "取消归档" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_board__ks_set_interval +msgid "Update Interval for new items only" +msgstr "更新新项目的时间间隔" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_auto_update_type__ks_live_update +msgid "Update at every instance." +msgstr "随时更新。" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_widget_toggle.xml:0 +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_icon +#, python-format +msgid "Upload Icon" +msgstr "上传图标" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#, python-format +msgid "Uploading..." +msgstr "上传中..." + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item_goal__ks_goal_value +msgid "Value" +msgstr "值" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_target_view +msgid "View" +msgstr "查看" + +#. module: ks_dashboard_ninja +#: model_terms:ir.ui.view,arch_db:ks_dashboard_ninja.board_tree +msgid "View Items" +msgstr "查看项目" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_item_color__warm +msgid "Warm" +msgstr "暖色" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_groupby__week +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_sub_groupby__week +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_item_action_date_groupby__week +msgid "Week" +msgstr "周" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_groupby__year +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item__ks_chart_date_sub_groupby__year +#: model:ir.model.fields.selection,name:ks_dashboard_ninja.selection__ks_dashboard_ninja_item_action__ks_item_action_date_groupby__year +msgid "Year" +msgstr "年份" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "Your personal dashboard is empty" +msgstr "无个人仪表板" + +#. module: ks_dashboard_ninja +#: code:addons/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py:0 +#, python-format +msgid "if target lines is selected then cannot be set pagination value" +msgstr "如果选择了目标行,则无法设置分页值" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,field_description:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_list_target_deviation_field +msgid "list_field_id" +msgstr "list_field_id" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "on top right corner." +msgstr "在右上角。" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dn_global_filter.xml:0 +#, python-format +msgid "or" +msgstr "或" + +#. module: ks_dashboard_ninja +#: model:ir.model,name:ks_dashboard_ninja.model_ks_to_do_description +msgid "to do description" +msgstr "用作说明" + +#. module: ks_dashboard_ninja +#: model:ir.model,name:ks_dashboard_ninja.model_ks_to_do_headers +msgid "to do headers" +msgstr "用作页眉" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "vs Prev" +msgstr "VS 上一期间" + +#. module: ks_dashboard_ninja +#. openerp-web +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_item_templates.xml:0 +#: code:addons/ks_dashboard_ninja/static/src/xml/ks_dashboard_ninja_templates.xml:0 +#, python-format +msgid "vs Target" +msgstr "与目标" + +#. module: ks_dashboard_ninja +#: model:ir.model.fields,help:ks_dashboard_ninja.field_ks_dashboard_ninja_item__ks_export_all_records +msgid "when click on boolean button, all the records will be downloaded which are present in entire list" +msgstr "点击布尔按钮后,将下载整个列表中的所有记录" diff --git a/ks_dashboard_ninja/models/Kpi_mail.py b/ks_dashboard_ninja/models/Kpi_mail.py new file mode 100644 index 000000000..3ff424843 --- /dev/null +++ b/ks_dashboard_ninja/models/Kpi_mail.py @@ -0,0 +1,9 @@ +from odoo import models, fields, api, _ + + +class KpSendMail(models.Model): + _name = 'ks_dashboard_ninja.kpi_mail' + _description = 'Dashboard Ninja Kpi mail' + + + name = fields.Char(string="Email To:") diff --git a/ks_dashboard_ninja/models/__init__.py b/ks_dashboard_ninja/models/__init__.py new file mode 100644 index 000000000..0530c9762 --- /dev/null +++ b/ks_dashboard_ninja/models/__init__.py @@ -0,0 +1,15 @@ +from . import ks_dashboard_ninja +from . import ks_dashboard_ninja_items +from . import ks_item_action +from . import ks_child_dashboard +from . import ks_dashboard_filters +from . import ks_dashboard_templates +from . import ks_dn_to_do_item +from . import ks_import_dashboard +from . import Kpi_mail +from . import res_settings +from . import ks_ai_ninja_dashboard +from . import ks_ai_whole_dashboard +from . import ks_key_fetch + + diff --git a/ks_dashboard_ninja/models/ks_ai_ninja_dashboard.py b/ks_dashboard_ninja/models/ks_ai_ninja_dashboard.py new file mode 100644 index 000000000..32a8eb558 --- /dev/null +++ b/ks_dashboard_ninja/models/ks_ai_ninja_dashboard.py @@ -0,0 +1,222 @@ +import json +import logging +import requests +from odoo import http, api, fields, models, _ +from odoo.exceptions import ValidationError + +_logger = logging.getLogger(__name__) + + +class KsDashboardNInjaAI(models.TransientModel): + _name = 'ks_dashboard_ninja.arti_int' + _description = 'AI Dashboard' + + ks_type = fields.Selection([('ks_model', 'Model'), ('ks_keyword', 'Keywords')], + string="Ks AI Type", default='ks_model') + + ks_import_model_id = fields.Many2one('ir.model', string='Model', + domain="[('access_ids','!=',False),('transient','=',False)," + "('model','not ilike','base_import%'),('model','not ilike','ir.%')," + "('model','not ilike','web_editor.%'),('model','not ilike','web_tour.%')," + "('model','!=','mail.thread'),('model','not ilike','ks_dash%'),('model','not ilike','ks_to%')]", + help="Data source to fetch and read the data for the creation of dashboard items. ") + + ks_import_model = fields.Many2one('ir.model', string='Model', + domain="[('access_ids','!=',False),('transient','=',False)," + "('model','not ilike','base_import%'),('model','not ilike','ir.%')," + "('model','not ilike','web_editor.%'),('model','not ilike','web_tour.%')," + "('model','!=','mail.thread'),('model','not ilike','ks_dash%'),('model','not ilike','ks_to%')]", + help="Data source to fetch and read the data for the creation of dashboard items. ") + ks_input_keywords = fields.Char("Ks Keywords") + ks_model_show = fields.Boolean(default = False, compute='_compute_show_model') + + @api.onchange('ks_input_keywords') + def _compute_show_model(self): + if self.ks_input_keywords and self.ks_type=="ks_keyword": + api_key = self.env['ir.config_parameter'].sudo().get_param( + 'ks_dashboard_ninja.dn_api_key') + url = self.env['ir.config_parameter'].sudo().get_param( + 'ks_dashboard_ninja.url') + if api_key and url: + json_data = {'name': api_key, + 'type': self.ks_type, + 'keyword': self.ks_input_keywords + } + url = url + "/api/v1/ks_dn_keyword_gen" + ks_response = requests.post(url, data=json_data) + if json.loads(ks_response.text) == False: + self.ks_model_show = True + else: + self.ks_model_show = False + else: + raise ValidationError(_("Please enter URL and API Key in General Settings")) + + else: + self.ks_model_show = False + + @api.model + def ks_get_keywords(self): + url = self.env['ir.config_parameter'].sudo().get_param( + 'ks_dashboard_ninja.url') + if url: + url = url + "/api/v1/ks_dn_get_keyword" + ks_response = requests.post(url) + if ks_response.status_code == 200: + return json.loads(ks_response.text) + else: + return [] + + + + def ks_do_action(self): + headers = {"Content-Type": "application/json", + "Accept": "application/json", + "Catch-Control": "no-cache", + } + + if self.ks_import_model_id: + ks_model_name = self.ks_import_model_id.model + ks_fields = self.env[ks_model_name].fields_get() + ks_filtered_fields = {key: val for key, val in ks_fields.items() if val['type'] not in ['many2many', 'one2many', 'binary'] and val['name'] != 'id' and val['name'] != 'sequence' and val['store'] == True} + ks_fields_name = {val['name']:val['type'] for val in ks_filtered_fields.values()} + question = ("columns: "+ f"{ks_fields_name}") + + api_key = self.env['ir.config_parameter'].sudo().get_param( + 'ks_dashboard_ninja.dn_api_key') + url = self.env['ir.config_parameter'].sudo().get_param( + 'ks_dashboard_ninja.url') + if api_key and url: + json_data = {'name': api_key, + 'question':question, + 'url': self.env['ir.config_parameter'].sudo().get_param('web.base.url'), + 'db_name': self.env.cr.dbname + } + url = url+"/api/v1/ks_dn_main_api" + ks_ai_response = requests.post(url, data=json_data) + if ks_ai_response.status_code == 200: + ks_ai_response = json.loads(ks_ai_response.text) + # create dummy dash to create items on the dashboard, later deleted it. + ks_create_record = self.env['ks_dashboard_ninja.board'].create({ + 'name': 'AI dashboard', + 'ks_dashboard_menu_name': 'AI menu', + 'ks_dashboard_default_template': self.env.ref('ks_dashboard_ninja.ks_blank', False).id, + 'ks_dashboard_top_menu_id': self.env['ir.ui.menu'].search([('name', '=', 'My Dashboard')])[0].id, + }) + ks_dash_id = ks_create_record.id + + ks_result = self.env['ks_dashboard_ninja.item'].create_ai_dash(ks_ai_response, ks_dash_id, + ks_model_name) + context = {'ks_dash_id': self._context['ks_dashboard_id'], + 'ks_dash_name': self.env['ks_dashboard_ninja.board'].search([ + ('id','=',self._context['ks_dashboard_id'])]).name,'ks_delete_dash_id':ks_dash_id } + + # return client action created through js for AI dashboard to render items on dummy dashboard + if (ks_result == "success"): + return { + 'type': 'ir.actions.client', + 'name': context['ks_dash_name'], + 'params': {'ks_dashboard_id': ks_create_record.id}, + 'tag': 'ks_dashboard_ninja_ai', + 'target': 'new', + 'context': context + } + else: + self.env['ks_dashboard_ninja.board'].browse(ks_dash_id).unlink() + raise ValidationError(_("Items didn't render because AI provides invalid response for this model.Please try again")) + else: + raise ValidationError(_("AI Responds with the following status:- %s") % ks_ai_response.text) + else: + raise ValidationError(_("Please enter URL and API Key in General Settings")) + else: + raise ValidationError(_("Please enter the Model")) + + + + def ks_generate_item(self): + if self.ks_input_keywords: + api_key = self.env['ir.config_parameter'].sudo().get_param( + 'ks_dashboard_ninja.dn_api_key') + url = self.env['ir.config_parameter'].sudo().get_param( + 'ks_dashboard_ninja.url') + if api_key and url: + json_data = {'name': api_key, + 'type': self.ks_type, + 'keyword':self.ks_input_keywords + } + url = url + "/api/v1/ks_dn_keyword_gen" + ks_response = requests.post(url, data=json_data) + else: + raise ValidationError(_("Please put API key and URL")) + if json.loads(ks_response.text) != False and ks_response.status_code==200 : + ks_ai_response = json.loads(ks_response.text) + ks_dash_id = self._context['ks_dashboard_id'] + ks_model_name = ks_ai_response[0]['model'] + ks_result = self.env['ks_dashboard_ninja.item'].create_ai_dash(ks_ai_response, ks_dash_id, + ks_model_name) + if ks_result == "success": + return{ + 'type': 'ir.actions.client', + 'tag': 'reload', + } + else: + raise ValidationError(_("Items didn't render, please try again!")) + else: + ks_model_name = self.ks_import_model.model + ks_fields = self.env[ks_model_name].fields_get() + ks_filtered_fields = {key: val for key, val in ks_fields.items() if + val['type'] not in ['many2many', 'one2many', 'binary'] and val[ + 'name'] != 'id' and val['name'] != 'sequence' and val['store'] == True} + ks_fields_name = {val['name']: val['type'] for val in ks_filtered_fields.values()} + question = ("schema: " + f"{ks_fields_name}") + model =("model:" + f"{ks_model_name}") + api_key = self.env['ir.config_parameter'].sudo().get_param( + 'ks_dashboard_ninja.dn_api_key') + url = self.env['ir.config_parameter'].sudo().get_param( + 'ks_dashboard_ninja.url') + if api_key and url: + json_data = {'name': api_key, + 'question': self.ks_input_keywords, + 'type':self.ks_type, + 'schema':question, + 'model':model, + 'url': self.env['ir.config_parameter'].sudo().get_param('web.base.url'), + 'db_name': self.env.cr.dbname + } + url = url + "/api/v1/ks_dn_main_api" + ks_ai_response = requests.post(url, data=json_data) + if ks_ai_response.status_code == 200: + ks_ai_response = json.loads(ks_ai_response.text) + ks_dash_id = self._context['ks_dashboard_id'] + ks_model_name = (ks_ai_response[0]['model']).lower() + if self.env['ir.model'].search([('model','=',ks_model_name)]).id or self.env['ir.model'].search([('name','=',ks_model_name)]).id: + if self.env['ir.model'].search([('name','=',ks_model_name)]).id: + ks_model_name = self.env['ir.model'].search([('name','=',ks_model_name)]).model + else: + ks_model_name = (ks_ai_response[0]['model']).lower() + ks_result = self.env['ks_dashboard_ninja.item'].create_ai_dash(ks_ai_response, ks_dash_id,ks_model_name) + if ks_result == "success": + return { + 'type': 'ir.actions.client', + 'tag': 'reload', + } + else: + raise ValidationError(_("Items didn't render, please try again!")) + else: + raise ValidationError(_("%s model does not exist.Please install")% ks_model_name) + else: + raise ValidationError( + _("AI Responds with the following status:- %s") % ks_ai_response.text) + + else: + raise ValidationError(_("Please enter URL and API Key in General Settings")) + else: + raise ValidationError(_("Enter the input keywords to render the item")) + + + + + + + + + diff --git a/ks_dashboard_ninja/models/ks_ai_whole_dashboard.py b/ks_dashboard_ninja/models/ks_ai_whole_dashboard.py new file mode 100644 index 000000000..f5ec3a8e0 --- /dev/null +++ b/ks_dashboard_ninja/models/ks_ai_whole_dashboard.py @@ -0,0 +1,91 @@ +import json +import logging +import requests +from odoo import http, api, fields, models, _ +from odoo.exceptions import ValidationError + +_logger = logging.getLogger(__name__) + + +class KsAIDashboardninja(models.TransientModel): + _name = 'ks_dashboard_ninja.ai_dashboard' + _description = 'AI Dashboard' + + ks_import_model_id = fields.Many2one('ir.model', string='Model', + domain="[('access_ids','!=',False),('transient','=',False)," + "('model','not ilike','base_import%'),('model','not ilike','ir.%')," + "('model','not ilike','web_editor.%'),('model','not ilike','web_tour.%')," + "('model','!=','mail.thread'),('model','not ilike','ks_dash%'),('model','not ilike','ks_to%')]", + help="Data source to fetch and read the data for the creation of dashboard items. ", required=True) + + ks_dash_name = fields.Char(string="Dashboard Name", required=True) + ks_menu_name = fields.Char(string="Menu Name", required=True) + ks_top_menu_id = fields.Many2one('ir.ui.menu', + domain="[('parent_id','=',False)]", + string="Show Under Menu", required=True, + default=lambda self: self.env['ir.ui.menu'].search( + [('name', '=', 'My Dashboard')])[0]) + ks_template = fields.Many2one('ks_dashboard_ninja.board_template', + default=lambda self: self.env.ref('ks_dashboard_ninja.ks_blank', + False), + string="Dashboard Template") + + def ks_do_action(self): + headers = {"Content-Type": "application/json", + "Accept": "application/json", + "Catch-Control": "no-cache", + } + + if self.ks_import_model_id: + ks_model_name = self.ks_import_model_id.model + ks_fields = self.env[ks_model_name].fields_get() + ks_filtered_fields = {key: val for key, val in ks_fields.items() if val['type'] not in ['many2many', 'one2many', 'binary'] and val['name'] != 'id' and val['name'] != 'sequence' and val['store'] == True} + ks_fields_name = {val['name']:val['type'] for val in ks_filtered_fields.values()} + question = ("columns: "+ f"{ks_fields_name}") + + api_key = self.env['ir.config_parameter'].sudo().get_param( + 'ks_dashboard_ninja.dn_api_key') + url = self.env['ir.config_parameter'].sudo().get_param( + 'ks_dashboard_ninja.url') + if api_key and url: + json_data = {'name': api_key, + 'question':question, + 'url':self.env['ir.config_parameter'].sudo().get_param('web.base.url'), + 'db_name':self.env.cr.dbname + } + url = url+"/api/v1/ks_dn_main_api" + ks_ai_response = requests.post(url, data=json_data) + if ks_ai_response.status_code == 200: + ks_ai_response = json.loads(ks_ai_response.text) + ks_create_record = self.env['ks_dashboard_ninja.board'].create({ + 'name': self.ks_dash_name, + 'ks_dashboard_menu_name': self.ks_menu_name, + 'ks_dashboard_default_template': self.ks_template.id, + 'ks_dashboard_top_menu_id': self.ks_top_menu_id.id, + }) + ks_dash_id = ks_create_record.id + + ks_result = self.env['ks_dashboard_ninja.item'].create_ai_dash(ks_ai_response, ks_dash_id, + ks_model_name) + + if (ks_result == "success"): + return { + 'type': 'ir.actions.client', + 'name': "Dashboard Ninja", + 'res_model': 'ks_dashboard_ninja.board', + 'params': {'ks_dashboard_id': ks_dash_id}, + 'tag': 'ks_dashboard_ninja', + } + else: + self.env['ks_dashboard_ninja.board'].browse(ks_dash_id).unlink() + raise ValidationError(_("Items didn't render, please try again!")) + else: + raise ValidationError(_("AI Responds with the following status:- %s") % ks_ai_response.text) + else: + raise ValidationError(_("Please enter URL and API Key in General Settings")) + else: + raise ValidationError(_("Please enter the Model")) + + + + diff --git a/ks_dashboard_ninja/models/ks_child_dashboard.py b/ks_dashboard_ninja/models/ks_child_dashboard.py new file mode 100644 index 000000000..acb4eb8da --- /dev/null +++ b/ks_dashboard_ninja/models/ks_child_dashboard.py @@ -0,0 +1,21 @@ +from odoo import models, fields, api, _ + + +class KsDashboardNinjaBoardItemAction(models.Model): + _name = 'ks_dashboard_ninja.child_board' + _description = 'Dashboard Ninja Child Board' + + name = fields.Char() + ks_dashboard_ninja_id = fields.Many2one("ks_dashboard_ninja.board", string="Select Dashboard") + ks_gridstack_config = fields.Char('Item Configurations') + # ks_board_active_user_ids = fields.Many2many('res.users') + ks_active = fields.Boolean("Is Selected") + ks_dashboard_menu_name = fields.Char(string="Menu Name", related='ks_dashboard_ninja_id.ks_dashboard_menu_name', store=True) + board_type = fields.Selection([('default', 'Default'), ('child', 'Child')]) + company_id = fields.Many2one('res.company', required=True, default=lambda self: self.env.company) + + + def set_grid_stack_config(self, dashboard_id, gridstack_config): + return self.search([('ks_dashboard_ninja_id', '=', dashboard_id)]).sudo().write({'ks_gridstack_config': gridstack_config}) + + diff --git a/ks_dashboard_ninja/models/ks_country_bounds.py b/ks_dashboard_ninja/models/ks_country_bounds.py new file mode 100644 index 000000000..e6aa3e930 --- /dev/null +++ b/ks_dashboard_ninja/models/ks_country_bounds.py @@ -0,0 +1,182 @@ +country = { + 'AF': ('Afghanistan', (60.5284298033, 29.318572496, 75.1580277851, 38.4862816432)), + 'AO': ('Angola', (11.6400960629, -17.9306364885, 24.0799052263, -4.43802336998)), + 'AL': ('Albania', (19.3044861183, 39.624997667, 21.0200403175, 42.6882473822)), + 'AE': ('United Arab Emirates', (51.5795186705, 22.4969475367, 56.3968473651, 26.055464179)), + 'AR': ('Argentina', (-73.4154357571, -55.25, -53.628348965, -21.8323104794)), + 'AM': ('Armenia', (43.5827458026, 38.7412014837, 46.5057198423, 41.2481285671)), + 'AQ': ('Antarctica', (-180.0, -90.0, 180.0, -63.2706604895)), + 'TF': ('Fr. S. and Antarctic Lands', (68.72, -49.775, 70.56, -48.625)), + 'AU': ('Australia', (113.338953078, -43.6345972634, 153.569469029, -10.6681857235)), + 'AT': ('Austria', (9.47996951665, 46.4318173285, 16.9796667823, 49.0390742051)), + 'AZ': ('Azerbaijan', (44.7939896991, 38.2703775091, 50.3928210793, 41.8606751572)), + 'BI': ('Burundi', (29.0249263852, -4.49998341229, 30.752262811, -2.34848683025)), + 'BE': ('Belgium', (2.51357303225, 49.5294835476, 6.15665815596, 51.4750237087)), + 'BJ': ('Benin', (0.772335646171, 6.14215770103, 3.79711225751, 12.2356358912)), + 'BF': ('Burkina Faso', (-5.47056494793, 9.61083486576, 2.17710778159, 15.1161577418)), + 'BD': ('Bangladesh', (88.0844222351, 20.670883287, 92.6727209818, 26.4465255803)), + 'BG': ('Bulgaria', (22.3805257504, 41.2344859889, 28.5580814959, 44.2349230007)), + 'BS': ('Bahamas', (-78.98, 23.71, -77.0, 27.04)), + 'BA': ('Bosnia and Herz.', (15.7500260759, 42.65, 19.59976, 45.2337767604)), + 'BY': ('Belarus', (23.1994938494, 51.3195034857, 32.6936430193, 56.1691299506)), + 'BZ': ('Belize', (-89.2291216703, 15.8869375676, -88.1068129138, 18.4999822047)), + 'BO': ('Bolivia', (-69.5904237535, -22.8729187965, -57.4983711412, -9.76198780685)), + 'BR': ('Brazil', (-73.9872354804, -33.7683777809, -34.7299934555, 5.24448639569)), + 'BN': ('Brunei', (114.204016555, 4.007636827, 115.450710484, 5.44772980389)), + 'BT': ('Bhutan', (88.8142484883, 26.7194029811, 92.1037117859, 28.2964385035)), + 'BW': ('Botswana', (19.8954577979, -26.8285429827, 29.4321883481, -17.6618156877)), + 'CF': ('Central African Rep.', (14.4594071794, 2.2676396753, 27.3742261085, 11.1423951278)), + 'CA': ('Canada', (-140.99778, 41.6751050889, -52.6480987209, 83.23324)), + 'CH': ('Switzerland', (6.02260949059, 45.7769477403, 10.4427014502, 47.8308275417)), + 'CL': ('Chile', (-75.6443953112, -55.61183, -66.95992, -17.5800118954)), + 'CN': ('China', (73.6753792663, 18.197700914, 135.026311477, 53.4588044297)), + 'CI': ('Ivory Coast', (-8.60288021487, 4.33828847902, -2.56218950033, 10.5240607772)), + 'CM': ('Cameroon', (8.48881554529, 1.72767263428, 16.0128524106, 12.8593962671)), + 'CD': ('Congo (Kinshasa)', (12.1823368669, -13.2572266578, 31.1741492042, 5.25608775474)), + 'CG': ('Congo (Brazzaville)', (11.0937728207, -5.03798674888, 18.4530652198, 3.72819651938)), + 'CO': ('Colombia', (-78.9909352282, -4.29818694419, -66.8763258531, 12.4373031682)), + 'CR': ('Costa Rica', (-85.94172543, 8.22502798099, -82.5461962552, 11.2171192489)), + 'CU': ('Cuba', (-84.9749110583, 19.8554808619, -74.1780248685, 23.1886107447)), + 'CY': ('Cyprus', (32.2566671079, 34.5718694118, 34.0048808123, 35.1731247015)), + 'CZ': ('Czech Rep.', (12.2401111182, 48.5553052842, 18.8531441586, 51.1172677679)), + 'DE': ('Germany', (5.98865807458, 47.3024876979, 15.0169958839, 54.983104153)), + 'DJ': ('Djibouti', (41.66176, 10.9268785669, 43.3178524107, 12.6996385767)), + 'DK': ('Denmark', (8.08997684086, 54.8000145534, 12.6900061378, 57.730016588)), + 'DO': ('Dominican Rep.', (-71.9451120673, 17.598564358, -68.3179432848, 19.8849105901)), + 'DZ': ('Algeria', (-8.68439978681, 19.0573642034, 11.9995056495, 37.1183806422)), + 'EC': ('Ecuador', (-80.9677654691, -4.95912851321, -75.2337227037, 1.3809237736)), + 'EG': ('Egypt', (24.70007, 22.0, 36.86623, 31.58568)), + 'ER': ('Eritrea', (36.3231889178, 12.4554157577, 43.0812260272, 17.9983074)), + 'ES': ('Spain', (-9.39288367353, 35.946850084, 3.03948408368, 43.7483377142)), + 'EE': ('Estonia', (23.3397953631, 57.4745283067, 28.1316992531, 59.6110903998)), + 'ET': ('Ethiopia', (32.95418, 3.42206, 47.78942, 14.95943)), + 'FI': ('Finland', (20.6455928891, 59.846373196, 31.5160921567, 70.1641930203)), + 'FJ': ('Fiji', (-180.0, -18.28799, 180.0, -16.0208822567)), + 'FK': ('Falkland Is.', (-61.2, -52.3, -57.75, -51.1)), + 'FR': ('France', (-54.5247541978, 2.05338918702, 9.56001631027, 51.1485061713)), + 'GA': ('Gabon', (8.79799563969, -3.97882659263, 14.4254557634, 2.32675751384)), + 'GB': ('United Kingdom', (-7.57216793459, 49.959999905, 1.68153079591, 58.6350001085)), + 'GE': ('Georgia', (39.9550085793, 41.0644446885, 46.6379081561, 43.553104153)), + 'GH': ('Ghana', (-3.24437008301, 4.71046214438, 1.0601216976, 11.0983409693)), + 'GN': ('Guinea', (-15.1303112452, 7.3090373804, -7.83210038902, 12.5861829696)), + 'GM': ('Gambia', (-16.8415246241, 13.1302841252, -13.8449633448, 13.8764918075)), + 'GW': ('Guinea Bissau', (-16.6774519516, 11.0404116887, -13.7004760401, 12.6281700708)), + 'GQ': ('Eq. Guinea', (9.3056132341, 1.01011953369, 11.285078973, 2.28386607504)), + 'GR': ('Greece', (20.1500159034, 34.9199876979, 26.6041955909, 41.8269046087)), + 'GL': ('Greenland', (-73.297, 60.03676, -12.20855, 83.64513)), + 'GT': ('Guatemala', (-92.2292486234, 13.7353376327, -88.2250227526, 17.8193260767)), + 'GY': ('Guyana', (-61.4103029039, 1.26808828369, -56.5393857489, 8.36703481692)), + 'HN': ('Honduras', (-89.3533259753, 12.9846857772, -83.147219001, 16.0054057886)), + 'HR': ('Croatia', (13.6569755388, 42.47999136, 19.3904757016, 46.5037509222)), + 'HT': ('Haiti', (-74.4580336168, 18.0309927434, -71.6248732164, 19.9156839055)), + 'HU': ('Hungary', (16.2022982113, 45.7594811061, 22.710531447, 48.6238540716)), + 'ID': ('Indonesia', (95.2930261576, -10.3599874813, 141.03385176, 5.47982086834)), + 'IN': ('India', (68.1766451354, 7.96553477623, 97.4025614766, 35.4940095078)), + 'IE': ('Ireland', (-9.97708574059, 51.6693012559, -6.03298539878, 55.1316222195)), + 'IR': ('Iran', (44.1092252948, 25.0782370061, 63.3166317076, 39.7130026312)), + 'IQ': ('Iraq', (38.7923405291, 29.0990251735, 48.5679712258, 37.3852635768)), + 'IS': ('Iceland', (-24.3261840479, 63.4963829617, -13.609732225, 66.5267923041)), + 'IL': ('Israel', (34.2654333839, 29.5013261988, 35.8363969256, 33.2774264593)), + 'IT': ('Italy', (6.7499552751, 36.619987291, 18.4802470232, 47.1153931748)), + 'JM': ('Jamaica', (-78.3377192858, 17.7011162379, -76.1996585761, 18.5242184514)), + 'JO': ('Jordan', (34.9226025734, 29.1974946152, 39.1954683774, 33.3786864284)), + 'JP': ('Japan', (129.408463169, 31.0295791692, 145.543137242, 45.5514834662)), + 'KZ': ('Kazakhstan', (46.4664457538, 40.6623245306, 87.3599703308, 55.3852501491)), + 'KE': ('Kenya', (33.8935689697, -4.67677, 41.8550830926, 5.506)), + 'KG': ('Kyrgyzstan', (69.464886916, 39.2794632025, 80.2599902689, 43.2983393418)), + 'KH': ('Cambodia', (102.3480994, 10.4865436874, 107.614547968, 14.5705838078)), + 'KR': ('S. Korea', (126.117397903, 34.3900458847, 129.468304478, 38.6122429469)), + 'KW': ('Kuwait', (46.5687134133, 28.5260627304, 48.4160941913, 30.0590699326)), + 'LA': ('Laos', (100.115987583, 13.88109101, 107.564525181, 22.4647531194)), + 'LB': ('Lebanon', (35.1260526873, 33.0890400254, 36.6117501157, 34.6449140488)), + 'LR': ('Liberia', (-11.4387794662, 4.35575511313, -7.53971513511, 8.54105520267)), + 'LY': ('Libya', (9.31941084152, 19.58047, 25.16482, 33.1369957545)), + 'LK': ('Sri Lanka', (79.6951668639, 5.96836985923, 81.7879590189, 9.82407766361)), + 'LS': ('Lesotho', (26.9992619158, -30.6451058896, 29.3251664568, -28.6475017229)), + 'LT': ('Lithuania', (21.0558004086, 53.9057022162, 26.5882792498, 56.3725283881)), + 'LU': ('Luxembourg', (5.67405195478, 49.4426671413, 6.24275109216, 50.1280516628)), + 'LV': ('Latvia', (21.0558004086, 55.61510692, 28.1767094256, 57.9701569688)), + 'MA': ('Morocco', (-17.0204284327, 21.4207341578, -1.12455115397, 35.7599881048)), + 'MD': ('Moldova', (26.6193367856, 45.4882831895, 30.0246586443, 48.4671194525)), + 'MG': ('Madagascar', (43.2541870461, -25.6014344215, 50.4765368996, -12.0405567359)), + 'MX': ('Mexico', (-117.12776, 14.5388286402, -86.811982388, 32.72083)), + 'MK': ('Macedonia', (20.46315, 40.8427269557, 22.9523771502, 42.3202595078)), + 'ML': ('Mali', (-12.1707502914, 10.0963607854, 4.27020999514, 24.9745740829)), + 'MM': ('Myanmar', (92.3032344909, 9.93295990645, 101.180005324, 28.335945136)), + 'ME': ('Montenegro', (18.45, 41.87755, 20.3398, 43.52384)), + 'MN': ('Mongolia', (87.7512642761, 41.5974095729, 119.772823928, 52.0473660345)), + 'MZ': ('Mozambique', (30.1794812355, -26.7421916643, 40.7754752948, -10.3170960425)), + 'MR': ('Mauritania', (-17.0634232243, 14.6168342147, -4.92333736817, 27.3957441269)), + 'MW': ('Malawi', (32.6881653175, -16.8012997372, 35.7719047381, -9.23059905359)), + 'MY': ('Malaysia', (100.085756871, 0.773131415201, 119.181903925, 6.92805288332)), + 'NA': ('Namibia', (11.7341988461, -29.045461928, 25.0844433937, -16.9413428687)), + 'NC': ('New Caledonia', (164.029605748, -22.3999760881, 167.120011428, -20.1056458473)), + 'NE': ('Niger', (0.295646396495, 11.6601671412, 15.9032466977, 23.4716684026)), + 'NG': ('Nigeria', (2.69170169436, 4.24059418377, 14.5771777686, 13.8659239771)), + 'NI': ('Nicaragua', (-87.6684934151, 10.7268390975, -83.147219001, 15.0162671981)), + 'NL': ('Netherlands', (3.31497114423, 50.803721015, 7.09205325687, 53.5104033474)), + 'NO': ('Norway', (4.99207807783, 58.0788841824, 31.29341841, 80.6571442736)), + 'NP': ('Nepal', (80.0884245137, 26.3978980576, 88.1748043151, 30.4227169866)), + 'NZ': ('New Zealand', (166.509144322, -46.641235447, 178.517093541, -34.4506617165)), + 'OM': ('Oman', (52.0000098, 16.6510511337, 59.8080603372, 26.3959343531)), + 'PK': ('Pakistan', (60.8742484882, 23.6919650335, 77.8374507995, 37.1330309108)), + 'PA': ('Panama', (-82.9657830472, 7.2205414901, -77.2425664944, 9.61161001224)), + 'PE': ('Peru', (-81.4109425524, -18.3479753557, -68.6650797187, -0.0572054988649)), + 'PH': ('Philippines', (117.17427453, 5.58100332277, 126.537423944, 18.5052273625)), + 'PG': ('Papua New Guinea', (141.000210403, -10.6524760881, 156.019965448, -2.50000212973)), + 'PL': ('Poland', (14.0745211117, 49.0273953314, 24.0299857927, 54.8515359564)), + 'PR': ('Puerto Rico', (-67.2424275377, 17.946553453, -65.5910037909, 18.5206011011)), + 'KP': ('N. Korea', (124.265624628, 37.669070543, 130.780007359, 42.9853868678)), + 'PT': ('Portugal', (-9.52657060387, 36.838268541, -6.3890876937, 42.280468655)), + 'PY': ('Paraguay', (-62.6850571357, -27.5484990374, -54.2929595608, -19.3427466773)), + 'QA': ('Qatar', (50.7439107603, 24.5563308782, 51.6067004738, 26.1145820175)), + 'RO': ('Romania', (20.2201924985, 43.6884447292, 29.62654341, 48.2208812526)), + 'RU': ('Russia', (-180.0, 41.151416124, 180.0, 81.2504)), + 'RW': ('Rwanda', (29.0249263852, -2.91785776125, 30.8161348813, -1.13465911215)), + 'SA': ('Saudi Arabia', (34.6323360532, 16.3478913436, 55.6666593769, 32.161008816)), + 'SD': ('Sudan', (21.93681, 8.61972971293, 38.4100899595, 22.0)), + 'SS': ('S. Sudan', (23.8869795809, 3.50917, 35.2980071182, 12.2480077571)), + 'SN': ('Senegal', (-17.6250426905, 12.332089952, -11.4678991358, 16.5982636581)), + 'SB': ('Solomon Is.', (156.491357864, -10.8263672828, 162.398645868, -6.59933847415)), + 'SL': ('Sierra Leone', (-13.2465502588, 6.78591685631, -10.2300935531, 10.0469839543)), + 'SV': ('El Salvador', (-90.0955545723, 13.1490168319, -87.7235029772, 14.4241327987)), + 'SO': ('Somalia', (40.98105, -1.68325, 51.13387, 12.02464)), + 'RS': ('Serbia', (18.82982, 42.2452243971, 22.9860185076, 46.1717298447)), + 'SR': ('Suriname', (-58.0446943834, 1.81766714112, -53.9580446031, 6.0252914494)), + 'SK': ('Slovakia', (16.8799829444, 47.7584288601, 22.5581376482, 49.5715740017)), + 'SI': ('Slovenia', (13.6981099789, 45.4523163926, 16.5648083839, 46.8523859727)), + 'SE': ('Sweden', (11.0273686052, 55.3617373725, 23.9033785336, 69.1062472602)), + 'SZ': ('Swaziland', (30.6766085141, -27.2858794085, 32.0716654803, -25.660190525)), + 'SY': ('Syria', (35.7007979673, 32.312937527, 42.3495910988, 37.2298725449)), + 'TD': ('Chad', (13.5403935076, 7.42192454674, 23.88689, 23.40972)), + 'TG': ('Togo', (-0.0497847151599, 5.92883738853, 1.86524051271, 11.0186817489)), + 'TH': ('Thailand', (97.3758964376, 5.69138418215, 105.589038527, 20.4178496363)), + 'TJ': ('Tajikistan', (67.4422196796, 36.7381712916, 74.9800024759, 40.9602133245)), + 'TM': ('Turkmenistan', (52.5024597512, 35.2706639674, 66.5461503437, 42.7515510117)), + 'TL': ('East Timor', (124.968682489, -9.39317310958, 127.335928176, -8.27334482181)), + 'TT': ('Trinidad and Tobago', (-61.95, 10.0, -60.895, 10.89)), + 'TN': ('Tunisia', (7.52448164229, 30.3075560572, 11.4887874691, 37.3499944118)), + 'TR': ('Turkey', (26.0433512713, 35.8215347357, 44.7939896991, 42.1414848903)), + 'TW': ('Taiwan', (120.106188593, 21.9705713974, 121.951243931, 25.2954588893)), + 'TZ': ('Tanzania', (29.3399975929, -11.7209380022, 40.31659, -0.95)), + 'UG': ('Uganda', (29.5794661801, -1.44332244223, 35.03599, 4.24988494736)), + 'UA': ('Ukraine', (22.0856083513, 44.3614785833, 40.0807890155, 52.3350745713)), + 'UY': ('Uruguay', (-58.4270741441, -34.9526465797, -53.209588996, -30.1096863746)), + 'US': ('United States', (-171.791110603, 18.91619, -66.96466, 71.3577635769)), + 'UZ': ('Uzbekistan', (55.9289172707, 37.1449940049, 73.055417108, 45.5868043076)), + 'VE': ('Venezuela', (-73.3049515449, 0.724452215982, -59.7582848782, 12.1623070337)), + 'VN': ('Vietnam', (102.170435826, 8.59975962975, 109.33526981, 23.3520633001)), + 'VU': ('Vanuatu', (166.629136998, -16.5978496233, 167.844876744, -14.6264970842)), + 'PS': ('West Bank', (34.9274084816, 31.3534353704, 35.5456653175, 32.5325106878)), + 'YE': ('Yemen', (42.6048726743, 12.5859504257, 53.1085726255, 19.0000033635)), + 'ZA': ('South Africa', (16.3449768409, -34.8191663551, 32.830120477, -22.0913127581)), + 'ZM': ('Zambia', (21.887842645, -17.9612289364, 33.4856876971, -8.23825652429)), + 'ZW': ('Zimbabwe', (25.2642257016, -22.2716118303, 32.8498608742, -15.5077869605)), +} + + +def get_country_code(country_id): + if country_id in country.keys(): + return country.get(country_id) + else: + return {} diff --git a/ks_dashboard_ninja/models/ks_dashboard_filters.py b/ks_dashboard_ninja/models/ks_dashboard_filters.py new file mode 100644 index 000000000..0bd5a0e60 --- /dev/null +++ b/ks_dashboard_ninja/models/ks_dashboard_filters.py @@ -0,0 +1,67 @@ +from odoo import models, fields, api, _ +from odoo.exceptions import ValidationError +from odoo.tools.safe_eval import safe_eval + + +class KsDashboardNinjaTemplate(models.Model): + _name = 'ks_dashboard_ninja.board_defined_filters' + _description = 'Dashboard Ninja Defined Filters' + + name = fields.Char("Filter Label") + ks_dashboard_board_id = fields.Many2one('ks_dashboard_ninja.board', string="Dashboard") + ks_model_id = fields.Many2one('ir.model', string='Model', + domain="[('access_ids','!=',False),('transient','=',False)," + "('model','not ilike','base_import%'),('model','not ilike','ir.%')," + "('model','not ilike','web_editor.%'),('model','not ilike','web_tour.%')," + "('model','!=','mail.thread'),('model','not ilike','ks_dash%'), ('model','not ilike','ks_to%')]", + help="Data source to fetch and read the data for the creation of dashboard items. ") + ks_domain = fields.Char(string="Domain", help="Define conditions for filter. ") + ks_domain_temp = fields.Char(string="Domain Substitute") + ks_model_name = fields.Char(related='ks_model_id.model', string="Model Name") + display_type = fields.Selection([ + ('line_section', "Section")], default=False, help="Technical field for UX purpose.") + sequence = fields.Integer(default=10, + help="Gives the sequence order when displaying a list of payment terms lines.") + ks_is_active = fields.Boolean(string="Active") + + @api.onchange('ks_domain') + def ks_domain_onchange(self): + for rec in self: + if rec.ks_model_id: + try: + ks_domain = rec.ks_domain + 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.company.id)) + self.env[rec.ks_model_id.model].search_count(safe_eval(ks_domain)) + except Exception as e: + raise ValidationError(_("Something went wrong . Possibly it is due to wrong input type for domain")) + + @api.constrains('ks_domain', 'ks_model_id') + def ks_domain_check(self): + for rec in self: + if rec.ks_model_id and not rec.ks_domain: + raise ValidationError(_("Domain can not be empty")) + + + +class KsDashboardNinjaTemplate(models.Model): + _name = 'ks_dashboard_ninja.board_custom_filters' + _description = 'Dashboard Ninja Custom Filters' + + name = fields.Char("Filter Label") + ks_dashboard_board_id = fields.Many2one('ks_dashboard_ninja.board', string="Dashboard") + ks_model_id = fields.Many2one('ir.model', string='Model', + domain="[('access_ids','!=',False),('transient','=',False)," + "('model','not ilike','base_import%'),('model','not ilike','ir.%')," + "('model','not ilike','web_editor.%'),('model','not ilike','web_tour.%')," + "('model','!=','mail.thread'),('model','not ilike','ks_dash%'), ('model','not ilike','ks_to%')]", + help="Data source to fetch and read the data for the creation of dashboard items. ") + ks_domain_field_id = fields.Many2one('ir.model.fields', + domain="[('model_id','=',ks_model_id)," + "('name','!=','id'),('store','=',True)," + "('ttype', 'in', ['boolean', 'char', " + "'date', 'datetime', 'float', 'integer', 'html', 'many2many', " + "'many2one', 'monetary', 'one2many', 'text', 'selection'])]", + string="Domain Field") diff --git a/ks_dashboard_ninja/models/ks_dashboard_ninja.py b/ks_dashboard_ninja/models/ks_dashboard_ninja.py new file mode 100644 index 000000000..7c5f89f99 --- /dev/null +++ b/ks_dashboard_ninja/models/ks_dashboard_ninja.py @@ -0,0 +1,1380 @@ +# -*- coding: utf-8 -*- + +from odoo import models, fields, api, _ +from odoo.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT +from odoo.exceptions import ValidationError +import datetime +import json +from odoo.addons.ks_dashboard_ninja.common_lib.ks_date_filter_selections import ks_get_date, ks_convert_into_local, \ + ks_convert_into_utc +from odoo.tools.safe_eval import safe_eval +import locale +from dateutil.parser import parse + + +class KsDashboardNinjaBoard(models.Model): + _name = 'ks_dashboard_ninja.board' + _description = 'Dashboard Ninja' + + name = fields.Char(string="Dashboard Name", required=True, size=35) + ks_dashboard_items_ids = fields.One2many('ks_dashboard_ninja.item', 'ks_dashboard_ninja_board_id', + string='Dashboard Items') + ks_dashboard_menu_name = fields.Char(string="Menu Name") + ks_dashboard_top_menu_id = fields.Many2one('ir.ui.menu', + domain="['|',('action','=',False),('parent_id','=',False)]", + string="Show Under Menu", + default=lambda self: self.env['ir.ui.menu'].search( + [('name', '=', 'My Dashboard')])) + ks_dashboard_client_action_id = fields.Many2one('ir.actions.client') + ks_dashboard_menu_id = fields.Many2one('ir.ui.menu') + ks_dashboard_state = fields.Char() + ks_dashboard_active = fields.Boolean(string="Active", default=True) + ks_dashboard_group_access = fields.Many2many('res.groups', string="Group Access") + + # DateFilter Fields + ks_dashboard_start_date = fields.Datetime(string="Start Date") + ks_dashboard_end_date = fields.Datetime(string="End Date") + ks_date_filter_selection = fields.Selection([ + ('l_none', 'All Time'), + ('l_day', 'Today'), + ('t_week', 'This Week'), + ('t_month', 'This Month'), + ('t_quarter', 'This Quarter'), + ('t_year', 'This Year'), + ('td_week', 'Week to Date'), + ('td_month', 'Month to Date'), + ('td_quarter', 'Quarter to Date'), + ('td_year', 'Year to Date'), + ('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'), + ], default='l_none', string="Default Date Filter") + + # for setting Global/Indian Format + ks_data_formatting = fields.Selection([ + ('global', 'Global'), + ('indian', 'Indian'), + ('exact', 'Exact') + ], string='Format') + + ks_gridstack_config = fields.Char('Item Configurations') + ks_dashboard_default_template = fields.Many2one('ks_dashboard_ninja.board_template', + default=lambda self: self.env.ref('ks_dashboard_ninja.ks_blank', + False), + string="Dashboard Template") + + ks_set_interval = fields.Selection([ + ('15000', '15 Seconds'), + ('30000', '30 Seconds'), + ('45000', '45 Seconds'), + ('60000', '1 minute'), + ('120000', '2 minute'), + ('300000', '5 minute'), + ('600000', '10 minute'), + ], string="Default Update Interval", help="Update Interval for new items only") + ks_dashboard_menu_sequence = fields.Integer(string="Menu Sequence", default=10, + help="Smallest sequence give high priority and Highest sequence give " + "low priority") + ks_child_dashboard_ids = fields.One2many('ks_dashboard_ninja.child_board', 'ks_dashboard_ninja_id') + ks_dashboard_defined_filters_ids = fields.One2many('ks_dashboard_ninja.board_defined_filters', + 'ks_dashboard_board_id', + string='Dashboard Predefined Filters') + ks_dashboard_custom_filters_ids = fields.One2many('ks_dashboard_ninja.board_custom_filters', + 'ks_dashboard_board_id', + string='Dashboard Custom Filters') + multi_layouts = fields.Boolean(string='Enable Multi-Dashboard Layouts', + help='Allow user to have multiple layouts of the same Dashboard') + + + @api.constrains('ks_dashboard_start_date', 'ks_dashboard_end_date') + def ks_date_validation(self): + for rec in self: + if rec.ks_dashboard_start_date > rec.ks_dashboard_end_date: + raise ValidationError(_('Start date must be less than end date')) + + @api.model_create_multi + def create(self, vals): + records = super(KsDashboardNinjaBoard, self).create(vals) + for record in records: + if record.ks_dashboard_top_menu_id and record.ks_dashboard_menu_name: + action_id = { + 'name': record.ks_dashboard_menu_name + " Action", + 'res_model': 'ks_dashboard_ninja.board', + 'tag': 'ks_dashboard_ninja', + 'params': {'ks_dashboard_id': record.id}, + } + record.ks_dashboard_client_action_id = self.env['ir.actions.client'].sudo().create(action_id) + + record.ks_dashboard_menu_id = self.env['ir.ui.menu'].sudo().create({ + 'name': record.ks_dashboard_menu_name, + 'active': record.ks_dashboard_active, + 'parent_id': record.ks_dashboard_top_menu_id.id, + 'action': "ir.actions.client," + str(record.ks_dashboard_client_action_id.id), + 'groups_id': record.ks_dashboard_group_access.ids if record.ks_dashboard_group_access else False, + 'sequence': record.ks_dashboard_menu_sequence if record.ks_dashboard_menu_sequence else 10 + }) + + if record.ks_dashboard_default_template and record.ks_dashboard_default_template.ks_item_count: + ks_gridstack_config = {} + template_data = json.loads(record.ks_dashboard_default_template.ks_gridstack_config) + for item_data in template_data: + if record.ks_dashboard_default_template.ks_template_type == 'ks_custom': + dashboard_item = self.env['ks_dashboard_ninja.item'].browse(int(item_data)).copy( + {'ks_dashboard_ninja_board_id': record.id}) + ks_gridstack_config[dashboard_item.id] = template_data[item_data] + else: + dashboard_item = self.env.ref(item_data['item_id']).copy({'ks_dashboard_ninja_board_id': record.id}) + ks_gridstack_config[dashboard_item.id] = item_data['data'] + record.ks_gridstack_config = json.dumps(ks_gridstack_config) + return records + + @api.onchange('ks_date_filter_selection') + def ks_date_filter_selection_onchange(self): + for rec in self: + if rec.ks_date_filter_selection and rec.ks_date_filter_selection != 'l_custom': + rec.ks_dashboard_start_date = False + rec.ks_dashboard_end_date = False + + def write(self, vals): + if vals.get('ks_date_filter_selection', False) and vals.get('ks_date_filter_selection') != 'l_custom': + vals.update({ + 'ks_dashboard_start_date': False, + 'ks_dashboard_end_date': False + + }) + record = super(KsDashboardNinjaBoard, self).write(vals) + for rec in self: + if 'ks_dashboard_menu_name' in vals: + if self.env.ref('ks_dashboard_ninja.ks_my_default_dashboard_board') and self.env.ref( + 'ks_dashboard_ninja.ks_my_default_dashboard_board').sudo().id == rec.id: + if self.env.ref('ks_dashboard_ninja.board_menu_root', False): + self.env.ref('ks_dashboard_ninja.board_menu_root').sudo().name = vals['ks_dashboard_menu_name'] + else: + rec.ks_dashboard_menu_id.sudo().name = vals['ks_dashboard_menu_name'] + if 'ks_dashboard_group_access' in vals: + if self.env.ref('ks_dashboard_ninja.ks_my_default_dashboard_board').id == rec.id: + if self.env.ref('ks_dashboard_ninja.board_menu_root', False): + self.env.ref('ks_dashboard_ninja.board_menu_root').groups_id = vals['ks_dashboard_group_access'] + else: + rec.ks_dashboard_menu_id.sudo().groups_id = vals['ks_dashboard_group_access'] + if 'ks_dashboard_active' in vals and rec.ks_dashboard_menu_id: + rec.ks_dashboard_menu_id.sudo().active = vals['ks_dashboard_active'] + + if 'ks_dashboard_top_menu_id' in vals: + rec.ks_dashboard_menu_id.write( + {'parent_id': vals['ks_dashboard_top_menu_id']} + ) + + if 'ks_dashboard_menu_sequence' in vals: + rec.ks_dashboard_menu_id.sudo().sequence = vals['ks_dashboard_menu_sequence'] + if 'name' in vals: + rec.ks_dashboard_client_action_id.sudo().name = vals['name'] + + return record + + def unlink(self): + if self.env.ref('ks_dashboard_ninja.ks_my_default_dashboard_board').id in self.ids: + raise ValidationError(_("Default Dashboard can't be deleted.")) + else: + for rec in self: + rec.ks_dashboard_client_action_id.sudo().unlink() + rec.ks_child_dashboard_ids.unlink() + rec.ks_dashboard_menu_id.sudo().unlink() + rec.ks_dashboard_items_ids.unlink() + res = super(KsDashboardNinjaBoard, self).unlink() + return res + + def ks_get_grid_config(self): + default_grid_id = self.env['ks_dashboard_ninja.child_board'].search( + [['id', 'in', self.ks_child_dashboard_ids.ids], ['company_id', '=', self.env.company.id], + ['board_type', '=', 'default']]) + + if not default_grid_id: + default_grid_id = self.env['ks_dashboard_ninja.child_board'].create({ + "ks_gridstack_config": self.ks_gridstack_config, + "ks_dashboard_ninja_id": self.id, + "name": "Default Board Layout", + "company_id": self.env.company.id, + "board_type": "default", + }) + + return default_grid_id + + @api.model + def ks_fetch_dashboard_data(self, ks_dashboard_id, ks_item_domain=False): + """ + Return Dictionary of Dashboard Data. + :param ks_dashboard_id: Integer + :param ks_item_domain: List[List] + :return: dict + """ + + ks_dn_active_ids = [] + if self._context.get('ks_dn_active_ids'): + ks_dn_active_ids = self._context.get('ks_dn_active_ids') + + ks_dn_active_ids.append(ks_dashboard_id) + self = self.with_context( + ks_dn_active_ids=ks_dn_active_ids, + ) + + has_group_ks_dashboard_manager = self.env.user.has_group('ks_dashboard_ninja.ks_dashboard_ninja_group_manager') + ks_dashboard_rec = self.browse(ks_dashboard_id) + dashboard_data = { + 'name': ks_dashboard_rec.name, + 'multi_layouts': ks_dashboard_rec.multi_layouts, + 'ks_company_id': self.env.company.id, + 'ks_dashboard_manager': has_group_ks_dashboard_manager, + 'ks_dashboard_list': self.search_read([], ['id', 'name']), + 'ks_dashboard_start_date': self._context.get('ksDateFilterStartDate', False) or self.browse( + ks_dashboard_id).ks_dashboard_start_date, + 'ks_dashboard_end_date': self._context.get('ksDateFilterEndDate', False) or self.browse( + ks_dashboard_id).ks_dashboard_end_date, + 'ks_date_filter_selection': self._context.get('ksDateFilterSelection', False) or self.browse( + ks_dashboard_id).ks_date_filter_selection, + 'ks_gridstack_config': "{}", + 'ks_set_interval': ks_dashboard_rec.ks_set_interval, + 'ks_data_formatting': ks_dashboard_rec.ks_data_formatting, + 'ks_dashboard_items_ids': ks_dashboard_rec.ks_dashboard_items_ids.ids, + 'ks_item_data': {}, + 'ks_child_boards': False, + 'ks_selected_board_id': False, + 'ks_dashboard_domain_data': ks_dashboard_rec.ks_prepare_dashboard_domain(), + 'ks_dashboard_pre_domain_filter': ks_dashboard_rec.ks_prepare_dashboard_pre_domain(), + 'ks_dashboard_custom_domain_filter': ks_dashboard_rec.ks_prepare_dashboard_custom_domain(), + 'ks_item_model_relation': dict([(x['id'], [x['ks_model_name'], x['ks_model_name_2']]) for x in + ks_dashboard_rec.ks_dashboard_items_ids.read( + ['ks_model_name', 'ks_model_name_2'])]), + 'ks_model_item_relation': {}, + } + + default_grid_id = ks_dashboard_rec.ks_get_grid_config() + dashboard_data['ks_gridstack_config'] = default_grid_id[0].ks_gridstack_config + dashboard_data['ks_gridstack_config_id'] = default_grid_id[0].id + + if self.env['ks_dashboard_ninja.child_board'].search( + [['id', 'in', ks_dashboard_rec.ks_child_dashboard_ids.ids], ['company_id', '=', self.env.company.id], + ['board_type', '!=', 'default']], limit=1): + dashboard_data['ks_child_boards'] = { + 'ks_default': [ks_dashboard_rec.name, default_grid_id[0].ks_gridstack_config]} + selecred_rec = self.env['ks_dashboard_ninja.child_board'].search( + [['id', 'in', ks_dashboard_rec.ks_child_dashboard_ids.ids], ['ks_active', '=', True], + ['company_id', '=', self.env.company.id], ['board_type', '!=', 'default']], limit=1) + if selecred_rec: + dashboard_data['ks_selected_board_id'] = str(selecred_rec.id) + dashboard_data['ks_gridstack_config'] = selecred_rec.ks_gridstack_config + else: + dashboard_data['ks_selected_board_id'] = 'ks_default' + for rec in self.env['ks_dashboard_ninja.child_board'].search_read( + [['id', 'in', ks_dashboard_rec.ks_child_dashboard_ids.ids], + ['company_id', '=', self.env.company.id], ['board_type', '!=', 'default']], + ['name', 'ks_gridstack_config']): + dashboard_data['ks_child_boards'][str(rec['id'])] = [rec['name'], rec['ks_gridstack_config']] + ks_item_domain = ks_item_domain or [] + try: + items = self.ks_dashboard_items_ids.search( + [['ks_dashboard_ninja_board_id', '=', ks_dashboard_id]] + ks_item_domain).ids + except Exception as e: + items = self.ks_dashboard_items_ids.search( + [['ks_dashboard_ninja_board_id', '=', ks_dashboard_id]] + ks_item_domain).ids + dashboard_data['ks_dashboard_items_ids'] = items + return dashboard_data + + @api.model + def ks_fetch_item(self, item_list, ks_dashboard_id, params={}): + """ + :rtype: object + :param item_list: list of item ids. + :return: {'id':[item_data]} + """ + self = self.ks_set_date(ks_dashboard_id) + items = {} + item_model = self.env['ks_dashboard_ninja.item'] + for item_id in item_list: + item = self.ks_fetch_item_data(item_model.browse(item_id), params) + items[item['id']] = item + return items + + # fetching Item info (Divided to make function inherit easily) + def ks_fetch_item_data(self, rec, params={}): + """ + :rtype: object + :param item_id: item object + :return: object with formatted item data + """ + try: + ks_precision = self.sudo().env.ref('ks_dashboard_ninja.ks_dashboard_ninja_precision') + ks_precision_digits = ks_precision.digits + if ks_precision_digits < 0: + ks_precision_digits = 2 + if ks_precision_digits > 100: + ks_precision_digits = 2 + except Exception as e: + ks_precision_digits = 2 + + action = {} + item_domain1 = params.get('ks_domain_1', []) + item_domain2 = params.get('ks_domain_2', []) + if rec.ks_actions: + context = {} + try: + context = safe_eval(rec.ks_actions.context) + except Exception: + context = {} + + # Managing those views that have the access rights + ks_actions = rec.ks_actions.sudo() + action['name'] = ks_actions.name + action['type'] = ks_actions.type + action['res_model'] = ks_actions.res_model + action['views'] = ks_actions.views + action['view_mode'] = ks_actions.view_mode + action['search_view_id'] = ks_actions.search_view_id.id + action['context'] = context + action['target'] = 'current' + elif rec.ks_is_client_action and rec.ks_client_action: + clint_action = {} + try: + context = safe_eval(rec.ks_client_action.context) + except Exception: + context = {} + ks_client_action = rec.ks_client_action.sudo() + clint_action['name'] = ks_client_action.name + clint_action['type'] = ks_client_action.type + clint_action['res_model'] = ks_client_action.res_model + clint_action['xml_id'] = ks_client_action.xml_id + clint_action['tag'] = ks_client_action.tag + clint_action['binding_type'] = ks_client_action.binding_type + clint_action['params'] = ks_client_action.params + clint_action['target'] = 'current' + clint_action['context'] = context, + clint_action['report_id'] = context.get('report_id', False) + clint_action['resId'] = ks_client_action.id + context.update({ + 'resId': ks_client_action.id + }) + + clint_action['params'] = { + 'options': context, + 'props': {'resId': ks_client_action.id} + } + + + action = clint_action, + else: + action = False + ks_currency_symbol = False + ks_currency_position = False + if rec.ks_unit and rec.ks_unit_selection == 'monetary': + try: + ks_currency_symbol = self.env.user.company_id.currency_id.symbol + ks_currency_position = self.env.user.company_id.currency_id.position + except Exception as E: + ks_currency_symbol = False + ks_currency_position = False + + item = { + 'name': rec.name if rec.name else rec.ks_model_id.name if rec.ks_model_id else "Name", + 'ks_background_color': rec.ks_background_color, + 'ks_font_color': rec.ks_font_color, + 'ks_header_bg_color': rec.ks_header_bg_color, + # 'ks_domain': rec.ks_domain.replace('"%UID"', str( + # self.env.user.id)) if rec.ks_domain and "%UID" in rec.ks_domain else rec.ks_domain, + 'ks_domain': rec.ks_convert_into_proper_domain(rec.ks_domain, rec, item_domain1), + 'ks_dashboard_id': rec.ks_dashboard_ninja_board_id.id, + 'ks_icon': rec.ks_icon, + 'ks_model_id': rec.ks_model_id.id, + 'ks_model_name': rec.ks_model_name, + 'ks_model_display_name': rec.ks_model_id.name, + 'ks_record_count_type': rec.ks_record_count_type, + 'ks_record_count': rec._ksGetRecordCount(item_domain1), + 'id': rec.id, + 'ks_layout': rec.ks_layout, + 'ks_icon_select': rec.ks_icon_select, + 'ks_default_icon': rec.ks_default_icon, + 'ks_default_icon_color': rec.ks_default_icon_color, + # Pro Fields + 'ks_dashboard_item_type': rec.ks_dashboard_item_type, + 'ks_chart_item_color': rec.ks_chart_item_color, + 'ks_chart_groupby_type': rec.ks_chart_groupby_type, + 'ks_chart_measure_field': rec.ks_chart_measure_field.ids, + 'ks_chart_measure_field_2': rec.ks_chart_measure_field_2.ids, + 'ks_chart_relation_groupby': rec.ks_chart_relation_groupby.id, + 'ks_chart_relation_groupby_name': rec.ks_chart_relation_groupby.name, + 'ks_chart_date_groupby': rec.ks_chart_date_groupby, + 'ks_chart_sub_groupby_type': rec.ks_chart_sub_groupby_type, + 'ks_chart_relation_sub_groupby': rec.ks_chart_relation_sub_groupby.id, + 'ks_chart_relation_sub_groupby_name': rec.ks_chart_relation_sub_groupby.name, + 'ks_chart_date_sub_groupby': rec.ks_chart_date_sub_groupby, + 'ks_record_field': rec.ks_record_field.id if rec.ks_record_field else False, + 'ks_chart_data': rec._ks_get_chart_data(item_domain1), + 'ks_list_view_data': rec._ksGetListViewData(item_domain1), + 'ks_chart_data_count_type': rec.ks_chart_data_count_type, + 'ks_bar_chart_stacked': rec.ks_bar_chart_stacked, + 'ks_semi_circle_chart': rec.ks_semi_circle_chart, + 'ks_list_view_type': rec.ks_list_view_type, + 'ks_list_view_group_fields': rec.ks_list_view_group_fields.ids if rec.ks_list_view_group_fields else False, + 'ks_previous_period': rec.ks_previous_period, + 'ks_kpi_data': rec._ksGetKpiData(item_domain1, item_domain2), + 'ks_goal_enable': rec.ks_goal_enable, + 'ks_model_id_2': rec.ks_model_id_2.id, + 'ks_record_field_2': rec.ks_record_field_2.id, + 'ks_data_comparison': rec.ks_data_comparison, + 'ks_target_view': rec.ks_target_view, + 'ks_date_filter_selection': rec.ks_date_filter_selection, + 'ks_show_data_value': rec.ks_show_data_value, + 'ks_show_records': rec.ks_show_records, + 'ks_unit': rec.ks_unit, + 'ks_unit_selection': rec.ks_unit_selection, + 'ks_chart_unit': rec.ks_chart_unit, + # 'action_id': rec.ks_actions.id if rec.ks_actions else False, + 'sequence': 0, + 'max_sequnce': len(rec.ks_action_lines) if rec.ks_action_lines else False, + 'action': action, + 'ks_hide_legend': rec.ks_hide_legend, + 'ks_radial_legend': rec.ks_radial_legend, + 'ks_data_calculation_type': rec.ks_data_calculation_type, + 'ks_export_all_records': rec.ks_export_all_records, + 'ks_data_formatting': rec.ks_data_format, + 'ks_is_client_action': rec.ks_is_client_action, + 'ks_pagination_limit': rec.ks_pagination_limit, + 'ks_record_data_limit': rec.ks_record_data_limit, + 'ks_chart_cumulative_field': rec.ks_chart_cumulative_field.ids, + 'ks_chart_cumulative': rec.ks_chart_cumulative, + 'ks_chart_is_cumulative': rec.ks_chart_is_cumulative, + 'ks_button_color': rec.ks_button_color, + 'ks_to_do_data': rec._ksGetToDOData(), + 'ks_multiplier_active': rec.ks_multiplier_active, + 'ks_multiplier': rec.ks_multiplier, + 'ks_goal_liness': True if rec.ks_goal_lines else False, + 'ks_currency_symbol': ks_currency_symbol, + 'ks_currency_id':self.env.user.company_id.currency_id.id, + 'ks_currency_position': ks_currency_position, + 'ks_precision_digits': ks_precision_digits if ks_precision_digits else 2, + 'ks_data_label_type': rec.ks_data_label_type, + 'ks_as_of_now': rec.ks_as_of_now, + 'ks_info': rec.ks_info, + 'ks_company': rec.ks_company_id.name if rec.ks_company_id else False, + 'ks_scatter_measure_x_id': rec.ks_scatter_measure_x_id, + 'ks_scatter_measure_y_id': rec.ks_scatter_measure_y_id, + 'ks_is_scatter_group': rec.ks_is_scatter_group, + 'ks_radial_item_color': rec.ks_radial_item_color, + 'ks_flower_item_color': rec.ks_flower_item_color, + 'ks_bounds': rec.ks_bounds, + 'ks_partners_map': rec.ks_partners_map, + 'ks_funnel_record_field':rec.ks_funnel_record_field, + 'ks_map_record_field':rec.ks_map_record_field, + 'ks_funnel_item_color':rec.ks_funnel_item_color, + 'ks_country_id':rec.ks_country_id.id + } + return item + + def ks_set_date(self, ks_dashboard_id): + ks_dashboard_rec = self.browse(ks_dashboard_id) + if self._context.get('ksDateFilterSelection', False): + ks_date_filter_selection = self._context['ksDateFilterSelection'] + if ks_date_filter_selection == 'l_custom': + ks_start_dt_parse = parse(self._context['ksDateFilterStartDate']) + ks_end_dt_parse = parse(self._context['ksDateFilterEndDate']) + self = self.with_context( + ksDateFilterStartDate=fields.datetime.strptime(ks_start_dt_parse.strftime("%Y-%m-%d %H:%M:%S"), + "%Y-%m-%d %H:%M:%S")) + self = self.with_context( + ksDateFilterEndDate=fields.datetime.strptime(ks_end_dt_parse.strftime("%Y-%m-%d %H:%M:%S"), + "%Y-%m-%d %H:%M:%S")) + self = self.with_context(ksIsDefultCustomDateFilter=False) + + else: + ks_date_filter_selection = ks_dashboard_rec.ks_date_filter_selection + self = self.with_context(ksDateFilterStartDate=ks_dashboard_rec.ks_dashboard_start_date) + self = self.with_context(ksDateFilterEndDate=ks_dashboard_rec.ks_dashboard_end_date) + self = self.with_context(ksDateFilterSelection=ks_date_filter_selection) + self = self.with_context(ksIsDefultCustomDateFilter=True) + + if ks_date_filter_selection not in ['l_custom', 'l_none']: + ks_date_data = ks_get_date(ks_date_filter_selection, self, 'datetime') + self = self.with_context(ksDateFilterStartDate=ks_date_data["selected_start_date"]) + self = self.with_context(ksDateFilterEndDate=ks_date_data["selected_end_date"]) + + return self + + @api.model + def ks_get_list_view_data_offset(self, ks_dashboard_item_id, offset, dashboard_id, params={}): + item_domain = params.get('ks_domain_1', []) + self = self.ks_set_date(dashboard_id) + item = self.ks_dashboard_items_ids.browse(ks_dashboard_item_id) + + return item.ks_get_next_offset(ks_dashboard_item_id, offset, item_domain) + + def ks_view_items_view(self): + self.ensure_one() + return { + 'name': _("Dashboard Items"), + 'res_model': 'ks_dashboard_ninja.item', + 'view_mode': 'tree,form', + 'view_type': 'form', + 'views': [(False, 'tree'), (False, 'form')], + 'type': 'ir.actions.act_window', + 'domain': [('ks_dashboard_ninja_board_id', '!=', False)], + 'search_view_id': self.env.ref('ks_dashboard_ninja.ks_item_search_view').id, + 'context': { + 'search_default_ks_dashboard_ninja_board_id': self.id, + 'group_by': 'ks_dashboard_ninja_board_id', + }, + 'help': _('''+ You can find all items related to Dashboard Here.
+ '''), + + } + + def ks_export_item(self, item_id): + return { + 'ks_file_format': 'ks_dashboard_ninja_item_export', + 'item': self.ks_export_item_data(self.ks_dashboard_items_ids.browse(int(item_id))) + } + + # fetching Item info (Divided to make function inherit easily) + def ks_export_item_data(self, rec): + ks_timezone = self._context.get('tz') or self.env.user.tz + ks_chart_measure_field = [] + ks_chart_measure_field_2 = [] + if rec.ks_many2many_field_ordering: + ks_many2many_field_ordering = json.loads(rec.ks_many2many_field_ordering) + else: + ks_many2many_field_ordering = {} + if ks_many2many_field_ordering.get('ks_list_view_fields', False): + ks_list_view_fields_list = self.env['ir.model.fields'].search([('id', 'in', + ks_many2many_field_ordering.get('ks_list_view_fields', False))]) + if ks_many2many_field_ordering.get('ks_list_view_group_fields', False): + ks_list_view_group_fields_list = self.env['ir.model.fields'].search([('id', 'in', + ks_many2many_field_ordering.get('ks_list_view_group_fields', False))]) + if ks_many2many_field_ordering.get('ks_chart_measure_field', False): + ks_chart_measure_field_list = self.env['ir.model.fields'].search([('id', 'in', + ks_many2many_field_ordering.get('ks_chart_measure_field', False))]) + if ks_many2many_field_ordering.get('ks_chart_measure_field_2', False): + ks_chart_measure_field_2_list = self.env['ir.model.fields'].search([('id', 'in', + ks_many2many_field_ordering.get('ks_chart_measure_field_2', False))]) + + try: + for res in ks_chart_measure_field_list: + ks_chart_measure_field.append(res.name) + except Exception as E: + ks_chart_measure_field = [] + try: + for res in ks_chart_measure_field_2_list: + ks_chart_measure_field_2.append(res.name) + except Exception as E: + ks_chart_measure_field_2 = [] + ks_multiplier_fields = [] + ks_multiplier_value = [] + if rec.ks_multiplier_lines: + for ress in rec.ks_multiplier_lines.ks_multiplier_fields: + ks_multiplier_fields.append(ress.name) + for ks_val in rec.ks_multiplier_lines: + ks_multiplier_value.append(ks_val.ks_multiplier_value) + + ks_list_view_group_fields = [] + try: + for res in ks_list_view_group_fields_list: + ks_list_view_group_fields.append(res.name) + except Exception as e: + ks_list_view_group_fields = [] + ks_goal_lines = [] + for res in rec.ks_goal_lines: + goal_line = { + 'ks_goal_date': datetime.datetime.strftime(res.ks_goal_date, "%Y-%m-%d"), + 'ks_goal_value': res.ks_goal_value, + } + ks_goal_lines.append(goal_line) + ks_dn_header_lines = [] + for res in rec.ks_dn_header_lines: + ks_dn_header_line = { + 'ks_to_do_header': res.ks_to_do_header + } + + if res.ks_to_do_description_lines: + ks_to_do_description_lines = [] + for ks_description_line in res.ks_to_do_description_lines: + description_line = { + 'ks_description': ks_description_line.ks_description, + 'ks_active': ks_description_line.ks_active, + } + ks_to_do_description_lines.append(description_line) + ks_dn_header_line[res.ks_to_do_header] = ks_to_do_description_lines + ks_dn_header_lines.append(ks_dn_header_line) + + ks_action_lines = [] + for res in rec.ks_action_lines: + action_line = { + 'ks_item_action_field': res.ks_item_action_field.name, + 'ks_item_action_date_groupby': res.ks_item_action_date_groupby, + 'ks_chart_type': res.ks_chart_type, + 'ks_sort_by_field': res.ks_sort_by_field.name, + 'ks_sort_by_order': res.ks_sort_by_order, + 'ks_record_limit': res.ks_record_limit, + 'sequence': res.sequence, + } + ks_action_lines.append(action_line) + ks_multiplier_lines = [] + for res in rec.ks_multiplier_lines: + ks_multiplier_line = { + 'ks_multiplier_fields': res.ks_multiplier_fields.id, + 'ks_multiplier_value': res.ks_multiplier_value, + 'ks_dashboard_item_id': rec.id, + 'ks_model_id': rec.ks_model_id.id + } + ks_multiplier_lines.append(ks_multiplier_line) + + ks_list_view_field = [] + try: + for res in ks_list_view_fields_list: + ks_list_view_field.append(res.name) + except Exception as e: + ks_list_view_field = [] + val = str(rec.id) + keys_data = {} + selecred_rec = self.env['ks_dashboard_ninja.child_board'].search( + [['id', 'in', rec.ks_dashboard_ninja_board_id.ks_child_dashboard_ids.ids], ['ks_active', '=', True], + ['company_id', '=', self.env.company.id]], limit=1) + if rec.ks_dashboard_ninja_board_id.ks_gridstack_config: + keys_data = json.loads(rec.ks_dashboard_ninja_board_id.ks_gridstack_config) + elif selecred_rec: + keys_data = json.loads(selecred_rec.ks_gridstack_config) + elif rec.ks_dashboard_ninja_board_id.ks_child_dashboard_ids[0].ks_gridstack_config: + keys_data = json.loads(rec.ks_dashboard_ninja_board_id.ks_child_dashboard_ids[0].ks_gridstack_config) + elif self._context.get('gridstack_config', False): + keys_data = self._context.get('gridstack_config', False) + else: + if rec.grid_corners: + keys_data = {rec.id: json.loads(rec.grid_corners.replace("\'", "\""))} + keys_list = keys_data.keys() + grid_corners = {} + if val in keys_list: + grid_corners = keys_data.get(str(val)) + + item = { + 'name': rec.name if rec.name else rec.ks_model_id.name if rec.ks_model_id else "Name", + 'ks_background_color': rec.ks_background_color, + 'ks_font_color': rec.ks_font_color, + 'ks_header_bg_color': rec.ks_header_bg_color, + 'ks_domain': rec.ks_domain, + 'ks_icon': str(rec.ks_icon) if rec.ks_icon else False, + 'ks_id': rec.id, + 'ks_model_id': rec.ks_model_name, + 'ks_record_count': rec.ks_record_count, + 'ks_layout': rec.ks_layout, + 'ks_icon_select': rec.ks_icon_select, + 'ks_default_icon': rec.ks_default_icon, + 'ks_default_icon_color': rec.ks_default_icon_color, + 'ks_record_count_type': rec.ks_record_count_type, + # Pro Fields + 'ks_dashboard_item_type': rec.ks_dashboard_item_type, + 'ks_chart_item_color': rec.ks_chart_item_color, + 'ks_chart_groupby_type': rec.ks_chart_groupby_type, + 'ks_chart_relation_groupby': rec.ks_chart_relation_groupby.name, + 'ks_chart_date_groupby': rec.ks_chart_date_groupby, + 'ks_record_field': rec.ks_record_field.name, + 'ks_chart_sub_groupby_type': rec.ks_chart_sub_groupby_type, + 'ks_chart_relation_sub_groupby': rec.ks_chart_relation_sub_groupby.name, + 'ks_chart_date_sub_groupby': rec.ks_chart_date_sub_groupby, + 'ks_chart_data_count_type': rec.ks_chart_data_count_type, + 'ks_chart_measure_field': ks_chart_measure_field, + 'ks_chart_measure_field_2': ks_chart_measure_field_2, + 'ks_list_view_fields': ks_list_view_field, + 'ks_list_view_group_fields': ks_list_view_group_fields, + 'ks_list_view_type': rec.ks_list_view_type, + 'ks_record_data_limit': rec.ks_record_data_limit, + 'ks_sort_by_order': rec.ks_sort_by_order, + 'ks_sort_by_field': rec.ks_sort_by_field.name, + 'ks_date_filter_field': rec.ks_date_filter_field.name, + 'ks_goal_enable': rec.ks_goal_enable, + 'ks_standard_goal_value': rec.ks_standard_goal_value, + 'ks_goal_liness': ks_goal_lines, + 'ks_date_filter_selection': rec.ks_date_filter_selection, + 'ks_item_start_date': rec.ks_item_start_date.strftime( + DEFAULT_SERVER_DATETIME_FORMAT) if rec.ks_item_start_date else False, + 'ks_item_end_date': rec.ks_item_end_date.strftime( + DEFAULT_SERVER_DATETIME_FORMAT) if rec.ks_item_end_date else False, + 'ks_date_filter_selection_2': rec.ks_date_filter_selection_2, + 'ks_item_start_date_2': rec.ks_item_start_date_2.strftime( + DEFAULT_SERVER_DATETIME_FORMAT) if rec.ks_item_start_date_2 else False, + 'ks_item_end_date_2': rec.ks_item_end_date_2.strftime( + DEFAULT_SERVER_DATETIME_FORMAT) if rec.ks_item_end_date_2 else False, + 'ks_previous_period': rec.ks_previous_period, + 'ks_target_view': rec.ks_target_view, + 'ks_data_comparison': rec.ks_data_comparison, + 'ks_record_count_type_2': rec.ks_record_count_type_2, + 'ks_record_field_2': rec.ks_record_field_2.name, + 'ks_model_id_2': rec.ks_model_id_2.model, + 'ks_date_filter_field_2': rec.ks_date_filter_field_2.name, + 'ks_action_liness': ks_action_lines, + 'ks_compare_period': rec.ks_compare_period, + 'ks_year_period': rec.ks_year_period, + 'ks_compare_period_2': rec.ks_compare_period_2, + 'ks_year_period_2': rec.ks_year_period_2, + 'ks_domain_2': rec.ks_domain_2, + 'ks_show_data_value': rec.ks_show_data_value, + 'ks_list_target_deviation_field': rec.ks_list_target_deviation_field.name, + 'ks_unit': rec.ks_unit, + 'ks_show_records': rec.ks_show_records, + 'ks_hide_legend': rec.ks_hide_legend, + 'ks_radial_legend': rec.ks_radial_legend, + 'ks_fill_temporal': rec.ks_fill_temporal, + 'ks_domain_extension': rec.ks_domain_extension, + 'ks_unit_selection': rec.ks_unit_selection, + 'ks_chart_unit': rec.ks_chart_unit, + 'ks_bar_chart_stacked': rec.ks_bar_chart_stacked, + 'ks_goal_bar_line': rec.ks_goal_bar_line, + 'ks_actions': rec.ks_actions.xml_id if rec.ks_actions else False, + 'ks_client_action': rec.ks_client_action.xml_id if rec.ks_client_action else False, + 'ks_is_client_action': rec.ks_is_client_action, + 'ks_export_all_records': rec.ks_export_all_records, + 'ks_record_data_limit_visibility': rec.ks_record_data_limit_visibility, + 'ks_data_format': rec.ks_data_format, + 'ks_pagination_limit': rec.ks_pagination_limit, + 'ks_chart_cumulative_field': rec.ks_chart_cumulative_field.ids, + 'ks_chart_cumulative': rec.ks_chart_cumulative, + 'ks_button_color': rec.ks_button_color, + 'ks_dn_header_line': ks_dn_header_lines, + 'ks_semi_circle_chart': rec.ks_semi_circle_chart, + 'ks_multiplier_active': rec.ks_multiplier_active, + 'ks_multiplier': rec.ks_multiplier, + 'ks_multiplier_lines': ks_multiplier_lines if ks_multiplier_lines else False, + 'ks_many2many_field_ordering': rec.ks_many2many_field_ordering, + 'ks_data_label_type': rec.ks_data_label_type, + 'ks_as_of_now': rec.ks_as_of_now, + 'ks_scatter_measure_x_id': rec.ks_chart_relation_groupby.name, + 'ks_scatter_measure_y_id': ks_chart_measure_field, + 'ks_is_scatter_group': rec.ks_is_scatter_group, + 'ks_country_id': rec.ks_country_id.id, + 'ks_bounds': rec.ks_bounds, + 'ks_partners_map': rec.ks_partners_map, + 'ks_funnel_item_color':rec.ks_funnel_item_color, + + } + if grid_corners: + item.update({ + 'grid_corners': grid_corners, + }) + return item + + def ks_open_import(self, **kwargs): + action = self.env['ir.actions.act_window']._for_xml_id('ks_dashboard_ninja.ks_import_dashboard_action') + return action + + def ks_open_setting(self, **kwargs): + action = self.env['ir.actions.act_window']._for_xml_id('ks_dashboard_ninja.board_form_tree_action_window') + # action['res_id'] = self.id + # action['target'] = 'new' + # action['context'] = {'form_view_ref':'ks_dashboard_ninja.board_form'} + # action['view_mode']='form' + return action + + def ks_delete_dashboard(self): + if str(self.id) in self.ks_dashboard_default_template: + raise ValidationError(_('You cannot delete any default template')) + else: + self.search([('id', '=', self.id)]).unlink() + return { + 'type': 'ir.actions.client', + 'name': "Dashboard Ninja", + 'res_model': 'ks_dashboard_ninja.board', + 'params': {'ks_dashboard_id': 1}, + 'tag': 'ks_dashboard_ninja', + } + + def ks_create_dashboard(self): + action = self.env['ir.actions.act_window']._for_xml_id('ks_dashboard_ninja.board_form_tree_action_window') + action['target'] = 'new' + return action + + def ks_import_item(self, dashboard_id, **kwargs): + try: + # ks_dashboard_data = json.loads(file) + file = kwargs.get('file', False) + ks_dashboard_file_read = json.loads(file) + except Exception: + raise ValidationError(_("This file is not supported")) + + if 'ks_file_format' in ks_dashboard_file_read and ks_dashboard_file_read[ + 'ks_file_format'] == 'ks_dashboard_ninja_item_export': + item = ks_dashboard_file_read['item'] + else: + raise ValidationError(_("Current Json File is not properly formatted according to Dashboard Ninja Model.")) + + item['ks_dashboard_ninja_board_id'] = int(dashboard_id) + item['ks_company_id'] = False + self.ks_create_item(item) + + return "Success" + + @api.model + def ks_dashboard_export(self, ks_dashboard_ids, **kwargs): + ks_dashboard_data = [] + ks_dashboard_export_data = {} + if kwargs.get('dashboard_id'): + ks_dashboard_ids = '['+str(ks_dashboard_ids)+']' + ks_dashboard_ids = json.loads(ks_dashboard_ids) + for ks_dashboard_id in ks_dashboard_ids: + dash = self.search([('id', '=', ks_dashboard_id)]) + selecred_rec = self.env['ks_dashboard_ninja.child_board'].search( + [['id', 'in', dash.ks_child_dashboard_ids.ids], ['ks_active', '=', True], + ['company_id', '=', self.env.company.id]], limit=1) + ks_dashboard_rec = self.browse(ks_dashboard_id) + if selecred_rec: + name = selecred_rec.name + grid_conf = selecred_rec.ks_gridstack_config + elif dash.ks_child_dashboard_ids: + name = dash.display_name + grid_conf = dash.ks_child_dashboard_ids[0].ks_gridstack_config + else: + name = dash.name + grid_conf = dash.ks_gridstack_config + dashboard_data = self.ks_prepare_export_data_vals(ks_dashboard_rec, grid_conf=grid_conf) + if selecred_rec: + dashboard_data['name'] = selecred_rec.name + dashboard_data['ks_gridstack_config'] = selecred_rec.ks_gridstack_config + elif len(ks_dashboard_rec.ks_child_dashboard_ids) > 1: + dashboard_data['name'] = ks_dashboard_rec.ks_child_dashboard_ids[0].name + dashboard_data['ks_gridstack_config'] = ks_dashboard_rec.ks_child_dashboard_ids[0].ks_gridstack_config + if dashboard_data['name'] == 'Default Board Layout': + dashboard_data['name'] = ks_dashboard_rec.ks_dashboard_menu_name + if len(ks_dashboard_rec.ks_dashboard_items_ids) < 1: + dashboard_data['ks_item_data'] = False + else: + items = [] + for rec in ks_dashboard_rec.ks_dashboard_items_ids: + item = self.ks_export_item_data(rec) + items.append(item) + + dashboard_data['ks_item_data'] = items + ks_dashboard_data.append(dashboard_data) + + ks_dashboard_export_data = { + 'ks_file_format': 'ks_dashboard_ninja_export_file', + 'ks_dashboard_data': ks_dashboard_data + } + return ks_dashboard_export_data + + def ks_prepare_export_data_vals(self, ks_dashboard_rec, grid_conf=None,): + dashboard_data = { + 'name': ks_dashboard_rec.name, + 'ks_dashboard_menu_name': ks_dashboard_rec.ks_dashboard_menu_name, + 'ks_gridstack_config': grid_conf if grid_conf else '{}', + 'ks_set_interval': ks_dashboard_rec.ks_set_interval, + 'ks_date_filter_selection': ks_dashboard_rec.ks_date_filter_selection, + 'ks_dashboard_start_date': ks_dashboard_rec.ks_dashboard_start_date, + 'ks_dashboard_end_date': ks_dashboard_rec.ks_dashboard_end_date, + 'ks_dashboard_top_menu_id': ks_dashboard_rec.ks_dashboard_top_menu_id.id, + 'ks_data_formatting': ks_dashboard_rec.ks_data_formatting, + } + return dashboard_data + + @api.model + def ks_import_dashboard(self, file, menu_id): + try: + # ks_dashboard_data = json.loads(file) + ks_dashboard_file_read = json.loads(file) + except Exception: + raise ValidationError(_("This file is not supported")) + + if 'ks_file_format' in ks_dashboard_file_read and ks_dashboard_file_read[ + 'ks_file_format'] == 'ks_dashboard_ninja_export_file': + ks_dashboard_data = ks_dashboard_file_read['ks_dashboard_data'] + for i in range(len(ks_dashboard_data)): + if 'ks_set_interval' in ks_dashboard_data[i].keys() and ks_dashboard_data[i].get('ks_item_data', False): + # del ks_dashboard_data[i]['ks_set_interval'] + for j in range(len(ks_dashboard_data[i].get('ks_item_data', False))): + if 'ks_update_items_data' in ks_dashboard_data[i].get('ks_item_data', False)[j].keys(): + del ks_dashboard_data[i].get('ks_item_data', False)[j]['ks_update_items_data'] + if 'ks_auto_update_type' in ks_dashboard_data[i].get('ks_item_data', False)[j].keys(): + del ks_dashboard_data[i].get('ks_item_data', False)[j]['ks_auto_update_type'] + if 'ks_show_live_pop_up' in ks_dashboard_data[i].get('ks_item_data', False)[j].keys(): + del ks_dashboard_data[i].get('ks_item_data', False)[j]['ks_show_live_pop_up'] + else: + raise ValidationError(_("Current Json File is not properly formatted according to Dashboard Ninja Model.")) + + ks_dashboard_key = ['name', 'ks_dashboard_menu_name', 'ks_gridstack_config'] + ks_dashboard_item_key = ['ks_model_id', 'ks_chart_measure_field', 'ks_list_view_fields', 'ks_record_field', + 'ks_chart_relation_groupby', 'ks_id'] + + # Fetching dashboard model info + for data in ks_dashboard_data: + if not all(key in data for key in ks_dashboard_key): + raise ValidationError( + _("Current Json File is not properly formatted according to Dashboard Ninja Model.")) + ks_dashboard_top_menu_id = data.get('ks_dashboard_top_menu_id', False) + if ks_dashboard_top_menu_id: + try: + self.env['ir.ui.menu'].browse(ks_dashboard_top_menu_id).name + ks_dashboard_top_menu_id = self.env['ir.ui.menu'].browse(ks_dashboard_top_menu_id) + except Exception: + ks_dashboard_top_menu_id = False + vals = self.ks_prepare_import_data_vals(data, menu_id) + # Creating Dashboard + dashboard_id = self.create(vals) + + if data['ks_gridstack_config']: + ks_gridstack_config = safe_eval(data['ks_gridstack_config']) + ks_grid_stack_config = {} + + item_ids = [] + item_new_ids = [] + ks_skiped = False + if data['ks_item_data']: + # Fetching dashboard item info + ks_skiped = 0 + for item in data['ks_item_data']: + item['ks_company_id'] = False + if not all(key in item for key in ks_dashboard_item_key): + raise ValidationError( + _("Current Json File is not properly formatted according to Dashboard Ninja Model.")) + + # Creating dashboard items + item['ks_dashboard_ninja_board_id'] = dashboard_id.id + item_ids.append(item['ks_id']) + del item['ks_id'] + + if 'ks_data_calculation_type' in item: + if item['ks_data_calculation_type'] == 'custom': + del item['ks_data_calculation_type'] + del item['ks_custom_query'] + del item['ks_xlabels'] + del item['ks_ylabels'] + del item['ks_list_view_layout'] + ks_item = self.ks_create_item(item) + item_new_ids.append(ks_item.id) + else: + ks_skiped += 1 + else: + ks_item = self.ks_create_item(item) + item_new_ids.append(ks_item.id) + + for id_index, id in enumerate(item_ids): + if data['ks_gridstack_config'] and str(id) in ks_gridstack_config: + ks_grid_stack_config[str(item_new_ids[id_index])] = ks_gridstack_config[str(id)] + # if id_index in item_new_ids: + + self.browse(dashboard_id.id).write({ + 'ks_gridstack_config': json.dumps(ks_grid_stack_config) + }) + + if ks_skiped: + return { + 'ks_skiped_items': ks_skiped, + } + + return "Success" + # separate function to make item for import + + def ks_prepare_import_data_vals(self, data, menu_id): + vals = { + 'name': data['name'], + 'ks_dashboard_menu_name': data['ks_dashboard_menu_name'], + 'ks_dashboard_top_menu_id': menu_id.id if menu_id else self.env.ref( + "ks_dashboard_ninja.board_menu_root").id, + 'ks_dashboard_active': True, + 'ks_gridstack_config': data['ks_gridstack_config'], + 'ks_dashboard_default_template': self.env.ref("ks_dashboard_ninja.ks_blank").id, + 'ks_dashboard_group_access': False, + 'ks_set_interval': data['ks_set_interval'], + 'ks_date_filter_selection': data['ks_date_filter_selection'], + 'ks_dashboard_start_date': data['ks_dashboard_start_date'], + 'ks_dashboard_end_date': data['ks_dashboard_end_date'], + } + return vals + + def ks_create_item(self, item): + model = self.env['ir.model'].search([('model', '=', item['ks_model_id'])]) + + if not model and not item['ks_dashboard_item_type'] == 'ks_to_do': + raise ValidationError(_( + "Please Install the Module which contains the following Model : %s " % item['ks_model_id'])) + + ks_model_name = item['ks_model_id'] + + ks_goal_lines = item['ks_goal_liness'].copy() if item.get('ks_goal_liness', False) else False + ks_action_lines = item['ks_action_liness'].copy() if item.get('ks_action_liness', False) else False + ks_multiplier_lines = item['ks_multiplier_lines'].copy() if item.get('ks_multiplier_lines', False) else False + ks_dn_header_line = item['ks_dn_header_line'].copy() if item.get('ks_dn_header_line', False) else False + + # Creating dashboard items + item = self.ks_prepare_item(item) + + if 'ks_goal_liness' in item: + del item['ks_goal_liness'] + if 'ks_id' in item: + del item['ks_id'] + if 'ks_action_liness' in item: + del item['ks_action_liness'] + if 'ks_icon' in item: + item['ks_icon_select'] = "Default" + item['ks_icon'] = False + if 'ks_dn_header_line' in item: + del item['ks_dn_header_line'] + if 'ks_multiplier_lines' in item: + del item['ks_multiplier_lines'] + + ks_item = self.env['ks_dashboard_ninja.item'].create(item) + + if ks_goal_lines and len(ks_goal_lines) != 0: + for line in ks_goal_lines: + line['ks_goal_date'] = datetime.datetime.strptime(line['ks_goal_date'].split(" ")[0], + '%Y-%m-%d') + line['ks_dashboard_item'] = ks_item.id + self.env['ks_dashboard_ninja.item_goal'].create(line) + + if ks_dn_header_line and len(ks_dn_header_line) != 0: + for line in ks_dn_header_line: + ks_line = {} + ks_line['ks_to_do_header'] = line.get('ks_to_do_header') + ks_line['ks_dn_item_id'] = ks_item.id + ks_dn_header_id = self.env['ks_to.do.headers'].create(ks_line) + if line.get(line.get('ks_to_do_header'), False): + for ks_task in line.get(line.get('ks_to_do_header')): + ks_task['ks_to_do_header_id'] = ks_dn_header_id.id + self.env['ks_to.do.description'].create(ks_task) + + if ks_action_lines and len(ks_action_lines) != 0: + + for line in ks_action_lines: + if line['ks_sort_by_field']: + ks_sort_by_field = line['ks_sort_by_field'] + ks_sort_record_id = self.env['ir.model.fields'].search( + [('model', '=', ks_model_name), ('name', '=', ks_sort_by_field)]) + if ks_sort_record_id: + line['ks_sort_by_field'] = ks_sort_record_id.id + else: + line['ks_sort_by_field'] = False + if line['ks_item_action_field']: + ks_item_action_field = line['ks_item_action_field'] + ks_record_id = self.env['ir.model.fields'].search( + [('model', '=', ks_model_name), ('name', '=', ks_item_action_field)]) + if ks_record_id: + line['ks_item_action_field'] = ks_record_id.id + line['ks_dashboard_item_id'] = ks_item.id + self.env['ks_dashboard_ninja.item_action'].create(line) + + if ks_multiplier_lines and len(ks_multiplier_lines) != 0: + for rec in ks_multiplier_lines: + ks_multiplier_field = rec['ks_multiplier_fields'] + ks_multiplier_field_id = self.env['ir.model.fields'].search( + [('model', '=', ks_model_name), ('id', '=', ks_multiplier_field)]) + if ks_multiplier_field: + rec['ks_multiplier_fields'] = ks_multiplier_field_id.id + rec['ks_dashboard_item_id'] = ks_item.id + self.env['ks_dashboard_item.multiplier'].create(rec) + + return ks_item + + def ks_prepare_item(self, item): + try: + ks_measure_field_ids = [] + ks_measure_field_2_ids = [] + ks_many2many_field_ordering = item['ks_many2many_field_ordering'] if item.get('ks_many2many_field_ordering', False) else False + ks_list_view_group_fields_name = False + ks_list_view_fields_name = False + ks_chart_measure_field_name = False + ks_chart_measure_field_2_name = False + if ks_many2many_field_ordering: + ks_many2many_field_ordering = json.loads(ks_many2many_field_ordering) + ks_list_view_group_fields_name = ks_many2many_field_ordering.get('ks_list_view_group_fields_name', False) + ks_list_view_fields_name = ks_many2many_field_ordering.get('ks_list_view_fields_name', False) + ks_chart_measure_field_name = ks_many2many_field_ordering.get('ks_chart_measure_field_name', False) + ks_chart_measure_field_2_name = ks_many2many_field_ordering.get('ks_chart_measure_field_2_name', False) + ks_chart_measure_field = item['ks_chart_measure_field'] + if ks_chart_measure_field_name and len(ks_chart_measure_field_name)>0: + ks_chart_measure_field = ks_chart_measure_field_name + for ks_measure in ks_chart_measure_field: + ks_measure_id = self.env['ir.model.fields'].search( + [('name', '=', ks_measure), ('model', '=', item['ks_model_id'])]) + if ks_measure_id: + ks_measure_field_ids.append(ks_measure_id.id) + item['ks_chart_measure_field'] = [(6, 0, ks_measure_field_ids)] + ks_chart_measure_field_2 = item['ks_chart_measure_field_2'] + if ks_chart_measure_field_name and len(ks_chart_measure_field_name) > 0: + ks_chart_measure_field_2 = ks_chart_measure_field_2_name + for ks_measure in ks_chart_measure_field_2: + ks_measure_id = self.env['ir.model.fields'].search( + [('name', '=', ks_measure), ('model', '=', item['ks_model_id'])]) + if ks_measure_id: + ks_measure_field_2_ids.append(ks_measure_id.id) + item['ks_chart_measure_field_2'] = [(6, 0, ks_measure_field_2_ids)] + + ks_list_view_group_fields_ids = [] + ks_list_view_group_fields = item['ks_list_view_group_fields'] + if ks_list_view_group_fields_name and len(ks_list_view_group_fields_name) > 0: + ks_list_view_group_fields = ks_list_view_group_fields_name + for ks_measure in ks_list_view_group_fields: + ks_measure_id = self.env['ir.model.fields'].search( + [('name', '=', ks_measure), ('model', '=', item['ks_model_id'])]) + + if ks_measure_id: + ks_list_view_group_fields_ids.append(ks_measure_id.id) + item['ks_list_view_group_fields'] = [(6, 0, ks_list_view_group_fields_ids)] + + ks_list_view_field_ids = [] + + ks_list_view_fields = item['ks_list_view_fields'] + if ks_list_view_fields_name and len(ks_list_view_fields_name) > 0: + ks_list_view_fields = ks_list_view_group_fields_name + for ks_list_field in ks_list_view_fields: + ks_list_field_id = self.env['ir.model.fields'].search( + [('name', '=', ks_list_field), ('model', '=', item['ks_model_id'])]) + if ks_list_field_id: + ks_list_view_field_ids.append(ks_list_field_id.id) + item['ks_list_view_fields'] = [(6, 0, ks_list_view_field_ids)] + + if item['ks_record_field']: + ks_record_field = item['ks_record_field'] + ks_record_id = self.env['ir.model.fields'].search( + [('name', '=', ks_record_field), ('model', '=', item['ks_model_id'])]) + if ks_record_id: + item['ks_record_field'] = ks_record_id.id + else: + item['ks_record_field'] = False + + if item['ks_date_filter_field']: + ks_date_filter_field = item['ks_date_filter_field'] + ks_record_id = self.env['ir.model.fields'].search( + [('name', '=', ks_date_filter_field), ('model', '=', item['ks_model_id'])]) + if ks_record_id: + item['ks_date_filter_field'] = ks_record_id.id + else: + item['ks_date_filter_field'] = False + + if item['ks_chart_relation_groupby']: + ks_group_by = item['ks_chart_relation_groupby'] + ks_record_id = self.env['ir.model.fields'].search( + [('name', '=', ks_group_by), ('model', '=', item['ks_model_id'])]) + if ks_record_id: + item['ks_chart_relation_groupby'] = ks_record_id.id + else: + item['ks_chart_relation_groupby'] = False + + if item['ks_chart_relation_sub_groupby']: + ks_group_by = item['ks_chart_relation_sub_groupby'] + ks_chart_relation_sub_groupby = self.env['ir.model.fields'].search( + [('name', '=', ks_group_by), ('model', '=', item['ks_model_id'])]) + if ks_chart_relation_sub_groupby: + item['ks_chart_relation_sub_groupby'] = ks_chart_relation_sub_groupby.id + else: + item['ks_chart_relation_sub_groupby'] = False + + if item['ks_dashboard_item_type'] == "ks_scatter_chart" and item['ks_scatter_measure_y_id'] and item[ + 'ks_scatter_measure_x_id']: + ks_scatter_id = self.env['ir.model.fields'].search( + [('name', '=', item['ks_scatter_measure_y_id'][0]), ('model', '=', item['ks_model_id'])]) + if ks_scatter_id: + item['ks_scatter_measure_y_id'] = ks_scatter_id.id + ks_scatter_group_by = item['ks_scatter_measure_x_id'] + ks_record_id = self.env['ir.model.fields'].search( + [('name', '=', ks_scatter_group_by), ('model', '=', item['ks_model_id'])]) + if ks_record_id: + item['ks_scatter_measure_x_id'] = ks_record_id.id + else: + item['ks_scatter_measure_x_id'] = False + if item["ks_dashboard_item_type"] != "ks_scatter_chart": + item['ks_scatter_measure_x_id'] = False + item['ks_scatter_measure_y_id'] = False + + # Sort by field : Many2one Entery + if item['ks_sort_by_field']: + ks_group_by = item['ks_sort_by_field'] + ks_sort_by_field = self.env['ir.model.fields'].search( + [('name', '=', ks_group_by), ('model', '=', item['ks_model_id'])]) + if ks_sort_by_field: + item['ks_sort_by_field'] = ks_sort_by_field.id + else: + item['ks_sort_by_field'] = False + + if item['ks_list_target_deviation_field']: + ks_list_target_deviation_field = item['ks_list_target_deviation_field'] + record_id = self.env['ir.model.fields'].search( + [('name', '=', ks_list_target_deviation_field), ('model', '=', item['ks_model_id'])]) + if record_id: + item['ks_list_target_deviation_field'] = record_id.id + else: + item['ks_list_target_deviation_field'] = False + + ks_model_id = self.env['ir.model'].search([('model', '=', item['ks_model_id'])]).id + + if item.get("ks_actions"): + ks_action = self.env.ref(item["ks_actions"], False) + if ks_action: + item["ks_actions"] = ks_action.id + else: + item["ks_actions"] = False + if item.get("ks_client_action"): + ks_action = self.env.ref(item["ks_client_action"], False) + if ks_action: + item["ks_client_action"] = ks_action.id + else: + item["ks_client_action"] = False + + if (item['ks_model_id_2']): + ks_model_2 = item['ks_model_id_2'].replace(".", "_") + ks_model_id_2 = self.env['ir.model'].search([('model', '=', item['ks_model_id_2'])]).id + if item['ks_record_field_2']: + ks_record_field = item['ks_record_field_2'] + ks_record_id = self.env['ir.model.fields'].search( + [('model', '=', item['ks_model_id_2']), ('name', '=', ks_record_field)]) + + if ks_record_id: + item['ks_record_field_2'] = ks_record_id.id + else: + item['ks_record_field_2'] = False + if item['ks_date_filter_field_2']: + ks_record_id = self.env['ir.model.fields'].search( + [('model', '=', item['ks_model_id_2']), ('name', '=', item['ks_date_filter_field_2'])]) + + if ks_record_id: + item['ks_date_filter_field_2'] = ks_record_id.id + else: + item['ks_date_filter_field_2'] = False + + item['ks_model_id_2'] = ks_model_id_2 + else: + item['ks_date_filter_field_2'] = False + item['ks_record_field_2'] = False + + item['ks_model_id'] = ks_model_id + + item['ks_goal_liness'] = False + item['ks_item_start_date'] = item['ks_item_start_date'] if \ + item['ks_item_start_date'] else False + item['ks_item_end_date'] = item['ks_item_end_date'] if \ + item['ks_item_end_date'] else False + item['ks_item_start_date_2'] = item['ks_item_start_date_2'] if \ + item['ks_item_start_date_2'] else False + item['ks_item_end_date_2'] = item['ks_item_end_date_2'] if \ + item['ks_item_end_date_2'] else False + + return item + except Exception as e: + raise ValidationError('JSON file not supported.') + @api.model + def update_child_board(self, action, dashboard_id, data): + dashboard_id = self.browse(dashboard_id) + selecred_rec = self.env['ks_dashboard_ninja.child_board'].search( + [['id', 'in', dashboard_id.ks_child_dashboard_ids.ids], + ['company_id', '=', self.env.company.id], ['ks_active', '=', True]], limit=1) + if action == 'create': + dashboard_id.ks_child_dashboard_ids.write({'ks_active': False}) + result = self.env['ks_dashboard_ninja.child_board'].create(data) + result = result.id + elif action == 'update': + # result = dashboard_id.ks_child_dashboard_ids.search([['ks_active', '=', True]]).write({'ks_active': False}) + if data['ks_selected_board_id'] != 'ks_default': + selecred_rec.ks_active = False + result = dashboard_id.ks_child_dashboard_ids.browse(int(data['ks_selected_board_id'])).write( + {'ks_active': True}) + else: + result = dashboard_id.ks_child_dashboard_ids.search([['ks_active', '=', True]]).write( + {'ks_active': False}) + for i in dashboard_id.ks_child_dashboard_ids: + if i.name == 'Default Board Layout': + i.ks_active = True + return result + + def ks_prepare_dashboard_domain(self): + pre_defined_filter_ids = self.env['ks_dashboard_ninja.board_defined_filters'].search( + [['id', 'in', self.ks_dashboard_defined_filters_ids.ids], '|', ['ks_is_active', '=', True], + ['display_type', '=', 'line_section']], order='sequence') + data = {} + filter_model_ids = pre_defined_filter_ids.mapped('ks_model_id').ids + for model_id in filter_model_ids: + filter_ids = self.env['ks_dashboard_ninja.board_defined_filters'].search( + [['id', 'in', pre_defined_filter_ids.ids], '|', ['ks_model_id', '=', model_id], + ['display_type', '=', 'line_section']], + order='sequence') + connect_symbol = '|' + for rec in filter_ids: + if rec.display_type == 'line_section': + connect_symbol = '&' + + if data.get(rec.ks_model_id.model) and rec.ks_domain: + data[rec.ks_model_id.model]['domain'] = data[rec.ks_model_id.model]['domain'] + safe_eval( + rec.ks_domain) + data[rec.ks_model_id.model]['domain'].insert(0, connect_symbol) + elif rec.ks_model_id.model: + ks_domain = rec.ks_domain + 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.company.id)) + data[rec.ks_model_id.model] = { + 'domain': safe_eval(ks_domain) if ks_domain else [], + 'ks_domain_index_data': [], + 'model_name': rec.ks_model_id.name, + 'item_ids': self.env['ks_dashboard_ninja.item'].search( + [['id', 'in', self.ks_dashboard_items_ids.ids], '|', + ['ks_model_id', '=', rec.ks_model_id.id], ['ks_model_id_2', '=', rec.ks_model_id.id]]).ids + } + + return data + + def ks_prepare_dashboard_pre_domain(self): + data = {} + pre_defined_filter_ids = self.env['ks_dashboard_ninja.board_defined_filters'].search( + [['id', 'in', self.ks_dashboard_defined_filters_ids.ids]], order='sequence') + categ_seq = 1 + for rec in pre_defined_filter_ids: + if rec.display_type == 'line_section': + categ_seq = categ_seq + 1 + ks_domain = rec.ks_domain + 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.company.id)) + + data[rec['id']] = { + 'id': rec.id, + 'name': rec.name, + 'model': rec.ks_model_id.model, + 'model_name': rec.ks_model_id.name, + 'active': rec.ks_is_active, + 'categ': rec.ks_model_id.model + '_' + str(categ_seq) if rec.display_type != 'line_section' else 0, + 'type': 'filter' if rec.display_type != 'line_section' else 'separator', + 'domain': safe_eval(ks_domain) if ks_domain else [], + 'sequence': rec.sequence + } + return data + + def ks_prepare_dashboard_custom_domain(self): + custom_filter_ids = self.env['ks_dashboard_ninja.board_custom_filters'].search( + [['id', 'in', self.ks_dashboard_custom_filters_ids.ids]], order='name') + data = {} + for rec in custom_filter_ids: + data[str(rec.id)] = { + 'id': rec.id, + 'name': rec.name, + 'model': rec.ks_model_id.model, + 'model_name': rec.ks_model_id.name, + 'field_name': rec.ks_domain_field_id.name, + 'field_type': rec.ks_domain_field_id.ttype, + 'special_data': {} + } + if rec.ks_domain_field_id.ttype == 'selection': + data[str(rec.id)]['special_data'] = { + 'select_options': + self.env[rec.ks_model_id.model].fields_get(allfields=[rec.ks_domain_field_id.name])[ + rec.ks_domain_field_id.name]['selection'] + } + return data diff --git a/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py b/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py new file mode 100644 index 000000000..65fb95761 --- /dev/null +++ b/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py @@ -0,0 +1,4554 @@ +# -*- coding: utf-8 -*- +import dateutil +import datetime as dt +from datetime import timezone +import pytz +import json +import xlrd +import csv +import os +import tempfile +import binascii +import pandas as pd +import babel +import ast +from datetime import timedelta +from odoo.tools.safe_eval import safe_eval +from odoo.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT, DEFAULT_SERVER_DATE_FORMAT +from collections import defaultdict +from datetime import datetime +from dateutil import relativedelta +from odoo import models, fields, api, _ +from odoo.exceptions import ValidationError, UserError +from odoo.addons.ks_dashboard_ninja.common_lib.ks_date_filter_selections import ks_get_date, ks_convert_into_utc, \ + ks_convert_into_local +from .ks_country_bounds import get_country_code +import logging +_logger = logging.getLogger("DS_NINJA") +# TODO : Check all imports if needed + + +read = fields.Many2one.read + + + +def ks_read(self, records): + if self.name == 'ks_list_view_fields' or self.name == 'ks_list_view_group_fields' or \ + self.name == 'ks_chart_measure_field' or self.name == 'ks_chart_measure_field_2': + 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' + ) + where_params.append(tuple(records.ids)) + + # retrieve lines and group them by record + group = defaultdict(list) + records._cr.execute(query, where_params) + + for record in records: + if self.name == 'ks_list_view_fields': + field = 'ks_list_view_fields' + elif self.name == 'ks_chart_measure_field': + field = 'ks_chart_measure_field' + elif self.name == 'ks_chart_measure_field_2': + field = 'ks_chart_measure_field_2' + 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) + + + rec_list = records._cr.fetchall() + if order: + for row in order: + group[record.id].append(row) + + else: + for row in rec_list: + group[row[0]].append(row[1]) + + # store result in cache + cache = records.env.cache + if order: + try: + group[record.id].sort(key=lambda x: order.index(x)) + except Exception as e: + pass + cache.set(record, self, tuple(group[record.id])) + + + else: + context = {'active_test': False} + context.update(self.context) + comodel = records.env[self.comodel_name].with_context(**context) + domain = self.get_domain_list(records) + comodel._flush_search(domain) + 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} + """.format(rel=self.relation, id1=self.column1, id2=self.column2, + tbl=comodel._table, from_c=from_c, where_c=where_c or '1=1', + 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 FIXME + +# read_group = models.BaseModel._read_group_process_groupby FIXME + + +def ks_time_addition(self, gb, query): + """ + Overwriting default to add minutes to Helper method to collect important + information about groupbys: raw field name, type, time information, qualified name, ... + """ + 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: + lang = self.env['res.lang']._lang_get(self.env.user.lang).time_format + if '%H' in lang: + display_formats = { + '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', + } + else: + display_formats = { + '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), + '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::timestamp)" % (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, + 'granularity': gb_function or 'month' if temporal else None, + } + + +# models.BaseModel._read_group_process_groupby = ks_time_addition # FIXME + + +class KsDashboardNinjaItems(models.Model): + _name = 'ks_dashboard_ninja.item' + _description = 'Dashboard Ninja items' + + name = fields.Char(string="Name", translate=True, help="The item will be represented by this unique name.") + ks_info = fields.Text(string="Item Description", translate=True) + ks_model_id = fields.Many2one('ir.model', string='Model', + domain="[('access_ids','!=',False),('transient','=',False)," + "('model','not ilike','base_import%'),'|',('model','not ilike','ir.%'), ('model','ilike','repair.%')," + "('model','not ilike','web_editor.%'),('model','not ilike','web_tour.%')," + "('model','!=','mail.thread'),('model','not ilike','ks_dash%'),('model','not ilike','ks_to%')]", + help="Data source to fetch and read the data for the creation of dashboard items. ") + ks_dashboard_board_template_id = fields.Many2one('ks_dashboard_ninja.board_template', string="Dashboard Template") + ks_domain = fields.Char(string="Domain", help="Define conditions for filter. ") + + 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','not ilike','web_editor.%'),('model','not ilike','web_tour.%')," + "('model','!=','mail.thread'),('model','not ilike','ks_dash%'), ('model','not ilike','ks_to%')]") + + ks_model_name_2 = fields.Char(related='ks_model_id_2.model', string="Kpi Model Name") + + # This field main purpose is to store %UID as current user id. Mainly used in JS file as container. + ks_domain_temp = fields.Char(string="Domain Substitute") + grid_corners = fields.Char(string="grid corners") + ks_background_color = fields.Char(string="Background Color", + default="#ffffff,0.99", help=' Select the background color with transparency. ') + ks_icon = fields.Binary(string="Upload Icon", attachment=True) + ks_default_icon = fields.Char(string="Icon", default="bar-chart", help='Select the icon to be displayed. ') + ks_default_icon_color = fields.Char(default="#ffffff,0.99", string="Icon Color", + help='Select the icon to be displayed. ') + ks_icon_select = fields.Selection([("Default","Default"),("Custom","Custom"),],string="Icon Option", default=("Default"), help='Choose the Icon option. ') + ks_font_color = fields.Char(default="#ffffff,0.99", string="Font Color", help='Select the font color. ') + ks_dashboard_item_theme = fields.Char(string="Theme", default="white", + help='Select the color theme for the display. ') + 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", + help=' Select the layout to display records. ') + ks_preview = fields.Integer(default=1, string="Preview") + ks_model_name = fields.Char(related='ks_model_id.model', string="Model Name") + + ks_record_count_type_2 = fields.Selection([('count', 'Count'), + ('sum', 'Sum'), + ('average', 'Average')], string="Kpi Record Type", default="sum") + 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="Kpi Record Field") + ks_record_count_2 = fields.Float(string="KPI Record Count", readonly=True, compute='ks_get_record_count_2', + compute_sudo=False) + ks_record_count_type = fields.Selection([('count', 'Count'), + ('sum', 'Sum'), + ('average', 'Average')], string="Record Type", default="count", + help="Type of record how record will show as count,sum and average of the record") + ks_record_count = fields.Float(string="Record Count", compute='ks_get_record_count', readonly=True, + compute_sudo=False) + ks_record_field = fields.Many2one('ir.model.fields', + domain="[('model_id','=',ks_model_id),('name','!=','id'),('store','=',True),'|'," + "'|',('ttype','=','integer'),('ttype','=','float')," + "('ttype','=','monetary')]", + string="Record Field") + ks_send_mail = fields.Boolean(string="Send Mail") + ks_email_to_ids = fields.Many2many('ks_dashboard_ninja.kpi_mail',string="Email Address") + ks_stop_mail_cron = fields.Boolean(string="Stop mail cron") + ks_record_data_limit_visibility = fields.Boolean(string="Record Limit Data Visibility", + help="To enable the record data limit field") + + # Date Filter Fields + # Condition to tell if date filter is applied or not + ks_isDateFilterApplied = fields.Boolean(default=False) + + # ---------------------------- Date Filter Fields ------------------------------------------ + 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'), + ('td_week', 'Week to Date'), + ('td_month', 'Month to Date'), + ('td_quarter', 'Quarter to Date'), + ('td_year', 'Year to Date'), + ('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, + help='Select interval of the records to be displayed. ') + 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", + help='Select the field for which Date Filter should be applicable.') + + 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="Kpi Date Filter Field") + + ks_item_start_date_2 = fields.Datetime(string="Kpi Start Date") + ks_item_end_date_2 = fields.Datetime(string="Kpi End Date") + + ks_domain_2 = fields.Char(string="Kpi Domain") + ks_domain_2_temp = fields.Char(string="Kpi Domain Substitute") + + 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'), + ('td_week', 'Week to Date'), + ('td_month', 'Month to Date'), + ('td_quarter', 'Quarter to Date'), + ('td_year', 'Year to Date'), + ('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="Kpi Date Filter Selection", required=True, default='l_none') + + ks_previous_period = fields.Boolean(string=" Compare With Previous Period ", help='Checkbox to show comparison between the data of present day and the previous selected period. ') + + # ------------------------ Pro Fields -------------------- + ks_dashboard_ninja_board_id = fields.Many2one('ks_dashboard_ninja.board', string="Dashboard", + 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_radialBar_chart', 'Radial Bar Chart'), + ('ks_scatter_chart', 'Scatter Chart'), + ('ks_list_view', 'List View'), + ('ks_radar_view', 'Radar View'), + ('ks_flower_view', 'Flower View'), + ('ks_kpi', 'KPI'), + ('ks_to_do', 'To Do'), + ('ks_map_view', 'Map View'), + ('ks_funnel_chart', 'Funnel Chart'), + ('ks_bullet_chart', 'Bullet Chart') + ], default=lambda self: self._context.get('ks_dashboard_item_type', + 'ks_tile'), required=True, + + help="Select the required type of dashboard to display. ") + ks_chart_groupby_type = fields.Char(compute='get_chart_groupby_type', compute_sudo=False) + ks_chart_sub_groupby_type = fields.Char(compute='get_chart_sub_groupby_type', compute_sudo=False) + 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", help=' Define the x-axis of the graph. ') + 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", + help='Select the second level of grouping. ') + 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="Dashboard Item Chart Group By Type") + ks_chart_date_sub_groupby = fields.Selection([('minute', 'Minute'), + ('hour', 'Hour'), + ('day', 'Day'), + ('week', 'Week'), + ('month', 'Month'), + ('quarter', 'Quarter'), + ('year', 'Year'), + ], string="Dashboard Item Chart Sub Group By Type") + ks_graph_preview = fields.Char(string="Graph Preview", default="Graph Preview") + ks_chart_data = fields.Char(string="Chart Data in string form", compute='ks_get_chart_data', compute_sudo=False) + ks_chart_data_count_type = fields.Selection([('count', 'Count'), ('sum', 'Sum'), ('average', 'Average')], + string="Data Type", default="sum") + 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="Measure 1", help='Data points to be selected.') + ks_chart_is_cumulative = fields.Boolean('Is Cumulative') + ks_chart_cumulative_field = fields.Many2many('ir.model.fields', 'ks_dn_cumulative_measure_field_rel', + 'measure_cumulative_field_id', + 'cumulative_field_id', + domain="[('model_id','=',ks_model_id),('name','!=','id'),('name'," + "'!=','sequence'), " + "('store','=',True),'|','|'," + "('ttype','=','integer'),('ttype','=','float')," + "('ttype','=','monetary')]", + string="Cumulative Fields", help='Data points to be selected.') + + ks_chart_cumulative = fields.Boolean("Cumulative As Line") + 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", + help='Data Points displayed with a line in the graph. ') + + ks_bar_chart_stacked = fields.Boolean(string="Stacked Bar Chart", help='Stack the columns of the same record. ') + + ks_semi_circle_chart = fields.Boolean(string="Semi Circle 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", help='Select the desired sorting preference. ') + ks_sort_by_order = fields.Selection([('ASC', 'Ascending'), ('DESC', 'Descending')], + string="Sort Order", help=' Select the order of the sorting. ') + ks_record_data_limit = fields.Integer(string="Record Limit", help=' Records to be displayed on the graph') + + ks_list_view_preview = fields.Char(string="List View Preview", default="List View Preview") + + ks_kpi_preview = fields.Char(string="Kpi Preview", default="KPI Preview") + + ks_kpi_type = fields.Selection([ + ('layout_1', 'KPI With Target'), + ('layout_2', 'Data Comparison'), + ], string="Kpi Layout", default="layout_1") + + ks_target_view = fields.Selection([("Number","Number"),("Progress Bar","Progress Bar"),],string="View", default="Number", help=' Select the view to compare target with data.') + + ks_data_comparison = fields.Selection([("None","None"),("Sum","Sum"),("Ratio","Ratio"),("Percentage","Percentage"),],string="Kpi Data Type", default="None") + + ks_kpi_data = fields.Char(string="KPI Data", compute="ks_get_kpi_data", compute_sudo=False) + + ks_chart_item_color = fields.Selection( + [('default', 'Default'), ('cool', 'Cool'), ('warm', 'Warm'), ('neon', 'Neon')], + string="Chart Color Palette", default="default", help='Select the display preference. ') + + # ------------------------ List View Fields ------------------------------ + + ks_list_view_type = fields.Selection([('ungrouped', 'Un-Grouped'), ('grouped', 'Grouped')], default="ungrouped", + string="List View Type", required=True, + help='Select the desired list view type. ') + 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),('ttype','!=','one2many')," + "('ttype','!=','many2many'),('ttype','!=','binary')]", + string="Fields to show in list", + help=' Select the fields you want to display in the list. ') + + ks_export_all_records = fields.Boolean(string="Export All Records", default=True, + help="when click on boolean button, all the records will be downloaded which are present in entire 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', + compute_sudo=False) + + # -------------------- Multi Company Feature --------------------- + ks_company_id = fields.Many2one('res.company', string='Company', default=lambda self: self.env.user.company_id, + help='Name of the company for which analytics will be displayed in the dashboard. ') + + # -------------------- Target Company Feature --------------------- + ks_goal_enable = fields.Boolean(string="Enable Target", help='Show the set target.') + ks_goal_bar_line = fields.Boolean(string="Show Target As Line") + ks_standard_goal_value = fields.Float(string="Standard Target", help='Show the set 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_many2many_field_ordering = fields.Char() + + # 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", help=' Display value on the graph. . ') + + 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", help="Redirects you to the selected view. ") + + ks_compare_period = fields.Integer(string="Include Period", + help=' Provide the number of Date Filter Selection you want to include while displaying the record.') + ks_year_period = fields.Integer(string="Same Period Previous Years", + help=' Display the record for the same Date field for the last year. ') + ks_compare_period_2 = fields.Integer(string="KPI Include Period") + ks_year_period_2 = fields.Integer(string="KPI Same Period Previous Years") + + ks_multiplier_active = fields.Boolean(string="Apply Multiplier", default=False, + help="Provides the visibility of multiplier field") + ks_multiplier = fields.Float(string="Multiplier",default=1, help="Provides the multiplication of record value") + + + + # User can select custom units for measure + ks_currency_id= fields.Many2one("res.currency",string="Currency", domain="['|', ('active', '=', False), ('active', '=', True)]", + default=lambda self: self.env.company.currency_id) + + ks_unit = fields.Boolean(string="Show Custom Unit", default=False, help='Display the unit of the data.') + ks_unit_selection = fields.Selection([ + ('monetary', 'Monetary'), + ('custom', 'Custom'), + ], string="Select Unit Type", help='Select the unit to be assigned to the value. ') + 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""") + # Field for fill temp data + ks_fill_temporal = fields.Boolean('Fill Temporal Value') + # Domain Extension field + ks_domain_extension = fields.Char('Domain Extension', help="Define conditions for filter to write manually") + 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) + ks_radial_legend = fields.Boolean('Show Legend', help="Hide all legend from the chart item", default=True) + ks_data_calculation_type = fields.Selection([('custom', 'Default Query'), + ('query', 'Custom Query')], string="Data Calculation Type", + default="custom", + help='Select the type of calculation you want to perform on the data.') + + # to show the Global / Indian / Exact Number Format + ks_data_format = fields.Selection([ + ('global', 'English Format'), + ('indian', 'Indian Format'), + ('colombian', 'Colombian Peso Format'), + ('exact', 'Exact Value')], + string='Number System', + default='global', + help="To Change the number format showing in chart to given option") + ks_button_color = fields.Char(string="Top Button Color", + default="#000000,0.99") + + + ks_is_client_action = fields.Boolean('Client Action', default=False) + ks_client_action = fields.Many2one('ir.actions.client', + string="Client Item Action", + domain="[('name','!=','App Store'),('name','!=','Updates'),('res_model','not ilike','ks_dashboard_ninja.%'),('name','!=','Discuss')]", + help="This Action will be Performed at the end of Drill Down Action") + ks_pagination_limit = fields.Integer('Pagination Limit', default=15) + + ks_multiplier_lines = fields.One2many('ks_dashboard_item.multiplier', 'ks_dashboard_item_id', + + readonly=False, store=True, + string="Multiplier Lines") + + ks_precision_digits = fields.Integer('Digits', compute="_ks_compute_precision_digits", store=True, readonly=False) + + ks_scatter_measure_x_id = fields.Many2one('ir.model.fields', + domain="[('model_id','=',ks_model_id),('name','!=','id'),('name','!=','sequence')," + "('store','=',True),'|','|'," + "('ttype','=','integer'),('ttype','=','float')," + "('ttype','=','monetary')]", + string="Measure X") + # ks_scatter_ungroup_measure_y_id = fields.Many2one('ir.model.fields', + # domain="[('model_id','=',ks_model_id),('name','!=','id'),('name','!=','sequence')," + # "('store','=',True),'|','|'," + # "('ttype','=','integer'),('ttype','=','float')," + # "('ttype','=','monetary')]", + # string="Measure Y") + ks_is_scatter_group = fields.Boolean(string="Group By") + ks_scatter_measure_y_id = fields.Many2one('ir.model.fields', + domain="[('model_id','=',ks_model_id),('name','!=','id'),('name','!=','sequence')," + "('store','=',True),'|','|'," + "('ttype','=','integer'),('ttype','=','float')," + "('ttype','=','monetary')]", + string="Measure Y") + ks_scatter_field_id = fields.Many2one('ir.model.fields', + domain="[('model_id','=',ks_model_id),('name','!=','id'),('name','!=','sequence')," + "('store','=',True),('ttype','!=','binary')," + "('ttype','!=','many2many'), ('ttype','!=','one2many')]", + string="Scatter Points") + + ks_data_label_type = fields.Selection([('percent', 'Percent'), ('value', 'Value')], string='Show Data Value Type', + help='When "Show Data Value Type" selected this field enables to select label type in percent or value', + default='percent') + ks_as_of_now = fields.Boolean("Data Till Now", + help="Display the total sum of each legends as it grows with times") + ks_radial_preview = fields.Char(string="Radial Preview", default="Radial Preview") + ks_radial_item_color = fields.Selection( + [('default', 'Default'), ('dark', 'Dark'), ('material', 'Material'), ('moonrise', 'Moonrise')], + string="Radial Chart Theme", default="default", help='Select the display preference. ') + ks_map_preview = fields.Char(string="Map Preview", default="Map Preview") + ks_partners_map = fields.Char(compute="_compute_map_partners") + ks_country_id = fields.Many2one('res.country', string="Country") + ks_country_code = fields.Char(related="ks_country_id.code", store=True) + ks_bounds = fields.Char(compute="_compute_bounds", store=True) + + ks_funnel_preview = fields.Char(string="Funnel Preview", default="Funnel Preview") + ks_funnel_record_field = fields.Many2one('ir.model.fields', + domain="[('model_id','=',ks_model_id),('name','!=','id'),('store','=',True),'|'," + "'|',('ttype','=','integer'),('ttype','=','float')," + "('ttype','=','monetary')]", + string="Funnel Record Field") + ks_map_record_field = fields.Many2one('ir.model.fields', + domain="[('model_id','=',ks_model_id),('name','!=','id'),('store','=',True),'|'," + "'|',('ttype','=','integer'),('ttype','=','float')," + "('ttype','=','monetary')]", + string="Map Record Field") + ks_funnel_item_color = fields.Selection( + [('default', 'Default'), ('dark', 'Dark'), ('material', 'Material'), ('moonrise', 'Moonrise')], + string="Funnel Chart Theme", default="default", help='Select the display preference. ') + ks_bullet_preview = fields.Char(string="Bullet Preview", default="Bullet Preview") + ks_flower_view_preview = fields.Char(string="Flower Preview", default="Flower Preview") + ks_flower_item_color = fields.Selection( + [('default', 'Default'), ('dark', 'Dark'), ('material', 'Material'), ('moonrise', 'Moonrise')], + string="Flower Chart Theme", default="default", help='Select the display preference. ') + + upload_excel = fields.Binary(string='Upload Excel File', attachment=False) + ks_csv_field = fields.Binary(string='Upload CSV File', attachment=False) + ks_group_by_lines = fields.One2many('ks.dashboard.group.by', 'ks_dashboard_group_by_id', string="Group By Lines") + ks_csv_group_by_lines = fields.One2many('ks.dashboard.csv.group.by', 'ks_dashboard_csv_group_by_id', string="Group By Lines") + filename = fields.Char(string='Filename') + name_seq = fields.Char(help="Sequential Queue ID", copy=False) + excel_bool = fields.Boolean(string='Excel Bool') + model_bool = fields.Boolean(string='Model Bool') + csv_bool = fields.Boolean(string='CSV Bool') + ks_is_external_db = fields.Boolean() + ks_host = fields.Char() + ks_port = fields.Char() + ks_db_name = fields.Char() + ks_db_password = fields.Char() + ks_db_user = fields.Char() + data_source = fields.Selection( + [('odoo', 'Odoo'), ('excel', 'Excel'), ('csv', 'CSV')], + string="Data Source",default='odoo') + + @api.model + def create_ai_dash(self, data, ks_dash_id, model): + try: + result= [] + for item in data: + ks_measure_field_ids = [] + value = {} + chart_switch = { + 'bar': "ks_bar_chart", + 'pie': 'ks_pie_chart', + 'donut': 'ks_doughnut_chart', + 'area': 'ks_area_chart', + 'line': 'ks_line_chart', + 'polar': 'ks_polarArea_chart', + 'horizontalbar': 'ks_horizontalBar_chart', + 'table': "ks_list_view" + } + if item["chart_type"].lower() in ['bar', 'line', 'pie', 'area', 'donut', 'polar', 'horizontalbar']: + ks_measure_id = self.env['ir.model.fields'].search( + [('name', '=', item["aggregations"][0]["field"]), ('model', '=', model)]) + if ks_measure_id and ks_measure_id['ttype'] in ['integer','float','monetary']: + ks_measure_field_ids.append(ks_measure_id.id) + value["ks_chart_measure_field"] = [(6, 0, ks_measure_field_ids)] + + ks_record_id = self.env['ir.model.fields'].search( + [('name', '=', item["group_by_column"]), ('model', '=', model)]) + if ks_record_id: + value['ks_chart_relation_groupby'] = ks_record_id.id + if ks_record_id['ttype'] == "datetime" or ks_record_id['ttype'] == "date": + value['ks_chart_date_groupby'] = "month" + + value["name"] = item["chart_name"] + + ks_model_id = self.env['ir.model'].search([('model', '=', model)]).id + value['ks_model_id'] = ks_model_id + + if item["aggregations"][0]["type"] == 'avg': + value['ks_chart_data_count_type'] = 'average' + else: + value['ks_chart_data_count_type'] = item["aggregations"][0]["type"] + + value['ks_dashboard_item_type'] = chart_switch.get(item['chart_type'], False) + value['ks_dashboard_ninja_board_id'] = ks_dash_id + if ks_measure_field_ids and ks_record_id and ks_model_id: + try: + ks_result = self.create(value) + result.append(ks_result) + except Exception as e: + result + elif item["chart_type"].lower() == "table": + value["name"] = item["chart_name"] + value['ks_dashboard_ninja_board_id'] = ks_dash_id + value['ks_dashboard_item_type'] = chart_switch.get(item['chart_type'], False) + + ks_model_id = self.env['ir.model'].search([('model', '=', model)]).id + value['ks_model_id'] = ks_model_id + + ks_measure_id = self.env['ir.model.fields'].search( + [('name', '=', item["aggregations"][0]["field"]), ('model', '=', model)]) + if ks_measure_id and ks_measure_id['ttype'] in ['integer','float','monetary']: + ks_measure_field_ids.append(ks_measure_id.id) + value["ks_list_view_group_fields"] = [(6, 0, ks_measure_field_ids)] + # value["ks_list_view_fields"] = [(6, 0, ks_measure_field_ids)] + + ks_record_id = self.env['ir.model.fields'].search( + [('name', '=', item["group_by_column"]), ('model', '=', model)]) + if ks_record_id: + value['ks_chart_relation_groupby'] = ks_record_id.id + if ks_record_id['ttype'] == "datetime" or ks_record_id['ttype'] == "date": + value['ks_chart_date_groupby'] = "month" + value['ks_list_view_type'] = 'grouped' + if ks_measure_field_ids and ks_record_id and ks_model_id: + try: + ks_result = self.create(value) + result.append(ks_result) + except Exception as e: + result + elif item["chart_type"].lower() == "kpi": + value["name"] = item["chart_name"] + value['ks_dashboard_ninja_board_id'] = ks_dash_id + value['ks_dashboard_item_type'] = "ks_kpi" + + ks_model_id = self.env['ir.model'].search([('model', '=', model)]).id + value['ks_model_id'] = ks_model_id + + ks_measure_id = self.env['ir.model.fields'].search( + [('name', '=', item["aggregations"][0]["field"]), ('model', '=', model)]) + if ks_measure_id: + value["ks_record_field"] = ks_measure_id.id + + if item["aggregations"][0]["type"] == 'avg': + value['ks_record_count_type'] = 'average' + else: + value['ks_record_count_type'] = item["aggregations"][0]["type"] + value['ks_background_color'] = "#ffffff,0.99" + value['ks_default_icon_color'] = "#000000,0.99" + value['ks_font_color'] = "#000000,0.99" + value['ks_button_color'] = "#000000,0.99" + + if ks_measure_id and ks_model_id: + try: + ks_result = self.create(value) + result.append(ks_result) + except Exception as e: + result + else: + pass + if len(result): + return "success" + else: + return "Abort" + except: + raise ValidationError(_("Getting invalid response from AI, please try again")) + + + + @api.onchange('ks_chart_relation_groupby', 'ks_model_id','ks_dashboard_item_type') + def add_domain(self): + if self.ks_dashboard_item_type == 'ks_map_view': + return { + 'domain': {'ks_chart_relation_groupby': ['&', '&', '&', '&', '&', '&', ('relation', '=', 'res.partner'), + ('store', '=', True), + ('ttype', '!=', 'many2many'), + ('ttype', '!=', 'one2many'), + ('name', '!=', 'sequence'), + ('name', '!=', 'id'), + ('model_id.name', '=', self.ks_model_id.name) + ]}} + + # Making model, csv and excel field invisible on condition. + @api.onchange('data_source') + def ks_make_invisible(self): + if self.data_source == 'excel': + self.excel_bool = True + self.model_bool = False + self.csv_bool = False + elif self.data_source == 'odoo': + self.model_bool = True + self.excel_bool = False + self.csv_bool = False + elif self.data_source == 'csv': + self.csv_bool = True + self.model_bool = False + self.excel_bool = False + elif not self.data_source: + self.model_bool = False + self.excel_bool = False + self.csv_bool = False + + # Reading the Csv file + @api.onchange('ks_csv_field') + def read_csv(self): + if self.ks_csv_field: + if ' ' in self.filename or '_' in self.filename: + try: + fp = tempfile.NamedTemporaryFile(delete=False, suffix=".csv") + fp.write(binascii.a2b_base64(self.ks_csv_field)) + fp.seek(0) + + with open(fp.name, 'r', encoding='utf-8') as csvfile: + csv_reader = csv.reader(csvfile) + fields = [] + values = {} + header_row = next(csv_reader) + + for row in header_row: + fields.append(row) + values[row] = None + del_group_by_field = """delete from ks_dashboard_csv_new;""" + self._cr.execute(del_group_by_field) + self.env['ks.dashboard.csv.new'].search([]) + for rec in fields: + self.env['ks.dashboard.csv.new'].create({ + 'name': rec, + }) + + for line in csv_reader: + for i, field in enumerate(fields): + values[field] = line[i] + + values = {} + for field in fields: + values[field] = None + + + except: + raise ValidationError(_("Invalid file!")) + else: + raise ValidationError('Please add filename which contain Spaces and Underscore in there name only.') + else: + if self.ks_model_id: + model = self.env['ir.model'].search([('id', '=', self.ks_model_id.id)]) + model.unlink() + if self.ks_csv_group_by_lines: + for rec in self.ks_csv_group_by_lines: + rec.unlink() + + # Reading the Excel file + @api.onchange('upload_excel') + def _read_xls(self): + if self.upload_excel: + if ' ' in self.filename or '_' in self.filename: + try: + fp = tempfile.NamedTemporaryFile(delete=False, suffix=".xlsx") + fp.write(binascii.a2b_base64(self.upload_excel)) + fp.seek(0) + values = {} + workbook = xlrd.open_workbook(fp.name) + sheet = workbook.sheet_by_index(0) + except Exception as e: + raise ValidationError(_(e)) + + for row_no in range(sheet.nrows): + val = {} + if row_no <= 0: + fields = list( + map(lambda row: isinstance(row.value, bytes) and row.value.encode('utf-8') or str(row.value), + sheet.row(row_no))) + del_group_by_field = """delete from ks_dashboard_new;""" + self._cr.execute(del_group_by_field) + self.env['ks.dashboard.new'].search([]) + for rec in fields: + self.env['ks.dashboard.new'].create({ + 'name': rec, + }) + else: + line = list( + map(lambda row: isinstance(row.value, bytes) and row.value.encode('utf-8') or str(row.value), + sheet.row(row_no))) + value = 0 + for field in fields: + while (value < len(line)): + values.update({ + field: line[value], + }) + value = value + 1 + break + else: + raise ValidationError('Please add filename which contain Spaces and Underscore in there name only.') + else: + if self.ks_group_by_lines: + for rec in self.ks_group_by_lines: + rec.unlink() + if self.ks_model_id: + model = self.env['ir.model'].search([('id', '=', self.ks_model_id.id)]) + model.unlink() + + # Syncing the data from table to page + def data_sync(self): + data = self.env['ks.dashboard.new'].search([]) + for rec in data: + self.write({ + 'ks_group_by_lines': [(0, 0, { + 'name': rec.name + })] + }) + + def csv_data_sync(self): + data = self.env['ks.dashboard.csv.new'].search([]) + for rec in data: + self.write({ + 'ks_csv_group_by_lines': [(0, 0, { + 'name': rec.name + })] + }) + + # Creating table in ir model and adding column in it. + def create_table(self): + records = self.ks_group_by_lines + dict = [] + if records: + for rec in records: + values = {} + if not rec.ttype: + raise ValidationError('Please Enter the type under Column Data Type Tab') + values.update({ + 'name': rec.name.lower().replace(' ', '_'), + 'type': rec.ttype + }) + dict.append(values) + if '_' and '-' in self.filename: + split = self.filename.lower().split('_') + split_value = '' + for res in split: + split_value += res + final_split = split_value.split('-') + elif' ' in self.filename: + final_split = self.filename.lower().split(' ') + elif'_' in self.filename: + final_split = self.filename.lower().split('_') + else: + final_split = self.filename.lower().split('.') + tablemodel = ('x_'+final_split[0]+'_'+self.name_seq).replace(' ','') + tablename = final_split[0]+' '+self.name_seq + model_creation = self.env['ir.model'].sudo().create({ + 'name': tablename, + 'model': tablemodel, + 'order': 'x_name asc, id desc', # valid order + }) + for value in dict: + column_name = value.get('name') + column_type = value.get('type') + if '/' in column_name: + column_name = value.get('name').replace('/', '_') + if ' ' in column_name: + column_name = value.get('name').replace(' ', '_') + if '(' and ')' in column_name: + column_name = value.get('name').replace(')', '').replace('(', '') + if column_name == 'name': + column_name = column_name.replace('name', 'name1') + model_creation.write({ + 'field_id': [(0, 0, { + 'name': 'x_'+column_name, + 'ttype': column_type, + 'field_description': column_name.replace('_', ' ') + })] + }) + self.env['ir.model.access'].sudo().create({ + 'name': model_creation.name + ' all_user', + 'model_id': model_creation.id, + 'perm_read': True, + 'perm_write': False, + 'perm_create': False, + 'perm_unlink': False, + }) + self.ks_model_id = model_creation.id + self.insert_data_into_table(tablemodel) + + # Inserting data into the ir model table. + def insert_data_into_table(self, tablemodel): + if self.upload_excel: + try: + fp = tempfile.NamedTemporaryFile(delete=False, suffix=".xlsx") + fp.write(binascii.a2b_base64(self.upload_excel)) + fp.seek(0) + values = {} + workbook = xlrd.open_workbook(fp.name) + sheet = workbook.sheet_by_index(0) + except: + raise ValidationError(_("Invalid file!")) + for row_no in range(sheet.nrows): + val = {} + if row_no <= 0: + fields = list( + map(lambda row: isinstance(row.value, bytes) and row.value.encode('utf-8') or str(row.value), + sheet.row(row_no))) + else: + line = list( + map(lambda row: isinstance(row.value, bytes) and row.value.encode('utf-8') or str(row.value), + sheet.row(row_no))) + value = 0 + for field in fields: + if '/' in field: + field = field.replace('/', ' ') + if ' ' in field: + field = field.replace(' ', '_') + if '(' and ')' in field: + field = field.replace(')', '').replace('(', '') + if field == 'Name': + field = field.replace('Name', 'name1') + if 'Date' in field or 'Deadline' in field or self.ks_group_by_lines[value].ttype in ['datetime','date']: + if line[value]: + if self.ks_group_by_lines[value].ttype in['datetime','date']: + final_date = pd.to_timedelta(float(line[value]), unit='D') + pd.to_datetime('1899-12-30') + while (value < len(line)): + values.update({ + field: final_date, + }) + value = value + 1 + break + else: + while (value < len(line)): + values.update({ + field: line[value], + }) + value = value + 1 + break + else: + while (value < len(line)): + values.update({ + field: 'Null', + }) + value = value + 1 + break + else: + while (value < len(line)): + if line[value]: + if '.' in line[value]: + if ',' in line[value]: + if self.ks_group_by_lines[value].ttype == 'char': + split = line[value].split(',') + split_value = '' + for res in split: + split_value += res + final_split = split_value.split('.') + final_split_value = '' + for final_res in final_split: + final_split_value += final_res + values.update({ + field: final_split_value, + }) + else: + split = line[value].split(',') + split_value = split[0] + split[1] + final_value = float(split_value) + values.update({ + field: final_value, + }) + elif '@' in line[value]: + values.update({ + field: line[value], + }) + else: + # final_value = (line[value]) + if self.ks_group_by_lines[value].ttype == 'integer': + try: + values.update({ + field: int(float(line[value])), + }) + except: + values.update({ + field: 0, + }) + + elif self.ks_group_by_lines[value].ttype == 'float': + try: + values.update({ + field: float(line[value]), + }) + except: + values.update({ + field: 0.00 + }) + + else: + values.update({ + field: line[value], + }) + elif "'" and '+' in line[value]: + split_value = line[value].split('+') + final_split = '+' + split_value[1] + values.update({ + field: final_split, + }) + elif "'" in line[value]: + split_value = line[value].split("'") + final_split_value = '' + for res in split_value: + final_split_value += res + values.update({ + field: final_split_value, + }) + elif self.ks_group_by_lines[value].ttype == 'integer': + try: + values.update({ + field: int(float(line[value])), + }) + except: + values.update({ + field: 0, + }) + elif self.ks_group_by_lines[value].ttype == 'float': + try: + values.update({ + field: float(line[value]), + }) + except: + values.update({ + field: 0.00, + }) + else: + values.update({ + field: line[value], + }) + value = value + 1 + break + else: + values.update({ + field: 'Null', + }) + value = value + 1 + break + final_values = [] + final_heading = [] + try: + if values.keys(): + data_values = dict([('x_' + key.lower().replace(' ', '_'), values[key]) for key in values if + values[key] != 'Null']) + self.env[tablemodel].sudo().create(data_values) + except Exception as e: + raise ValidationError("found error while Table creation {}".format(e)) + + def csv_create_table(self): + records = self.ks_csv_group_by_lines + dict = [] + if records: + for rec in records: + values = {} + if not rec.ttype: + raise ValidationError('Please Enter the type under Column Data Type Tab') + values.update({ + 'name': rec.name.lower().replace(' ', '_'), + 'type': rec.ttype + }) + dict.append(values) + if '_' and '-' in self.filename: + split = self.filename.lower().split('_') + split_value = '' + for res in split: + split_value += res + final_split = split_value.split('-') + elif ' ' in self.filename: + final_split = self.filename.lower().split(' ') + elif '_' in self.filename: + final_split = self.filename.lower().split('_') + else: + final_split = self.filename.lower().split('.') + tablemodel = 'x_'+final_split[0]+'_'+self.name_seq.replace(' ','') + tablename = final_split[0]+' '+self.name_seq + model_creation = self.env['ir.model'].sudo().create({ + 'name': tablename, + 'model': tablemodel, + 'order': 'x_name asc, id desc', # valid order + }) + for value in dict: + column_name = value.get('name') + column_type = value.get('type') + if '/' in column_name: + column_name = value.get('name').replace('/', '_') + if ' ' in column_name: + column_name = value.get('name').replace(' ', '_') + if '(' and ')' in column_name: + column_name = value.get('name').replace(')', '').replace('(', '') + if column_name == 'name': + column_name = column_name.replace('name', 'name1') + model_creation.write({ + 'field_id': [(0, 0, { + 'name': 'x_'+column_name, + 'ttype': column_type, + 'field_description': column_name.replace('_', ' ') + })] + }) + self.env['ir.model.access'].sudo().create({ + 'name': model_creation.name + ' all_user', + 'model_id': model_creation.id, + 'perm_read': True, + 'perm_write': False, + 'perm_create': False, + 'perm_unlink': False, + }) + self.ks_model_id = model_creation.id + self.insert_data_into_csv_table(tablemodel) + + def insert_data_into_csv_table(self, tablemodel): + if self.ks_csv_field: + fp = tempfile.NamedTemporaryFile(delete=False, suffix=".csv") + fp.write(binascii.a2b_base64(self.ks_csv_field)) + fp.seek(0) + + with open(fp.name, 'r', encoding='utf-8') as csvfile: + csv_reader = csv.reader(csvfile) + fields = [] + values = {} + field_values = {} + header_row = next(csv_reader) + for row in header_row: + fields.append(row) + field_values[row] = None + for line in csv_reader: + value = 0 + for field in fields: + if ' ' in field: + field = field.replace(' ', '_') + if '/' in field: + field = field.replace('/', ' ') + if '(' and ')' in field: + field = field.replace(')', '').replace('(', '') + if field == 'Name': + field = field.replace('Name', 'name1') + if 'Date' in field or 'Deadline' in field or self.ks_csv_group_by_lines[value].ttype in ['datetime','date']: + if line[value]: + if self.ks_csv_group_by_lines[value].ttype == 'datetime': + final_date = line[value].split(' ')[0] + while (value < len(line)): + values.update({ + field: final_date, + }) + value = value + 1 + break + else: + try: + while (value < len(line)): + values.update({ + field: line[value], + }) + value = value + 1 + break + except: + while (value < len(line)): + values.update({ + field: 'Null', + }) + value = value + 1 + break + + else: + while (value < len(line)): + values.update({ + field: 'Null', + }) + value = value + 1 + break + else: + while (value < len(line)): + if line[value]: + if '$' in line[value]: + line[value] = line[value].replace('$', '') + if '-' in line[value]: + line[value] = line[value].replace('-', '') + if '(' and ')' in line[value]: + line[value] = line[value].replace(')', '').replace('(', '') + if '.' in line[value]: + if ',' in line[value]: + if self.ks_csv_group_by_lines[value].ttype == 'char': + split = line[value].split(',') + split_value = '' + for res in split: + split_value += res + final_split = split_value.split('.') + final_split_value = '' + for final_res in final_split: + final_split_value += final_res + values.update({ + field: final_split_value, + }) + else: + split = line[value].split(',') + split_value = split[0] + split[1] + if self.ks_csv_group_by_lines[value].ttype == 'float': + try: + values.update({ + field: float(split_value), + }) + except: + values.update({ + field: 0.00, + }) + + elif self.ks_csv_group_by_lines[value].ttype == 'integer': + try: + values.update({ + field: int(float(split_value)), + }) + except: + values.update({ + field: 0, + }) + + else: + values.update({ + field: split_value, + }) + elif '@' in line[value]: + values.update({ + field: line[value], + }) + else: + if self.ks_csv_group_by_lines[value].ttype == 'float': + try: + values.update({ + field: float(line[value]), + }) + except: + values.update({ + field:0.00, + }) + elif self.ks_csv_group_by_lines[value].ttype == 'integer': + try: + values.update({ + field: int(float(line[value])), + }) + except: + values.update({ + field: 0, + }) + else: + values.update({ + field: line[value], + }) + elif "'" and '+' in line[value]: + split_value = line[value].split('+') + final_split = '+' + split_value[1] + values.update({ + field: final_split, + }) + elif "'" in line[value]: + split_value = line[value].split("'") + final_split_value = '' + for res in split_value: + final_split_value += res + values.update({ + field: final_split_value, + }) + elif line[value] == ' ': + values.update({ + field: 'Null', + }) + value = value + 1 + break + elif self.ks_csv_group_by_lines[value].ttype == 'integer': + try: + values.update({ + field: int(float(line[value])), + }) + except: + values.update({ + field: 0, + }) + elif self.ks_csv_group_by_lines[value].ttype == 'float': + try: + values.update({ + field: float(line[value]), + }) + except: + values.update({ + field: 0.00, + }) + else: + values.update({ + field: line[value], + }) + value = value + 1 + break + else: + values.update({ + field: 'Null', + }) + value = value + 1 + break + final_values = [] + final_heading = [] + try: + if values.keys(): + data_values = dict([('x_' + key.lower().replace(' ', '_'), values[key]) for key in values if + values[key] != 'Null']) + self.env[tablemodel].sudo().create(data_values) + except Exception as e: + raise ValidationError("found error while Table creation error {}".format(e)) + + def check_target(self): + base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url') + sales_target = self.env['ks_dashboard_ninja.item'].search([ + ('ks_dashboard_item_type', '=', 'ks_kpi'), + ('ks_send_mail', '=', True), + ('ks_stop_mail_cron', '=' , False) + ]) + menu_record = self.env.ref('ks_dashboard_ninja.board_menu_root') + menu_id_1 = menu_record.id + recipient_emails = [] + email_from = self.env['res.company'].search([], limit=1) + for res in sales_target: + if res.ks_record_count >= res.ks_standard_goal_value: + dashboard_id = res.ks_dashboard_ninja_board_id.id + action_id = res.ks_dashboard_ninja_board_id.ks_dashboard_menu_id.action.id if res.ks_dashboard_ninja_board_id.ks_dashboard_menu_id.action and res.ks_dashboard_ninja_board_id.ks_dashboard_menu_id.action.id else menu_record.action.id + for partner in res.ks_email_to_ids: + recipient_emails.append(partner.name) + kpi_mail = self.env['mail.mail'].create({ + 'body_html': 'Congratulations! The Target of '+ str(res.ks_standard_goal_value) +' for '+ res.name +' is achieved!!
' + f"Click here to check the dashboard: " + f"Dashboard Link
", + 'subject' : 'Commendable Achievement: Meeting and Exceeding Sales Targets', + 'email_from' : email_from.email, + 'email_to': ','.join(recipient_emails), + }) + kpi_mail.sudo().send() + res.ks_stop_mail_cron = True + recipient_emails = [] + + def write(self, vals): + if vals.get('ks_standard_goal_value') or vals.get('ks_record_count_type'): + self.ks_stop_mail_cron = False + return super(KsDashboardNinjaItems, self).write(vals) + + + @api.onchange('ks_year_period', 'ks_year_period_2') + def ks_year_neg_val_not_allow(self): + for rec in self: + if rec.ks_year_period < 0 or rec.ks_year_period_2 < 0 : + raise ValidationError(_(" Negative periods are not allowed ")) + + @api.onchange('ks_item_start_date', 'ks_item_end_date') + def ks_item_date_validation(self): + for rec in self: + if rec.ks_item_start_date and rec.ks_item_end_date: + if rec.ks_item_start_date > rec.ks_item_end_date: + raise ValidationError(_('Start date must be less than end date')) + + @api.onchange('ks_item_start_date_2', 'ks_item_end_date_2') + def ks_item_date_validation_2(self): + for rec in self: + if rec.ks_item_start_date_2 and rec.ks_item_end_date_2: + if rec.ks_item_start_date_2 > rec.ks_item_end_date_2: + raise ValidationError(_('Start date must be less than end date')) + + @api.depends('ks_dashboard_item_type') + def _ks_compute_precision_digits(self): + for rec in self: + try: + precision_digits = self.sudo().env.ref('ks_dashboard_ninja.ks_dashboard_ninja_precision') + ks_precision_digits = precision_digits.digits + if ks_precision_digits < 0: + ks_precision_digits = 2 + if ks_precision_digits > 100: + ks_precision_digits = 2 + + rec.ks_precision_digits = ks_precision_digits + except Exception as E: + rec.ks_precision_digits = 2 + # default = lambda self: self.sudo().env.ref('ks_dashboard_ninja.ks_dashboard_ninja_precision') + + @api.onchange('ks_multiplier_active', 'ks_chart_measure_field', + 'ks_chart_measure_field_2' ,'ks_list_view_group_fields') + def _ks_compute_multiplier_lines(self): + for rec in self: + rec.ks_multiplier_lines = [(5, 0, 0)] + ks_chart_measure_fields = rec.ks_chart_measure_field + if rec.ks_multiplier_active: + if rec.ks_dashboard_item_type == 'ks_list_view' and rec.ks_list_view_type == 'grouped': + ks_chart_measure_fields = rec.ks_list_view_group_fields + ks_temp_list = [] + ks_chart_measure_id = [] + for ks_chart_measure_field in ks_chart_measure_fields: + ks_dict = { + 'ks_dashboard_item_id': rec.id, + 'ks_multiplier_fields': ks_chart_measure_field.ids[0], + 'ks_multiplier_value': 1 + } + ks_chart_measure_id.append(ks_chart_measure_field.ids[0]) + ks_line = self.env['ks_dashboard_item.multiplier'].create(ks_dict) + ks_temp_list.append(ks_line.id) + + if rec.ks_chart_measure_field_2: + for ks_chart_measure_field in rec.ks_chart_measure_field_2: + if ks_chart_measure_field.ids[0] not in ks_chart_measure_id: + ks_dict = { + 'ks_dashboard_item_id': rec.id, + 'ks_multiplier_fields': ks_chart_measure_field.ids[0], + 'ks_multiplier_value': 1 + } + ks_line = self.env['ks_dashboard_item.multiplier'].create(ks_dict) + ks_temp_list.append(ks_line.id) + # rec.ks_multiplier_lines = [(6, 0, [])] + # rec.ks_multiplier_lines = [(6, 0, ks_temp_list)] + rec.ks_multiplier_lines = [(6, 0, [])] + rec.ks_multiplier_lines = [(6, 0, ks_temp_list)] + + if len(rec.ks_chart_measure_field) == 0: + rec.ks_chart_cumulative_field = False + + + + + + @api.onchange('ks_list_view_type') + def _ks_onchange_ks_list_view_type(self): + for rec in self: + if rec.ks_list_view_type == 'ungrouped': + rec.ks_multiplier_active = False + + @api.onchange('ks_data_calculation_type') + def _ks_onchange_ks_data_calculation_type(self): + for rec in self: + if rec.ks_data_calculation_type == 'query': + rec.ks_list_view_type = 'ungrouped' + rec.ks_multiplier_active = False + + @api.onchange('ks_goal_lines') + def ks_is_goal_lines(self): + for rec in self: + if rec.ks_goal_enable and rec.ks_goal_lines: + rec.ks_pagination_limit = 0 + elif rec.ks_goal_enable and not rec.ks_goal_lines: + rec.ks_pagination_limit = 15 + + + @api.onchange('ks_goal_enable') + def ks_is_goal_enable(self): + for rec in self: + if not rec.ks_goal_enable : + rec.ks_goal_lines = False + rec.ks_pagination_limit = 15 + elif rec.ks_goal_enable and not rec.ks_goal_lines: + rec.ks_pagination_limit = 15 + + + @api.onchange('ks_pagination_limit') + def ks_on_negativ_limit(self): + for rec in self: + if rec.ks_pagination_limit > 0: + rec.ks_pagination_limit = rec.ks_pagination_limit + elif not rec.ks_goal_lines and rec.ks_pagination_limit <= 0: + raise ValidationError(_("Pagination limit value cannot be Negative or Zero")) + if rec.ks_goal_lines and rec.ks_pagination_limit > 0 or rec.ks_pagination_limit < 0: + raise ValidationError(_("if target lines is selected then cannot be set pagination value")) + + @api.onchange('ks_is_client_action') + def ks_on_change_item_action_to_client(self): + for rec in self: + if rec.ks_is_client_action: + rec.ks_actions = False + + @api.onchange('ks_record_data_limit_visibility') + def ks_on_change_record_data_visibility(self): + for rec in self: + if not rec.ks_record_data_limit_visibility: + rec.ks_record_data_limit = 0 + + + + @api.onchange('ks_fill_temporal') + def ks_onchange_fill_temporal(self): + if self.ks_fill_temporal: + self.ks_sort_by_field = self.ks_chart_relation_groupby.id + self.ks_sort_by_order = 'ASC' + else: + self.ks_sort_by_field = False + self.ks_sort_by_order = False + + @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.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_lines: + raise ValidationError(_( + "Cannot set aggregation having Date time (Hour, Minute) when target lines per date are being used." + " To proceed this, first delete target lines")) + 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)) + if rec.ks_chart_relation_sub_groupby.ttype == 'date' and rec.ks_chart_date_sub_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_sub_groupby)) + + 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] + if 'ks_multiplier_lines' not in default: + default['ks_multiplier_lines'] = [(0, 0, line.copy_data()[0]) for line in self.ks_multiplier_lines] + ks_many2many_field_ordering = self.ks_many2many_field_ordering + ks_list_view_group_fields = [] + ks_list_view_fields = [] + ks_chart_measure_field = [] + ks_chart_measure_field_2 = [] + if ks_many2many_field_ordering: + ks_many2many_field_ordering = json.loads(ks_many2many_field_ordering) + ks_list_view_group_fields = ks_many2many_field_ordering.get('ks_list_view_group_fields', False) + ks_list_view_fields = ks_many2many_field_ordering.get('ks_list_view_fields', False) + ks_chart_measure_field = ks_many2many_field_ordering.get('ks_chart_measure_field', False) + ks_chart_measure_field_2 = ks_many2many_field_ordering.get('ks_chart_measure_field_2', False) + if 'ks_list_view_group_fields' not in default: + default['ks_list_view_group_fields'] = ks_list_view_group_fields + if 'ks_list_view_fields' not in default: + default['ks_list_view_fields'] = ks_list_view_fields + if 'ks_chart_measure_field' not in default: + default['ks_chart_measure_field'] = ks_chart_measure_field + if 'ks_chart_measure_field_2' not in default: + default['ks_chart_measure_field_2'] = ks_chart_measure_field_2 + return super(KsDashboardNinjaItems, self).copy_data(default) + + def copy(self, default=None): + default = default or {} + res = super(KsDashboardNinjaItems, self).copy(default) + + if self.ks_dn_header_lines: + for line in self.ks_dn_header_lines: + ks_line = {} + ks_line['ks_to_do_header'] = line.ks_to_do_header + ks_line['ks_dn_item_id'] = res.id + ks_dn_header_id = self.env['ks_to.do.headers'].create(ks_line) + if line.ks_to_do_description_lines: + for ks_task in line.ks_to_do_description_lines: + ks_task_line = { + 'ks_to_do_header_id': ks_dn_header_id.id, + 'ks_description': ks_task.ks_description, + 'ks_active': ks_task.ks_active + } + + self.env['ks_to.do.description'].create(ks_task_line) + return res + + 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.model_create_multi + def create(self, values): + """ Override to save list view fields ordering """ + for i in range(len(values)): + if not values[i].get('ks_many2many_field_ordering', False): + ks_list_view_group_fields_name = [] + ks_list_view_fields_name = [] + ks_chart_measure_field_name = [] + ks_chart_measure_field_2_name = [] + if values[i].get('ks_list_view_group_fields', False) and len(values[i]['ks_list_view_group_fields'][0][2]) > 0: + for measure in values[i]['ks_list_view_group_fields'][0][2]: + ks_measure_id = self.env['ir.model.fields'].search( + [('id', '=', measure)]) + ks_list_view_group_fields_name.append(ks_measure_id.name) + if values[i].get('ks_list_view_fields', False) and len(values[i]['ks_list_view_fields'][0][2]) > 0: + for measure in values[i]['ks_list_view_fields'][0][2]: + ks_measure_id = self.env['ir.model.fields'].search( + [('id', '=', measure)]) + ks_list_view_fields_name.append(ks_measure_id.name) + if values[i].get('ks_chart_measure_field', False) and len(values[i]['ks_chart_measure_field'][0][2]) > 0: + for measure in values[i]['ks_chart_measure_field'][0][2]: + ks_measure_id = self.env['ir.model.fields'].search( + [('id', '=', measure)]) + ks_chart_measure_field_name.append(ks_measure_id.name) + if values[i].get('ks_chart_measure_field_2', False) and len(values[i]['ks_chart_measure_field_2'][0][2]) > 0: + for measure in values[i]['ks_chart_measure_field_2'][0][2]: + ks_measure_id = self.env['ir.model.fields'].search( + [('id', '=', measure)]) + ks_chart_measure_field_2_name.append(ks_measure_id.name) + ks_many2many_field_ordering = { + 'ks_list_view_fields': values[i]['ks_list_view_fields'][0][2] if values[i].get('ks_list_view_fields', False) else [], + 'ks_list_view_fields_name': ks_list_view_fields_name, + 'ks_list_view_group_fields': values[i]['ks_list_view_group_fields'][0][2] if values[i].get('ks_list_view_group_fields', False) else [], + 'ks_list_view_group_fields_name': ks_list_view_group_fields_name , + 'ks_chart_measure_field': values[i]['ks_chart_measure_field'][0][2] if values[i].get('ks_chart_measure_field', False) else [], + 'ks_chart_measure_field_name': ks_chart_measure_field_name, + 'ks_chart_measure_field_2': values[i]['ks_chart_measure_field_2'][0][2] if values[i].get('ks_chart_measure_field_2', False) else [], + 'ks_chart_measure_field_2_name': ks_chart_measure_field_2_name, + } + values[i]['ks_many2many_field_ordering'] = json.dumps(ks_many2many_field_ordering) + seq = self.env['ir.sequence'].next_by_code('ks_dashboard_ninja.item') or 'New' + values[0]['name_seq'] = seq + return super(KsDashboardNinjaItems, self).create( + values) + + @api.onchange('ks_list_view_fields') + def ks_list_view_fields_onchange(self): + ks_many2many_field_ordering = {} + for rec in self: + if rec.ks_many2many_field_ordering: + ks_many2many_field_ordering = json.loads(rec.ks_many2many_field_ordering) + ks_many2many_field_ordering['ks_list_view_fields'] = rec.ks_list_view_fields.ids + ks_many2many_field_ordering['ks_list_view_fields_name'] = [x.name for x in rec.ks_list_view_fields] + + rec.ks_many2many_field_ordering = json.dumps(ks_many2many_field_ordering) + + @api.onchange('ks_list_view_group_fields') + def ks_list_view_group_fields_onchange(self): + ks_many2many_field_ordering = {} + for rec in self: + if rec.ks_many2many_field_ordering: + ks_many2many_field_ordering = json.loads(rec.ks_many2many_field_ordering) + ks_many2many_field_ordering['ks_list_view_group_fields'] = rec.ks_list_view_group_fields.ids + ks_many2many_field_ordering['ks_list_view_group_fields_name'] = [x.name for x in rec.ks_list_view_group_fields] + rec.ks_many2many_field_ordering = json.dumps(ks_many2many_field_ordering) + + @api.onchange('ks_chart_measure_field') + def ks_chart_measure_field_onchange(self): + for rec in self: + ks_many2many_field_ordering = {} + if rec.ks_many2many_field_ordering: + ks_many2many_field_ordering = json.loads(rec.ks_many2many_field_ordering) + ks_many2many_field_ordering['ks_chart_measure_field'] = rec.ks_chart_measure_field.ids + ks_many2many_field_ordering['ks_chart_measure_field_name'] = [x.name for x in + rec.ks_chart_measure_field] + rec.ks_many2many_field_ordering = json.dumps(ks_many2many_field_ordering) + + @api.onchange('ks_chart_measure_field_2') + def ks_chart_measure_field_2_onchange(self): + ks_many2many_field_ordering = {} + for rec in self: + if rec.ks_many2many_field_ordering: + ks_many2many_field_ordering = json.loads(rec.ks_many2many_field_ordering) + ks_many2many_field_ordering['ks_chart_measure_field_2'] = rec.ks_chart_measure_field_2.ids + ks_many2many_field_ordering['ks_chart_measure_field_2_name'] = [x.name for x in + rec.ks_chart_measure_field_2] + rec.ks_many2many_field_ordering = json.dumps(ks_many2many_field_ordering) + + + + @api.onchange('ks_layout','ks_dashboard_item_theme') + def layout_four_font_change(self): + if self.ks_dashboard_item_theme != "white": + if self.ks_layout == 'layout4' and self.ks_dashboard_item_theme in ['red','blue','yellow','green']: + self.ks_font_color = self.ks_background_color + self.ks_default_icon_color = "#ffffff,0.99" + elif self.ks_layout == 'layout4' and self.ks_dashboard_item_theme not in ['red','blue','yellow','green']: + self.ks_font_color = '#000000,0.99' + if self.ks_background_color=="#000000,0.99": + self.ks_default_icon_color="#ffffff,0.99" + else: + self.ks_default_icon_color = "#000000,0.99" + elif self.ks_layout != 'layout4' and self.ks_dashboard_item_theme not in ['red', 'blue', 'yellow', 'green']: + self.ks_font_color = "#000000,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 = "#000000,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 = "#000000,0.99" + self.ks_default_icon_color = "#000000,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_funnel_record_field = False + rec.ks_map_record_field = False + 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 + rec.ks_scatter_measure_x_id = False + rec.ks_scatter_measure_y_id = 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" + self.ks_button_color = "#000000,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" + self.ks_button_color = "#000000,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" + self.ks_button_color = "#000000,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" + self.ks_button_color = "#000000,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" + self.ks_button_color = "#000000,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" + self.ks_button_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.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_data_format') + def ks_get_record_count(self): + for rec in self: + rec.ks_record_count = rec._ksGetRecordCount(domain=[]) + + def _ksGetRecordCount(self, domain=[]): + rec = self + if rec.ks_record_count_type == 'count' or rec.ks_dashboard_item_type == 'ks_list_view': + ks_record_count = rec.ks_fetch_model_data(rec.ks_model_name, rec.ks_domain, 'search_count', rec, domain) + 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, + domain) + 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)): + 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 + return ks_record_count + + # Writing separate function to fetch dashboard item data + def ks_fetch_model_data(self, ks_model_name, ks_domain, ks_func, rec, domain=[]): + data = 0 + try: + if ks_domain and ks_domain != '[]' and ks_model_name: + proper_domain = self.ks_convert_into_proper_domain(ks_domain, rec, domain) + 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.name], [], lazy=False) + 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, domain) + 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.name], [], lazy=False) + else: + return [] + except Exception as e: + return 0 + return data + + def ks_convert_into_proper_domain(self, ks_domain, rec, domain=[]): + 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.company.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) + ks_is_def_custom_filter = self._context.get('ksIsDefultCustomDateFilter', False) + ks_timezone = self._context.get('tz') or self.env.user.tz + if selected_start_date and selected_end_date and rec.ks_date_filter_field.ttype == 'datetime' and not ks_is_def_custom_filter: + selected_start_date = ks_convert_into_utc(selected_start_date, ks_timezone) + selected_end_date = ks_convert_into_utc(selected_end_date, ks_timezone) + if selected_start_date and selected_end_date and rec.ks_date_filter_field.ttype == 'date' and ks_is_def_custom_filter: + selected_start_date = ks_convert_into_local(selected_start_date, ks_timezone) + selected_end_date = ks_convert_into_local(selected_end_date, ks_timezone) + + if self._context.get('ksDateFilterSelection', False) and self._context['ksDateFilterSelection'] not in [ + 'l_none', 'l_custom']: + ks_date_data = ks_get_date(self._context.get('ksDateFilterSelection'), self, + rec.ks_date_filter_field.ttype) + selected_start_date = ks_date_data["selected_start_date"] + selected_end_date = ks_date_data["selected_end_date"] + + 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, rec.ks_date_filter_field.ttype) + selected_start_date = ks_date_data["selected_start_date"] + selected_end_date = ks_date_data["selected_end_date"] + else: + selected_start_date = False + selected_end_date = False + if rec.ks_item_start_date or rec.ks_item_end_date: + selected_start_date = rec.ks_item_start_date + selected_end_date = rec.ks_item_end_date + if rec.ks_date_filter_field.ttype == 'date' and rec.ks_item_start_date and rec.ks_item_end_date: + ks_timezone = self._context.get('tz') or self.env.user.tz + selected_start_date = ks_convert_into_local(rec.ks_item_start_date, ks_timezone) + selected_end_date = ks_convert_into_local(rec.ks_item_end_date, ks_timezone) + + if selected_start_date and selected_end_date: + if rec.ks_compare_period: + 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 + if rec.ks_date_filter_field.ttype == "date" and rec.ks_date_filter_selection == 'l_day': + selected_end_date = selected_end_date + timedelta(days=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_date_filter_field.ttype == "date" and rec.ks_date_filter_selection == 'l_day': + selected_start_date = selected_end_date - timedelta(days=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) + selected_end_date = fields.datetime.strftime(selected_end_date, DEFAULT_SERVER_DATETIME_FORMAT) + 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) + 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) + 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) + if domain: + proper_domain.extend(domain) + + 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 "%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.company.id)) + if "%MYCOMPANY" in ks_extensiom_domain: + ks_extensiom_domain = ks_extensiom_domain.replace("'%MYCOMPANY'", str(self.env.company.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.company.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 :[['\n * \tThe destination magnification factor can also be specified when goto is a page number or a named destination. (see documentation below)\n * (set magFactor in options). XYZ is the default.\n *
\n *\n * Links, Text, Popup, and FreeText are supported.\n *
\n *\n * Options In PDF spec Not Implemented Yet\n *
If pageNumber is specified, top and zoom may also be specified
\n * @name link\n * @function\n * @param {number} x\n * @param {number} y\n * @param {number} w\n * @param {number} h\n * @param {Object} options\n */\n jsPDFAPI.link = function(x, y, w, h, options) {\n var pageInfo = this.internal.getCurrentPageInfo();\n var getHorizontalCoordinateString = this.internal.getCoordinateString;\n var getVerticalCoordinateString = this.internal.getVerticalCoordinateString;\n\n pageInfo.pageContext.annotations.push({\n finalBounds: {\n x: getHorizontalCoordinateString(x),\n y: getVerticalCoordinateString(y),\n w: getHorizontalCoordinateString(x + w),\n h: getVerticalCoordinateString(y + h)\n },\n options: options,\n type: \"link\"\n });\n };\n\n /**\n * Currently only supports single line text.\n * Returns the width of the text/link\n *\n * @name textWithLink\n * @function\n * @param {string} text\n * @param {number} x\n * @param {number} y\n * @param {Object} options\n * @returns {number} width the width of the text/link\n */\n jsPDFAPI.textWithLink = function(text, x, y, options) {\n var totalLineWidth = this.getTextWidth(text);\n var lineHeight = this.internal.getLineHeight() / this.internal.scaleFactor;\n var linkHeight, linkWidth;\n\n // Checking if maxWidth option is passed to determine lineWidth and number of lines for each line\n if (options.maxWidth !== undefined) {\n var { maxWidth } = options;\n linkWidth = maxWidth;\n var numOfLines = this.splitTextToSize(text, linkWidth).length;\n linkHeight = Math.ceil(lineHeight * numOfLines);\n } else {\n linkWidth = totalLineWidth;\n linkHeight = lineHeight;\n }\n\n this.text(text, x, y, options);\n\n //TODO We really need the text baseline height to do this correctly.\n // Or ability to draw text on top, bottom, center, or baseline.\n y += lineHeight * 0.2;\n //handle x position based on the align option\n if (options.align === \"center\") {\n x = x - totalLineWidth / 2; //since starting from center move the x position by half of text width\n }\n if (options.align === \"right\") {\n x = x - totalLineWidth;\n }\n this.link(x, y - lineHeight, linkWidth, linkHeight, options);\n return totalLineWidth;\n };\n\n //TODO move into external library\n /**\n * @name getTextWidth\n * @function\n * @param {string} text\n * @returns {number} txtWidth\n */\n jsPDFAPI.getTextWidth = function(text) {\n var fontSize = this.internal.getFontSize();\n var txtWidth =\n (this.getStringUnitWidth(text) * fontSize) / this.internal.scaleFactor;\n return txtWidth;\n };\n\n return this;\n})(jsPDF.API);\n","/**\n * @license\n * Copyright (c) 2017 Aras Abbasi\n *\n * Licensed under the MIT License.\n * http://opensource.org/licenses/mit-license\n */\n\nimport { jsPDF } from \"../jspdf.js\";\n\n/**\n * jsPDF arabic parser PlugIn\n *\n * @name arabic\n * @module\n */\n(function(jsPDFAPI) {\n \"use strict\";\n\n /**\n * Arabic shape substitutions: char code => (isolated, final, initial, medial).\n * Arabic Substition A\n */\n var arabicSubstitionA = {\n 0x0621: [0xfe80], // ARABIC LETTER HAMZA\n 0x0622: [0xfe81, 0xfe82], // ARABIC LETTER ALEF WITH MADDA ABOVE\n 0x0623: [0xfe83, 0xfe84], // ARABIC LETTER ALEF WITH HAMZA ABOVE\n 0x0624: [0xfe85, 0xfe86], // ARABIC LETTER WAW WITH HAMZA ABOVE\n 0x0625: [0xfe87, 0xfe88], // ARABIC LETTER ALEF WITH HAMZA BELOW\n 0x0626: [0xfe89, 0xfe8a, 0xfe8b, 0xfe8c], // ARABIC LETTER YEH WITH HAMZA ABOVE\n 0x0627: [0xfe8d, 0xfe8e], // ARABIC LETTER ALEF\n 0x0628: [0xfe8f, 0xfe90, 0xfe91, 0xfe92], // ARABIC LETTER BEH\n 0x0629: [0xfe93, 0xfe94], // ARABIC LETTER TEH MARBUTA\n 0x062a: [0xfe95, 0xfe96, 0xfe97, 0xfe98], // ARABIC LETTER TEH\n 0x062b: [0xfe99, 0xfe9a, 0xfe9b, 0xfe9c], // ARABIC LETTER THEH\n 0x062c: [0xfe9d, 0xfe9e, 0xfe9f, 0xfea0], // ARABIC LETTER JEEM\n 0x062d: [0xfea1, 0xfea2, 0xfea3, 0xfea4], // ARABIC LETTER HAH\n 0x062e: [0xfea5, 0xfea6, 0xfea7, 0xfea8], // ARABIC LETTER KHAH\n 0x062f: [0xfea9, 0xfeaa], // ARABIC LETTER DAL\n 0x0630: [0xfeab, 0xfeac], // ARABIC LETTER THAL\n 0x0631: [0xfead, 0xfeae], // ARABIC LETTER REH\n 0x0632: [0xfeaf, 0xfeb0], // ARABIC LETTER ZAIN\n 0x0633: [0xfeb1, 0xfeb2, 0xfeb3, 0xfeb4], // ARABIC LETTER SEEN\n 0x0634: [0xfeb5, 0xfeb6, 0xfeb7, 0xfeb8], // ARABIC LETTER SHEEN\n 0x0635: [0xfeb9, 0xfeba, 0xfebb, 0xfebc], // ARABIC LETTER SAD\n 0x0636: [0xfebd, 0xfebe, 0xfebf, 0xfec0], // ARABIC LETTER DAD\n 0x0637: [0xfec1, 0xfec2, 0xfec3, 0xfec4], // ARABIC LETTER TAH\n 0x0638: [0xfec5, 0xfec6, 0xfec7, 0xfec8], // ARABIC LETTER ZAH\n 0x0639: [0xfec9, 0xfeca, 0xfecb, 0xfecc], // ARABIC LETTER AIN\n 0x063a: [0xfecd, 0xfece, 0xfecf, 0xfed0], // ARABIC LETTER GHAIN\n 0x0641: [0xfed1, 0xfed2, 0xfed3, 0xfed4], // ARABIC LETTER FEH\n 0x0642: [0xfed5, 0xfed6, 0xfed7, 0xfed8], // ARABIC LETTER QAF\n 0x0643: [0xfed9, 0xfeda, 0xfedb, 0xfedc], // ARABIC LETTER KAF\n 0x0644: [0xfedd, 0xfede, 0xfedf, 0xfee0], // ARABIC LETTER LAM\n 0x0645: [0xfee1, 0xfee2, 0xfee3, 0xfee4], // ARABIC LETTER MEEM\n 0x0646: [0xfee5, 0xfee6, 0xfee7, 0xfee8], // ARABIC LETTER NOON\n 0x0647: [0xfee9, 0xfeea, 0xfeeb, 0xfeec], // ARABIC LETTER HEH\n 0x0648: [0xfeed, 0xfeee], // ARABIC LETTER WAW\n 0x0649: [0xfeef, 0xfef0, 64488, 64489], // ARABIC LETTER ALEF MAKSURA\n 0x064a: [0xfef1, 0xfef2, 0xfef3, 0xfef4], // ARABIC LETTER YEH\n 0x0671: [0xfb50, 0xfb51], // ARABIC LETTER ALEF WASLA\n 0x0677: [0xfbdd], // ARABIC LETTER U WITH HAMZA ABOVE\n 0x0679: [0xfb66, 0xfb67, 0xfb68, 0xfb69], // ARABIC LETTER TTEH\n 0x067a: [0xfb5e, 0xfb5f, 0xfb60, 0xfb61], // ARABIC LETTER TTEHEH\n 0x067b: [0xfb52, 0xfb53, 0xfb54, 0xfb55], // ARABIC LETTER BEEH\n 0x067e: [0xfb56, 0xfb57, 0xfb58, 0xfb59], // ARABIC LETTER PEH\n 0x067f: [0xfb62, 0xfb63, 0xfb64, 0xfb65], // ARABIC LETTER TEHEH\n 0x0680: [0xfb5a, 0xfb5b, 0xfb5c, 0xfb5d], // ARABIC LETTER BEHEH\n 0x0683: [0xfb76, 0xfb77, 0xfb78, 0xfb79], // ARABIC LETTER NYEH\n 0x0684: [0xfb72, 0xfb73, 0xfb74, 0xfb75], // ARABIC LETTER DYEH\n 0x0686: [0xfb7a, 0xfb7b, 0xfb7c, 0xfb7d], // ARABIC LETTER TCHEH\n 0x0687: [0xfb7e, 0xfb7f, 0xfb80, 0xfb81], // ARABIC LETTER TCHEHEH\n 0x0688: [0xfb88, 0xfb89], // ARABIC LETTER DDAL\n 0x068c: [0xfb84, 0xfb85], // ARABIC LETTER DAHAL\n 0x068d: [0xfb82, 0xfb83], // ARABIC LETTER DDAHAL\n 0x068e: [0xfb86, 0xfb87], // ARABIC LETTER DUL\n 0x0691: [0xfb8c, 0xfb8d], // ARABIC LETTER RREH\n 0x0698: [0xfb8a, 0xfb8b], // ARABIC LETTER JEH\n 0x06a4: [0xfb6a, 0xfb6b, 0xfb6c, 0xfb6d], // ARABIC LETTER VEH\n 0x06a6: [0xfb6e, 0xfb6f, 0xfb70, 0xfb71], // ARABIC LETTER PEHEH\n 0x06a9: [0xfb8e, 0xfb8f, 0xfb90, 0xfb91], // ARABIC LETTER KEHEH\n 0x06ad: [0xfbd3, 0xfbd4, 0xfbd5, 0xfbd6], // ARABIC LETTER NG\n 0x06af: [0xfb92, 0xfb93, 0xfb94, 0xfb95], // ARABIC LETTER GAF\n 0x06b1: [0xfb9a, 0xfb9b, 0xfb9c, 0xfb9d], // ARABIC LETTER NGOEH\n 0x06b3: [0xfb96, 0xfb97, 0xfb98, 0xfb99], // ARABIC LETTER GUEH\n 0x06ba: [0xfb9e, 0xfb9f], // ARABIC LETTER NOON GHUNNA\n 0x06bb: [0xfba0, 0xfba1, 0xfba2, 0xfba3], // ARABIC LETTER RNOON\n 0x06be: [0xfbaa, 0xfbab, 0xfbac, 0xfbad], // ARABIC LETTER HEH DOACHASHMEE\n 0x06c0: [0xfba4, 0xfba5], // ARABIC LETTER HEH WITH YEH ABOVE\n 0x06c1: [0xfba6, 0xfba7, 0xfba8, 0xfba9], // ARABIC LETTER HEH GOAL\n 0x06c5: [0xfbe0, 0xfbe1], // ARABIC LETTER KIRGHIZ OE\n 0x06c6: [0xfbd9, 0xfbda], // ARABIC LETTER OE\n 0x06c7: [0xfbd7, 0xfbd8], // ARABIC LETTER U\n 0x06c8: [0xfbdb, 0xfbdc], // ARABIC LETTER YU\n 0x06c9: [0xfbe2, 0xfbe3], // ARABIC LETTER KIRGHIZ YU\n 0x06cb: [0xfbde, 0xfbdf], // ARABIC LETTER VE\n 0x06cc: [0xfbfc, 0xfbfd, 0xfbfe, 0xfbff], // ARABIC LETTER FARSI YEH\n 0x06d0: [0xfbe4, 0xfbe5, 0xfbe6, 0xfbe7], //ARABIC LETTER E\n 0x06d2: [0xfbae, 0xfbaf], // ARABIC LETTER YEH BARREE\n 0x06d3: [0xfbb0, 0xfbb1] // ARABIC LETTER YEH BARREE WITH HAMZA ABOVE\n };\n\n /*\n var ligaturesSubstitutionA = {\n 0xFBEA: []// ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF ISOLATED FORM\n };\n */\n\n var ligatures = {\n 0xfedf: {\n 0xfe82: 0xfef5, // ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM\n 0xfe84: 0xfef7, // ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM\n 0xfe88: 0xfef9, // ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM\n 0xfe8e: 0xfefb // ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM\n },\n 0xfee0: {\n 0xfe82: 0xfef6, // ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM\n 0xfe84: 0xfef8, // ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM\n 0xfe88: 0xfefa, // ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM\n 0xfe8e: 0xfefc // ARABIC LIGATURE LAM WITH ALEF FINAL FORM\n },\n 0xfe8d: { 0xfedf: { 0xfee0: { 0xfeea: 0xfdf2 } } }, // ALLAH\n 0x0651: {\n 0x064c: 0xfc5e, // Shadda + Dammatan\n 0x064d: 0xfc5f, // Shadda + Kasratan\n 0x064e: 0xfc60, // Shadda + Fatha\n 0x064f: 0xfc61, // Shadda + Damma\n 0x0650: 0xfc62 // Shadda + Kasra\n }\n };\n\n var arabic_diacritics = {\n 1612: 64606, // Shadda + Dammatan\n 1613: 64607, // Shadda + Kasratan\n 1614: 64608, // Shadda + Fatha\n 1615: 64609, // Shadda + Damma\n 1616: 64610 // Shadda + Kasra\n };\n\n var alfletter = [1570, 1571, 1573, 1575];\n\n var noChangeInForm = -1;\n var isolatedForm = 0;\n var finalForm = 1;\n var initialForm = 2;\n var medialForm = 3;\n\n jsPDFAPI.__arabicParser__ = {};\n\n //private\n var isInArabicSubstitutionA = (jsPDFAPI.__arabicParser__.isInArabicSubstitutionA = function(\n letter\n ) {\n return typeof arabicSubstitionA[letter.charCodeAt(0)] !== \"undefined\";\n });\n\n var isArabicLetter = (jsPDFAPI.__arabicParser__.isArabicLetter = function(\n letter\n ) {\n return (\n typeof letter === \"string\" &&\n /^[\\u0600-\\u06FF\\u0750-\\u077F\\u08A0-\\u08FF\\uFB50-\\uFDFF\\uFE70-\\uFEFF]+$/.test(\n letter\n )\n );\n });\n\n var isArabicEndLetter = (jsPDFAPI.__arabicParser__.isArabicEndLetter = function(\n letter\n ) {\n return (\n isArabicLetter(letter) &&\n isInArabicSubstitutionA(letter) &&\n arabicSubstitionA[letter.charCodeAt(0)].length <= 2\n );\n });\n\n var isArabicAlfLetter = (jsPDFAPI.__arabicParser__.isArabicAlfLetter = function(\n letter\n ) {\n return (\n isArabicLetter(letter) && alfletter.indexOf(letter.charCodeAt(0)) >= 0\n );\n });\n\n jsPDFAPI.__arabicParser__.arabicLetterHasIsolatedForm = function(letter) {\n return (\n isArabicLetter(letter) &&\n isInArabicSubstitutionA(letter) &&\n arabicSubstitionA[letter.charCodeAt(0)].length >= 1\n );\n };\n\n var arabicLetterHasFinalForm = (jsPDFAPI.__arabicParser__.arabicLetterHasFinalForm = function(\n letter\n ) {\n return (\n isArabicLetter(letter) &&\n isInArabicSubstitutionA(letter) &&\n arabicSubstitionA[letter.charCodeAt(0)].length >= 2\n );\n });\n\n jsPDFAPI.__arabicParser__.arabicLetterHasInitialForm = function(letter) {\n return (\n isArabicLetter(letter) &&\n isInArabicSubstitutionA(letter) &&\n arabicSubstitionA[letter.charCodeAt(0)].length >= 3\n );\n };\n\n var arabicLetterHasMedialForm = (jsPDFAPI.__arabicParser__.arabicLetterHasMedialForm = function(\n letter\n ) {\n return (\n isArabicLetter(letter) &&\n isInArabicSubstitutionA(letter) &&\n arabicSubstitionA[letter.charCodeAt(0)].length == 4\n );\n });\n\n var resolveLigatures = (jsPDFAPI.__arabicParser__.resolveLigatures = function(\n letters\n ) {\n var i = 0;\n var tmpLigatures = ligatures;\n var result = \"\";\n var effectedLetters = 0;\n\n for (i = 0; i < letters.length; i += 1) {\n if (typeof tmpLigatures[letters.charCodeAt(i)] !== \"undefined\") {\n effectedLetters++;\n tmpLigatures = tmpLigatures[letters.charCodeAt(i)];\n\n if (typeof tmpLigatures === \"number\") {\n result += String.fromCharCode(tmpLigatures);\n tmpLigatures = ligatures;\n effectedLetters = 0;\n }\n if (i === letters.length - 1) {\n tmpLigatures = ligatures;\n result += letters.charAt(i - (effectedLetters - 1));\n i = i - (effectedLetters - 1);\n effectedLetters = 0;\n }\n } else {\n tmpLigatures = ligatures;\n result += letters.charAt(i - effectedLetters);\n i = i - effectedLetters;\n effectedLetters = 0;\n }\n }\n\n return result;\n });\n\n jsPDFAPI.__arabicParser__.isArabicDiacritic = function(letter) {\n return (\n letter !== undefined &&\n arabic_diacritics[letter.charCodeAt(0)] !== undefined\n );\n };\n\n var getCorrectForm = (jsPDFAPI.__arabicParser__.getCorrectForm = function(\n currentChar,\n beforeChar,\n nextChar\n ) {\n if (!isArabicLetter(currentChar)) {\n return -1;\n }\n\n if (isInArabicSubstitutionA(currentChar) === false) {\n return noChangeInForm;\n }\n if (\n !arabicLetterHasFinalForm(currentChar) ||\n (!isArabicLetter(beforeChar) && !isArabicLetter(nextChar)) ||\n (!isArabicLetter(nextChar) && isArabicEndLetter(beforeChar)) ||\n (isArabicEndLetter(currentChar) && !isArabicLetter(beforeChar)) ||\n (isArabicEndLetter(currentChar) && isArabicAlfLetter(beforeChar)) ||\n (isArabicEndLetter(currentChar) && isArabicEndLetter(beforeChar))\n ) {\n return isolatedForm;\n }\n\n if (\n arabicLetterHasMedialForm(currentChar) &&\n isArabicLetter(beforeChar) &&\n !isArabicEndLetter(beforeChar) &&\n isArabicLetter(nextChar) &&\n arabicLetterHasFinalForm(nextChar)\n ) {\n return medialForm;\n }\n\n if (isArabicEndLetter(currentChar) || !isArabicLetter(nextChar)) {\n return finalForm;\n }\n return initialForm;\n });\n\n /**\n * @name processArabic\n * @function\n * @param {string} text\n * @returns {string}\n */\n var parseArabic = function(text) {\n text = text || \"\";\n\n var result = \"\";\n var i = 0;\n var j = 0;\n var position = 0;\n var currentLetter = \"\";\n var prevLetter = \"\";\n var nextLetter = \"\";\n\n var words = text.split(\"\\\\s+\");\n var newWords = [];\n for (i = 0; i < words.length; i += 1) {\n newWords.push(\"\");\n for (j = 0; j < words[i].length; j += 1) {\n currentLetter = words[i][j];\n prevLetter = words[i][j - 1];\n nextLetter = words[i][j + 1];\n if (isArabicLetter(currentLetter)) {\n position = getCorrectForm(currentLetter, prevLetter, nextLetter);\n if (position !== -1) {\n newWords[i] += String.fromCharCode(\n arabicSubstitionA[currentLetter.charCodeAt(0)][position]\n );\n } else {\n newWords[i] += currentLetter;\n }\n } else {\n newWords[i] += currentLetter;\n }\n }\n\n newWords[i] = resolveLigatures(newWords[i]);\n }\n result = newWords.join(\" \");\n\n return result;\n };\n\n var processArabic = (jsPDFAPI.__arabicParser__.processArabic = jsPDFAPI.processArabic = function() {\n var text =\n typeof arguments[0] === \"string\" ? arguments[0] : arguments[0].text;\n var tmpText = [];\n var result;\n\n if (Array.isArray(text)) {\n var i = 0;\n tmpText = [];\n for (i = 0; i < text.length; i += 1) {\n if (Array.isArray(text[i])) {\n tmpText.push([parseArabic(text[i][0]), text[i][1], text[i][2]]);\n } else {\n tmpText.push([parseArabic(text[i])]);\n }\n }\n result = tmpText;\n } else {\n result = parseArabic(text);\n }\n if (typeof arguments[0] === \"string\") {\n return result;\n } else {\n arguments[0].text = result;\n return arguments[0];\n }\n });\n\n jsPDFAPI.events.push([\"preProcessText\", processArabic]);\n})(jsPDF.API);\n","/** @license\n * jsPDF Autoprint Plugin\n *\n * Licensed under the MIT License.\n * http://opensource.org/licenses/mit-license\n */\n\nimport { jsPDF } from \"../jspdf.js\";\n\n/**\n * @name autoprint\n * @module\n */\n(function(jsPDFAPI) {\n \"use strict\";\n\n /**\n * Makes the PDF automatically open the print-Dialog when opened in a PDF-viewer.\n *\n * @name autoPrint\n * @function\n * @param {Object} options (optional) Set the attribute variant to 'non-conform' (default) or 'javascript' to activate different methods of automatic printing when opening in a PDF-viewer .\n * @returns {jsPDF}\n * @example\n * var doc = new jsPDF();\n * doc.text(10, 10, 'This is a test');\n * doc.autoPrint({variant: 'non-conform'});\n * doc.save('autoprint.pdf');\n */\n jsPDFAPI.autoPrint = function(options) {\n \"use strict\";\n var refAutoPrintTag;\n options = options || {};\n options.variant = options.variant || \"non-conform\";\n\n switch (options.variant) {\n case \"javascript\":\n //https://github.com/Rob--W/pdf.js/commit/c676ecb5a0f54677b9f3340c3ef2cf42225453bb\n this.addJS(\"print({});\");\n break;\n case \"non-conform\":\n default:\n this.internal.events.subscribe(\"postPutResources\", function() {\n refAutoPrintTag = this.internal.newObject();\n this.internal.out(\"<<\");\n this.internal.out(\"/S /Named\");\n this.internal.out(\"/Type /Action\");\n this.internal.out(\"/N /Print\");\n this.internal.out(\">>\");\n this.internal.out(\"endobj\");\n });\n\n this.internal.events.subscribe(\"putCatalog\", function() {\n this.internal.out(\"/OpenAction \" + refAutoPrintTag + \" 0 R\");\n });\n break;\n }\n return this;\n };\n})(jsPDF.API);\n","/**\n * @license\n * Copyright (c) 2014 Steven Spungin (TwelveTone LLC) steven@twelvetone.tv\n *\n * Licensed under the MIT License.\n * http://opensource.org/licenses/mit-license\n */\n\nimport { jsPDF } from \"../jspdf.js\";\n\n/**\n * jsPDF Canvas PlugIn\n * This plugin mimics the HTML5 Canvas\n *\n * The goal is to provide a way for current canvas users to print directly to a PDF.\n * @name canvas\n * @module\n */\n(function(jsPDFAPI) {\n \"use strict\";\n\n /**\n * @class Canvas\n * @classdesc A Canvas Wrapper for jsPDF\n */\n var Canvas = function() {\n var jsPdfInstance = undefined;\n Object.defineProperty(this, \"pdf\", {\n get: function() {\n return jsPdfInstance;\n },\n set: function(value) {\n jsPdfInstance = value;\n }\n });\n\n var _width = 150;\n /**\n * The height property is a positive integer reflecting the height HTML attribute of the