Skip to content

Commit

Permalink
Merge pull request #69 from Escodoo/14.0-add-mis_builder_kpi_code
Browse files Browse the repository at this point in the history
[14.0][ADD] mis_builder_kpi_code: add new module
  • Loading branch information
marcelsavegnago authored May 2, 2024
2 parents 50e09a9 + 974aa48 commit d6e4fa8
Show file tree
Hide file tree
Showing 21 changed files with 966 additions and 0 deletions.
71 changes: 71 additions & 0 deletions mis_builder_kpi_code/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
====================
MIS Builder KPI Code
====================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:de0015ad668a8823ac2513115d7e71cae0d60124519c91a708190607873cbf07
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-Escodoo%2Faccount--addons-lightgray.png?logo=github
:target: https://github.com/Escodoo/account-addons/tree/14.0/mis_builder_kpi_code
:alt: Escodoo/account-addons

|badge1| |badge2| |badge3|

This module includes the option to fill in the code field when creating a KPI in the MIS Report Template. This code field will be visible in the MIS Report Preview in the first column and will also be included when exporting documents to PDF or XLSX formats.

**Table of contents**

.. contents::
:local:

Usage
=====

To use this module, you need to:

1. Fill in the code field when creating or editing a KPI in a MIS Report Template.
2. Open a MIS Report using this Template and see the new column in Preview Mode or in the exported PDF or XLSX files.

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/Escodoo/account-addons/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/Escodoo/account-addons/issues/new?body=module:%20mis_builder_kpi_code%0Aversion:%2014.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Do not contact contributors directly about support or help with technical issues.

Credits
=======

Authors
~~~~~~~

* Escodoo

Contributors
~~~~~~~~~~~~

* `Escodoo <https://www.escodoo.com.br>`_:

* Marcel Savegnago <[email protected]>
* Wesley Oliveira <[email protected]>

Maintainers
~~~~~~~~~~~

This module is part of the `Escodoo/account-addons <https://github.com/Escodoo/account-addons/tree/14.0/mis_builder_kpi_code>`_ project on GitHub.

You are welcome to contribute.
2 changes: 2 additions & 0 deletions mis_builder_kpi_code/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import models
from . import report
21 changes: 21 additions & 0 deletions mis_builder_kpi_code/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Copyright 2024 - TODAY, Escodoo
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

{
"name": "MIS Builder KPI Code",
"summary": """
MIS Builder KPI Code""",
"version": "14.0.1.0.0",
"license": "AGPL-3",
"author": "Escodoo",
"website": "https://github.com/Escodoo/account-addons",
"depends": ["mis_builder"],
"data": [
"views/mis_report.xml",
"report/mis_report_instance_qweb.xml",
],
"qweb": [
"static/src/xml/mis_report_widget.xml",
],
"demo": [],
}
2 changes: 2 additions & 0 deletions mis_builder_kpi_code/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import mis_report
from . import mis_report_instance
11 changes: 11 additions & 0 deletions mis_builder_kpi_code/models/mis_report.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Copyright 2024 - TODAY, Wesley Oliveira <[email protected]>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo import fields, models


class MisReportKpi(models.Model):

_inherit = "mis.report.kpi"

code = fields.Char()
30 changes: 30 additions & 0 deletions mis_builder_kpi_code/models/mis_report_instance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Copyright 2024 - TODAY, Wesley Oliveira <[email protected]>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo import models


class MisReportInstance(models.Model):

_inherit = "mis.report.instance"

def compute(self):
self.ensure_one()
kpi_matrix = self._compute_matrix()
kpi_matrix_dict = kpi_matrix.as_dict()

empty_col = [{"label": "", "description": "", "colspan": 1}]
kpi_matrix_dict["header"][0]["cols"] = (
empty_col + kpi_matrix_dict["header"][0]["cols"]
)
kpi_matrix_dict["header"][1]["cols"] = (
empty_col + kpi_matrix_dict["header"][1]["cols"]
)

for idx, row in enumerate(kpi_matrix_dict["body"]):
code = self.report_id.kpi_ids.filtered(
lambda k: k.name == row["row_id"]
).code
kpi_matrix_dict["body"][idx].update({"code": code})

return kpi_matrix_dict
4 changes: 4 additions & 0 deletions mis_builder_kpi_code/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
* `Escodoo <https://www.escodoo.com.br>`_:

* Marcel Savegnago <[email protected]>
* Wesley Oliveira <[email protected]>
1 change: 1 addition & 0 deletions mis_builder_kpi_code/readme/DESCRIPTION.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This module includes the option to fill in the code field when creating a KPI in the MIS Report Template. This code field will be visible in the MIS Report Preview in the first column and will also be included when exporting documents to PDF or XLSX formats.
4 changes: 4 additions & 0 deletions mis_builder_kpi_code/readme/USAGE.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
To use this module, you need to:

1. Fill in the code field when creating or editing a KPI in a MIS Report Template.
2. Open a MIS Report using this Template and see the new column in Preview Mode or in the exported PDF or XLSX files.
1 change: 1 addition & 0 deletions mis_builder_kpi_code/report/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import mis_report_instance_xlsx
49 changes: 49 additions & 0 deletions mis_builder_kpi_code/report/mis_report_instance_qweb.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!-- Copyright 2024 - TODAY, Wesley Oliveira <[email protected]>
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<odoo>
<template
id="assets_report"
name="mis_builder_kpi_code"
inherit_id="web.report_assets_common"
>
<xpath expr="." position="inside">
<link
href="/mis_builder_kpi_code/static/src/css/report.css"
rel="stylesheet"
/>
</xpath>
</template>
<template
id="report_mis_report_instance"
inherit_id="mis_builder.report_mis_report_instance"
>
<xpath
expr="//div[hasclass('mis_thead')]/div[hasclass('mis_row')][1]/div[hasclass('mis_collabel')][1]"
position="before"
>
<div class="mis_cell mis_collabel" />
</xpath>
<xpath
expr="//div[hasclass('mis_thead')]/div[hasclass('mis_row')][2]/div[hasclass('mis_collabel')][1]"
position="before"
>
<div class="mis_cell mis_collabel" />
</xpath>
<xpath
expr="//div[hasclass('mis_tbody')]/t[@t-as='row']/div[hasclass('mis_row')]/div[hasclass('mis_rowlabel')]"
position="before"
>
<div
t-att-style="style_obj.to_css_style(row.style_props)"
class="mis_cell mis_rowlabel"
>
<t
t-set="code"
t-value="o.report_id.kpi_ids.filtered(lambda k: k.id == row.kpi.id).code"
/>
<t t-esc="code or ''" />
</div>
</xpath>
</template>
</odoo>
181 changes: 181 additions & 0 deletions mis_builder_kpi_code/report/mis_report_instance_xlsx.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
# Copyright 2024 - TODAY, Wesley Oliveira <[email protected]>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

import logging
import numbers
from collections import defaultdict
from datetime import datetime

from odoo import _, fields, models

from odoo.addons.mis_builder.models.accounting_none import AccountingNone
from odoo.addons.mis_builder.models.data_error import DataError
from odoo.addons.mis_builder.models.mis_report_style import TYPE_STR

_logger = logging.getLogger(__name__)


ROW_HEIGHT = 15 # xlsxwriter units
COL_WIDTH = 0.9 # xlsxwriter units
MIN_COL_WIDTH = 10 # characters
MAX_COL_WIDTH = 50 # characters


class MisBuilderXlsx(models.AbstractModel):
_inherit = "report.mis_builder.mis_report_instance_xlsx"

def generate_xlsx_report(self, workbook, data, objects):

# get the computed result of the report
matrix = objects._compute_matrix()
style_obj = self.env["mis.report.style"]

# create worksheet
report_name = "{} - {}".format(
objects[0].name, ", ".join([a.name for a in objects[0].query_company_ids])
)
sheet = workbook.add_worksheet(report_name[:31])
row_pos = 0
col_pos = 0
# width of the labels column
label_col_width = MIN_COL_WIDTH
# {col_pos: max width in characters}
col_width = defaultdict(lambda: MIN_COL_WIDTH)

# document title
bold = workbook.add_format({"bold": True})
header_format = workbook.add_format(
{"bold": True, "align": "center", "bg_color": "#F0EEEE"}
)
sheet.write(row_pos, 0, report_name, bold)
row_pos += 2

# filters
if not objects.hide_analytic_filters:
for filter_description in objects.get_filter_descriptions_from_context():
sheet.write(row_pos, 0, filter_description)
row_pos += 1
row_pos += 1

# column headers
sheet.write(row_pos, 0, "", header_format)
sheet.write(row_pos, 1, "", header_format)
col_pos = 2
for col in matrix.iter_cols():
label = col.label
if col.description:
label += "\n" + col.description
sheet.set_row(row_pos, ROW_HEIGHT * 2)
if col.colspan > 1:
sheet.merge_range(
row_pos,
col_pos,
row_pos,
col_pos + col.colspan - 1,
label,
header_format,
)
else:
sheet.write(row_pos, col_pos, label, header_format)
col_width[col_pos] = max(
col_width[col_pos], len(col.label or ""), len(col.description or "")
)
col_pos += col.colspan
row_pos += 1

# sub column headers
sheet.write(row_pos, 0, "", header_format)
sheet.write(row_pos, 1, "", header_format)
col_pos = 2
for subcol in matrix.iter_subcols():
label = subcol.label
if subcol.description:
label += "\n" + subcol.description
sheet.set_row(row_pos, ROW_HEIGHT * 2)
sheet.write(row_pos, col_pos, label, header_format)
col_width[col_pos] = max(
col_width[col_pos],
len(subcol.label or ""),
len(subcol.description or ""),
)
col_pos += 1
row_pos += 1

# rows
for row in matrix.iter_rows():
if (
row.style_props.hide_empty and row.is_empty()
) or row.style_props.hide_always:
continue
row_xlsx_style = style_obj.to_xlsx_style(TYPE_STR, row.style_props)
row_format = workbook.add_format(row_xlsx_style)
col_pos = 0

code = (
objects[0].report_id.kpi_ids.filtered(lambda k: k.id == row.kpi.id).code
)
sheet.write(row_pos, col_pos, code, row_format)
col_pos += 1

label = row.label
if row.description:
label += "\n" + row.description
sheet.set_row(row_pos, ROW_HEIGHT * 2)
sheet.write(row_pos, col_pos, label, row_format)
label_col_width = max(
label_col_width, len(row.label or ""), len(row.description or "")
)
for cell in row.iter_cells():
col_pos += 1
if not cell or cell.val is AccountingNone:
# TODO col/subcol format
sheet.write(row_pos, col_pos, "", row_format)
continue
cell_xlsx_style = style_obj.to_xlsx_style(
cell.val_type, cell.style_props, no_indent=True
)
cell_xlsx_style["align"] = "right"
cell_format = workbook.add_format(cell_xlsx_style)
if isinstance(cell.val, DataError):
val = cell.val.name
# TODO display cell.val.msg as Excel comment?
elif cell.val is None or cell.val is AccountingNone:
val = ""
else:
divider = float(cell.style_props.get("divider", 1))
if (
divider != 1
and isinstance(cell.val, numbers.Number)
and not cell.val_type == "pct"
):
val = cell.val / divider
else:
val = cell.val
sheet.write(row_pos, col_pos, val, cell_format)
col_width[col_pos] = max(
col_width[col_pos], len(cell.val_rendered or "")
)
row_pos += 1

# Add date/time footer
row_pos += 1
footer_format = workbook.add_format(
{"italic": True, "font_color": "#202020", "size": 9}
)
lang_model = self.env["res.lang"]
lang = lang_model._lang_get(self.env.user.lang)

now_tz = fields.Datetime.context_timestamp(
self.env["res.users"], datetime.now()
)
create_date = _("Generated on {} at {}").format(
now_tz.strftime(lang.date_format), now_tz.strftime(lang.time_format)
)
sheet.write(row_pos, 0, create_date, footer_format)

# adjust col widths
sheet.set_column(0, 1, min(label_col_width, MAX_COL_WIDTH) * COL_WIDTH)
data_col_width = min(MAX_COL_WIDTH, max(col_width.values()))
min_col_pos = min(col_width.keys())
max_col_pos = max(col_width.keys())
sheet.set_column(min_col_pos, max_col_pos, data_col_width * COL_WIDTH)
Binary file added mis_builder_kpi_code/static/description/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit d6e4fa8

Please sign in to comment.