Browse Source

[IMP] export general ledger to XLSX format

pull/367/head
Damien Crier 9 years ago
committed by Jordi Ballester
parent
commit
6673e9c535
  1. 1
      account_financial_report_qweb/__openerp__.py
  2. 1
      account_financial_report_qweb/report/__init__.py
  3. 95
      account_financial_report_qweb/report/general_ledger_xlsx.py
  4. 9
      account_financial_report_qweb/reports.xml
  5. 2
      account_financial_report_qweb/wizard/general_ledger_wizard.xml
  6. 172
      account_financial_report_qweb/wizard/ledger_report_wizard.py

1
account_financial_report_qweb/__openerp__.py

@ -17,6 +17,7 @@
'account_full_reconcile', 'account_full_reconcile',
'date_range', 'date_range',
'account_fiscal_year', 'account_fiscal_year',
'report_xlsx',
], ],
'data': [ 'data': [
'wizard/aged_partner_balance_wizard_view.xml', 'wizard/aged_partner_balance_wizard_view.xml',

1
account_financial_report_qweb/report/__init__.py

@ -5,3 +5,4 @@
from . import common from . import common
from . import general_ledger from . import general_ledger
from . import open_invoice from . import open_invoice
from . import general_ledger_xlsx

95
account_financial_report_qweb/report/general_ledger_xlsx.py

@ -0,0 +1,95 @@
# -*- coding: utf-8 -*-
# Author: Damien Crier
# Copyright 2016 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import logging
from openerp.addons.report_xlsx.report.report_xlsx import ReportXlsx
from openerp.report import report_sxw
from ..wizard.ledger_report_wizard import FIELDS_TO_READ
_logger = logging.getLogger(__name__)
FIELDS_TO_READ_INV = {v: k for k, v in FIELDS_TO_READ.iteritems()}
class GeneralLedgerXslx(ReportXlsx):
def __init__(self, name, table, rml=False, parser=False, header=True,
store=False):
super(GeneralLedgerXslx, self).__init__(
name, table, rml, parser, header, store)
def generate_xlsx_report(self, workbook, data, objects):
data = objects.compute()
report_name = data['header'][0].get('title', 'GeneralLedgerXslx')
sheet = workbook.add_worksheet(report_name[:31])
row_pos = 0
col_pos = 0
sheet.set_column(col_pos, col_pos, 30)
bold = workbook.add_format({'bold': True})
header_format = workbook.add_format({'bold': True,
'align': 'center',
'border': True,
'bg_color': '#FFFFCC'})
std_cell_format = workbook.add_format({'bold': False,
'align': 'left',
'border': False,
'bg_color': '#FFFFFF'})
# write report title on first cell A0 in XLSX sheet
sheet.write(row_pos, 0, report_name, bold)
row_pos += 2
# write filters taken for this report
col = 1
for k, v in data['header'][0].get('filters').iteritems():
sheet.write(row_pos, col, k, header_format)
sheet.write(row_pos+1, col, v, header_format)
col += 2
row_pos += 5
# write header line
col = 0
content = data['content'][0]
header_done = False
sorted_acc = content.keys()
sorted_acc.sort()
for acc in sorted_acc:
for move_lines in content[acc]:
# write line with account name
# sheet.write(row_pos, col+1, acc, bold)
# row_pos += 1
# write column headers
if not header_done:
for k, v in move_lines.iteritems():
position = FIELDS_TO_READ_INV.get(k, 'remove')
if position == 'remove':
continue
sheet.write(row_pos, position, k, bold)
# col2 += 1
row_pos += 1
header_done = True
for k, v in move_lines.iteritems():
if isinstance(v, (list, tuple)):
v = v[1]
position = FIELDS_TO_READ_INV.get(k, 'remove')
if position == 'remove':
continue
if position == 0:
sheet.write(row_pos, position, v, bold)
else:
sheet.write(row_pos, position, v, std_cell_format)
# col2 += 1
row_pos += 1
GeneralLedgerXslx('report.ledger.report.wizard.xlsx',
'ledger.report.wizard', parser=report_sxw.rml_parse)

9
account_financial_report_qweb/reports.xml

@ -36,5 +36,14 @@
</record> </record>
<record id="general_ledger_xls_export" model="ir.actions.report.xml">
<field name="name">General Ledger XLSX report</field>
<field name="model">ledger.report.wizard</field>
<field name="type">ir.actions.report.xml</field>
<field name="report_name">ledger.report.wizard.xlsx</field>
<field name="report_type">xlsx</field>
<field name="auto" eval="False"/>
</record>
</data> </data>
</openerp> </openerp>

2
account_financial_report_qweb/wizard/general_ledger_wizard.xml

@ -33,6 +33,8 @@
<footer> <footer>
<button name="button_view" string="View" type="object" default_focus="1" class="oe_highlight"/> <button name="button_view" string="View" type="object" default_focus="1" class="oe_highlight"/>
or or
<button name="check_report_xlsx" string="Export XLSX" type="object"/>
or
<button string="Cancel" class="oe_link" special="cancel" /> <button string="Cancel" class="oe_link" special="cancel" />
</footer> </footer>
</form> </form>

172
account_financial_report_qweb/wizard/ledger_report_wizard.py

@ -2,8 +2,29 @@
# Author: Damien Crier # Author: Damien Crier
# Copyright 2016 Camptocamp SA # Copyright 2016 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from operator import itemgetter
from openerp import models, fields, api, _ from openerp import models, fields, api, _
# order to be placed on the report: field
FIELDS_TO_READ = {1: 'date',
0: 'account_id',
4: 'account_code',
2: 'move_name',
3: 'journal_id',
5: 'partner_name',
6: 'ref',
7: 'label',
8: 'debit',
9: 'credit',
30: 'amount_currency',
40: 'currency_code',
50: 'month',
60: 'partner_ref',
10: 'cumul_balance',
70: 'init_balance',
}
class LedgerReportWizard(models.TransientModel): class LedgerReportWizard(models.TransientModel):
"""Base ledger report wizard.""" """Base ledger report wizard."""
@ -215,3 +236,154 @@ class LedgerReportWizardLine(models.TransientModel):
invoice_number = fields.Char() invoice_number = fields.Char()
centralized = fields.Boolean() centralized = fields.Boolean()
@api.multi
def check_report_xlsx(self):
self.ensure_one()
data = {}
data['ids'] = self.env.context.get('active_ids', [])
# data['model'] = 'general.ledger.line'
data['model'] = self.env.context.get('active_model', 'ir.ui.menu')
data['form'] = self.read(['date_from', 'date_to',
'journal_ids', 'target_move'])[0]
used_context = self._build_contexts(data)
data['form']['used_context'] = dict(
used_context,
lang=self.env.context.get('lang', 'en_US'))
return self._print_report_xlsx(data)
@api.multi
def _print_report_xlsx(self, data):
return {
'name': 'export xlsx general ledger',
'model': 'ledger.report.wizard',
'type': 'ir.actions.report.xml',
'report_name': 'ledger.report.wizard.xlsx',
'report_type': 'xlsx',
'context': self.env.context,
}
@api.multi
def _get_centralized_move_ids(self, domain):
""" Get last line of each selected centralized accounts """
# inverse search on centralized boolean to finish the search to get the
# ids of last lines of centralized accounts
# XXX USE DISTINCT to speed up ?
domain = domain[:]
centralize_index = domain.index(('centralized', '=', False))
domain[centralize_index] = ('centralized', '=', True)
gl_lines = self.env['general.ledger.line'].search(domain)
accounts = gl_lines.mapped('account_id')
line_ids = []
for acc in accounts:
acc_lines = gl_lines.filtered(lambda rec: rec.account_id == acc)
line_ids.append(acc_lines[-1].id)
return line_ids
@api.multi
def _get_moves_from_dates_domain(self):
""" Prepare domain for `_get_moves_from_dates` """
domain = []
if self.centralize:
domain = [('centralized', '=', False)]
start_date = self.date_from
end_date = self.date_to
if start_date:
domain += [('date', '>=', start_date)]
if end_date:
domain += [('date', '<=', end_date)]
if self.target_move == 'posted':
domain += [('move_state', '=', 'posted')]
if self.account_ids:
domain += [('account_id', 'in', self.account_ids.ids)]
return domain
def compute_domain(self):
ret = self._get_moves_from_dates_domain()
if self.centralize:
centralized_ids = self._get_centralized_move_ids(ret)
if centralized_ids:
ret.insert(0, '|')
ret.append(('id', 'in', centralized_ids))
return ret
def initial_balance_line(self, amount, account_name, account_code, date):
return {'date': date,
'account_id': account_name,
'account_code': account_code,
'move_name': '',
'journal_id': '',
'partner_name': '',
'ref': '',
'label': _('Initial Balance'),
'debit': '',
'credit': '',
'amount_currency': '',
'currency_code': '',
'month': '',
'partner_ref': '',
'cumul_balance': amount,
'init_balance': ''}
def group_general_ledger(self, report_lines, date_start):
"""
group lines by account and order by account then date
"""
result = {}
accounts = report_lines.mapped('account_id')
for account in accounts:
lines = report_lines.filtered(
lambda a: a.account_id.id == account.id)
acc_full_name = account.name_get()[0][1]
sorted_lines = sorted(lines.read(FIELDS_TO_READ.values()),
key=itemgetter('date'))
initial_balance = sorted_lines[0]['init_balance']
sorted_lines.insert(0, self.initial_balance_line(initial_balance,
acc_full_name,
account.code,
date_start))
result[acc_full_name] = sorted_lines
return result
def construct_header(self):
result = {}
result['title'] = _('General Ledger')
filters = {}
filters['centralized'] = _('%s' % self.centralize)
filters['start_date'] = self.date_from
filters['end_date'] = self.date_to
filters['target_moves'] = self.target_move
filters['accounts'] = _('All')
if self.account_ids:
filters['accounts'] = ', '.join([a.code for a in self.account_ids])
result['filters'] = filters
return result
@api.multi
def compute(self):
self.ensure_one()
# header filled with a dict
header = []
header.append(self.construct_header())
# content filled with dicts
content = []
domain = self.compute_domain()
report_lines = self.env['general.ledger.line'].search(domain)
lines_general_ledger = self.group_general_ledger(report_lines,
self.date_from)
content.append(lines_general_ledger)
return {'header': header,
'content': content}
Loading…
Cancel
Save