[IMP] account_asset_management: Add reporting
This commit is contained in:
parent
0d332ba006
commit
e4796d3bd5
@ -1,2 +1,3 @@
|
|||||||
from . import models
|
from . import models
|
||||||
|
from . import report
|
||||||
from . import wizard
|
from . import wizard
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright 2009-2018 Noviat
|
# Copyright 2009-2019 Noviat
|
||||||
# Copyright 2019 Tecnativa - Pedro M. Baeza
|
# Copyright 2019 Tecnativa - Pedro M. Baeza
|
||||||
# Copyright 2021 Tecnativa - João Marques
|
# Copyright 2021 Tecnativa - João Marques
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
@ -7,7 +7,7 @@
|
|||||||
"name": "Assets Management",
|
"name": "Assets Management",
|
||||||
"version": "14.0.1.0.4",
|
"version": "14.0.1.0.4",
|
||||||
"license": "AGPL-3",
|
"license": "AGPL-3",
|
||||||
"depends": ["account"],
|
"depends": ["account", "report_xlsx_helper"],
|
||||||
"excludes": ["account_asset"],
|
"excludes": ["account_asset"],
|
||||||
"external_dependencies": {"python": ["python-dateutil"]},
|
"external_dependencies": {"python": ["python-dateutil"]},
|
||||||
"author": "Noviat, Odoo Community Association (OCA)",
|
"author": "Noviat, Odoo Community Association (OCA)",
|
||||||
@ -26,5 +26,6 @@
|
|||||||
"views/account_move_line.xml",
|
"views/account_move_line.xml",
|
||||||
"views/menuitem.xml",
|
"views/menuitem.xml",
|
||||||
"data/cron.xml",
|
"data/cron.xml",
|
||||||
|
"wizard/wiz_account_asset_report.xml",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
@ -1202,3 +1202,85 @@ class AccountAsset(models.Model):
|
|||||||
triggers.sudo().write(recompute_vals)
|
triggers.sudo().write(recompute_vals)
|
||||||
|
|
||||||
return (result, error_log)
|
return (result, error_log)
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def _xls_acquisition_fields(self):
|
||||||
|
"""
|
||||||
|
Update list in custom module to add/drop columns or change order
|
||||||
|
"""
|
||||||
|
return [
|
||||||
|
"account",
|
||||||
|
"name",
|
||||||
|
"code",
|
||||||
|
"date_start",
|
||||||
|
"depreciation_base",
|
||||||
|
"salvage_value",
|
||||||
|
]
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def _xls_active_fields(self):
|
||||||
|
"""
|
||||||
|
Update list in custom module to add/drop columns or change order
|
||||||
|
"""
|
||||||
|
return [
|
||||||
|
"account",
|
||||||
|
"name",
|
||||||
|
"code",
|
||||||
|
"date_start",
|
||||||
|
"depreciation_base",
|
||||||
|
"salvage_value",
|
||||||
|
"period_start_value",
|
||||||
|
"period_depr",
|
||||||
|
"period_end_value",
|
||||||
|
"period_end_depr",
|
||||||
|
"method",
|
||||||
|
"method_number",
|
||||||
|
"prorata",
|
||||||
|
"state",
|
||||||
|
]
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def _xls_removal_fields(self):
|
||||||
|
"""
|
||||||
|
Update list in custom module to add/drop columns or change order
|
||||||
|
"""
|
||||||
|
return [
|
||||||
|
"account",
|
||||||
|
"name",
|
||||||
|
"code",
|
||||||
|
"date_remove",
|
||||||
|
"depreciation_base",
|
||||||
|
"salvage_value",
|
||||||
|
]
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def _xls_asset_template(self):
|
||||||
|
"""
|
||||||
|
Template updates
|
||||||
|
|
||||||
|
"""
|
||||||
|
return {}
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def _xls_acquisition_template(self):
|
||||||
|
"""
|
||||||
|
Template updates
|
||||||
|
|
||||||
|
"""
|
||||||
|
return {}
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def _xls_active_template(self):
|
||||||
|
"""
|
||||||
|
Template updates
|
||||||
|
|
||||||
|
"""
|
||||||
|
return {}
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def _xls_removal_template(self):
|
||||||
|
"""
|
||||||
|
Template updates
|
||||||
|
|
||||||
|
"""
|
||||||
|
return {}
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
# Copyright 2009-2018 Noviat
|
# Copyright 2009-2020 Noviat
|
||||||
# Copyright 2019 Tecnativa - Pedro M. Baeza
|
# Copyright 2019 Tecnativa - Pedro M. Baeza
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
from odoo import api, fields, models
|
from odoo import api, fields, models
|
||||||
|
from odoo.osv import expression
|
||||||
|
|
||||||
|
|
||||||
class AccountAssetGroup(models.Model):
|
class AccountAssetGroup(models.Model):
|
||||||
_name = "account.asset.group"
|
_name = "account.asset.group"
|
||||||
_description = "Asset Group"
|
_description = "Asset Group"
|
||||||
_order = "name"
|
_order = "code, name"
|
||||||
_parent_store = True
|
_parent_store = True
|
||||||
|
|
||||||
name = fields.Char(string="Name", size=64, required=True, index=True)
|
name = fields.Char(string="Name", size=64, required=True, index=True)
|
||||||
@ -25,7 +26,53 @@ class AccountAssetGroup(models.Model):
|
|||||||
string="Parent Asset Group",
|
string="Parent Asset Group",
|
||||||
ondelete="restrict",
|
ondelete="restrict",
|
||||||
)
|
)
|
||||||
|
child_ids = fields.One2many(
|
||||||
|
comodel_name="account.asset.group",
|
||||||
|
inverse_name="parent_id",
|
||||||
|
string="Child Asset Groups",
|
||||||
|
)
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _default_company_id(self):
|
def _default_company_id(self):
|
||||||
return self.env.company
|
return self.env.company
|
||||||
|
|
||||||
|
def name_get(self):
|
||||||
|
result = []
|
||||||
|
params = self.env.context.get("params")
|
||||||
|
list_view = params and params.get("view_type") == "list"
|
||||||
|
short_name_len = 16
|
||||||
|
for rec in self:
|
||||||
|
if rec.code:
|
||||||
|
full_name = rec.code + " " + rec.name
|
||||||
|
short_name = rec.code
|
||||||
|
else:
|
||||||
|
full_name = rec.name
|
||||||
|
if len(full_name) > short_name_len:
|
||||||
|
short_name = full_name[:16] + "..."
|
||||||
|
else:
|
||||||
|
short_name = full_name
|
||||||
|
if list_view:
|
||||||
|
name = short_name
|
||||||
|
else:
|
||||||
|
name = full_name
|
||||||
|
result.append((rec.id, name))
|
||||||
|
return result
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def _name_search(
|
||||||
|
self, name, args=None, operator="ilike", limit=100, name_get_uid=None
|
||||||
|
):
|
||||||
|
args = args or []
|
||||||
|
domain = []
|
||||||
|
if name:
|
||||||
|
domain = [
|
||||||
|
"|",
|
||||||
|
("code", "=ilike", name.split(" ")[0] + "%"),
|
||||||
|
("name", operator, name),
|
||||||
|
]
|
||||||
|
if operator in expression.NEGATIVE_TERM_OPERATORS:
|
||||||
|
domain = ["&", "!"] + domain[1:]
|
||||||
|
rec_ids = self._search(
|
||||||
|
expression.AND([domain, args]), limit=limit, access_rights_uid=name_get_uid
|
||||||
|
)
|
||||||
|
return self.browse(rec_ids).name_get()
|
||||||
|
@ -15,7 +15,5 @@ or automatically by two ways:
|
|||||||
|
|
||||||
These options are compatibles each other.
|
These options are compatibles each other.
|
||||||
|
|
||||||
Excel based reporting is available via the 'account_asset_management_xls' module.
|
|
||||||
|
|
||||||
The module contains a large number of functional enhancements compared to
|
The module contains a large number of functional enhancements compared to
|
||||||
the standard account_asset module from Odoo.
|
the standard account_asset module from Odoo.
|
||||||
|
1
account_asset_management/report/__init__.py
Normal file
1
account_asset_management/report/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
from . import account_asset_report_xls
|
684
account_asset_management/report/account_asset_report_xls.py
Normal file
684
account_asset_management/report/account_asset_report_xls.py
Normal file
@ -0,0 +1,684 @@
|
|||||||
|
# Copyright 2009-2019 Noviat
|
||||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from odoo import _, models
|
||||||
|
from odoo.exceptions import UserError
|
||||||
|
from odoo.tools.translate import translate
|
||||||
|
|
||||||
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
IR_TRANSLATION_NAME = "account.asset.report"
|
||||||
|
|
||||||
|
|
||||||
|
class AssetReportXlsx(models.AbstractModel):
|
||||||
|
_name = "report.account_asset_management.asset_report_xls"
|
||||||
|
_description = "Dynamic XLS asset report generator"
|
||||||
|
_inherit = "report.report_xlsx.abstract"
|
||||||
|
|
||||||
|
def _(self, src):
|
||||||
|
lang = self.env.context.get("lang", "en_US")
|
||||||
|
val = translate(self.env.cr, IR_TRANSLATION_NAME, "report", lang, src) or src
|
||||||
|
return val
|
||||||
|
|
||||||
|
def _get_ws_params(self, wb, data, wiz):
|
||||||
|
self._grouped_assets = self._get_assets(wiz)
|
||||||
|
s1 = self._get_acquisition_ws_params(wb, data, wiz)
|
||||||
|
s2 = self._get_active_ws_params(wb, data, wiz)
|
||||||
|
s3 = self._get_removal_ws_params(wb, data, wiz)
|
||||||
|
return [s1, s2, s3]
|
||||||
|
|
||||||
|
def _get_asset_template(self):
|
||||||
|
|
||||||
|
asset_template = {
|
||||||
|
"account": {
|
||||||
|
"header": {"type": "string", "value": self._("Account")},
|
||||||
|
"asset": {
|
||||||
|
"type": "string",
|
||||||
|
"value": self._render("asset.profile_id.account_asset_id.code"),
|
||||||
|
},
|
||||||
|
"totals": {"type": "string", "value": self._("Totals")},
|
||||||
|
"width": 20,
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"header": {"type": "string", "value": self._("Name")},
|
||||||
|
"asset_group": {
|
||||||
|
"type": "string",
|
||||||
|
"value": self._render("group.name or ''"),
|
||||||
|
},
|
||||||
|
"asset": {"type": "string", "value": self._render("asset.name")},
|
||||||
|
"width": 40,
|
||||||
|
},
|
||||||
|
"code": {
|
||||||
|
"header": {"type": "string", "value": self._("Reference")},
|
||||||
|
"asset_group": {
|
||||||
|
"type": "string",
|
||||||
|
"value": self._render("group.code or ''"),
|
||||||
|
},
|
||||||
|
"asset": {"type": "string", "value": self._render("asset.code or ''")},
|
||||||
|
"width": 20,
|
||||||
|
},
|
||||||
|
"date_start": {
|
||||||
|
"header": {"type": "string", "value": self._("Asset Start Date")},
|
||||||
|
"asset": {
|
||||||
|
"value": self._render("asset.date_start"),
|
||||||
|
"format": self.format_tcell_date_left,
|
||||||
|
},
|
||||||
|
"width": 20,
|
||||||
|
},
|
||||||
|
"date_remove": {
|
||||||
|
"header": {"type": "string", "value": self._("Asset Removal Date")},
|
||||||
|
"asset": {
|
||||||
|
"value": self._render("asset.date_remove"),
|
||||||
|
"format": self.format_tcell_date_left,
|
||||||
|
},
|
||||||
|
"width": 20,
|
||||||
|
},
|
||||||
|
"depreciation_base": {
|
||||||
|
"header": {
|
||||||
|
"type": "string",
|
||||||
|
"value": self._("Depreciation Base"),
|
||||||
|
"format": self.format_theader_yellow_right,
|
||||||
|
},
|
||||||
|
"asset_group": {
|
||||||
|
"type": "number",
|
||||||
|
"value": self._render("group._depreciation_base"),
|
||||||
|
"format": self.format_theader_blue_amount_right,
|
||||||
|
},
|
||||||
|
"asset": {
|
||||||
|
"type": "number",
|
||||||
|
"value": self._render("asset.depreciation_base"),
|
||||||
|
"format": self.format_tcell_amount_right,
|
||||||
|
},
|
||||||
|
"totals": {
|
||||||
|
"type": "formula",
|
||||||
|
"value": self._render("asset_total_formula"),
|
||||||
|
"format": self.format_theader_yellow_amount_right,
|
||||||
|
},
|
||||||
|
"width": 18,
|
||||||
|
},
|
||||||
|
"salvage_value": {
|
||||||
|
"header": {
|
||||||
|
"type": "string",
|
||||||
|
"value": self._("Salvage Value"),
|
||||||
|
"format": self.format_theader_yellow_right,
|
||||||
|
},
|
||||||
|
"asset_group": {
|
||||||
|
"type": "number",
|
||||||
|
"value": self._render("group._salvage_value"),
|
||||||
|
"format": self.format_theader_blue_amount_right,
|
||||||
|
},
|
||||||
|
"asset": {
|
||||||
|
"type": "number",
|
||||||
|
"value": self._render("asset.salvage_value"),
|
||||||
|
"format": self.format_tcell_amount_right,
|
||||||
|
},
|
||||||
|
"totals": {
|
||||||
|
"type": "formula",
|
||||||
|
"value": self._render("salvage_total_formula"),
|
||||||
|
"format": self.format_theader_yellow_amount_right,
|
||||||
|
},
|
||||||
|
"width": 18,
|
||||||
|
},
|
||||||
|
"period_start_value": {
|
||||||
|
"header": {
|
||||||
|
"type": "string",
|
||||||
|
"value": self._("Period Start Value"),
|
||||||
|
"format": self.format_theader_yellow_right,
|
||||||
|
},
|
||||||
|
"asset_group": {
|
||||||
|
"type": "number",
|
||||||
|
"value": self._render("group._period_start_value"),
|
||||||
|
"format": self.format_theader_blue_amount_right,
|
||||||
|
},
|
||||||
|
"asset": {
|
||||||
|
"type": "number",
|
||||||
|
"value": self._render("asset._period_start_value"),
|
||||||
|
"format": self.format_tcell_amount_right,
|
||||||
|
},
|
||||||
|
"totals": {
|
||||||
|
"type": "formula",
|
||||||
|
"value": self._render("period_start_total_formula"),
|
||||||
|
"format": self.format_theader_yellow_amount_right,
|
||||||
|
},
|
||||||
|
"width": 18,
|
||||||
|
},
|
||||||
|
"period_depr": {
|
||||||
|
"header": {
|
||||||
|
"type": "string",
|
||||||
|
"value": self._("Period Depreciation"),
|
||||||
|
"format": self.format_theader_yellow_right,
|
||||||
|
},
|
||||||
|
"asset_group": {
|
||||||
|
"type": "formula",
|
||||||
|
"value": self._render("period_diff_formula"),
|
||||||
|
"format": self.format_theader_blue_amount_right,
|
||||||
|
},
|
||||||
|
"asset": {
|
||||||
|
"type": "formula",
|
||||||
|
"value": self._render("period_diff_formula"),
|
||||||
|
"format": self.format_tcell_amount_right,
|
||||||
|
},
|
||||||
|
"totals": {
|
||||||
|
"type": "formula",
|
||||||
|
"value": self._render("period_diff_formula"),
|
||||||
|
"format": self.format_theader_yellow_amount_right,
|
||||||
|
},
|
||||||
|
"width": 18,
|
||||||
|
},
|
||||||
|
"period_end_value": {
|
||||||
|
"header": {
|
||||||
|
"type": "string",
|
||||||
|
"value": self._("Period End Value"),
|
||||||
|
"format": self.format_theader_yellow_right,
|
||||||
|
},
|
||||||
|
"asset_group": {
|
||||||
|
"type": "number",
|
||||||
|
"value": self._render("group._period_end_value"),
|
||||||
|
"format": self.format_theader_blue_amount_right,
|
||||||
|
},
|
||||||
|
"asset": {
|
||||||
|
"type": "number",
|
||||||
|
"value": self._render("asset._period_end_value"),
|
||||||
|
"format": self.format_tcell_amount_right,
|
||||||
|
},
|
||||||
|
"totals": {
|
||||||
|
"type": "formula",
|
||||||
|
"value": self._render("period_end_total_formula"),
|
||||||
|
"format": self.format_theader_yellow_amount_right,
|
||||||
|
},
|
||||||
|
"width": 18,
|
||||||
|
},
|
||||||
|
"period_end_depr": {
|
||||||
|
"header": {
|
||||||
|
"type": "string",
|
||||||
|
"value": self._("Tot. Depreciation"),
|
||||||
|
"format": self.format_theader_yellow_right,
|
||||||
|
},
|
||||||
|
"asset_group": {
|
||||||
|
"type": "formula",
|
||||||
|
"value": self._render("total_depr_formula"),
|
||||||
|
"format": self.format_theader_blue_amount_right,
|
||||||
|
},
|
||||||
|
"asset": {
|
||||||
|
"type": "formula",
|
||||||
|
"value": self._render("total_depr_formula"),
|
||||||
|
"format": self.format_tcell_amount_right,
|
||||||
|
},
|
||||||
|
"totals": {
|
||||||
|
"type": "formula",
|
||||||
|
"value": self._render("total_depr_formula"),
|
||||||
|
"format": self.format_theader_yellow_amount_right,
|
||||||
|
},
|
||||||
|
"width": 18,
|
||||||
|
},
|
||||||
|
"method": {
|
||||||
|
"header": {
|
||||||
|
"type": "string",
|
||||||
|
"value": self._("Comput. Method"),
|
||||||
|
"format": self.format_theader_yellow_center,
|
||||||
|
},
|
||||||
|
"asset": {
|
||||||
|
"type": "string",
|
||||||
|
"value": self._render("asset.method or ''"),
|
||||||
|
"format": self.format_tcell_center,
|
||||||
|
},
|
||||||
|
"width": 20,
|
||||||
|
},
|
||||||
|
"method_number": {
|
||||||
|
"header": {
|
||||||
|
"type": "string",
|
||||||
|
"value": self._("Number of Years"),
|
||||||
|
"format": self.format_theader_yellow_center,
|
||||||
|
},
|
||||||
|
"asset": {
|
||||||
|
"type": "number",
|
||||||
|
"value": self._render("asset.method_number"),
|
||||||
|
"format": self.format_tcell_integer_center,
|
||||||
|
},
|
||||||
|
"width": 20,
|
||||||
|
},
|
||||||
|
"prorata": {
|
||||||
|
"header": {
|
||||||
|
"type": "string",
|
||||||
|
"value": self._("Prorata Temporis"),
|
||||||
|
"format": self.format_theader_yellow_center,
|
||||||
|
},
|
||||||
|
"asset": {
|
||||||
|
"type": "boolean",
|
||||||
|
"value": self._render("asset.prorata"),
|
||||||
|
"format": self.format_tcell_center,
|
||||||
|
},
|
||||||
|
"width": 20,
|
||||||
|
},
|
||||||
|
"state": {
|
||||||
|
"header": {
|
||||||
|
"type": "string",
|
||||||
|
"value": self._("Status"),
|
||||||
|
"format": self.format_theader_yellow_center,
|
||||||
|
},
|
||||||
|
"asset": {
|
||||||
|
"type": "string",
|
||||||
|
"value": self._render("asset.state"),
|
||||||
|
"format": self.format_tcell_center,
|
||||||
|
},
|
||||||
|
"width": 8,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
asset_template.update(self.env["account.asset"]._xls_asset_template())
|
||||||
|
|
||||||
|
return asset_template
|
||||||
|
|
||||||
|
def _get_acquisition_ws_params(self, wb, data, wiz):
|
||||||
|
|
||||||
|
acquisition_template = self._get_asset_template()
|
||||||
|
acquisition_template.update(
|
||||||
|
self.env["account.asset"]._xls_acquisition_template()
|
||||||
|
)
|
||||||
|
wl_acq = self.env["account.asset"]._xls_acquisition_fields()
|
||||||
|
title = self._get_title(wiz, "acquisition", format="normal")
|
||||||
|
title_short = self._get_title(wiz, "acquisition", format="short")
|
||||||
|
sheet_name = title_short[:31].replace("/", "-")
|
||||||
|
|
||||||
|
return {
|
||||||
|
"ws_name": sheet_name,
|
||||||
|
"generate_ws_method": "_asset_report",
|
||||||
|
"title": title,
|
||||||
|
"wanted_list": wl_acq,
|
||||||
|
"col_specs": acquisition_template,
|
||||||
|
"report_type": "acquisition",
|
||||||
|
}
|
||||||
|
|
||||||
|
def _get_active_ws_params(self, wb, data, wiz):
|
||||||
|
|
||||||
|
active_template = self._get_asset_template()
|
||||||
|
active_template.update(self.env["account.asset"]._xls_active_template())
|
||||||
|
wl_act = self.env["account.asset"]._xls_active_fields()
|
||||||
|
title = self._get_title(wiz, "active", format="normal")
|
||||||
|
title_short = self._get_title(wiz, "active", format="short")
|
||||||
|
sheet_name = title_short[:31].replace("/", "-")
|
||||||
|
|
||||||
|
return {
|
||||||
|
"ws_name": sheet_name,
|
||||||
|
"generate_ws_method": "_asset_report",
|
||||||
|
"title": title,
|
||||||
|
"wanted_list": wl_act,
|
||||||
|
"col_specs": active_template,
|
||||||
|
"report_type": "active",
|
||||||
|
}
|
||||||
|
|
||||||
|
def _get_removal_ws_params(self, wb, data, wiz):
|
||||||
|
|
||||||
|
removal_template = self._get_asset_template()
|
||||||
|
removal_template.update(self.env["account.asset"]._xls_removal_template())
|
||||||
|
wl_dsp = self.env["account.asset"]._xls_removal_fields()
|
||||||
|
title = self._get_title(wiz, "removal", format="normal")
|
||||||
|
title_short = self._get_title(wiz, "removal", format="short")
|
||||||
|
sheet_name = title_short[:31].replace("/", "-")
|
||||||
|
|
||||||
|
return {
|
||||||
|
"ws_name": sheet_name,
|
||||||
|
"generate_ws_method": "_asset_report",
|
||||||
|
"title": title,
|
||||||
|
"wanted_list": wl_dsp,
|
||||||
|
"col_specs": removal_template,
|
||||||
|
"report_type": "removal",
|
||||||
|
}
|
||||||
|
|
||||||
|
def _get_title(self, wiz, report, format="normal"):
|
||||||
|
|
||||||
|
prefix = "{} - {}".format(wiz.date_from, wiz.date_to)
|
||||||
|
if report == "acquisition":
|
||||||
|
if format == "normal":
|
||||||
|
title = prefix + " : " + _("New Acquisitions")
|
||||||
|
else:
|
||||||
|
title = "ACQ"
|
||||||
|
elif report == "active":
|
||||||
|
if format == "normal":
|
||||||
|
title = prefix + " : " + _("Active Assets")
|
||||||
|
else:
|
||||||
|
title = "ACT"
|
||||||
|
else:
|
||||||
|
if format == "normal":
|
||||||
|
title = prefix + " : " + _("Removed Assets")
|
||||||
|
else:
|
||||||
|
title = "DSP"
|
||||||
|
return title
|
||||||
|
|
||||||
|
def _report_title(self, ws, row_pos, ws_params, data, wiz):
|
||||||
|
return self._write_ws_title(ws, row_pos, ws_params)
|
||||||
|
|
||||||
|
def _empty_report(self, ws, row_pos, ws_params, data, wiz):
|
||||||
|
report = ws_params["report_type"]
|
||||||
|
if report == "acquisition":
|
||||||
|
suffix = _("New Acquisitions")
|
||||||
|
elif report == "active":
|
||||||
|
suffix = _("Active Assets")
|
||||||
|
else:
|
||||||
|
suffix = _("Removed Assets")
|
||||||
|
no_entries = _("No") + " " + suffix
|
||||||
|
ws.write_string(row_pos, 0, no_entries, self.format_left_bold)
|
||||||
|
|
||||||
|
def _get_assets(self, wiz):
|
||||||
|
|
||||||
|
dom = [
|
||||||
|
("date_start", "<=", wiz.date_to),
|
||||||
|
"|",
|
||||||
|
("date_remove", "=", False),
|
||||||
|
("date_remove", ">=", wiz.date_from),
|
||||||
|
]
|
||||||
|
|
||||||
|
parent_group = wiz.asset_group_id
|
||||||
|
if parent_group:
|
||||||
|
|
||||||
|
def _child_get(parent):
|
||||||
|
groups = [parent]
|
||||||
|
children = parent.child_ids
|
||||||
|
children = children.sorted(lambda r: r.code or r.name)
|
||||||
|
for child in children:
|
||||||
|
if child in groups:
|
||||||
|
raise UserError(
|
||||||
|
_(
|
||||||
|
"Inconsistent reporting structure."
|
||||||
|
"\nPlease correct Asset Group '%s' (id %s)"
|
||||||
|
)
|
||||||
|
% (child.name, child.id)
|
||||||
|
)
|
||||||
|
groups.extend(_child_get(child))
|
||||||
|
return groups
|
||||||
|
|
||||||
|
groups = _child_get(parent_group)
|
||||||
|
dom.append(("group_ids", "in", [x.id for x in groups]))
|
||||||
|
|
||||||
|
if not wiz.draft:
|
||||||
|
dom.append(("state", "!=", "draft"))
|
||||||
|
self._assets = self.env["account.asset"].search(dom)
|
||||||
|
grouped_assets = {}
|
||||||
|
self._group_assets(self._assets, parent_group, grouped_assets)
|
||||||
|
return grouped_assets
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def acquisition_filter(wiz, asset):
|
||||||
|
return asset.date_start >= wiz.date_from
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def active_filter(wiz, asset):
|
||||||
|
return True
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def removal_filter(wiz, asset):
|
||||||
|
return (
|
||||||
|
asset.date_remove
|
||||||
|
and asset.date_remove >= wiz.date_from
|
||||||
|
and asset.date_remove <= wiz.date_to
|
||||||
|
)
|
||||||
|
|
||||||
|
def _group_assets(self, assets, group, grouped_assets):
|
||||||
|
if group:
|
||||||
|
group_assets = assets.filtered(lambda r: group in r.group_ids)
|
||||||
|
else:
|
||||||
|
group_assets = assets
|
||||||
|
group_assets = group_assets.sorted(lambda r: (r.date_start or "", r.code))
|
||||||
|
grouped_assets[group] = {"assets": group_assets}
|
||||||
|
for child in group.child_ids:
|
||||||
|
self._group_assets(assets, child, grouped_assets[group])
|
||||||
|
|
||||||
|
def _create_report_entries(
|
||||||
|
self, ws_params, wiz, entries, group, group_val, error_dict
|
||||||
|
):
|
||||||
|
report = ws_params["report_type"]
|
||||||
|
|
||||||
|
def asset_filter(asset):
|
||||||
|
filter = getattr(self, "{}_filter".format(report))
|
||||||
|
return filter(wiz, asset)
|
||||||
|
|
||||||
|
def _has_assets(group, group_val):
|
||||||
|
assets = group_val.get("assets")
|
||||||
|
assets = assets.filtered(asset_filter)
|
||||||
|
if assets:
|
||||||
|
return True
|
||||||
|
for child in group.child_ids:
|
||||||
|
if _has_assets(child, group_val[child]):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
assets = group_val.get("assets")
|
||||||
|
assets = assets.filtered(asset_filter)
|
||||||
|
|
||||||
|
# remove empty entries
|
||||||
|
if not _has_assets(group, group_val):
|
||||||
|
return
|
||||||
|
|
||||||
|
asset_entries = []
|
||||||
|
group._depreciation_base = 0.0
|
||||||
|
group._salvage_value = 0.0
|
||||||
|
group._period_start_value = 0.0
|
||||||
|
group._period_end_value = 0.0
|
||||||
|
for asset in assets:
|
||||||
|
group._depreciation_base += asset.depreciation_base
|
||||||
|
group._salvage_value += asset.salvage_value
|
||||||
|
dls_all = asset.depreciation_line_ids.filtered(
|
||||||
|
lambda r: r.type == "depreciate"
|
||||||
|
)
|
||||||
|
dls_all = dls_all.sorted(key=lambda r: r.line_date)
|
||||||
|
if not dls_all:
|
||||||
|
error_dict["no_table"] += asset
|
||||||
|
# period_start_value
|
||||||
|
dls = dls_all.filtered(lambda r: r.line_date <= wiz.date_from)
|
||||||
|
if dls:
|
||||||
|
value_depreciated = dls[-1].depreciated_value + dls[-1].amount
|
||||||
|
else:
|
||||||
|
value_depreciated = 0.0
|
||||||
|
asset._period_start_value = asset.depreciation_base - value_depreciated
|
||||||
|
group._period_start_value += asset._period_start_value
|
||||||
|
# period_end_value
|
||||||
|
dls = dls_all.filtered(lambda r: r.line_date <= wiz.date_to)
|
||||||
|
if dls:
|
||||||
|
value_depreciated = dls[-1].depreciated_value + dls[-1].amount
|
||||||
|
else:
|
||||||
|
value_depreciated = 0.0
|
||||||
|
asset._period_end_value = asset.depreciation_base - value_depreciated
|
||||||
|
group._period_end_value += asset._period_end_value
|
||||||
|
|
||||||
|
asset_entries.append({"asset": asset})
|
||||||
|
|
||||||
|
todos = []
|
||||||
|
for g in group.child_ids:
|
||||||
|
if _has_assets(g, group_val[g]):
|
||||||
|
todos.append(g)
|
||||||
|
|
||||||
|
entries.append({"group": group})
|
||||||
|
entries.extend(asset_entries)
|
||||||
|
for todo in todos:
|
||||||
|
self._create_report_entries(
|
||||||
|
ws_params, wiz, entries, todo, group_val[todo], error_dict
|
||||||
|
)
|
||||||
|
|
||||||
|
def _asset_report(self, workbook, ws, ws_params, data, wiz):
|
||||||
|
report = ws_params["report_type"]
|
||||||
|
|
||||||
|
ws.set_portrait()
|
||||||
|
ws.fit_to_pages(1, 0)
|
||||||
|
ws.set_header(self.xls_headers["standard"])
|
||||||
|
ws.set_footer(self.xls_footers["standard"])
|
||||||
|
|
||||||
|
wl = ws_params["wanted_list"]
|
||||||
|
if "account" not in wl:
|
||||||
|
raise UserError(
|
||||||
|
_(
|
||||||
|
"The 'account' field is a mandatory entry of the "
|
||||||
|
"'_xls_%s_fields' list !"
|
||||||
|
)
|
||||||
|
% report
|
||||||
|
)
|
||||||
|
|
||||||
|
self._set_column_width(ws, ws_params)
|
||||||
|
|
||||||
|
row_pos = 0
|
||||||
|
row_pos = self._report_title(ws, row_pos, ws_params, data, wiz)
|
||||||
|
|
||||||
|
def asset_filter(asset):
|
||||||
|
filter = getattr(self, "{}_filter".format(report))
|
||||||
|
return filter(wiz, asset)
|
||||||
|
|
||||||
|
assets = self._assets.filtered(asset_filter)
|
||||||
|
|
||||||
|
if not assets:
|
||||||
|
return self._empty_report(ws, row_pos, ws_params, data, wiz)
|
||||||
|
|
||||||
|
row_pos = self._write_line(
|
||||||
|
ws,
|
||||||
|
row_pos,
|
||||||
|
ws_params,
|
||||||
|
col_specs_section="header",
|
||||||
|
default_format=self.format_theader_yellow_left,
|
||||||
|
)
|
||||||
|
|
||||||
|
ws.freeze_panes(row_pos, 0)
|
||||||
|
|
||||||
|
row_pos_start = row_pos
|
||||||
|
depreciation_base_pos = "depreciation_base" in wl and wl.index(
|
||||||
|
"depreciation_base"
|
||||||
|
)
|
||||||
|
salvage_value_pos = "salvage_value" in wl and wl.index("salvage_value")
|
||||||
|
period_start_value_pos = "period_start_value" in wl and wl.index(
|
||||||
|
"period_start_value"
|
||||||
|
)
|
||||||
|
period_end_value_pos = "period_end_value" in wl and wl.index("period_end_value")
|
||||||
|
|
||||||
|
entries = []
|
||||||
|
root = wiz.asset_group_id
|
||||||
|
root_val = self._grouped_assets[root]
|
||||||
|
error_dict = {
|
||||||
|
"no_table": self.env["account.asset"],
|
||||||
|
"dups": self.env["account.asset"],
|
||||||
|
}
|
||||||
|
|
||||||
|
self._create_report_entries(ws_params, wiz, entries, root, root_val, error_dict)
|
||||||
|
|
||||||
|
# traverse entries in reverse order to calc totals
|
||||||
|
for i, entry in enumerate(reversed(entries)):
|
||||||
|
group = entry.get("group")
|
||||||
|
if "group" in entry:
|
||||||
|
parent = group.parent_id
|
||||||
|
for e in reversed(entries[: -i - 1]):
|
||||||
|
g = e.get("group")
|
||||||
|
if g == parent:
|
||||||
|
g._depreciation_base += group._depreciation_base
|
||||||
|
g._salvage_value += group._salvage_value
|
||||||
|
g._period_start_value += group._period_start_value
|
||||||
|
g._period_end_value += group._period_end_value
|
||||||
|
continue
|
||||||
|
|
||||||
|
processed = []
|
||||||
|
for entry in entries:
|
||||||
|
|
||||||
|
period_start_value_cell = period_start_value_pos and self._rowcol_to_cell(
|
||||||
|
row_pos, period_start_value_pos
|
||||||
|
)
|
||||||
|
period_end_value_cell = period_end_value_pos and self._rowcol_to_cell(
|
||||||
|
row_pos, period_end_value_pos
|
||||||
|
)
|
||||||
|
depreciation_base_cell = depreciation_base_pos and self._rowcol_to_cell(
|
||||||
|
row_pos, depreciation_base_pos
|
||||||
|
)
|
||||||
|
period_diff_formula = period_end_value_cell and (
|
||||||
|
period_start_value_cell + "-" + period_end_value_cell
|
||||||
|
)
|
||||||
|
total_depr_formula = period_end_value_cell and (
|
||||||
|
depreciation_base_cell + "-" + period_end_value_cell
|
||||||
|
)
|
||||||
|
|
||||||
|
if "group" in entry:
|
||||||
|
row_pos = self._write_line(
|
||||||
|
ws,
|
||||||
|
row_pos,
|
||||||
|
ws_params,
|
||||||
|
col_specs_section="asset_group",
|
||||||
|
render_space={
|
||||||
|
"group": entry["group"],
|
||||||
|
"period_diff_formula": period_diff_formula,
|
||||||
|
"total_depr_formula": total_depr_formula,
|
||||||
|
},
|
||||||
|
default_format=self.format_theader_blue_left,
|
||||||
|
)
|
||||||
|
|
||||||
|
else:
|
||||||
|
asset = entry["asset"]
|
||||||
|
if asset in processed:
|
||||||
|
error_dict["dups"] += asset
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
processed.append(asset)
|
||||||
|
row_pos = self._write_line(
|
||||||
|
ws,
|
||||||
|
row_pos,
|
||||||
|
ws_params,
|
||||||
|
col_specs_section="asset",
|
||||||
|
render_space={
|
||||||
|
"asset": asset,
|
||||||
|
"period_diff_formula": period_diff_formula,
|
||||||
|
"total_depr_formula": total_depr_formula,
|
||||||
|
},
|
||||||
|
default_format=self.format_tcell_left,
|
||||||
|
)
|
||||||
|
|
||||||
|
asset_total_formula = depreciation_base_pos and self._rowcol_to_cell(
|
||||||
|
row_pos_start, depreciation_base_pos
|
||||||
|
)
|
||||||
|
salvage_total_formula = salvage_value_pos and self._rowcol_to_cell(
|
||||||
|
row_pos_start, salvage_value_pos
|
||||||
|
)
|
||||||
|
period_start_total_formula = period_start_value_pos and self._rowcol_to_cell(
|
||||||
|
row_pos_start, period_start_value_pos
|
||||||
|
)
|
||||||
|
period_end_total_formula = period_end_value_pos and self._rowcol_to_cell(
|
||||||
|
row_pos_start, period_end_value_pos
|
||||||
|
)
|
||||||
|
period_start_value_cell = period_start_value_pos and self._rowcol_to_cell(
|
||||||
|
row_pos, period_start_value_pos
|
||||||
|
)
|
||||||
|
period_end_value_cell = period_end_value_pos and self._rowcol_to_cell(
|
||||||
|
row_pos, period_end_value_pos
|
||||||
|
)
|
||||||
|
depreciation_base_cell = depreciation_base_pos and self._rowcol_to_cell(
|
||||||
|
row_pos, depreciation_base_pos
|
||||||
|
)
|
||||||
|
period_diff_formula = period_end_value_cell and (
|
||||||
|
period_start_value_cell + "-" + period_end_value_cell
|
||||||
|
)
|
||||||
|
total_depr_formula = period_end_value_cell and (
|
||||||
|
depreciation_base_cell + "-" + period_end_value_cell
|
||||||
|
)
|
||||||
|
|
||||||
|
row_pos = self._write_line(
|
||||||
|
ws,
|
||||||
|
row_pos,
|
||||||
|
ws_params,
|
||||||
|
col_specs_section="totals",
|
||||||
|
render_space={
|
||||||
|
"asset_total_formula": asset_total_formula,
|
||||||
|
"salvage_total_formula": salvage_total_formula,
|
||||||
|
"period_start_total_formula": period_start_total_formula,
|
||||||
|
"period_end_total_formula": period_end_total_formula,
|
||||||
|
"period_diff_formula": period_diff_formula,
|
||||||
|
"total_depr_formula": total_depr_formula,
|
||||||
|
},
|
||||||
|
default_format=self.format_theader_yellow_left,
|
||||||
|
)
|
||||||
|
|
||||||
|
for k in error_dict:
|
||||||
|
if error_dict[k]:
|
||||||
|
if k == "no_table":
|
||||||
|
reason = _("Missing depreciation table")
|
||||||
|
elif k == "dups":
|
||||||
|
reason = _("Duplicate reporting entries")
|
||||||
|
else:
|
||||||
|
reason = _("Undetermined error")
|
||||||
|
row_pos += 1
|
||||||
|
err_msg = _("Assets to be corrected") + ": "
|
||||||
|
err_msg += "%s" % [x[1] for x in error_dict[k].name_get()]
|
||||||
|
err_msg += " - " + _("Reason") + ": " + reason
|
||||||
|
ws.write_string(row_pos, 0, err_msg, self.format_left_bold)
|
@ -15,3 +15,4 @@ access_account_asset_group_user,account.asset.group,model_account_asset_group,ac
|
|||||||
access_account_asset_group_manager,account.asset.group,model_account_asset_group,account.group_account_manager,1,1,1,1
|
access_account_asset_group_manager,account.asset.group,model_account_asset_group,account.group_account_manager,1,1,1,1
|
||||||
access_account_asset_remove_user,account.asset.remove,model_account_asset_remove,account.group_account_user,1,1,1,1
|
access_account_asset_remove_user,account.asset.remove,model_account_asset_remove,account.group_account_user,1,1,1,1
|
||||||
access_account_asset_compute_user,account.asset.compute,model_account_asset_compute,account.group_account_user,1,1,1,1
|
access_account_asset_compute_user,account.asset.compute,model_account_asset_compute,account.group_account_user,1,1,1,1
|
||||||
|
access_wiz_account_asset_report,wiz.account.asset.report,model_wiz_account_asset_report,account.group_account_readonly,1,1,1,0
|
||||||
|
|
@ -1 +1,2 @@
|
|||||||
from . import test_account_asset_management
|
from . import test_account_asset_management
|
||||||
|
from . import test_asset_management_xls
|
||||||
|
37
account_asset_management/tests/test_asset_management_xls.py
Normal file
37
account_asset_management/tests/test_asset_management_xls.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# Copyright 2009-2019 Noviat.
|
||||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
|
from odoo import fields
|
||||||
|
from odoo.tests.common import SavepointCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestAssetManagementXls(SavepointCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
super(TestAssetManagementXls, cls).setUpClass()
|
||||||
|
|
||||||
|
module = __name__.split("addons.")[1].split(".")[0]
|
||||||
|
cls.xls_report_name = "{}.asset_report_xls".format(module)
|
||||||
|
cls.wiz_model = cls.env["wiz.account.asset.report"]
|
||||||
|
cls.company = cls.env.ref("base.main_company")
|
||||||
|
asset_group_id = cls.wiz_model._default_asset_group_id()
|
||||||
|
fy_dates = cls.company.compute_fiscalyear_dates(fields.date.today())
|
||||||
|
|
||||||
|
wiz_vals = {
|
||||||
|
"asset_group_id": asset_group_id,
|
||||||
|
"date_from": fy_dates["date_from"],
|
||||||
|
"date_to": fy_dates["date_to"],
|
||||||
|
}
|
||||||
|
cls.xls_report = cls.wiz_model.create(wiz_vals)
|
||||||
|
cls.report_action = cls.xls_report.xls_export()
|
||||||
|
|
||||||
|
def test_01_action_xls(self):
|
||||||
|
""" Check report XLS action """
|
||||||
|
self.assertGreaterEqual(
|
||||||
|
self.report_action.items(),
|
||||||
|
{
|
||||||
|
"type": "ir.actions.report",
|
||||||
|
"report_type": "xlsx",
|
||||||
|
"report_name": self.xls_report_name,
|
||||||
|
}.items(),
|
||||||
|
)
|
@ -315,6 +315,7 @@
|
|||||||
<field name="date_remove" />
|
<field name="date_remove" />
|
||||||
<field name="profile_id" />
|
<field name="profile_id" />
|
||||||
<field name="state" />
|
<field name="state" />
|
||||||
|
<field name="group_ids" widget="many2many_tags" />
|
||||||
<field name="company_id" groups="base.group_multi_company" />
|
<field name="company_id" groups="base.group_multi_company" />
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
@ -353,6 +354,7 @@
|
|||||||
<field name="code" />
|
<field name="code" />
|
||||||
<field name="date_start" />
|
<field name="date_start" />
|
||||||
<field name="profile_id" />
|
<field name="profile_id" />
|
||||||
|
<field name="group_ids" />
|
||||||
<field
|
<field
|
||||||
name="partner_id"
|
name="partner_id"
|
||||||
filter_domain="[('partner_id', 'child_of', self)]"
|
filter_domain="[('partner_id', 'child_of', self)]"
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
from . import account_asset_compute
|
from . import account_asset_compute
|
||||||
from . import account_asset_remove
|
from . import account_asset_remove
|
||||||
|
from . import wiz_account_asset_report
|
||||||
|
73
account_asset_management/wizard/wiz_account_asset_report.py
Normal file
73
account_asset_management/wizard/wiz_account_asset_report.py
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
# Copyright 2009-2019 Noviat
|
||||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
|
import unicodedata
|
||||||
|
|
||||||
|
from odoo import _, api, fields, models
|
||||||
|
from odoo.exceptions import UserError
|
||||||
|
|
||||||
|
|
||||||
|
class WizAccountAssetReport(models.TransientModel):
|
||||||
|
_name = "wiz.account.asset.report"
|
||||||
|
_description = "Financial Assets report"
|
||||||
|
|
||||||
|
asset_group_id = fields.Many2one(
|
||||||
|
comodel_name="account.asset.group",
|
||||||
|
string="Asset Group",
|
||||||
|
default=lambda self: self._default_asset_group_id(),
|
||||||
|
)
|
||||||
|
date_from = fields.Date(string="Start Date", required=True)
|
||||||
|
date_to = fields.Date(string="End Date", required=True)
|
||||||
|
draft = fields.Boolean(string="Include draft assets")
|
||||||
|
company_id = fields.Many2one(
|
||||||
|
comodel_name="res.company",
|
||||||
|
string="Company",
|
||||||
|
required=True,
|
||||||
|
default=lambda self: self._default_company_id(),
|
||||||
|
)
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def _default_asset_group_id(self):
|
||||||
|
return (
|
||||||
|
self.env["account.asset.group"]
|
||||||
|
.search([("parent_id", "=", False)], limit=1)
|
||||||
|
.id
|
||||||
|
)
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def _default_company_id(self):
|
||||||
|
return self.env.user.company_id
|
||||||
|
|
||||||
|
@api.onchange("company_id")
|
||||||
|
def _onchange_company_id(self):
|
||||||
|
fy_dates = self.company_id.compute_fiscalyear_dates(fields.date.today())
|
||||||
|
self.date_from = fy_dates["date_from"]
|
||||||
|
self.date_to = fy_dates["date_to"]
|
||||||
|
|
||||||
|
@api.constrains("date_from", "date_to")
|
||||||
|
def _check_dates(self):
|
||||||
|
for wiz in self:
|
||||||
|
if wiz.date_to <= wiz.date_from:
|
||||||
|
raise UserError(_("The Start Date must precede the Ending Date."))
|
||||||
|
|
||||||
|
def xls_export(self):
|
||||||
|
self.ensure_one()
|
||||||
|
report_name = "account_asset_management.asset_report_xls"
|
||||||
|
if self.asset_group_id:
|
||||||
|
prefix = (
|
||||||
|
unicodedata.normalize("NFKD", self.asset_group_id.name)
|
||||||
|
.encode("ascii", "ignore")
|
||||||
|
.decode("ascii")
|
||||||
|
)
|
||||||
|
prefix = "".join(x for x in prefix if x.isalnum())
|
||||||
|
report_file = "{}_asset_report".format(prefix)
|
||||||
|
else:
|
||||||
|
report_file = "asset_report"
|
||||||
|
report = {
|
||||||
|
"type": "ir.actions.report",
|
||||||
|
"report_type": "xlsx",
|
||||||
|
"report_name": report_name,
|
||||||
|
"context": dict(self.env.context, report_file=report_file),
|
||||||
|
"data": {"dynamic_report": True},
|
||||||
|
}
|
||||||
|
return report
|
52
account_asset_management/wizard/wiz_account_asset_report.xml
Normal file
52
account_asset_management/wizard/wiz_account_asset_report.xml
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<odoo>
|
||||||
|
<record id="wiz_account_asset_report_view_form" model="ir.ui.view">
|
||||||
|
<field name="name">Financial Assets report</field>
|
||||||
|
<field name="model">wiz.account.asset.report</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="Financial Assets report">
|
||||||
|
<group col="2" colspan="4">
|
||||||
|
<field
|
||||||
|
name="asset_group_id"
|
||||||
|
options="{'no_create_edit': True, 'no_create': True}"
|
||||||
|
/>
|
||||||
|
<field name="date_from" />
|
||||||
|
<field name="date_to" />
|
||||||
|
<field name="draft" />
|
||||||
|
<field name="company_id" groups="base.group_multi_company" />
|
||||||
|
</group>
|
||||||
|
<footer>
|
||||||
|
<button
|
||||||
|
name="xls_export"
|
||||||
|
string="Generate Report"
|
||||||
|
type="object"
|
||||||
|
default_focus="1"
|
||||||
|
class="oe_highlight"
|
||||||
|
/>
|
||||||
|
or
|
||||||
|
<button string="Cancel" class="oe_link" special="cancel" />
|
||||||
|
</footer>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
<record id="wiz_account_asset_report_action" model="ir.actions.act_window">
|
||||||
|
<field name="name">Financial Assets report</field>
|
||||||
|
<field name="type">ir.actions.act_window</field>
|
||||||
|
<field name="res_model">wiz.account.asset.report</field>
|
||||||
|
<field name="view_mode">form</field>
|
||||||
|
<field name="view_id" ref="wiz_account_asset_report_view_form" />
|
||||||
|
<field name="target">new</field>
|
||||||
|
</record>
|
||||||
|
<menuitem
|
||||||
|
id="account_asset_report_menu"
|
||||||
|
name="Financial Assets"
|
||||||
|
parent="account.menu_finance_reports"
|
||||||
|
/>
|
||||||
|
<menuitem
|
||||||
|
id="wiz_account_asset_report_menu"
|
||||||
|
name="Financial Assets report"
|
||||||
|
parent="account_asset_report_menu"
|
||||||
|
action="wiz_account_asset_report_action"
|
||||||
|
sequence="200"
|
||||||
|
/>
|
||||||
|
</odoo>
|
Loading…
Reference in New Issue
Block a user