[MODULE] +v1.1.0 from https://www.odoo.com/apps/7.0/account_financial_report_webkit/
[burette/account_financial_report_webkit.git] / report / partners_ledger.py
1 # -*- encoding: utf-8 -*-
2 ##############################################################################
3 #
4 # Author: Nicolas Bessi, Guewen Baconnier
5 # Copyright Camptocamp SA 2011
6 #
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU Affero General Public License as
9 # published by the Free Software Foundation, either version 3 of the
10 # License, or (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU Affero General Public License for more details.
16 #
17 # You should have received a copy of the GNU Affero General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #
20 ##############################################################################
21
22 from collections import defaultdict
23 from datetime import datetime
24
25 from openerp import pooler
26 from openerp.osv import osv
27 from openerp.report import report_sxw
28 from openerp.tools.translate import _
29 from .common_partner_reports import CommonPartnersReportHeaderWebkit
30 from .webkit_parser_header_fix import HeaderFooterTextWebKitParser
31
32
33 class PartnersLedgerWebkit(report_sxw.rml_parse, CommonPartnersReportHeaderWebkit):
34
35 def __init__(self, cursor, uid, name, context):
36 super(PartnersLedgerWebkit, self).__init__(cursor, uid, name, context=context)
37 self.pool = pooler.get_pool(self.cr.dbname)
38 self.cursor = self.cr
39
40 company = self.pool.get('res.users').browse(self.cr, uid, uid, context=context).company_id
41 header_report_name = ' - '.join((_('PARTNER LEDGER'), company.name, company.currency_id.name))
42
43 footer_date_time = self.formatLang(str(datetime.today()), date_time=True)
44
45 self.localcontext.update({
46 'cr': cursor,
47 'uid': uid,
48 'report_name': _('Partner Ledger'),
49 'display_account_raw': self._get_display_account_raw,
50 'filter_form': self._get_filter,
51 'target_move': self._get_target_move,
52 'initial_balance': self._get_initial_balance,
53 'amount_currency': self._get_amount_currency,
54 'display_partner_account': self._get_display_partner_account,
55 'display_target_move': self._get_display_target_move,
56 'additional_args': [
57 ('--header-font-name', 'Helvetica'),
58 ('--footer-font-name', 'Helvetica'),
59 ('--header-font-size', '10'),
60 ('--footer-font-size', '6'),
61 ('--header-left', header_report_name),
62 ('--header-spacing', '2'),
63 ('--footer-left', footer_date_time),
64 ('--footer-right', ' '.join((_('Page'), '[page]', _('of'), '[topage]'))),
65 ('--footer-line',),
66 ],
67 })
68
69 def _get_initial_balance_mode(self, start_period):
70 """ Force computing of initial balance for the partner ledger,
71 because we cannot use the entries generated by
72 OpenERP in the opening period.
73
74 OpenERP allows to reconcile move lines between different partners,
75 so the generated entries in the opening period are unreliable.
76 """
77 return 'initial_balance'
78
79 def set_context(self, objects, data, ids, report_type=None):
80 """Populate a ledger_lines attribute on each browse record that will be used
81 by mako template"""
82 new_ids = data['form']['chart_account_id']
83
84 # account partner memoizer
85 # Reading form
86 main_filter = self._get_form_param('filter', data, default='filter_no')
87 target_move = self._get_form_param('target_move', data, default='all')
88 start_date = self._get_form_param('date_from', data)
89 stop_date = self._get_form_param('date_to', data)
90 start_period = self.get_start_period_br(data)
91 stop_period = self.get_end_period_br(data)
92 fiscalyear = self.get_fiscalyear_br(data)
93 partner_ids = self._get_form_param('partner_ids', data)
94 result_selection = self._get_form_param('result_selection', data)
95 chart_account = self._get_chart_account_id_br(data)
96
97 if main_filter == 'filter_no' and fiscalyear:
98 start_period = self.get_first_fiscalyear_period(fiscalyear)
99 stop_period = self.get_last_fiscalyear_period(fiscalyear)
100
101 # Retrieving accounts
102 filter_type = ('payable', 'receivable')
103 if result_selection == 'customer':
104 filter_type = ('receivable',)
105 if result_selection == 'supplier':
106 filter_type = ('payable',)
107
108 accounts = self.get_all_accounts(new_ids, exclude_type=['view'],
109 only_type=filter_type)
110
111 if not accounts:
112 raise osv.except_osv(_('Error'), _('No accounts to print.'))
113
114 if main_filter == 'filter_date':
115 start = start_date
116 stop = stop_date
117 else:
118 start = start_period
119 stop = stop_period
120
121 # when the opening period is included in the selected range of periods and
122 # the opening period contains move lines, we must not compute the initial balance from previous periods
123 # but only display the move lines of the opening period
124 # we identify them as:
125 # - 'initial_balance' means compute the sums of move lines from previous periods
126 # - 'opening_balance' means display the move lines of the opening period
127 init_balance = main_filter in ('filter_no', 'filter_period')
128 initial_balance_mode = init_balance and self._get_initial_balance_mode(start) or False
129
130 initial_balance_lines = {}
131 if initial_balance_mode == 'initial_balance':
132 initial_balance_lines = self._compute_partners_initial_balances(accounts,
133 start_period,
134 partner_filter=partner_ids,
135 exclude_reconcile=False)
136
137 ledger_lines = self._compute_partner_ledger_lines(accounts,
138 main_filter,
139 target_move,
140 start,
141 stop,
142 partner_filter=partner_ids)
143 objects = []
144 for account in self.pool.get('account.account').browse(self.cursor, self.uid, accounts):
145 account.ledger_lines = ledger_lines.get(account.id, {})
146 account.init_balance = initial_balance_lines.get(account.id, {})
147 ## we have to compute partner order based on inital balance
148 ## and ledger line as we may have partner with init bal
149 ## that are not in ledger line and vice versa
150 ledg_lines_pids = ledger_lines.get(account.id, {}).keys()
151 if initial_balance_mode:
152 non_null_init_balances = dict([(ib, amounts) for ib, amounts in account.init_balance.iteritems()
153 if amounts['init_balance'] or amounts['init_balance_currency']])
154 init_bal_lines_pids = non_null_init_balances.keys()
155 else:
156 account.init_balance = {}
157 init_bal_lines_pids = []
158
159 account.partners_order = self._order_partners(ledg_lines_pids, init_bal_lines_pids)
160 objects.append(account)
161
162 self.localcontext.update({
163 'fiscalyear': fiscalyear,
164 'start_date': start_date,
165 'stop_date': stop_date,
166 'start_period': start_period,
167 'stop_period': stop_period,
168 'partner_ids': partner_ids,
169 'chart_account': chart_account,
170 'initial_balance_mode': initial_balance_mode,
171 })
172
173 return super(PartnersLedgerWebkit, self).set_context(objects, data, new_ids,
174 report_type=report_type)
175
176 def _compute_partner_ledger_lines(self, accounts_ids, main_filter, target_move, start, stop, partner_filter=False):
177 res = defaultdict(dict)
178
179 for acc_id in accounts_ids:
180 move_line_ids = self.get_partners_move_lines_ids(acc_id,
181 main_filter,
182 start,
183 stop,
184 target_move,
185 exclude_reconcile=False,
186 partner_filter=partner_filter)
187 if not move_line_ids:
188 continue
189 for partner_id in move_line_ids:
190 partner_line_ids = move_line_ids.get(partner_id, [])
191 lines = self._get_move_line_datas(list(set(partner_line_ids)))
192 res[acc_id][partner_id] = lines
193 return res
194
195
196 HeaderFooterTextWebKitParser('report.account.account_report_partners_ledger_webkit',
197 'account.account',
198 'addons/account_financial_report_webkit/report/templates/account_report_partners_ledger.mako',
199 parser=PartnersLedgerWebkit)