Repository
OCA/mis-builder · module folder · Try on Runboat
Module version
1.2.0
Category
Reporting
Folder size
1.94 MB
License
AGPL-3
Application
Yes
Auto-installable
No
Website
https://github.com/OCA/mis-builder
Last tracking update
2026-08-07 09:06:25
Authors
ACSONE SA/NV, Odoo Community Association (OCA)
Maintainers
ACSONE SA/NV, Odoo Community Association (OCA)
Committers
Stéphane Bidoul, Pierre Verkest, Víctor Martínez, Weblate, OCA-git-bot, oca-ci, Asta
Odoo dependencies
Python dependencies
xlrd, xlsxwriter
System dependencies
None
Required by
l10n_be_mis_reports, l10n_br_mis_report, l10n_es_mis_report, l10n_fr_mis_reports, l10n_mx_account_reports, mis_builder_budget
Description
This module allows you to build Management Information Systems
dashboards. Such style of reports presents KPI in rows and time periods
in columns. Reports mainly fetch data from account moves, but can also
combine data coming from arbitrary Odoo models. Reports can be exported
to PDF, Excel and they can be added to Odoo dashboards.

Code Analysis

Views touched (12)
XML IDNameModelTypeStatus
mis_report_instance_add_to_dashboard_form_view add.mis.report.instance.dashboard.wizard.view add.mis.report.instance.dashboard.wizard form New
mis_report_instance_period_view_form mis.report.instance.period form New
mis_report_instance_result_view_form mis.report.instance.result.view.form mis.report.instance form New
mis_report_instance_view_form mis.report.instance.view.form mis.report.instance form New
mis_report_instance_view_list mis.report.instance.view.list mis.report.instance list New
mis_report_style_view_form mis.report.style.view.form mis.report.style form New
mis_report_style_view_list mis.report.style.view.list mis.report.style list New
mis_report_view_form mis.report.view.form mis.report form New
mis_report_view_kpi_form mis.report.view.kpi.form mis.report.kpi form New
mis_report_view_list mis.report.view.list mis.report list New
report_mis_report_instance report_mis_report_instance ir.ui.view qweb New
wizard_mis_report_instance_view_form mis.report.instance form Inherits mis_builder.mis_report_instance_view_form
HTTP endpoints (0)

No HTTP endpoints found for this module.

Models touched (16)

New fields (2)
  • dashboard_id Many2one → ir.actions.act_window
    domain="[('res_model', '=', 'board.board')]" required=True args: 'ir.actions.act_window'
  • name Char
    required=True
Public methods (2)
  • action_add_to_dashboard(self)
  • default_get(self, fields_list)
    @api.model

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (7)
  • amount Float
  • date_from Date
    required=True string='From'
  • date_to Date
    required=True string='To'
  • kpi_expression_id Many2one → mis.report.kpi.expression
    comodel_name='mis.report.kpi.expression' ondelete='restrict' required=True string='KPI'
  • name Char
    compute='_compute_name' required=False
  • seq1 Integer
    related='kpi_expression_id.kpi_id.sequence' store=True string='KPI Sequence'
  • seq2 Integer
    related='kpi_expression_id.subkpi_id.sequence' store=True string='Sub-KPI Sequence'
Public methods (0)

No public methods.

New fields (10)
  • account_model Char
    compute='_compute_account_model'
  • all_kpi_ids One2many → mis.report.kpi
    comodel_name='mis.report.kpi' compute='_compute_all_kpi_ids' help='KPIs of this report and subreports.'
  • description Char
    required=False translate=True
  • kpi_ids One2many → mis.report.kpi
    copy=True string="KPI's" args: 'mis.report.kpi', 'report_id'
  • move_lines_source Many2one → ir.model
    comodel_name='ir.model' default=<expr> domain=[('field_id.name', '=', 'debit'), ('field_id.name', '=', 'credit'), ('field_id.name', '=', 'account_id'), ('field_id.name', '=', 'date'), ('field_id.name', '=', 'company_id')] help="A 'move line like' model, ie having at least debit, credit, date, account_id and company_id fields. This model is the data source for column Actuals." ondelete='cascade' required=True
  • name Char
    required=True translate=True
  • query_ids One2many → mis.report.query
    copy=True string='Queries' args: 'mis.report.query', 'report_id'
  • style_id Many2one → mis.report.style
    comodel_name='mis.report.style'
  • subkpi_ids One2many → mis.report.subkpi
    copy=True string='Sub KPI' args: 'mis.report.subkpi', 'report_id'
  • subreport_ids One2many → mis.report.subreport
    copy=True string='Sub reports' args: 'mis.report.subreport', 'report_id'
Public methods (7)
  • copy(self, default=None)
  • declare_and_compute_period(self, kpi_matrix, col_key, col_label, col_description, aep, date_from, date_to, subkpis_filter=None, get_additional_move_line_filter=None, get_additional_query_filter=None, locals_dict=None, aml_model=None, no_auto_expand_accounts=False)
  • evaluate(self, aep, date_from, date_to, target_move='posted', aml_model=None, subkpis_filter=None, get_additional_move_line_filter=None, get_additional_query_filter=None)
    Simplified method to evaluate a report over a time period. :param aep: an AccountingExpressionProcessor instance created using _prepare_aep() :param date_from, date_to: the starting and ending date :param target_move: all|posted :param aml_model: the name of a model that is compatible with account.move.line (default: account.move.line) :param subkpis_filter: a list of subkpis to include in the evaluation (if empty, use all subkpis) :param get_additional_move_line_filter: a bound method that takes no arguments and returns a domain compatible with account.move.line :param get_additional_query_filter: a bound method that takes a single query argument and returns a domain compatible with the query underlying model :return: a dictionary where keys are KPI names, and values are the evaluated results; some additional keys might be present: these should be ignored as they might be removed in the future.
  • get_kpis_by_account_id(self, company)
    Return { account_id: set(kpi) }
  • get_wizard_report_action(self)
  • prepare_kpi_matrix(self, companies=None)
  • prepare_locals_dict(self)

New fields (31)
  • analytic_domain Text
    default='[]' help='A domain to additionally filter move lines considered in this report. Caution: when using different move line sources in different columns, such as budgets by account, make sure to use only fields that are available in all move line sources.'
  • company_id Many2one → res.company
    comodel_name='res.company' default=<expr> required=False string='Allowed company'
  • company_ids Many2many → res.company
    comodel_name='res.company' help='Select companies for which data will be searched.' string='Allowed companies'
  • comparison_mode Boolean
    compute='_compute_comparison_mode' inverse='_inverse_comparison_mode'
  • currency_id Many2one → res.currency
    comodel_name='res.currency' help='Select target currency for the report. Required if companies have different currencies.' required=False
  • date Date
    help='Report base date (leave empty to use current date)' string='Base date'
  • date_from Date
    string='From'
  • date_range_id Many2one → date.range
    comodel_name='date.range'
  • date_to Date
    string='To'
  • description Char
    related='report_id.description'
  • display_columns_description Boolean
    help='Display the date range details in the column headers.'
  • landscape_pdf Boolean
    string='Landscape PDF'
  • multi_company Boolean
    default=False help='Check if you wish to specify several companies to be searched for data.' string='Multiple companies'
  • name Char
    required=True translate=True
  • no_auto_expand_accounts Boolean
    string='Disable account details expansion'
  • period_ids One2many → mis.report.instance.period
    comodel_name='mis.report.instance.period' copy=True inverse_name='report_instance_id' required=True string='Periods'
  • pivot_date Date
    compute='_compute_pivot_date'
  • query_company_ids Many2many → res.company
    comodel_name='res.company' compute='_compute_query_company_ids' help='Companies for which data will be searched.' string='Effective companies'
  • report_id Many2one → mis.report
    required=True args: 'mis.report'
  • sequence Integer
    default=10
  • source_aml_model_id Many2one
    related='report_id.move_lines_source'
  • source_aml_model_name Char
    related='source_aml_model_id.model' related_sudo=True
  • target_move Selection
    default='posted' required=True string='Target Moves' args: [('posted', 'All Posted Entries'), ('all', 'All Entries')]
  • temporary Boolean
    default=False
  • user_can_edit_annotation Boolean
    compute='_compute_user_can_edit_annotation'
  • user_can_read_annotation Boolean
    compute='_compute_user_can_read_annotation'
  • wide_display_by_default Boolean
    string='Open report in wide mode by default'
  • widget_search_view_id Many2one → ir.ui.view
    comodel_name='ir.ui.view' compute='_compute_widget_search_view_id' domain='[("type", "=", "search"), ("model", "=", source_aml_model_name)]' help='Search view to customize the filter box in the report widget.' readonly=False store=True string='Filter box search view'
  • widget_show_filters Boolean
    default=True help='Show the filter bar in the report widget.' string='Show filters box'
  • widget_show_pivot_date Boolean
    default=False help='Show the Pivot Date in the report widget filter bar.' string='Show Pivot Date'
  • widget_show_settings_button Boolean
    default=False help='Show the settings button in the report widget.' string='Show settings button'
Public methods (11)
  • compute(self)
  • copy(self, default=None)
  • display_settings(self)
  • drilldown(self, arg)
  • export_xls(self)
  • get_filter_descriptions(self)
    @api.model
  • get_notes_by_cell_id(self) -> dict
  • get_views(self, views, options=None)
    @api.model
    Override to get correct form view on dashboard
  • preview(self)
  • print_pdf(self)
  • save_report(self)

New fields (5)
  • annotation_context Json
    help='\n Context used when adding annotation\n '
  • kpi_id Many2one → mis.report.kpi
    comodel_name='mis.report.kpi' ondelete='cascade' required=True
  • note Char
  • period_id Many2one → mis.report.instance.period
    comodel_name='mis.report.instance.period' ondelete='cascade' required=True
  • subkpi_id Many2one → mis.report.subkpi
    comodel_name='mis.report.subkpi' ondelete='cascade'
Public methods (3)
  • init(self)
  • remove_annotation(self, cell_id, instance_id)
    @api.model
  • set_annotation(self, cell_id, instance_id, note)
    @api.model

New fields (27)
  • allowed_cmpcol_ids Many2many → mis.report.instance.period
    comodel_name='mis.report.instance.period' compute='_compute_allowed_cmpcol_ids'
  • analytic_domain Text
    default='[]' help='A domain to additionally filter move lines considered in this column.'
  • date_from Date
    compute='_compute_dates' string='From (computed)'
  • date_range_id Many2one → date.range
    comodel_name='date.range'
  • date_range_type_id Many2one → date.range.type
    comodel_name='date.range.type' domain=[('allow_overlap', '=', False)]
  • date_to Date
    compute='_compute_dates' string='To (computed)'
  • duration Integer
    default=1 help='Number of periods'
  • is_ytd Boolean
    default=False help='Forces the start date to Jan 1st of the relevant year' string='Year to date'
  • manual_date_from Date
    string='From'
  • manual_date_to Date
    string='To'
  • mode Selection
    default=MODE_FIX required=True args: [(MODE_FIX, 'Fixed dates'), (MODE_REL, 'Relative to report base date'), (MODE_NONE, 'No date filter')]
  • name Char
    required=True string='Label' translate=True
  • normalize_factor Integer
    default=1 help='Factor to use to normalize the period (used in comparison' string='Factor'
  • offset Integer
    default=-1 help='Offset from current period'
  • report_id Many2one
    related='report_instance_id.report_id'
  • report_instance_id Many2one → mis.report.instance
    comodel_name='mis.report.instance' ondelete='cascade' required=True
  • sequence Integer
    default=100
  • source Selection
    default=SRC_ACTUALS help='Actuals: current data, from accounting and other queries.\nActuals (alternative): current data from an alternative source (eg a database view providing look-alike account move lines).\nSum columns: summation (+/-) of other columns.\nCompare to column: compare to other column.\n' required=True args: [(SRC_ACTUALS, 'Actuals'), (SRC_ACTUALS_ALT, 'Actuals (alternative)'), (SRC_SUMCOL, 'Sum columns'), (SRC_CMPCOL, 'Compare columns')]
  • source_aml_model_id Many2one → ir.model
    comodel_name='ir.model' compute='_compute_source_aml_model_id' domain=[('field_id.name', '=', 'debit'), ('field_id.name', '=', 'credit'), ('field_id.name', '=', 'account_id'), ('field_id.name', '=', 'date'), ('field_id.name', '=', 'company_id'), ('field_id.model_id.model', '!=', 'account.move.line')] help="A 'move line like' model, ie having at least debit, credit, date, account_id and company_id fields." readonly=False store=True string='Move lines source'
  • source_aml_model_name Char
    related='source_aml_model_id.model' string='Move lines source model name'
  • source_cmpcol_from_id Many2one → mis.report.instance.period
    comodel_name='mis.report.instance.period' string='versus'
  • source_cmpcol_to_id Many2one → mis.report.instance.period
    comodel_name='mis.report.instance.period' string='Compare'
  • source_sumcol_accdet Boolean
    string='Sum account details'
  • source_sumcol_ids One2many → mis.report.instance.period.sum
    comodel_name='mis.report.instance.period.sum' inverse_name='period_id' string='Columns to sum'
  • subkpi_ids Many2many → mis.report.subkpi
    string='Sub KPI Filter' args: 'mis.report.subkpi'
  • type Selection
    string='Period type' args: [('d', 'Day'), ('w', 'Week'), ('m', 'Month'), ('y', 'Year'), ('date_range', 'Date Range')]
  • valid Boolean
    compute='_compute_dates' type='boolean'
Public methods (1)
  • copy_data(self, default=None)

New fields (3)
  • period_id Many2one → mis.report.instance.period
    comodel_name='mis.report.instance.period' ondelete='cascade' required=True string='Parent column'
  • period_to_sum_id Many2one → mis.report.instance.period
    comodel_name='mis.report.instance.period' ondelete='restrict' required=True string='Column'
  • sign Selection
    default='+' required=True args: [('+', '+'), ('-', '-')]
Public methods (0)

No public methods.

New fields (14)
  • accumulation_method Selection
    default=ACC_SUM help='Determines how values of this kpi spanning over a time period are transformed to match the reporting period. Sum: values of shorter period are added, values of longest or partially overlapping periods are adjusted pro-rata temporis.\nAverage: values of included period are averaged with a pro-rata temporis weight.' required=True args: [(ACC_SUM, 'Sum'), (ACC_AVG, 'Average'), (ACC_NONE, 'None')]
  • auto_expand_accounts Boolean
    string='Display details by account'
  • auto_expand_accounts_style_id Many2one → mis.report.style
    comodel_name='mis.report.style' required=False string='Style for account detail rows'
  • compare_method Selection
    default=CMP_PCT required=True string='Comparison Method' args: [(CMP_DIFF, 'Difference'), (CMP_PCT, 'Percentage'), (CMP_NONE, 'None')]
  • description Char
    required=True translate=True
  • expression Char
    compute='_compute_expression' inverse='_inverse_expression'
  • expression_ids One2many → mis.report.kpi.expression
    comodel_name='mis.report.kpi.expression' copy=True inverse_name='kpi_id' string='Expressions'
  • multi Boolean
  • name Char
    required=True
  • report_id Many2one → mis.report
    ondelete='cascade' required=True args: 'mis.report'
  • sequence Integer
    default=100
  • style_expression Char
    help='An expression that returns a style depending on the KPI value. Such style is applied on top of the row style.'
  • style_id Many2one → mis.report.style
    comodel_name='mis.report.style' required=False
  • type Selection
    default=TYPE_NUM required=True string='Value type' args: [(TYPE_NUM, 'Numeric'), (TYPE_PCT, 'Percentage'), (TYPE_STR, 'String')]
Public methods (0)

No public methods.

New fields (4)
  • kpi_id Many2one → mis.report.kpi
    ondelete='cascade' required=True args: 'mis.report.kpi'
  • name Char
    string='Expression'
  • sequence Integer
    related='subkpi_id.sequence' store=True
  • subkpi_id Many2one → mis.report.subkpi
    ondelete='cascade' readonly=False args: 'mis.report.subkpi'
Public methods (0)

No public methods.

New fields (9)
  • aggregate Selection
    args: [('sum', 'Sum'), ('avg', 'Average'), ('min', 'Min'), ('max', 'Max')]
  • company_field_id Many2one → ir.model.fields
    comodel_name='ir.model.fields' domain="[('model_id', '=', model_id)]" help='Field that defines company on related model.When set, it will be automatically be added in search domain of query.' ondelete='set null'
  • date_field Many2one → ir.model.fields
    comodel_name='ir.model.fields' domain="[('ttype', 'in', ('date', 'datetime')),('model_id', '=', model_id)]" ondelete='cascade' required=True
  • domain Char
  • field_ids Many2many → ir.model.fields
    required=True string='Fields to fetch' args: 'ir.model.fields'
  • field_names Char
    compute='_compute_field_names' string='Fetched fields name'
  • model_id Many2one → ir.model
    ondelete='cascade' required=True args: 'ir.model'
  • name Char
    required=True
  • report_id Many2one → mis.report
    comodel_name='mis.report' ondelete='cascade' required=True
Public methods (0)

No public methods.

New fields (26)
  • background_color Char
    default='#FFFFFF' help='Background color in valid RGB code (from #000000 to #FFFFFF)'
  • background_color_inherit Boolean
    default=True
  • color Char
    default='#000000' help='Text color in valid RGB code (from #000000 to #FFFFFF)' string='Text color'
  • color_inherit Boolean
    default=True
  • description Html
    compute='_compute_description' help='Describe specific values that are not inherited'
  • divider Selection
    default='1' string='Factor' args: [('1e-6', 'µ'), ('1e-3', 'm'), ('1', '1'), ('1e3', 'k'), ('1e6', 'M')]
  • divider_inherit Boolean
    default=True
  • dp Integer
    default=0 string='Rounding'
  • dp_inherit Boolean
    default=True
  • font_size Selection
    selection=_font_size_selection
  • font_size_inherit Boolean
    default=True
  • font_style Selection
    selection=_font_style_selection
  • font_style_inherit Boolean
    default=True
  • font_weight Selection
    selection=_font_weight_selection
  • font_weight_inherit Boolean
    default=True
  • hide_always Boolean
    default=False
  • hide_always_inherit Boolean
    default=True
  • hide_empty Boolean
    default=False
  • hide_empty_inherit Boolean
    default=True
  • indent_level Integer
  • indent_level_inherit Boolean
    default=True
  • name Char
    required=True string='Style name'
  • prefix Char
  • prefix_inherit Boolean
    default=True
  • suffix Char
  • suffix_inherit Boolean
    default=True
Public methods (9)
  • check_positive_val(self)
    @api.constrains('indent_level')
  • compare_and_render(self, lang, style_props, var_type, compare_method, value, base_value, average_value=1, average_base_value=1)
    @api.model
    :param lang: res.lang record :param style_props: PropertyDict with style properties :param var_type: num, pct or str :param compare_method: diff, pct, none :param value: value to compare (value - base_value) :param base_value: value compared with (value - base_value) :param average_value: value = value / average_value :param average_base_value: base_value = base_value / average_base_value :return: tuple with 4 elements - delta = comparison result (Float or AccountingNone) - delta_r = delta rendered in formatted string (String) - delta_style = PropertyDict with style properties - delta_type = Type of the comparison result (num or pct)
  • merge(self, styles)
    @api.model
    Merge several styles, giving priority to the last. Returns a PropertyDict of style properties.
  • render(self, lang, style_props, var_type, value, sign='-')
    @api.model
  • render_num(self, lang, value, divider=1.0, dp=0, prefix=None, suffix=None, sign='-')
    @api.model
  • render_pct(self, lang, value, dp=1, sign='-')
    @api.model
  • render_str(self, lang, value)
    @api.model
  • to_css_style(self, props, no_indent=False)
    @api.model
  • to_xlsx_style(self, var_type, props, no_indent=False)
    @api.model

New fields (5)
  • description Char
    required=True translate=True
  • expression_ids One2many → mis.report.kpi.expression
    args: 'mis.report.kpi.expression', 'subkpi_id'
  • name Char
    required=True
  • report_id Many2one → mis.report
    comodel_name='mis.report' ondelete='cascade' required=True
  • sequence Integer
    default=1
Public methods (0)

No public methods.

New fields (3)
  • name Char
    required=True
  • report_id Many2one → mis.report
    comodel_name='mis.report' ondelete='cascade' required=True
  • subreport_id Many2one → mis.report
    comodel_name='mis.report' ondelete='restrict' required=True
Public methods (0)

No public methods.

New fields (3)
  • date Date
    compute=<expr> help='Dummy field that adapts searches on date to searches on date_from/date_to.' search='_search_date'
  • date_from Date
    required=True
  • date_to Date
    required=True
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (1)
  • generate_xlsx_report(self, workbook, data, objects)

Loading…

Loading…

Loading…

Loading…

Loading…

Loading…

Loading…

Loading…

Loading…

Loading…

Loading…

Loading…