1 # -*- coding: utf-8 -*-
2 ##############################################################################
4 # Copyright (c) 2011 Camptocamp SA (http://www.camptocamp.com)
6 # Author: Guewen Baconnier (Camptocamp)
8 # WARNING: This program as such is intended to be used by professional
9 # programmers who take the whole responsability of assessing all potential
10 # consequences resulting from its eventual inadequacies and bugs
11 # End users who are looking for a ready-to-use solution with commercial
12 # garantees and support are strongly adviced to contract a Free Software
15 # This program is Free Software; you can redistribute it and/or
16 # modify it under the terms of the GNU General Public License
17 # as published by the Free Software Foundation; either version 2
18 # of the License, or (at your option) any later version.
20 # This program is distributed in the hope that it will be useful,
21 # but WITHOUT ANY WARRANTY; without even the implied warranty of
22 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 # GNU General Public License for more details.
25 # You should have received a copy of the GNU General Public License
26 # along with this program; if not, write to the Free Software
27 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 ##############################################################################
33 from lxml
import etree
34 from datetime
import datetime
35 from openerp
.osv
import fields
, orm
36 from openerp
.tools
.translate
import _
39 def previous_year_date(date
, nb_prev
=1):
42 parsed_date
= datetime
.strptime(date
, '%Y-%m-%d')
43 previous_date
= datetime(year
=parsed_date
.year
- nb_prev
,
44 month
=parsed_date
.month
,
49 class AccountBalanceCommonWizard(orm
.TransientModel
):
50 """Will launch trial balance report and pass required args"""
52 _inherit
= "account.common.account.report"
53 _name
= "account.common.balance.report"
54 _description
= "Common Balance Report"
56 # an update module should be done if changed
57 # in order to create fields in db
60 COMPARE_SELECTION
= [('filter_no', 'No Comparison'),
61 ('filter_year', 'Fiscal Year'),
62 ('filter_date', 'Date'),
63 ('filter_period', 'Periods'),
64 ('filter_opening', 'Opening Only')]
66 M2O_DYNAMIC_FIELDS
= [f
% index
for f
in ["comp%s_fiscalyear_id",
69 for index
in range(COMPARISON_LEVEL
)]
70 SIMPLE_DYNAMIC_FIELDS
= [f
% index
for f
in ["comp%s_filter",
73 for index
in range(COMPARISON_LEVEL
)]
74 DYNAMIC_FIELDS
= M2O_DYNAMIC_FIELDS
+ SIMPLE_DYNAMIC_FIELDS
76 def _get_account_ids(self
, cr
, uid
, context
=None):
78 if context
.get('active_model', False) == 'account.account' and context
.get('active_ids', False):
79 res
= context
['active_ids']
83 'account_ids': fields
.many2many('account.account', string
='Filter on accounts',
84 help="Only selected accounts will be printed. Leave empty to print all accounts."),
85 'filter': fields
.selection([('filter_no', 'No Filters'),
86 ('filter_date', 'Date'),
87 ('filter_period', 'Periods'),
88 ('filter_opening', 'Opening Only')],
91 help='Filter by date: no opening balance will be displayed. '
92 '(opening balance can only be computed based on period to be correct).'),
95 for index
in range(COMPARISON_LEVEL
):
97 {"comp%s_filter" % index
: fields
.selection(COMPARE_SELECTION
, string
='Compare By', required
=True),
98 "comp%s_fiscalyear_id" % index
: fields
.many2one('account.fiscalyear', 'Fiscal Year'),
99 "comp%s_period_from" % index
: fields
.many2one('account.period', 'Start Period'),
100 "comp%s_period_to" % index
: fields
.many2one('account.period', 'End Period'),
101 "comp%s_date_from" % index
: fields
.date("Start Date"),
102 "comp%s_date_to" % index
: fields
.date("End Date")})
105 'account_ids': _get_account_ids
,
108 def _check_fiscalyear(self
, cr
, uid
, ids
, context
=None):
109 obj
= self
.read(cr
, uid
, ids
[0], ['fiscalyear_id', 'filter'], context
=context
)
110 if not obj
['fiscalyear_id'] and obj
['filter'] == 'filter_no':
115 (_check_fiscalyear
, 'When no Fiscal year is selected, you must choose to filter by periods or by date.', ['filter']),
118 def default_get(self
, cr
, uid
, fields
, context
=None):
120 To get default values for the object.
122 @param self: The object pointer.
123 @param cr: A database cursor
124 @param uid: ID of the user currently logged in
125 @param fields: List of fields for which we want default values
126 @param context: A standard dictionary
128 @return: A dictionary which of fields with values.
131 res
= super(AccountBalanceCommonWizard
, self
).default_get(cr
, uid
, fields
, context
=context
)
132 for index
in range(self
.COMPARISON_LEVEL
):
133 field
= "comp%s_filter" % (index
,)
134 if not res
.get(field
, False):
135 res
[field
] = 'filter_no'
138 def fields_view_get(self
, cr
, uid
, view_id
=None, view_type
='form', context
=None, toolbar
=False, submenu
=False):
139 res
= super(AccountBalanceCommonWizard
, self
).fields_view_get(cr
, uid
, view_id
, view_type
, context
=context
, toolbar
=toolbar
, submenu
=submenu
)
141 res
['fields'].update(self
.fields_get(cr
, uid
,
142 allfields
=self
.DYNAMIC_FIELDS
,
143 context
=context
, write_access
=True))
145 eview
= etree
.fromstring(res
['arch'])
146 placeholder
= eview
.xpath("//page[@name='placeholder']")
148 placeholder
= placeholder
[0]
149 for index
in range(self
.COMPARISON_LEVEL
):
150 page
= etree
.Element(
152 {'name': "comp%s" % index
,
153 'string': _("Comparison %s") % (index
+ 1, )})
154 group
= etree
.Element('group')
157 def modifiers_and_append(elem
):
158 orm
.setup_modifiers(elem
)
161 modifiers_and_append(etree
.Element(
163 {'name': "comp%s_filter" % index
,
164 'on_change': "onchange_comp_filter(%(index)s, filter, comp%(index)s_filter, fiscalyear_id, date_from, date_to)" % {'index': index
}}))
165 modifiers_and_append(etree
.Element(
167 {'name': "comp%s_fiscalyear_id" % index
,
169 "{'required': [('comp%(index)s_filter','in',('filter_year','filter_opening'))]," \
170 " 'invisible': [('comp%(index)s_filter','not in',('filter_year','filter_opening'))]}" % {'index': index
}}))
172 dates_attrs
= "{'required': [('comp%(index)s_filter','=','filter_date')], " \
173 " 'invisible': [('comp%(index)s_filter','!=','filter_date')]}" % {'index': index
}
174 modifiers_and_append(etree
.Element(
176 {'string': _('Dates'),
178 'attrs': dates_attrs
}))
179 modifiers_and_append(etree
.Element(
181 {'name': "comp%s_date_from" % index
,
182 'attrs': dates_attrs
}))
183 modifiers_and_append(etree
.Element(
185 {'name': "comp%s_date_to" % index
,
186 'attrs': dates_attrs
}))
188 periods_attrs
= "{'required': [('comp%(index)s_filter','=','filter_period')]," \
189 " 'invisible': [('comp%(index)s_filter','!=','filter_period')]}" % {'index': index
}
190 periods_domain
= "[('special', '=', False)]"
191 modifiers_and_append(etree
.Element(
193 {'string': _('Periods'),
195 'attrs': periods_attrs
}))
196 modifiers_and_append(etree
.Element(
198 {'name': "comp%s_period_from" % index
,
199 'attrs': periods_attrs
,
200 'domain': periods_domain
}))
201 modifiers_and_append(etree
.Element(
203 {'name': "comp%s_period_to" % index
,
204 'attrs': periods_attrs
,
205 'domain': periods_domain
}))
207 placeholder
.addprevious(page
)
208 placeholder
.getparent().remove(placeholder
)
209 res
['arch'] = etree
.tostring(eview
)
212 def onchange_filter(self
, cr
, uid
, ids
, filter='filter_no', fiscalyear_id
=False, context
=None):
214 if filter == 'filter_no':
215 res
['value'] = {'period_from': False, 'period_to': False, 'date_from': False, 'date_to': False}
216 if filter == 'filter_date':
218 fyear
= self
.pool
.get('account.fiscalyear').browse(cr
, uid
, fiscalyear_id
, context
=context
)
219 date_from
= fyear
.date_start
220 date_to
= fyear
.date_stop
> time
.strftime('%Y-%m-%d') and time
.strftime('%Y-%m-%d') or fyear
.date_stop
222 date_from
, date_to
= time
.strftime('%Y-01-01'), time
.strftime('%Y-%m-%d')
223 res
['value'] = {'period_from': False, 'period_to': False, 'date_from': date_from
, 'date_to': date_to
}
224 if filter == 'filter_period' and fiscalyear_id
:
225 start_period
= end_period
= False
227 SELECT * FROM (SELECT p.id
228 FROM account_period p
229 LEFT JOIN account_fiscalyear f ON (p.fiscalyear_id = f.id)
231 AND COALESCE(p.special, FALSE) = FALSE
232 ORDER BY p.date_start ASC
233 LIMIT 1) AS period_start
235 SELECT * FROM (SELECT p.id
236 FROM account_period p
237 LEFT JOIN account_fiscalyear f ON (p.fiscalyear_id = f.id)
239 AND p.date_start < NOW()
240 AND COALESCE(p.special, FALSE) = FALSE
241 ORDER BY p.date_stop DESC
242 LIMIT 1) AS period_stop''', (fiscalyear_id
, fiscalyear_id
))
243 periods
= [i
[0] for i
in cr
.fetchall()]
245 start_period
= end_period
= periods
[0]
247 end_period
= periods
[1]
248 res
['value'] = {'period_from': start_period
, 'period_to': end_period
, 'date_from': False, 'date_to': False}
251 def onchange_comp_filter(self
, cr
, uid
, ids
, index
, main_filter
='filter_no', comp_filter
='filter_no', fiscalyear_id
=False, start_date
=False, stop_date
=False, context
=None):
253 fy_obj
= self
.pool
.get('account.fiscalyear')
254 last_fiscalyear_id
= False
256 fiscalyear
= fy_obj
.browse(cr
, uid
, fiscalyear_id
, context
=context
)
257 last_fiscalyear_ids
= fy_obj
.search(cr
, uid
, [('date_stop', '<', fiscalyear
.date_start
)],
258 limit
=self
.COMPARISON_LEVEL
, order
='date_start desc', context
=context
)
259 if last_fiscalyear_ids
:
260 if len(last_fiscalyear_ids
) > index
:
261 last_fiscalyear_id
= last_fiscalyear_ids
[index
] # first element for the comparison 1, second element for the comparison 2
263 fy_id_field
= "comp%s_fiscalyear_id" % (index
,)
264 period_from_field
= "comp%s_period_from" % (index
,)
265 period_to_field
= "comp%s_period_to" % (index
,)
266 date_from_field
= "comp%s_date_from" % (index
,)
267 date_to_field
= "comp%s_date_to" % (index
,)
269 if comp_filter
== 'filter_no':
272 period_from_field
: False,
273 period_to_field
: False,
274 date_from_field
: False,
277 if comp_filter
in ('filter_year', 'filter_opening'):
279 fy_id_field
: last_fiscalyear_id
,
280 period_from_field
: False,
281 period_to_field
: False,
282 date_from_field
: False,
285 if comp_filter
== 'filter_date':
287 if main_filter
== 'filter_date':
289 'date_start': previous_year_date(start_date
, index
+ 1).strftime('%Y-%m-%d'),
290 'date_stop': previous_year_date(stop_date
, index
+ 1).strftime('%Y-%m-%d'),
292 elif last_fiscalyear_id
:
293 dates
= fy_obj
.read(cr
, uid
, last_fiscalyear_id
, ['date_start', 'date_stop'], context
=context
)
295 res
['value'] = {fy_id_field
: False, period_from_field
: False, period_to_field
: False, date_from_field
: dates
.get('date_start', False), date_to_field
: dates
.get('date_stop', False)}
296 if comp_filter
== 'filter_period' and last_fiscalyear_id
:
297 start_period
= end_period
= False
299 SELECT * FROM (SELECT p.id
300 FROM account_period p
301 LEFT JOIN account_fiscalyear f ON (p.fiscalyear_id = f.id)
302 WHERE f.id = %(fiscalyear)s
303 AND COALESCE(p.special, FALSE) = FALSE
304 ORDER BY p.date_start ASC
305 LIMIT 1) AS period_start
307 SELECT * FROM (SELECT p.id
308 FROM account_period p
309 LEFT JOIN account_fiscalyear f ON (p.fiscalyear_id = f.id)
310 WHERE f.id = %(fiscalyear)s
311 AND p.date_start < NOW()
312 AND COALESCE(p.special, FALSE) = FALSE
313 ORDER BY p.date_stop DESC
314 LIMIT 1) AS period_stop''', {'fiscalyear': last_fiscalyear_id
})
315 periods
= [i
[0] for i
in cr
.fetchall()]
316 if periods
and len(periods
) > 1:
317 start_period
= end_period
= periods
[0]
319 end_period
= periods
[1]
320 res
['value'] = {fy_id_field
: False,
321 period_from_field
: start_period
,
322 period_to_field
: end_period
,
323 date_from_field
: False,
324 date_to_field
: False}
327 def pre_print_report(self
, cr
, uid
, ids
, data
, context
=None):
328 data
= super(AccountBalanceCommonWizard
, self
).pre_print_report(
329 cr
, uid
, ids
, data
, context
)
333 # will be used to attach the report on the main account
334 data
['ids'] = [data
['form']['chart_account_id']]
336 fields_to_read
= ['account_ids', ]
337 fields_to_read
+= self
.DYNAMIC_FIELDS
338 vals
= self
.read(cr
, uid
, ids
, fields_to_read
, context
=context
)[0]
340 # extract the id from the m2o tuple (id, name)
341 for field
in self
.M2O_DYNAMIC_FIELDS
:
342 if isinstance(vals
[field
], tuple):
343 vals
[field
] = vals
[field
][0]
345 vals
['max_comparison'] = self
.COMPARISON_LEVEL
346 data
['form'].update(vals
)