TIP: You can type at any time to perform a new search.
MIS Builder
mis_builder · OCA/mis-builder
- 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 ID | Name | Model | Type | Status |
|---|---|---|---|---|
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_idMany2one → ir.actions.act_windowdomain="[('res_model', '=', 'board.board')]"required=True args: 'ir.actions.act_window' -
nameCharrequired=True
-
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)
-
amountFloat -
date_fromDaterequired=Truestring='From' -
date_toDaterequired=Truestring='To' -
kpi_expression_idMany2one → mis.report.kpi.expressioncomodel_name='mis.report.kpi.expression'ondelete='restrict'required=Truestring='KPI' -
nameCharcompute='_compute_name'required=False -
seq1Integerrelated='kpi_expression_id.kpi_id.sequence'store=Truestring='KPI Sequence' -
seq2Integerrelated='kpi_expression_id.subkpi_id.sequence'store=Truestring='Sub-KPI Sequence'
No public methods.
New fields (10)
-
account_modelCharcompute='_compute_account_model' -
all_kpi_idsOne2many → mis.report.kpicomodel_name='mis.report.kpi'compute='_compute_all_kpi_ids'help='KPIs of this report and subreports.' -
descriptionCharrequired=Falsetranslate=True -
kpi_idsOne2many → mis.report.kpicopy=Truestring="KPI's" args: 'mis.report.kpi', 'report_id' -
move_lines_sourceMany2one → ir.modelcomodel_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 -
nameCharrequired=Truetranslate=True -
query_idsOne2many → mis.report.querycopy=Truestring='Queries' args: 'mis.report.query', 'report_id' -
style_idMany2one → mis.report.stylecomodel_name='mis.report.style' -
subkpi_idsOne2many → mis.report.subkpicopy=Truestring='Sub KPI' args: 'mis.report.subkpi', 'report_id' -
subreport_idsOne2many → mis.report.subreportcopy=Truestring='Sub reports' args: 'mis.report.subreport', 'report_id'
-
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_domainTextdefault='[]'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_idMany2one → res.companycomodel_name='res.company'default=<expr>required=Falsestring='Allowed company' -
company_idsMany2many → res.companycomodel_name='res.company'help='Select companies for which data will be searched.'string='Allowed companies' -
comparison_modeBooleancompute='_compute_comparison_mode'inverse='_inverse_comparison_mode' -
currency_idMany2one → res.currencycomodel_name='res.currency'help='Select target currency for the report. Required if companies have different currencies.'required=False -
dateDatehelp='Report base date (leave empty to use current date)'string='Base date' -
date_fromDatestring='From' -
date_range_idMany2one → date.rangecomodel_name='date.range' -
date_toDatestring='To' -
descriptionCharrelated='report_id.description' -
display_columns_descriptionBooleanhelp='Display the date range details in the column headers.' -
landscape_pdfBooleanstring='Landscape PDF' -
multi_companyBooleandefault=Falsehelp='Check if you wish to specify several companies to be searched for data.'string='Multiple companies' -
nameCharrequired=Truetranslate=True -
no_auto_expand_accountsBooleanstring='Disable account details expansion' -
period_idsOne2many → mis.report.instance.periodcomodel_name='mis.report.instance.period'copy=Trueinverse_name='report_instance_id'required=Truestring='Periods' -
pivot_dateDatecompute='_compute_pivot_date' -
query_company_idsMany2many → res.companycomodel_name='res.company'compute='_compute_query_company_ids'help='Companies for which data will be searched.'string='Effective companies' -
report_idMany2one → mis.reportrequired=True args: 'mis.report' -
sequenceIntegerdefault=10 -
source_aml_model_idMany2onerelated='report_id.move_lines_source' -
source_aml_model_nameCharrelated='source_aml_model_id.model'related_sudo=True -
target_moveSelectiondefault='posted'required=Truestring='Target Moves' args: [('posted', 'All Posted Entries'), ('all', 'All Entries')] -
temporaryBooleandefault=False -
user_can_edit_annotationBooleancompute='_compute_user_can_edit_annotation' -
user_can_read_annotationBooleancompute='_compute_user_can_read_annotation' -
wide_display_by_defaultBooleanstring='Open report in wide mode by default' -
widget_search_view_idMany2one → ir.ui.viewcomodel_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=Falsestore=Truestring='Filter box search view' -
widget_show_filtersBooleandefault=Truehelp='Show the filter bar in the report widget.'string='Show filters box' -
widget_show_pivot_dateBooleandefault=Falsehelp='Show the Pivot Date in the report widget filter bar.'string='Show Pivot Date' -
widget_show_settings_buttonBooleandefault=Falsehelp='Show the settings button in the report widget.'string='Show settings button'
-
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.modelOverride to get correct form view on dashboard -
preview(self) -
print_pdf(self) -
save_report(self)
New fields (5)
-
annotation_contextJsonhelp='\n Context used when adding annotation\n ' -
kpi_idMany2one → mis.report.kpicomodel_name='mis.report.kpi'ondelete='cascade'required=True -
noteChar -
period_idMany2one → mis.report.instance.periodcomodel_name='mis.report.instance.period'ondelete='cascade'required=True -
subkpi_idMany2one → mis.report.subkpicomodel_name='mis.report.subkpi'ondelete='cascade'
-
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_idsMany2many → mis.report.instance.periodcomodel_name='mis.report.instance.period'compute='_compute_allowed_cmpcol_ids' -
analytic_domainTextdefault='[]'help='A domain to additionally filter move lines considered in this column.' -
date_fromDatecompute='_compute_dates'string='From (computed)' -
date_range_idMany2one → date.rangecomodel_name='date.range' -
date_range_type_idMany2one → date.range.typecomodel_name='date.range.type'domain=[('allow_overlap', '=', False)] -
date_toDatecompute='_compute_dates'string='To (computed)' -
durationIntegerdefault=1help='Number of periods' -
is_ytdBooleandefault=Falsehelp='Forces the start date to Jan 1st of the relevant year'string='Year to date' -
manual_date_fromDatestring='From' -
manual_date_toDatestring='To' -
modeSelectiondefault=MODE_FIXrequired=True args: [(MODE_FIX, 'Fixed dates'), (MODE_REL, 'Relative to report base date'), (MODE_NONE, 'No date filter')] -
nameCharrequired=Truestring='Label'translate=True -
normalize_factorIntegerdefault=1help='Factor to use to normalize the period (used in comparison'string='Factor' -
offsetIntegerdefault=-1help='Offset from current period' -
report_idMany2onerelated='report_instance_id.report_id' -
report_instance_idMany2one → mis.report.instancecomodel_name='mis.report.instance'ondelete='cascade'required=True -
sequenceIntegerdefault=100 -
sourceSelectiondefault=SRC_ACTUALShelp='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_idMany2one → ir.modelcomodel_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=Falsestore=Truestring='Move lines source' -
source_aml_model_nameCharrelated='source_aml_model_id.model'string='Move lines source model name' -
source_cmpcol_from_idMany2one → mis.report.instance.periodcomodel_name='mis.report.instance.period'string='versus' -
source_cmpcol_to_idMany2one → mis.report.instance.periodcomodel_name='mis.report.instance.period'string='Compare' -
source_sumcol_accdetBooleanstring='Sum account details' -
source_sumcol_idsOne2many → mis.report.instance.period.sumcomodel_name='mis.report.instance.period.sum'inverse_name='period_id'string='Columns to sum' -
subkpi_idsMany2many → mis.report.subkpistring='Sub KPI Filter' args: 'mis.report.subkpi' -
typeSelectionstring='Period type' args: [('d', 'Day'), ('w', 'Week'), ('m', 'Month'), ('y', 'Year'), ('date_range', 'Date Range')] -
validBooleancompute='_compute_dates'type='boolean'
-
copy_data(self, default=None)
New fields (3)
-
period_idMany2one → mis.report.instance.periodcomodel_name='mis.report.instance.period'ondelete='cascade'required=Truestring='Parent column' -
period_to_sum_idMany2one → mis.report.instance.periodcomodel_name='mis.report.instance.period'ondelete='restrict'required=Truestring='Column' -
signSelectiondefault='+'required=True args: [('+', '+'), ('-', '-')]
No public methods.
New fields (14)
-
accumulation_methodSelectiondefault=ACC_SUMhelp='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_accountsBooleanstring='Display details by account' -
auto_expand_accounts_style_idMany2one → mis.report.stylecomodel_name='mis.report.style'required=Falsestring='Style for account detail rows' -
compare_methodSelectiondefault=CMP_PCTrequired=Truestring='Comparison Method' args: [(CMP_DIFF, 'Difference'), (CMP_PCT, 'Percentage'), (CMP_NONE, 'None')] -
descriptionCharrequired=Truetranslate=True -
expressionCharcompute='_compute_expression'inverse='_inverse_expression' -
expression_idsOne2many → mis.report.kpi.expressioncomodel_name='mis.report.kpi.expression'copy=Trueinverse_name='kpi_id'string='Expressions' -
multiBoolean -
nameCharrequired=True -
report_idMany2one → mis.reportondelete='cascade'required=True args: 'mis.report' -
sequenceIntegerdefault=100 -
style_expressionCharhelp='An expression that returns a style depending on the KPI value. Such style is applied on top of the row style.' -
style_idMany2one → mis.report.stylecomodel_name='mis.report.style'required=False -
typeSelectiondefault=TYPE_NUMrequired=Truestring='Value type' args: [(TYPE_NUM, 'Numeric'), (TYPE_PCT, 'Percentage'), (TYPE_STR, 'String')]
No public methods.
New fields (4)
-
kpi_idMany2one → mis.report.kpiondelete='cascade'required=True args: 'mis.report.kpi' -
nameCharstring='Expression' -
sequenceIntegerrelated='subkpi_id.sequence'store=True -
subkpi_idMany2one → mis.report.subkpiondelete='cascade'readonly=False args: 'mis.report.subkpi'
No public methods.
New fields (9)
-
aggregateSelectionargs: [('sum', 'Sum'), ('avg', 'Average'), ('min', 'Min'), ('max', 'Max')] -
company_field_idMany2one → ir.model.fieldscomodel_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_fieldMany2one → ir.model.fieldscomodel_name='ir.model.fields'domain="[('ttype', 'in', ('date', 'datetime')),('model_id', '=', model_id)]"ondelete='cascade'required=True -
domainChar -
field_idsMany2many → ir.model.fieldsrequired=Truestring='Fields to fetch' args: 'ir.model.fields' -
field_namesCharcompute='_compute_field_names'string='Fetched fields name' -
model_idMany2one → ir.modelondelete='cascade'required=True args: 'ir.model' -
nameCharrequired=True -
report_idMany2one → mis.reportcomodel_name='mis.report'ondelete='cascade'required=True
No public methods.
New fields (26)
-
background_colorChardefault='#FFFFFF'help='Background color in valid RGB code (from #000000 to #FFFFFF)' -
background_color_inheritBooleandefault=True -
colorChardefault='#000000'help='Text color in valid RGB code (from #000000 to #FFFFFF)'string='Text color' -
color_inheritBooleandefault=True -
descriptionHtmlcompute='_compute_description'help='Describe specific values that are not inherited' -
dividerSelectiondefault='1'string='Factor' args: [('1e-6', 'µ'), ('1e-3', 'm'), ('1', '1'), ('1e3', 'k'), ('1e6', 'M')] -
divider_inheritBooleandefault=True -
dpIntegerdefault=0string='Rounding' -
dp_inheritBooleandefault=True -
font_sizeSelectionselection=_font_size_selection -
font_size_inheritBooleandefault=True -
font_styleSelectionselection=_font_style_selection -
font_style_inheritBooleandefault=True -
font_weightSelectionselection=_font_weight_selection -
font_weight_inheritBooleandefault=True -
hide_alwaysBooleandefault=False -
hide_always_inheritBooleandefault=True -
hide_emptyBooleandefault=False -
hide_empty_inheritBooleandefault=True -
indent_levelInteger -
indent_level_inheritBooleandefault=True -
nameCharrequired=Truestring='Style name' -
prefixChar -
prefix_inheritBooleandefault=True -
suffixChar -
suffix_inheritBooleandefault=True
-
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.modelMerge 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)
-
descriptionCharrequired=Truetranslate=True -
expression_idsOne2many → mis.report.kpi.expressionargs: 'mis.report.kpi.expression', 'subkpi_id' -
nameCharrequired=True -
report_idMany2one → mis.reportcomodel_name='mis.report'ondelete='cascade'required=True -
sequenceIntegerdefault=1
No public methods.
New fields (3)
-
nameCharrequired=True -
report_idMany2one → mis.reportcomodel_name='mis.report'ondelete='cascade'required=True -
subreport_idMany2one → mis.reportcomodel_name='mis.report'ondelete='restrict'required=True
No public methods.
New fields (3)
-
dateDatecompute=<expr>help='Dummy field that adapts searches on date to searches on date_from/date_to.'search='_search_date' -
date_fromDaterequired=True -
date_toDaterequired=True
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…