Browse Source
Merge pull request #449 from Noviat/10-aml_report_xls
Merge pull request #449 from Noviat/10-aml_report_xls
[10.0][MIG]account_move_line_export_xlspull/423/merge
Pedro M. Baeza
6 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 550 additions and 518 deletions
-
25account_move_line_report_xls/README.rst
-
31account_move_line_report_xls/__init__.py
-
32account_move_line_report_xls/__manifest__.py
-
57account_move_line_report_xls/account_move_line.py
-
15account_move_line_report_xls/i18n/fr.po
-
15account_move_line_report_xls/i18n/nl.po
-
2account_move_line_report_xls/models/__init__.py
-
49account_move_line_report_xls/models/account_move_line.py
-
23account_move_line_report_xls/report/__init__.py
-
721account_move_line_report_xls/report/move_line_list_xls.py
-
34account_move_line_report_xls/report/move_line_list_xls.xml
-
39account_move_line_report_xls/static/description/index.html
-
2account_move_line_report_xls/tests/__init__.py
-
21account_move_line_report_xls/tests/test_aml_report_xlsx.py
@ -1,30 +1,9 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# |
|||
# Copyright (c) 2014 Noviat nv/sa (www.noviat.com). All rights reserved. |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
# -*- coding: utf-8 -*- |
|||
from . import models |
|||
try: |
|||
from . import account_move_line |
|||
from . import report |
|||
except ImportError: |
|||
import logging |
|||
logging.getLogger('openerp.module').\ |
|||
warning('''report_xls not available in addons path. |
|||
account_financial_report_webkit_xls will not be usable''') |
|||
logging.getLogger('odoo.module').\ |
|||
warning('''report_xlsx_helper not available in addons path. |
|||
account_move_line_report_xls will not be usable''') |
@ -1,35 +1,17 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# |
|||
# Copyright (c) 2014 Noviat nv/sa (www.noviat.com). All rights reserved. |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2009-2018 Noviat. |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
|||
|
|||
{ |
|||
'name': 'Account Move Line XLS export', |
|||
'version': '8.0.0.6.0', |
|||
'name': 'Account Move Line XLSX export', |
|||
'version': '10.0.1.0.0', |
|||
'license': 'AGPL-3', |
|||
'author': "Noviat, Odoo Community Association (OCA)", |
|||
'category': 'Accounting & Finance', |
|||
'summary': 'Journal Items Excel export', |
|||
'depends': ['account', 'report_xls'], |
|||
'depends': ['account', 'report_xlsx_helper'], |
|||
'data': [ |
|||
'report/move_line_list_xls.xml', |
|||
], |
|||
'installable': False, |
|||
'installable': True, |
|||
} |
@ -1,57 +0,0 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# |
|||
# Copyright (c) 2014 Noviat nv/sa (www.noviat.com). All rights reserved. |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
from openerp import models, api |
|||
|
|||
|
|||
class account_move_line(models.Model): |
|||
_inherit = 'account.move.line' |
|||
|
|||
# override list in custom module to add/drop columns or change order |
|||
@api.model |
|||
def _report_xls_fields(self): |
|||
return [ |
|||
'move', 'name', 'date', 'journal', 'period', 'partner', 'account', |
|||
'date_maturity', 'debit', 'credit', 'balance', |
|||
'reconcile', 'reconcile_partial', 'analytic_account', |
|||
# 'ref', 'partner_ref', 'tax_code', 'tax_amount', |
|||
# 'amount_residual', 'amount_currency', 'currency_name', |
|||
# 'company_currency', 'amount_residual_currency', |
|||
# 'product', 'product_ref', 'product_uom', 'quantity', |
|||
# 'statement', 'invoice', 'narration', 'blocked', |
|||
] |
|||
|
|||
# Change/Add Template entries |
|||
@api.model |
|||
def _report_xls_template(self): |
|||
""" |
|||
Template updates, e.g. |
|||
|
|||
my_change = { |
|||
'move':{ |
|||
'header': [1, 20, 'text', _('My Move Title')], |
|||
'lines': [1, 0, 'text', _render("line.move_id.name or ''")], |
|||
'totals': [1, 0, 'text', None]}, |
|||
} |
|||
return my_change |
|||
""" |
|||
return {} |
@ -0,0 +1,2 @@ |
|||
# -*- coding: utf-8 -*- |
|||
from . import account_move_line |
@ -0,0 +1,49 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2009-2018 Noviat. |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
|||
|
|||
from odoo import api, models |
|||
from odoo.addons.report_xlsx_helper.report.abstract_report_xlsx \ |
|||
import AbstractReportXlsx |
|||
_render = AbstractReportXlsx._render |
|||
|
|||
|
|||
class AccountMoveLine(models.Model): |
|||
_inherit = 'account.move.line' |
|||
|
|||
# Change list in custom module e.g. to add/drop columns or change order |
|||
@api.model |
|||
def _report_xlsx_fields(self): |
|||
return [ |
|||
'move', 'name', 'date', 'journal', 'partner', 'account', |
|||
'date_maturity', 'debit', 'credit', 'balance', |
|||
'full_reconcile', 'reconcile_amount', |
|||
# 'analytic_account_name', 'analytic_account', |
|||
# 'ref', 'partner_ref', |
|||
# 'amount_residual', 'amount_currency', 'currency_name', |
|||
# 'company_currency', 'amount_residual_currency', |
|||
# 'product', 'product_ref', 'product_uom', 'quantity', |
|||
# 'statement', 'invoice', 'narration', 'blocked', |
|||
# 'id', 'matched_debit_ids', 'matched_credit_ids', |
|||
] |
|||
|
|||
# Change/Add Template entries |
|||
@api.model |
|||
def _report_xlsx_template(self): |
|||
""" |
|||
Template updates, e.g. |
|||
|
|||
my_change = { |
|||
'move': { |
|||
'header': { |
|||
'value': 'My Move Title', |
|||
}, |
|||
'lines': { |
|||
'value': _render("line.move_id.name or ''"), |
|||
}, |
|||
'width': 20, |
|||
}, |
|||
} |
|||
return my_change |
|||
""" |
|||
return {} |
@ -1,23 +1,2 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# |
|||
# Copyright (c) 2014 Noviat nv/sa (www.noviat.com). All rights reserved. |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
# -*- coding: utf-8 -*- |
|||
from . import move_line_list_xls |
@ -1,373 +1,450 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# OpenERP, Open Source Management Solution |
|||
# |
|||
# Copyright (c) 2014 Noviat nv/sa (www.noviat.com). All rights reserved. |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2009-2018 Noviat |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
|||
|
|||
import xlwt |
|||
from datetime import datetime |
|||
from openerp.osv import orm |
|||
from openerp.report import report_sxw |
|||
from openerp.addons.report_xls.report_xls import report_xls |
|||
from openerp.addons.report_xls.utils import rowcol_to_cell, _render |
|||
from openerp.tools.translate import translate, _ |
|||
import logging |
|||
_logger = logging.getLogger(__name__) |
|||
|
|||
_ir_translation_name = 'move.line.list.xls' |
|||
|
|||
from odoo.addons.report_xlsx_helper.report.abstract_report_xlsx \ |
|||
import AbstractReportXlsx |
|||
from odoo.report import report_sxw |
|||
from odoo.tools.translate import translate |
|||
|
|||
class move_line_xls_parser(report_sxw.rml_parse): |
|||
|
|||
def __init__(self, cr, uid, name, context): |
|||
super(move_line_xls_parser, self).__init__( |
|||
cr, uid, name, context=context) |
|||
move_obj = self.pool.get('account.move.line') |
|||
self.context = context |
|||
wanted_list = move_obj._report_xls_fields(cr, uid, context) |
|||
template_changes = move_obj._report_xls_template(cr, uid, context) |
|||
self.localcontext.update({ |
|||
'datetime': datetime, |
|||
'wanted_list': wanted_list, |
|||
'template_changes': template_changes, |
|||
'_': self._, |
|||
}) |
|||
_logger = logging.getLogger(__name__) |
|||
|
|||
def _(self, src): |
|||
lang = self.context.get('lang', 'en_US') |
|||
return translate(self.cr, _ir_translation_name, 'report', lang, src) \ |
|||
or src |
|||
IR_TRANSLATION_NAME = 'move.line.list.xls' |
|||
|
|||
|
|||
class move_line_xls(report_xls): |
|||
class MoveLineXlsx(AbstractReportXlsx): |
|||
|
|||
def __init__(self, name, table, rml=False, parser=False, header=True, |
|||
store=False): |
|||
super(move_line_xls, self).__init__( |
|||
name, table, rml, parser, header, store) |
|||
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 |
|||
|
|||
# Cell Styles |
|||
_xs = self.xls_styles |
|||
# header |
|||
rh_cell_format = _xs['bold'] + _xs['fill'] + _xs['borders_all'] |
|||
self.rh_cell_style = xlwt.easyxf(rh_cell_format) |
|||
self.rh_cell_style_center = xlwt.easyxf(rh_cell_format + _xs['center']) |
|||
self.rh_cell_style_right = xlwt.easyxf(rh_cell_format + _xs['right']) |
|||
# lines |
|||
aml_cell_format = _xs['borders_all'] |
|||
self.aml_cell_style = xlwt.easyxf(aml_cell_format) |
|||
self.aml_cell_style_center = xlwt.easyxf( |
|||
aml_cell_format + _xs['center']) |
|||
self.aml_cell_style_date = xlwt.easyxf( |
|||
aml_cell_format + _xs['left'], |
|||
num_format_str=report_xls.date_format) |
|||
self.aml_cell_style_decimal = xlwt.easyxf( |
|||
aml_cell_format + _xs['right'], |
|||
num_format_str=report_xls.decimal_format) |
|||
# totals |
|||
rt_cell_format = _xs['bold'] + _xs['fill'] + _xs['borders_all'] |
|||
self.rt_cell_style = xlwt.easyxf(rt_cell_format) |
|||
self.rt_cell_style_right = xlwt.easyxf(rt_cell_format + _xs['right']) |
|||
self.rt_cell_style_decimal = xlwt.easyxf( |
|||
rt_cell_format + _xs['right'], |
|||
num_format_str=report_xls.decimal_format) |
|||
def _get_ws_params(self, workbook, data, amls): |
|||
|
|||
# XLS Template |
|||
self.col_specs_template = { |
|||
# XLSX Template |
|||
col_specs = { |
|||
'move': { |
|||
'header': [1, 20, 'text', _render("_('Entry')")], |
|||
'lines': [1, 0, 'text', _render("line.move_id.name or ''")], |
|||
'totals': [1, 0, 'text', None]}, |
|||
'header': { |
|||
'value': self._('Entry'), |
|||
}, |
|||
'lines': { |
|||
'value': self._render("line.move_id.name"), |
|||
}, |
|||
'width': 20, |
|||
}, |
|||
'name': { |
|||
'header': [1, 42, 'text', _render("_('Name')")], |
|||
'lines': [1, 0, 'text', _render("line.name or ''")], |
|||
'totals': [1, 0, 'text', None]}, |
|||
'header': { |
|||
'value': self._('Name'), |
|||
}, |
|||
'lines': { |
|||
'value': self._render("line.name"), |
|||
}, |
|||
'width': 42, |
|||
}, |
|||
'ref': { |
|||
'header': [1, 42, 'text', _render("_('Reference')")], |
|||
'lines': [1, 0, 'text', _render("line.ref or ''")], |
|||
'totals': [1, 0, 'text', None]}, |
|||
'header': { |
|||
'value': self._('Reference'), |
|||
}, |
|||
'lines': { |
|||
'value': self._render("line.ref"), |
|||
}, |
|||
'width': 42, |
|||
}, |
|||
'date': { |
|||
'header': [1, 13, 'text', _render("_('Effective Date')")], |
|||
'lines': [1, 0, 'date', |
|||
_render("datetime.strptime(line.date,'%Y-%m-%d')"), |
|||
None, self.aml_cell_style_date], |
|||
'totals': [1, 0, 'text', None]}, |
|||
'period': { |
|||
'header': [1, 12, 'text', _render("_('Period')")], |
|||
'lines': |
|||
[1, 0, 'text', |
|||
_render("line.period_id.code or line.period_id.name")], |
|||
'totals': [1, 0, 'text', None]}, |
|||
'header': { |
|||
'value': self._('Effective Date'), |
|||
}, |
|||
'lines': { |
|||
'value': self._render( |
|||
"datetime.strptime(line.date, '%Y-%m-%d')"), |
|||
'format': self.format_tcell_date_left, |
|||
}, |
|||
'width': 13, |
|||
}, |
|||
'partner': { |
|||
'header': [1, 36, 'text', _render("_('Partner')")], |
|||
'lines': |
|||
[1, 0, 'text', |
|||
_render("line.partner_id and line.partner_id.name or ''")], |
|||
'totals': [1, 0, 'text', None]}, |
|||
'header': { |
|||
'value': self._('Partner'), |
|||
}, |
|||
'lines': { |
|||
'value': self._render( |
|||
"line.partner_id and line.partner_id.name"), |
|||
}, |
|||
'width': 36, |
|||
}, |
|||
'partner_ref': { |
|||
'header': [1, 36, 'text', _render("_('Partner Reference')")], |
|||
'lines': |
|||
[1, 0, 'text', |
|||
_render("line.partner_id and line.partner_id.ref or ''")], |
|||
'totals': [1, 0, 'text', None]}, |
|||
'header': { |
|||
'value': self._('Partner Reference'), |
|||
}, |
|||
'lines': { |
|||
'value': self._render( |
|||
"line.partner_id and line.partner_id.ref"), |
|||
}, |
|||
'width': 36, |
|||
}, |
|||
'account': { |
|||
'header': [1, 12, 'text', _render("_('Account')")], |
|||
'lines': [1, 0, 'text', _render("line.account_id.code")], |
|||
'totals': [1, 0, 'text', None]}, |
|||
'header': { |
|||
'value': self._('Account'), |
|||
}, |
|||
'lines': { |
|||
'value': self._render( |
|||
"line.account_id.code"), |
|||
}, |
|||
'width': 12, |
|||
}, |
|||
'date_maturity': { |
|||
'header': [1, 13, 'text', _render("_('Maturity Date')")], |
|||
'lines': |
|||
[1, 0, |
|||
_render("line.date_maturity and 'date' or 'text'"), |
|||
_render( |
|||
"line.date_maturity" |
|||
" and datetime.strptime(line.date_maturity,'%Y-%m-%d')" |
|||
" or None"), |
|||
None, self.aml_cell_style_date], |
|||
'totals': [1, 0, 'text', None]}, |
|||
'header': { |
|||
'value': self._('Maturity Date'), |
|||
}, |
|||
'lines': { |
|||
'value': self._render( |
|||
"datetime.strptime(line.date_maturity,'%Y-%m-%d')"), |
|||
'format': self.format_tcell_date_left, |
|||
}, |
|||
'width': 13, |
|||
}, |
|||
'debit': { |
|||
'header': [1, 18, 'text', _render("_('Debit')"), None, |
|||
self.rh_cell_style_right], |
|||
'lines': [1, 0, 'number', _render("line.debit"), None, |
|||
self.aml_cell_style_decimal], |
|||
'totals': [1, 0, 'number', None, _render("debit_formula"), |
|||
self.rt_cell_style_decimal]}, |
|||
'header': { |
|||
'value': self._('Debit'), |
|||
'format': self.format_theader_yellow_right, |
|||
}, |
|||
'lines': { |
|||
'value': self._render("line.debit"), |
|||
'format': self.format_tcell_amount_right, |
|||
}, |
|||
'totals': { |
|||
'type': 'formula', |
|||
'value': self._render("debit_formula"), |
|||
'format': self.format_theader_yellow_amount_right, |
|||
}, |
|||
'width': 18, |
|||
}, |
|||
'credit': { |
|||
'header': [1, 18, 'text', _render("_('Credit')"), None, |
|||
self.rh_cell_style_right], |
|||
'lines': [1, 0, 'number', _render("line.credit"), None, |
|||
self.aml_cell_style_decimal], |
|||
'totals': [1, 0, 'number', None, _render("credit_formula"), |
|||
self.rt_cell_style_decimal]}, |
|||
'header': { |
|||
'value': self._('Credit'), |
|||
'format': self.format_theader_yellow_right, |
|||
}, |
|||
'lines': { |
|||
'value': self._render("line.credit"), |
|||
'format': self.format_tcell_amount_right, |
|||
}, |
|||
'totals': { |
|||
'type': 'formula', |
|||
'value': self._render("credit_formula"), |
|||
'format': self.format_theader_yellow_amount_right, |
|||
}, |
|||
'width': 18, |
|||
}, |
|||
'balance': { |
|||
'header': [1, 18, 'text', _render("_('Balance')"), None, |
|||
self.rh_cell_style_right], |
|||
'lines': [1, 0, 'number', None, _render("bal_formula"), |
|||
self.aml_cell_style_decimal], |
|||
'totals': [1, 0, 'number', None, _render("bal_formula"), |
|||
self.rt_cell_style_decimal]}, |
|||
'reconcile': { |
|||
'header': [1, 12, 'text', _render("_('Rec.')"), None, |
|||
self.rh_cell_style_center], |
|||
'lines': [1, 0, 'text', |
|||
_render("line.reconcile_id.name or ''"), None, |
|||
self.aml_cell_style_center], |
|||
'totals': [1, 0, 'text', None]}, |
|||
'reconcile_partial': { |
|||
'header': [1, 12, 'text', _render("_('Part. Rec.')"), None, |
|||
self.rh_cell_style_center], |
|||
'lines': [1, 0, 'text', |
|||
_render("line.reconcile_partial_id.name or ''"), |
|||
None, self.aml_cell_style_center], |
|||
'totals': [1, 0, 'text', None]}, |
|||
'tax_code': { |
|||
'header': [1, 12, 'text', _render("_('Tax Code')"), None, |
|||
self.rh_cell_style_center], |
|||
'lines': [1, 0, 'text', _render("line.tax_code_id.code or ''"), |
|||
None, self.aml_cell_style_center], |
|||
'totals': [1, 0, 'text', None]}, |
|||
'tax_amount': { |
|||
'header': [1, 18, 'text', _render("_('Tax/Base Amount')"), |
|||
None, self.rh_cell_style_right], |
|||
'lines': [1, 0, 'number', _render("line.tax_amount"), None, |
|||
self.aml_cell_style_decimal], |
|||
'totals': [1, 0, 'text', None]}, |
|||
'header': { |
|||
'value': self._('Balance'), |
|||
'format': self.format_theader_yellow_right, |
|||
}, |
|||
'lines': { |
|||
'value': self._render("line.balance"), |
|||
'format': self.format_tcell_amount_right, |
|||
}, |
|||
'totals': { |
|||
'type': 'formula', |
|||
'value': self._render("bal_formula"), |
|||
'format': self.format_theader_yellow_amount_right, |
|||
}, |
|||
'width': 18, |
|||
}, |
|||
'full_reconcile': { |
|||
'header': { |
|||
'value': self._('Rec.'), |
|||
'format': self.format_theader_yellow_center, |
|||
}, |
|||
'lines': { |
|||
'value': self._render( |
|||
"line.full_reconcile_id " |
|||
"and line.full_reconcile_id.name"), |
|||
'format': self.format_tcell_center, |
|||
}, |
|||
'width': 12, |
|||
}, |
|||
'reconcile_amount': { |
|||
'header': { |
|||
'value': self._('Reconcile Amount'), |
|||
}, |
|||
'lines': { |
|||
'value': self._render( |
|||
"line.full_reconcile_id and line.balance or " |
|||
"(sum(line.matched_credit_ids.mapped('amount')) - " |
|||
"sum(line.matched_debit_ids.mapped('amount')))"), |
|||
'format': self.format_tcell_amount_right, |
|||
}, |
|||
'width': 12, |
|||
}, |
|||
'matched_debit_ids': { |
|||
'header': { |
|||
'value': self._('Matched Debits'), |
|||
}, |
|||
'lines': { |
|||
'value': self._render( |
|||
"line.matched_debit_ids " |
|||
"and str([x.debit_move_id.id " |
|||
"for x in line.matched_debit_ids])"), |
|||
}, |
|||
'width': 20, |
|||
}, |
|||
'matched_credit_ids': { |
|||
'header': { |
|||
'value': self._('Matched Credits'), |
|||
}, |
|||
'lines': { |
|||
'value': self._render( |
|||
"line.matched_credit_ids " |
|||
"and str([x.credit_move_id.id " |
|||
"for x in line.matched_credit_ids])"), |
|||
}, |
|||
'width': 20, |
|||
}, |
|||
'amount_currency': { |
|||
'header': [1, 18, 'text', _render("_('Am. Currency')"), None, |
|||
self.rh_cell_style_right], |
|||
'lines': |
|||
[1, 0, |
|||
_render("line.amount_currency and 'number' or 'text'"), |
|||
_render("line.amount_currency or None"), |
|||
None, self.aml_cell_style_decimal], |
|||
'totals': [1, 0, 'text', None]}, |
|||
'header': { |
|||
'value': self._('Am. Currency'), |
|||
'format': self.format_theader_yellow_right, |
|||
}, |
|||
'lines': { |
|||
'value': self._render("line.amount_currency"), |
|||
'format': self.format_tcell_amount_right, |
|||
}, |
|||
'width': 18, |
|||
}, |
|||
'currency_name': { |
|||
'header': [1, 6, 'text', _render("_('Curr.')"), None, |
|||
self.rh_cell_style_center], |
|||
'lines': |
|||
[1, 0, 'text', |
|||
_render("line.currency_id and line.currency_id.name or ''"), |
|||
None, self.aml_cell_style_center], |
|||
'totals': [1, 0, 'text', None]}, |
|||
'header': { |
|||
'value': self._('Curr.'), |
|||
'format': self.format_theader_yellow_center, |
|||
}, |
|||
'lines': { |
|||
'value': self._render( |
|||
"line.currency_id and line.currency_id.name"), |
|||
'format': self.format_tcell_center, |
|||
}, |
|||
'width': 6, |
|||
}, |
|||
'journal': { |
|||
'header': [1, 12, 'text', _render("_('Journal')")], |
|||
'lines': [1, 0, 'text', _render("line.journal_id.code or ''")], |
|||
'totals': [1, 0, 'text', None]}, |
|||
'header': { |
|||
'value': self._('Journal'), |
|||
}, |
|||
'lines': { |
|||
'value': self._render("line.journal_id.code"), |
|||
}, |
|||
'width': 12, |
|||
}, |
|||
'company_currency': { |
|||
'header': [1, 10, 'text', _render("_('Comp. Curr.')")], |
|||
'lines': [1, 0, 'text', |
|||
_render("line.company_id.currency_id.name or ''"), |
|||
None, self.aml_cell_style_center], |
|||
'totals': [1, 0, 'text', None]}, |
|||
'header': { |
|||
'value': self._('Comp. Curr.'), |
|||
'format': self.format_theader_yellow_center, |
|||
}, |
|||
'lines': { |
|||
'value': self._render( |
|||
"line.company_id.currency_id.name"), |
|||
'format': self.format_tcell_center, |
|||
}, |
|||
'width': 10, |
|||
}, |
|||
'analytic_account': { |
|||
'header': [1, 36, 'text', _render("_('Analytic Account')")], |
|||
'lines': [1, 0, 'text', |
|||
_render("line.analytic_account_id.code or ''")], |
|||
'totals': [1, 0, 'text', None]}, |
|||
'header': { |
|||
'value': self._('Analytic Account Reference'), |
|||
}, |
|||
'lines': { |
|||
'value': self._render( |
|||
"line.analytic_account_id " |
|||
"and line.analytic_account_id.code"), |
|||
}, |
|||
'width': 36, |
|||
}, |
|||
'analytic_account_name': { |
|||
'header': { |
|||
'value': self._('Analytic Account'), |
|||
}, |
|||
'lines': { |
|||
'value': self._render( |
|||
"line.analytic_account_id " |
|||
"and line.analytic_account_id.name"), |
|||
}, |
|||
'width': 36, |
|||
}, |
|||
'product': { |
|||
'header': [1, 36, 'text', _render("_('Product')")], |
|||
'lines': [1, 0, 'text', _render("line.product_id.name or ''")], |
|||
'totals': [1, 0, 'text', None]}, |
|||
'header': { |
|||
'value': self._('Product'), |
|||
}, |
|||
'lines': { |
|||
'value': self._render( |
|||
"line.product_id and line.product_id.name"), |
|||
}, |
|||
'width': 36, |
|||
}, |
|||
'product_ref': { |
|||
'header': [1, 36, 'text', _render("_('Product Reference')")], |
|||
'lines': [1, 0, 'text', |
|||
_render("line.product_id.default_code or ''")], |
|||
'totals': [1, 0, 'text', None]}, |
|||
'header': { |
|||
'value': self._('Product Reference'), |
|||
}, |
|||
'lines': { |
|||
'value': self._render( |
|||
"line.product_id and line.product_id.default_code " |
|||
"or ''"), |
|||
}, |
|||
'width': 36, |
|||
}, |
|||
'product_uom': { |
|||
'header': [1, 20, 'text', _render("_('Unit of Measure')")], |
|||
'lines': [1, 0, 'text', |
|||
_render("line.product_uom_id.name or ''")], |
|||
'totals': [1, 0, 'text', None]}, |
|||
'header': { |
|||
'value': self._('Unit of Measure'), |
|||
}, |
|||
'lines': { |
|||
'value': self._render( |
|||
"line.product_uom_id and line.product_uom_id.name"), |
|||
}, |
|||
'width': 20, |
|||
}, |
|||
'quantity': { |
|||
'header': [1, 8, 'text', _render("_('Qty')"), None, |
|||
self.rh_cell_style_right], |
|||
'lines': [1, 0, |
|||
_render("line.quantity and 'number' or 'text'"), |
|||
_render("line.quantity or None"), None, |
|||
self.aml_cell_style_decimal], |
|||
'totals': [1, 0, 'text', None]}, |
|||
'header': { |
|||
'value': self._('Qty'), |
|||
'format': self.format_theader_yellow_right, |
|||
}, |
|||
'lines': { |
|||
'value': self._render("line.quantity"), |
|||
'format': self.format_tcell_amount_right, |
|||
}, |
|||
'width': 8, |
|||
}, |
|||
'statement': { |
|||
'header': [1, 20, 'text', _render("_('Statement')")], |
|||
'lines': |
|||
[1, 0, 'text', |
|||
_render("line.statement_id and line.statement_id.name or ''") |
|||
], |
|||
'totals': [1, 0, 'text', None]}, |
|||
'header': { |
|||
'value': self._('Statement'), |
|||
}, |
|||
'lines': { |
|||
'value': self._render( |
|||
"line.statement_id and line.statement_id.name"), |
|||
}, |
|||
'width': 20, |
|||
}, |
|||
'invoice': { |
|||
'header': [1, 20, 'text', _render("_('Invoice')")], |
|||
'lines': |
|||
[1, 0, 'text', |
|||
_render("line.invoice and line.invoice.number or ''")], |
|||
'totals': [1, 0, 'text', None]}, |
|||
'header': { |
|||
'value': self._('Invoice'), |
|||
}, |
|||
'lines': { |
|||
'value': self._render( |
|||
"line.invoice_id and line.invoice_id.number"), |
|||
}, |
|||
'width': 20, |
|||
}, |
|||
'amount_residual': { |
|||
'header': [1, 18, 'text', _render("_('Residual Amount')"), |
|||
None, self.rh_cell_style_right], |
|||
'lines': |
|||
[1, 0, |
|||
_render("line.amount_residual and 'number' or 'text'"), |
|||
_render("line.amount_residual or None"), |
|||
None, self.aml_cell_style_decimal], |
|||
'totals': [1, 0, 'text', None]}, |
|||
'header': { |
|||
'value': self._('Residual Amount'), |
|||
'format': self.format_theader_yellow_right, |
|||
}, |
|||
'lines': { |
|||
'value': self._render("line.amount_residual"), |
|||
'format': self.format_tcell_amount_right, |
|||
}, |
|||
'width': 18, |
|||
}, |
|||
'amount_residual_currency': { |
|||
'header': [1, 18, 'text', _render("_('Res. Am. in Curr.')"), |
|||
None, self.rh_cell_style_right], |
|||
'lines': |
|||
[1, 0, |
|||
_render( |
|||
"line.amount_residual_currency and 'number' or 'text'"), |
|||
_render("line.amount_residual_currency or None"), |
|||
None, self.aml_cell_style_decimal], |
|||
'totals': [1, 0, 'text', None]}, |
|||
'header': { |
|||
'value': self._('Res. Am. in Curr.'), |
|||
'format': self.format_theader_yellow_right, |
|||
}, |
|||
'lines': { |
|||
'value': self._render("line.amount_residual_currency"), |
|||
'format': self.format_tcell_amount_right, |
|||
}, |
|||
'width': 18, |
|||
}, |
|||
'narration': { |
|||
'header': [1, 42, 'text', _render("_('Notes')")], |
|||
'lines': [1, 0, 'text', |
|||
_render("line.move_id.narration or ''")], |
|||
'totals': [1, 0, 'text', None]}, |
|||
'header': { |
|||
'value': self._('Notes'), |
|||
}, |
|||
'lines': { |
|||
'value': self._render("line.move_id.narration or ''"), |
|||
}, |
|||
'width': 42, |
|||
}, |
|||
'blocked': { |
|||
'header': [1, 4, 'text', _('Lit.'), |
|||
None, self.rh_cell_style_right], |
|||
'lines': [1, 0, 'text', _render("line.blocked and 'x' or ''"), |
|||
None, self.aml_cell_style_center], |
|||
'totals': [1, 0, 'text', None]}, |
|||
'header': { |
|||
'value': self._('Lit.'), |
|||
'format': self.format_theader_yellow_center, |
|||
}, |
|||
'lines': { |
|||
'value': self._render("line.blocked and 'x' or ''"), |
|||
'format': self.format_tcell_center, |
|||
}, |
|||
'width': 4, |
|||
}, |
|||
'id': { |
|||
'header': { |
|||
'value': self._('Id'), |
|||
'format': self.format_theader_yellow_right, |
|||
}, |
|||
'lines': { |
|||
'value': self._render("line.id"), |
|||
'format': self.format_tcell_integer_right, |
|||
}, |
|||
'width': 12, |
|||
}, |
|||
} |
|||
col_specs.update(self.env['account.move.line']._report_xlsx_template()) |
|||
wanted_list = self.env['account.move.line']._report_xlsx_fields() |
|||
title = self._("Journal Items") |
|||
|
|||
def generate_xls_report(self, _p, _xs, data, objects, wb): |
|||
return [{ |
|||
'ws_name': title, |
|||
'generate_ws_method': '_amls_export', |
|||
'title': title, |
|||
'wanted_list': wanted_list, |
|||
'col_specs': col_specs, |
|||
}] |
|||
|
|||
wanted_list = _p.wanted_list |
|||
self.col_specs_template.update(_p.template_changes) |
|||
_ = _p._ |
|||
def _amls_export(self, workbook, ws, ws_params, data, amls): |
|||
|
|||
debit_pos = 'debit' in wanted_list and wanted_list.index('debit') |
|||
credit_pos = 'credit' in wanted_list and wanted_list.index('credit') |
|||
if not (credit_pos and debit_pos) and 'balance' in wanted_list: |
|||
raise orm.except_orm( |
|||
_('Customisation Error!'), |
|||
_("The 'Balance' field is a calculated XLS field requiring \ |
|||
the presence of the 'Debit' and 'Credit' fields !")) |
|||
ws.set_landscape() |
|||
ws.fit_to_pages(1, 0) |
|||
ws.set_header(self.xls_headers['standard']) |
|||
ws.set_footer(self.xls_footers['standard']) |
|||
|
|||
self._set_column_width(ws, ws_params) |
|||
|
|||
# report_name = objects[0]._description or objects[0]._name |
|||
report_name = _("Journal Items") |
|||
ws = wb.add_sheet(report_name[:31]) |
|||
ws.panes_frozen = True |
|||
ws.remove_splits = True |
|||
ws.portrait = 0 # Landscape |
|||
ws.fit_width_to_pages = 1 |
|||
row_pos = 0 |
|||
row_pos = self._write_ws_title(ws, row_pos, ws_params) |
|||
|
|||
# set print header/footer |
|||
ws.header_str = self.xls_headers['standard'] |
|||
ws.footer_str = self.xls_footers['standard'] |
|||
row_pos = self._write_line( |
|||
ws, row_pos, ws_params, col_specs_section='header', |
|||
default_format=self.format_theader_yellow_left) |
|||
|
|||
# Title |
|||
cell_style = xlwt.easyxf(_xs['xls_title']) |
|||
c_specs = [ |
|||
('report_name', 1, 0, 'text', report_name), |
|||
] |
|||
row_data = self.xls_row_template(c_specs, ['report_name']) |
|||
row_pos = self.xls_write_row( |
|||
ws, row_pos, row_data, row_style=cell_style) |
|||
row_pos += 1 |
|||
ws.freeze_panes(row_pos, 0) |
|||
|
|||
# Column headers |
|||
c_specs = map(lambda x: self.render( |
|||
x, self.col_specs_template, 'header', render_space={'_': _p._}), |
|||
wanted_list) |
|||
row_data = self.xls_row_template(c_specs, [x[0] for x in c_specs]) |
|||
row_pos = self.xls_write_row( |
|||
ws, row_pos, row_data, row_style=self.rh_cell_style, |
|||
set_column_size=True) |
|||
ws.set_horz_split_pos(row_pos) |
|||
wanted_list = ws_params['wanted_list'] |
|||
debit_pos = 'debit' in wanted_list and wanted_list.index('debit') |
|||
credit_pos = 'credit' in wanted_list and wanted_list.index('credit') |
|||
|
|||
# account move lines |
|||
for line in objects: |
|||
debit_cell = rowcol_to_cell(row_pos, debit_pos) |
|||
credit_cell = rowcol_to_cell(row_pos, credit_pos) |
|||
bal_formula = debit_cell + '-' + credit_cell |
|||
_logger.debug('dummy call - %s', bal_formula) |
|||
c_specs = map( |
|||
lambda x: self.render(x, self.col_specs_template, 'lines'), |
|||
wanted_list) |
|||
row_data = self.xls_row_template(c_specs, [x[0] for x in c_specs]) |
|||
row_pos = self.xls_write_row( |
|||
ws, row_pos, row_data, row_style=self.aml_cell_style) |
|||
for line in amls: |
|||
row_pos = self._write_line( |
|||
ws, row_pos, ws_params, col_specs_section='lines', |
|||
render_space={'line': line}, |
|||
default_format=self.format_tcell_left) |
|||
|
|||
# Totals |
|||
aml_cnt = len(objects) |
|||
debit_start = rowcol_to_cell(row_pos - aml_cnt, debit_pos) |
|||
debit_stop = rowcol_to_cell(row_pos - 1, debit_pos) |
|||
aml_cnt = len(amls) |
|||
debit_start = self._rowcol_to_cell(row_pos - aml_cnt, debit_pos) |
|||
debit_stop = self._rowcol_to_cell(row_pos - 1, debit_pos) |
|||
debit_formula = 'SUM(%s:%s)' % (debit_start, debit_stop) |
|||
_logger.debug('dummy call - %s', debit_formula) |
|||
credit_start = rowcol_to_cell(row_pos - aml_cnt, credit_pos) |
|||
credit_stop = rowcol_to_cell(row_pos - 1, credit_pos) |
|||
credit_start = self._rowcol_to_cell(row_pos - aml_cnt, credit_pos) |
|||
credit_stop = self._rowcol_to_cell(row_pos - 1, credit_pos) |
|||
credit_formula = 'SUM(%s:%s)' % (credit_start, credit_stop) |
|||
_logger.debug('dummy call - %s', credit_formula) |
|||
debit_cell = rowcol_to_cell(row_pos, debit_pos) |
|||
credit_cell = rowcol_to_cell(row_pos, credit_pos) |
|||
debit_cell = self._rowcol_to_cell(row_pos, debit_pos) |
|||
credit_cell = self._rowcol_to_cell(row_pos, credit_pos) |
|||
bal_formula = debit_cell + '-' + credit_cell |
|||
_logger.debug('dummy call - %s', bal_formula) |
|||
c_specs = map( |
|||
lambda x: self.render(x, self.col_specs_template, 'totals'), |
|||
wanted_list) |
|||
row_data = self.xls_row_template(c_specs, [x[0] for x in c_specs]) |
|||
row_pos = self.xls_write_row( |
|||
ws, row_pos, row_data, row_style=self.rt_cell_style_right) |
|||
row_pos = self._write_line( |
|||
ws, row_pos, ws_params, col_specs_section='totals', |
|||
render_space={ |
|||
'debit_formula': debit_formula, |
|||
'credit_formula': credit_formula, |
|||
'bal_formula': bal_formula, |
|||
}, |
|||
default_format=self.format_theader_yellow_left) |
|||
|
|||
|
|||
move_line_xls('report.move.line.list.xls', |
|||
'account.move.line', |
|||
parser=move_line_xls_parser) |
|||
MoveLineXlsx('report.move.line.list.xls', |
|||
'account.move.line', |
|||
parser=report_sxw.rml_parse) |
@ -1,22 +1,20 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
<odoo> |
|||
|
|||
<record id="action_move_line_list_xls" model="ir.actions.report.xml"> |
|||
<field name="name">Export Selected Lines</field> |
|||
<field name="model">account.move.line</field> |
|||
<field name="type">ir.actions.report.xml</field> |
|||
<field name="report_name">move.line.list.xls</field> |
|||
<field name="report_type">xls</field> |
|||
<field name="auto" eval="False"/> |
|||
</record> |
|||
<record id="action_move_line_list_xls" model="ir.actions.report.xml"> |
|||
<field name="name">Export Selected Lines</field> |
|||
<field name="model">account.move.line</field> |
|||
<field name="type">ir.actions.report.xml</field> |
|||
<field name="report_name">move.line.list.xls</field> |
|||
<field name="report_type">xlsx</field> |
|||
<field name="auto" eval="False"/> |
|||
</record> |
|||
|
|||
<record model="ir.values" id="action_move_line_list_xls_values"> |
|||
<field name="name">Export Selected Lines</field> |
|||
<field name="key2">client_action_multi</field> |
|||
<field name="value" eval="'ir.actions.report.xml,' +str(ref('action_move_line_list_xls'))" /> |
|||
<field name="model">account.move.line</field> |
|||
</record> |
|||
<record model="ir.values" id="action_move_line_list_xls_values"> |
|||
<field name="name">Export Selected Lines</field> |
|||
<field name="key2">client_action_multi</field> |
|||
<field name="value" eval="'ir.actions.report.xml,' +str(ref('action_move_line_list_xls'))" /> |
|||
<field name="model">account.move.line</field> |
|||
</record> |
|||
|
|||
</data> |
|||
</openerp> |
|||
</odoo> |
@ -0,0 +1,2 @@ |
|||
# -*- coding: utf-8 -*- |
|||
from . import test_aml_report_xlsx |
@ -0,0 +1,21 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2009-2018 Noviat. |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
|||
|
|||
from odoo.tests.common import TransactionCase |
|||
|
|||
|
|||
class TestAmlReportXlsx(TransactionCase): |
|||
|
|||
def setUp(self): |
|||
super(TestAmlReportXlsx, self).setUp() |
|||
ctx = {'xlsx_export': True} |
|||
self.report = self.env['ir.actions.report.xml'].with_context(ctx) |
|||
self.report_name = 'move.line.list.xls' |
|||
inv = self.env.ref('l10n_generic_coa.demo_invoice_1') |
|||
self.amls = inv.move_id.line_ids |
|||
|
|||
def test_aml_report_xlsx(self): |
|||
report_xls = self.report.render_report( |
|||
self.amls.ids, self.report_name, {}) |
|||
self.assertEqual(report_xls[1], 'xlsx') |
Write
Preview
Loading…
Cancel
Save
Reference in new issue