Merge lp:~unifield-team/unifield-wm/uf-2246 into lp:unifield-wm

Proposed by jftempo
Status: Needs review
Proposed branch: lp:~unifield-team/unifield-wm/uf-2246
Merge into: lp:unifield-wm
Diff against target: 1736 lines (+1605/-2)
17 files modified
account_corrections/account_move_line.py (+3/-0)
account_journal/account_journal.py (+1/-0)
account_journal/project/project.py (+1/-0)
analytic_distribution/wizard/mass_reallocation_wizard.py (+1/-1)
msf_chart_of_account/data/journal_data.xml (+12/-0)
msf_currency_revaluation/__init__.py (+26/-0)
msf_currency_revaluation/__openerp__.py (+72/-0)
msf_currency_revaluation/account.py (+146/-0)
msf_currency_revaluation/account_view.xml (+22/-0)
msf_currency_revaluation/res_currency.py (+52/-0)
msf_currency_revaluation/res_currency_view.xml (+22/-0)
msf_currency_revaluation/test/currency_revaluation.yml (+321/-0)
msf_currency_revaluation/wizard/__init__.py (+1/-0)
msf_currency_revaluation/wizard/wizard_currency_revaluation.py (+863/-0)
msf_currency_revaluation/wizard/wizard_currency_revaluation_view.xml (+60/-0)
msf_profile/__openerp__.py (+1/-0)
res_currency_functional/res_currency_rate_functional.py (+1/-1)
To merge this branch: bzr merge lp:~unifield-team/unifield-wm/uf-2246
Reviewer Review Type Date Requested Status
UniField Reviewer Team Pending
Review via email: mp+201818@code.launchpad.net
To post a comment you must log in.
1901. By Olivier DOSSMANN

UF-2246 [DEL] Useless code that was disrupting behaviour we should have

The solution to substract reval lines was wrong because the computation is wrong with the booking balance.

Some missing values disrupt the booking balance computation: revaluation lines are not OK. This will be fixed in a next commit.

1902. By Olivier DOSSMANN

UF-2246 [FIX] Booking balance computation is wrong because of wrong amount_currency in revaluation lines.

They should be set to 0.0 as debit_currency and credit_currency fields to permit OpenERP to compute in the right way the booking balance.

1903. By Olivier DOSSMANN

UF-2246 [FIX] Do not use msf_chart_of_account dependancy on msf_currency_revaluation module.

Unmerged revisions

1903. By Olivier DOSSMANN

UF-2246 [FIX] Do not use msf_chart_of_account dependancy on msf_currency_revaluation module.

1902. By Olivier DOSSMANN

UF-2246 [FIX] Booking balance computation is wrong because of wrong amount_currency in revaluation lines.

They should be set to 0.0 as debit_currency and credit_currency fields to permit OpenERP to compute in the right way the booking balance.

1901. By Olivier DOSSMANN

UF-2246 [DEL] Useless code that was disrupting behaviour we should have

The solution to substract reval lines was wrong because the computation is wrong with the booking balance.

Some missing values disrupt the booking balance computation: revaluation lines are not OK. This will be fixed in a next commit.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'account_corrections/account_move_line.py'
2--- account_corrections/account_move_line.py 2013-12-09 10:47:09 +0000
3+++ account_corrections/account_move_line.py 2014-01-16 13:10:58 +0000
4@@ -94,6 +94,9 @@
5 # False if the account is used in a cash/bank/cheque journal
6 if ml.account_id.id in account_ids:
7 res[ml.id] = False
8+ # False if this line is a revaluation
9+ if ml.journal_id.type == 'revaluation':
10+ res[ml.id] = False
11 return res
12
13 _columns = {
14
15=== modified file 'account_journal/account_journal.py'
16--- account_journal/account_journal.py 2013-11-26 15:51:50 +0000
17+++ account_journal/account_journal.py 2014-01-16 13:10:58 +0000
18@@ -71,6 +71,7 @@
19 ('situation', 'Opening/Closing Situation'),
20 ('purchase', 'Purchase'),
21 ('purchase_refund','Purchase Refund'),
22+ ('revaluation', 'Revaluation'),
23 ('sale', 'Sale'),
24 ('sale_refund','Sale Refund'),
25 ('stock', 'Stock'),
26
27=== modified file 'account_journal/project/project.py'
28--- account_journal/project/project.py 2013-11-12 14:33:35 +0000
29+++ account_journal/project/project.py 2014-01-16 13:10:58 +0000
30@@ -48,6 +48,7 @@
31 ('migration', 'Migration'),
32 ('extra', 'OD-Extra Accounting'),
33 ('purchase','Purchase'),
34+ ('revaluation', 'Revaluation'),
35 ('sale','Sale'),
36 ('situation','Situation'),
37 ]
38
39=== modified file 'analytic_distribution/wizard/mass_reallocation_wizard.py'
40--- analytic_distribution/wizard/mass_reallocation_wizard.py 2013-11-27 15:35:21 +0000
41+++ analytic_distribution/wizard/mass_reallocation_wizard.py 2014-01-16 13:10:58 +0000
42@@ -178,7 +178,7 @@
43 ('id', 'in', context.get('active_ids')), '|', '|', '|', '|', '|', '|',
44 ('commitment_line_id', '!=', False), ('is_reallocated', '=', True),
45 ('is_reversal', '=', True),
46- ('journal_id.type', '=', 'engagement'),
47+ ('journal_id.type', 'in', ['engagement', 'revaluation']),
48 ('from_write_off', '=', True),
49 ('move_state', '=', 'draft'),
50 ('account_id.category', 'in', ['FREE1', 'FREE2'])
51
52=== modified file 'msf_chart_of_account/data/journal_data.xml'
53--- msf_chart_of_account/data/journal_data.xml 2013-10-25 11:39:40 +0000
54+++ msf_chart_of_account/data/journal_data.xml 2014-01-16 13:10:58 +0000
55@@ -266,5 +266,17 @@
56 <field name="type">migration</field>
57 <field name="analytic_journal_id" ref="account_journal.analytic_migration_journal"/>
58 </record>
59+
60+ <record id="account_journal.analytic_currency_revaluation" model="account.analytic.journal">
61+ <field name="name">Revaluation</field>
62+ <field name="code">REVAL</field>
63+ <field name="type">revaluation</field>
64+ </record>
65+ <record id="account_journal.currency_revaluation" model="account.journal">
66+ <field name="name">Revaluation</field>
67+ <field name="code">REVAL</field>
68+ <field name="type">revaluation</field>
69+ <field name="analytic_journal_id" ref="account_journal.analytic_currency_revaluation"/>
70+ </record>
71 </data>
72 </openerp>
73
74=== added directory 'msf_currency_revaluation'
75=== added file 'msf_currency_revaluation/__init__.py'
76--- msf_currency_revaluation/__init__.py 1970-01-01 00:00:00 +0000
77+++ msf_currency_revaluation/__init__.py 2014-01-16 13:10:58 +0000
78@@ -0,0 +1,26 @@
79+# -*- coding: utf-8 -*-
80+##############################################################################
81+#
82+# Author: Yannick Vaucher
83+# Copyright 2012 Camptocamp SA
84+#
85+# This program is free software: you can redistribute it and/or modify
86+# it under the terms of the GNU Affero General Public License as
87+# published by the Free Software Foundation, either version 3 of the
88+# License, or (at your option) any later version.
89+#
90+# This program is distributed in the hope that it will be useful,
91+# but WITHOUT ANY WARRANTY; without even the implied warranty of
92+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
93+# GNU Affero General Public License for more details.
94+#
95+# You should have received a copy of the GNU Affero General Public License
96+# along with this program. If not, see <http://www.gnu.org/licenses/>.
97+#
98+##############################################################################
99+
100+from . import account
101+from . import res_currency
102+from . import wizard
103+
104+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
105
106=== added file 'msf_currency_revaluation/__openerp__.py'
107--- msf_currency_revaluation/__openerp__.py 1970-01-01 00:00:00 +0000
108+++ msf_currency_revaluation/__openerp__.py 2014-01-16 13:10:58 +0000
109@@ -0,0 +1,72 @@
110+# -*- coding: utf-8 -*-
111+##############################################################################
112+#
113+# Author: Yannick Vaucher
114+# Copyright 2012 Camptocamp SA
115+
116+# Author: Sebastien Alix
117+# Copyright 2013 TeMPO Consulting
118+#
119+# This program is free software: you can redistribute it and/or modify
120+# it under the terms of the GNU Affero General Public License as
121+# published by the Free Software Foundation, either version 3 of the
122+# License, or (at your option) any later version.
123+#
124+# This program is distributed in the hope that it will be useful,
125+# but WITHOUT ANY WARRANTY; without even the implied warranty of
126+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
127+# GNU Affero General Public License for more details.
128+#
129+# You should have received a copy of the GNU Affero General Public License
130+# along with this program. If not, see <http://www.gnu.org/licenses/>.
131+#
132+##############################################################################
133+
134+{"name": "Unrealized currency gain & loss",
135+ "version": "6.0",
136+ "category": "Finance",
137+ "description": """
138+NOTE: Module 'account_unrealized_currency_gain_loss' ported from OpenERP 6.1
139+and adapted to UniField.
140+
141+Add a wizard to generate the unrealized currency gain & loss entries. This adjusts accounts' balance of account with a foreign currency.
142+
143+To configure it, Foreign currency gain & loss account have been added in company parameters.
144+
145+For UK (Revaluation) :
146+ LOSS GAIN
147+- Revaluation account [x] [x]
148+- Provision B.S account [ ] [ ]
149+- Provision P&L account [ ] [ ]
150+
151+For CH (Provision) :
152+ LOSS GAIN
153+- Revaluation account [ ] [ ]
154+- Provision B.S account [x] [ ]
155+- Provision P&L account [x] [ ]
156+
157+For FR
158+ LOSS GAIN
159+- Revaluation account [x] [x]
160+- Provision B.S account [x] [ ]
161+- Provision P&L account [x] [ ]
162+
163+""",
164+
165+ "author": "Camptocamp, TeMPO Consulting",
166+ "license": 'AGPL-3',
167+ "depends": ["base",
168+ "account",
169+ ],
170+ "init_xml": [
171+ #"res_currency_view.xml",
172+ "account_view.xml",
173+ "wizard/wizard_currency_revaluation_view.xml"],
174+ "update_xml": [],
175+ #"test": ["test/currency_revaluation.yml"],
176+ "demo_xml": [],
177+ "installable": True,
178+ "active": False,
179+# 'certificate': 'certificate',
180+}
181+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
182
183=== added file 'msf_currency_revaluation/account.py'
184--- msf_currency_revaluation/account.py 1970-01-01 00:00:00 +0000
185+++ msf_currency_revaluation/account.py 2014-01-16 13:10:58 +0000
186@@ -0,0 +1,146 @@
187+# -*- coding: utf-8 -*-
188+##############################################################################
189+#
190+# Author: Yannick Vaucher, Guewen Baconnier
191+# Copyright 2012 Camptocamp SA
192+#
193+# This program is free software: you can redistribute it and/or modify
194+# it under the terms of the GNU Affero General Public License as
195+# published by the Free Software Foundation, either version 3 of the
196+# License, or (at your option) any later version.
197+#
198+# This program is distributed in the hope that it will be useful,
199+# but WITHOUT ANY WARRANTY; without even the implied warranty of
200+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
201+# GNU Affero General Public License for more details.
202+#
203+# You should have received a copy of the GNU Affero General Public License
204+# along with this program. If not, see <http://www.gnu.org/licenses/>.
205+#
206+##############################################################################
207+
208+from osv import osv, fields
209+from tools.translate import _
210+
211+
212+class account_move_line(osv.osv):
213+
214+ _inherit = 'account.move.line'
215+ _columns = {
216+ # [account_unrealized_currency_gain_loss module]
217+ # By convention added columns stats with gl_.
218+ 'gl_foreign_balance': fields.float('Aggregated Amount curency'),
219+ 'gl_balance': fields.float('Aggregated Amount'),
220+ 'gl_revaluated_balance': fields.float('Revaluated Amount'),
221+ 'gl_currency_rate': fields.float('Currency rate'),
222+ # [/account_unrealized_currency_gain_loss module]
223+ 'is_revaluated_ok': fields.boolean(
224+ _("Revaluation line"), readonly=True),
225+ }
226+
227+ _defaults = {
228+ 'is_revaluated_ok': False,
229+ }
230+
231+account_move_line()
232+
233+
234+class account_account(osv.osv):
235+
236+ _inherit = 'account.account'
237+
238+ _columns = {
239+ 'currency_revaluation': fields.boolean(
240+ string=_("Included in revaluation?")),
241+ 'user_type_code': fields.related(
242+ 'user_type', 'code',
243+ type='char', string=_(u"Type (code)")),
244+ 'instance_level': fields.related(
245+ 'company_id', 'instance_id', 'level',
246+ type='char', string=_(u"Instance level")),
247+ }
248+
249+ _defaults = {'currency_revaluation': False}
250+
251+ _sql_mapping = {
252+ 'balance': "COALESCE(SUM(l.debit),0) - COALESCE(SUM(l.credit), 0) as balance",
253+ 'debit': "COALESCE(SUM(l.debit), 0) as debit",
254+ 'credit': "COALESCE(SUM(l.credit), 0) as credit",
255+ 'foreign_balance': "COALESCE(SUM(l.amount_currency), 0) as foreign_balance"}
256+
257+ def _revaluation_query(self, cr, uid, ids, revaluation_date, context=None):
258+ lines_where_clause = self.pool.get('account.move.line').\
259+ _query_get(cr, uid, context=context)
260+ query = ("SELECT l.account_id as id, l.currency_id, " +
261+ ', '.join(self._sql_mapping.values()) +
262+ " FROM account_move_line l "
263+ " WHERE l.account_id IN %(account_ids)s AND "
264+ " l.date <= %(revaluation_date)s AND "
265+ " l.currency_id IS NOT NULL AND "
266+ " l.reconcile_id IS NULL AND "
267+ + lines_where_clause +
268+ " GROUP BY l.account_id, l.currency_id")
269+ params = {'revaluation_date': revaluation_date,
270+ 'account_ids': tuple(ids)}
271+ return query, params
272+
273+ def compute_revaluations(
274+ self, cr, uid, ids, period_ids, fiscalyear_id,
275+ revaluation_date, revaluation_method, context=None):
276+ if context is None:
277+ context = {}
278+ accounts = {}
279+
280+ # Compute for each account the balance/debit/credit from the move lines
281+ ctx_query = context.copy()
282+ ctx_query['periods'] = period_ids
283+ ctx_query['fiscalyear'] = fiscalyear_id
284+ query, params = self._revaluation_query(
285+ cr, uid, ids,
286+ revaluation_date,
287+ context=ctx_query)
288+ cr.execute(query, params)
289+ lines = cr.dictfetchall()
290+ for line in lines:
291+ # generate a tree
292+ # - account_id
293+ # -- currency_id
294+ # ----- balances
295+ account_id, currency_id = line['id'], line['currency_id']
296+ accounts.setdefault(account_id, {})
297+ accounts[account_id].setdefault(currency_id, {})
298+ accounts[account_id][currency_id] = line
299+
300+ # Compute for each account the initial balance/debit/credit from the
301+ # move lines and add it to the previous result
302+ if revaluation_method == 'liquidity_month':
303+ ctx_query = context.copy()
304+ ctx_query['periods'] = period_ids
305+ ctx_query['fiscalyear'] = fiscalyear_id
306+ ctx_query['initial_bal'] = True
307+ query, params = self._revaluation_query(
308+ cr, uid, ids,
309+ revaluation_date,
310+ context=ctx_query)
311+ cr.execute(query, params)
312+ lines = cr.dictfetchall()
313+ for line in lines:
314+ # generate a tree
315+ # - account_id
316+ # -- currency_id
317+ # ----- balances
318+ account_id, currency_id = line['id'], line['currency_id']
319+ accounts.setdefault(account_id, {})
320+ accounts[account_id].setdefault(
321+ currency_id,
322+ {'balance': 0, 'foreign_balance': 0, 'credit': 0, 'debit': 0})
323+ accounts[account_id][currency_id]['balance'] += line['balance']
324+ accounts[account_id][currency_id]['foreign_balance'] += line['foreign_balance']
325+ accounts[account_id][currency_id]['credit'] += line['credit']
326+ accounts[account_id][currency_id]['debit'] += line['debit']
327+
328+ return accounts
329+
330+account_account()
331+
332+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
333
334=== added file 'msf_currency_revaluation/account_view.xml'
335--- msf_currency_revaluation/account_view.xml 1970-01-01 00:00:00 +0000
336+++ msf_currency_revaluation/account_view.xml 2014-01-16 13:10:58 +0000
337@@ -0,0 +1,22 @@
338+<?xml version="1.0" encoding="utf-8"?>
339+<openerp>
340+ <data>
341+
342+ <record id="view_account_form_inherit" model="ir.ui.view">
343+ <field name="name">account.account.form</field>
344+ <field name="model">account.account</field>
345+ <field name="type">form</field>
346+ <field name="inherit_id" ref="account.view_account_form"/>
347+ <field name="arch" type="xml">
348+ <xpath expr="//notebook" position="inside">
349+ <page string="Currency Revaluation" attrs="{'invisible': [('instance_level', '!=', 'section')]}">
350+ <field name="instance_level" invisible="1"/>
351+ <field name="currency_revaluation"
352+ attrs="{'readonly': [('user_type_code', 'not in', ['receivables', 'payables', 'cash', 'asset', 'stock'])]}"/>
353+ </page>
354+ </xpath>
355+ </field>
356+ </record>
357+
358+ </data>
359+</openerp>
360
361=== added directory 'msf_currency_revaluation/i18n'
362=== added file 'msf_currency_revaluation/res_currency.py'
363--- msf_currency_revaluation/res_currency.py 1970-01-01 00:00:00 +0000
364+++ msf_currency_revaluation/res_currency.py 2014-01-16 13:10:58 +0000
365@@ -0,0 +1,52 @@
366+# -*- coding: utf-8 -*-
367+##############################################################################
368+#
369+# Author: Guewen Baconnier
370+# Copyright 2012 Camptocamp SA
371+#
372+# This program is free software: you can redistribute it and/or modify
373+# it under the terms of the GNU Affero General Public License as
374+# published by the Free Software Foundation, either version 3 of the
375+# License, or (at your option) any later version.
376+#
377+# This program is distributed in the hope that it will be useful,
378+# but WITHOUT ANY WARRANTY; without even the implied warranty of
379+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
380+# GNU Affero General Public License for more details.
381+#
382+# You should have received a copy of the GNU Affero General Public License
383+# along with this program. If not, see <http://www.gnu.org/licenses/>.
384+#
385+##############################################################################
386+
387+import time
388+
389+from osv import osv
390+from tools.translate import _
391+
392+
393+class res_currency(osv.osv):
394+
395+ _inherit = 'res.currency'
396+
397+ def _get_conversion_rate(self, cr, uid, from_currency,
398+ to_currency, context=None):
399+ if context is None:
400+ context = {}
401+ if 'revaluation' in context:
402+ currency = self.browse(cr, uid, from_currency.id, context=context)
403+ rate = currency.rate
404+ if rate == 0.0:
405+ date = context.get('date', time.strftime('%Y-%m-%d'))
406+ raise osv.except_osv(_('Error'),
407+ _('No rate found \n'
408+ 'for the currency: %s \n'
409+ 'at the date: %s') %
410+ (currency.symbol, date))
411+ return 1.0 / rate
412+
413+ else:
414+ return super(res_currency, self)._get_conversion_rate(
415+ cr, uid, from_currency, to_currency, context=context)
416+
417+res_currency()
418
419=== added file 'msf_currency_revaluation/res_currency_view.xml'
420--- msf_currency_revaluation/res_currency_view.xml 1970-01-01 00:00:00 +0000
421+++ msf_currency_revaluation/res_currency_view.xml 2014-01-16 13:10:58 +0000
422@@ -0,0 +1,22 @@
423+<?xml version="1.0" encoding="utf-8"?>
424+<openerp>
425+ <data>
426+
427+ <record id="view_currency_form_inherit" model="ir.ui.view">
428+ <field name="name">res.currency.form</field>
429+ <field name="model">res.currency</field>
430+ <field name="type">form</field>
431+ <field name="inherit_id" ref="base.view_currency_form"/>
432+ <field name="arch" type="xml">
433+ <xpath expr="//form[@string='Rates']/field[@name='rate']" position="after">
434+ <field name="currency_rate_type_id"/>
435+ </xpath>
436+ <xpath expr="//tree[@string='Rates']/field[@name='rate']" position="after">
437+ <field name="currency_rate_type_id"/>
438+ </xpath>
439+ </field>
440+ </record>
441+
442+
443+ </data>
444+</openerp>
445
446=== added directory 'msf_currency_revaluation/security'
447=== added directory 'msf_currency_revaluation/test'
448=== added file 'msf_currency_revaluation/test/currency_revaluation.yml'
449--- msf_currency_revaluation/test/currency_revaluation.yml 1970-01-01 00:00:00 +0000
450+++ msf_currency_revaluation/test/currency_revaluation.yml 2014-01-16 13:10:58 +0000
451@@ -0,0 +1,321 @@
452+-
453+ In order to test the currency revaluation wizard
454+ I will set all 6 provision account
455+ And set 2 new currencies
456+ currency1 with an old rate and a new rate that will make loss
457+ currency2 with an old rate and a new rate that will make profit
458+ Then I define an account with currency1 with a starting amount
459+ Then I create a move to increase balance of account1
460+ Then I define an account with currency2 with a starting amount
461+ Then I create a move to increase balance of account2
462+ Then I launch the revaluation wizard
463+ Then I check 8 entries have been correctly created
464+-
465+ I create 6 provision accounts
466+-
467+ !record {model: account.account, id: acc_reval_loss}:
468+ name: "Reval Loss"
469+ code: "XR001"
470+ #company_id: default
471+ type: "other"
472+ user_type: !ref {model: account.account.type,
473+ search: "[('code', '=', 'asset'), ('close_method', '=', 'balance')]"}
474+-
475+ !record {model: account.account, id: acc_reval_gain}:
476+ name: "Reval Gain"
477+ code: "XR002"
478+ #company_id: default
479+ type: "other"
480+ user_type: !ref {model: account.account.type,
481+ search: "[('code', '=', 'asset'), ('close_method', '=', 'balance')]"}
482+-
483+ !record {model: account.account, id: acc_prov_bs_loss}:
484+ name: "Prov B.S Loss"
485+ code: "XPBS001"
486+ #company_id: default
487+ type: "other"
488+ user_type: !ref {model: account.account.type,
489+ search: "[('code', '=', 'asset'), ('close_method', '=', 'balance')]"}
490+-
491+ !record {model: account.account, id: acc_prov_bs_gain}:
492+ name: "Prov B.S Gain"
493+ code: "XPBS002"
494+ #company_id: default
495+ type: "other"
496+ user_type: !ref {model: account.account.type,
497+ search: "[('code', '=', 'asset'), ('close_method', '=', 'balance')]"}
498+-
499+ !record {model: account.account, id: acc_prov_pl_loss}:
500+ name: "Prov P&L Loss"
501+ code: "XPPL001"
502+ #company_id: default
503+ type: "other"
504+ user_type: !ref {model: account.account.type,
505+ search: "[('code', '=', 'asset'), ('close_method', '=', 'balance')]"}
506+-
507+ !record {model: account.account, id: acc_prov_pl_gain}:
508+ name: "Prov P&L Gain"
509+ code: "XPPL002"
510+ #company_id: default
511+ type: "other"
512+ user_type: !ref {model: account.account.type,
513+ search: "[('code', '=', 'asset'), ('close_method', '=', 'balance')]"}
514+
515+-
516+ I set the 6 provision account in company
517+-
518+ !python {model: res.company}: |
519+ #select first company
520+ cp_id = self.search(cr, uid, [], limit=1)[0]
521+
522+ data_accounts = {'revaluation_loss_account_id': ref('acc_reval_loss'),
523+ 'revaluation_gain_account_id': ref('acc_reval_gain'),
524+ 'provision_bs_loss_account_id': ref('acc_prov_bs_loss'),
525+ 'provision_bs_gain_account_id': ref('acc_prov_bs_gain'),
526+ 'provision_pl_loss_account_id': ref('acc_prov_pl_loss'),
527+ 'provision_pl_gain_account_id': ref('acc_prov_pl_gain')}
528+ self.write(cr, uid, cp_id, data_accounts)
529+
530+-
531+ I create a rate type
532+-
533+ !record {model: res.currency.rate.type, id: rate_type1}:
534+ name: "Type 1"
535+
536+-
537+ I ensure there is an opening entry if a previous fiscalyear exists
538+-
539+ !python {model: account.fiscalyear}: |
540+ from datetime import datetime
541+
542+ user_obj = self.pool.get('res.users')
543+ move_obj = self.pool.get('account.move')
544+ move_line_obj = self.pool.get('account.move.line')
545+ journal_obj = self.pool.get('account.journal')
546+ period_obj = self.pool.get('account.period')
547+ cp = user_obj.browse(cr, uid, uid).company_id
548+
549+ my_date = '%s-01-01' %(datetime.now().year)
550+
551+ previous_fy = self.search(cr, uid,
552+ [('date_stop', '<', my_date),
553+ ('company_id', '=', cp.id)],
554+ limit=1,
555+ context=context)
556+
557+ if previous_fy:
558+
559+ journal_ids = journal_obj.search(cr, uid,
560+ [('type', '=', 'situation')],
561+ limit=1)
562+ current_fy_id = self.search(cr, uid,
563+ [('date_start', '<=', my_date),
564+ ('date_stop', '>=', my_date),
565+ ('company_id', '=', cp.id)],
566+ limit=1,
567+ context=context)[0]
568+ current_fy = self.browse(cr, uid, current_fy_id)
569+ period_id = [p.id for p in current_fy.period_ids if p.special == True][0]
570+
571+ # Create an entry
572+ move_data = {'name': "Opening entry",
573+ 'journal_id': journal_ids[0],
574+ 'period_id': period_id,
575+ 'date': my_date}
576+ move_id = move_obj.create(cr, uid, move_data, context=context)
577+
578+
579+-
580+ I set a default rate of our type for all currency to ensure all account will pass
581+-
582+ !python {model: res.currency}: |
583+ rate_obj = self.pool.get('res.currency.rate')
584+ currency_ids = self.search(cr, uid, [])
585+ currencies = self.browse(cr, uid, currency_ids)
586+ for cur in currencies:
587+ rate_data = {'name': "2010-01-01",
588+ 'rate': cur.rate,
589+ 'currency_id': cur.id,
590+ 'currency_rate_type_id': ref('rate_type1')}
591+ rate_obj.create(cr, uid, rate_data)
592+
593+-
594+ I create 2 foreign currencies
595+-
596+ !record {model: res.currency, id: currency1}:
597+ name: "Florin"
598+ symbol: "fl"
599+ rate_ids:
600+ - name: !eval "'%s-01-01' %(datetime.now().year)"
601+ rate: 100
602+ currency_rate_type_id: rate_type1
603+ - name: !eval "'%s-01-11' %(datetime.now().year)"
604+ rate: 50
605+ currency_rate_type_id: rate_type1
606+-
607+ !record {model: res.currency, id: currency2}:
608+ name: "Sesterce"
609+ symbol: "HS"
610+ rate_ids:
611+ - name: !eval "'%s-01-01' %(datetime.now().year)"
612+ rate: 2
613+ currency_rate_type_id: rate_type1
614+ - name: !eval "'%s-01-11' %(datetime.now().year)"
615+ rate: 4
616+ currency_rate_type_id: rate_type1
617+
618+-
619+ I define a 2 accounts
620+-
621+ !record {model: account.account, id: wiz_test_acc1}:
622+ name: "Account 1"
623+ code: "acc1"
624+ #company_id: default
625+ #type: default
626+ user_type: !ref {model: account.account.type,
627+ search: "[('code','=','asset'), ('close_method', '!=', 'none')]"}
628+ #currency_mode: default
629+ currency_id: currency1
630+-
631+ !record {model: account.account, id: wiz_test_acc2}:
632+ name: "Account 2"
633+ code: "acc2"
634+ #company_id: default
635+ #type: default
636+ user_type: !ref {model: account.account.type,
637+ search: "[('code','=','asset'), ('close_method', '!=', 'none')]"}
638+ #currency_mode: default
639+ currency_id: currency2
640+
641+-
642+ I create a journal
643+-
644+ !record {model: account.journal, id: wiz_general_journal}:
645+ name: "A General Journal"
646+ code: "GJ"
647+ type: 'general'
648+ view_id: !ref {model: account.journal.view,
649+ search: "[('name', '=', 'Bank/Cash Journal (Multi-Currency) View')]"}
650+
651+-
652+ I increase balance of my 2 accounts on 1st january (using old rate)
653+-
654+ !record {model: account.move, id: wiz_test_move1}:
655+ #name: default
656+ #period_id: default
657+ journal_id: !ref {model: account.journal,
658+ search: "[('type', '=', 'sale')]"}
659+ state: 'posted'
660+ date: !eval "'%s-01-01' %(datetime.now().year)"
661+- !record {model: account.move, id: wiz_test_move2}:
662+ #name: default
663+ #period_id: default
664+ journal_id: !ref {model: account.journal,
665+ search: "[('type', '=', 'sale')]"}
666+ state: 'posted'
667+ date: !eval "'%s-01-01' %(datetime.now().year)"
668+
669+-
670+ I insert a move line in move 1
671+-
672+ !python {model: account.move.line}: |
673+ from datetime import datetime
674+ vals = {
675+ 'account_id': ref('wiz_test_acc1'),
676+ 'amount_currency': -100000.0,
677+ 'currency_id': ref('currency1'),
678+ 'credit': 1000.0,
679+ 'date': '%s-01-01' %(datetime.now().year),
680+ 'debit': 0.0,
681+ 'name': 'Increase balance',
682+ 'quantity': 0.0,
683+ 'move_id': ref('wiz_test_move1'),
684+ 'state': 'valid'
685+ }
686+ line_id = self.create(cr, uid, vals)
687+ assert line_id, "Account move line has not been created"
688+
689+-
690+ I insert a move line in move 2
691+-
692+ !python {model: account.move.line}: |
693+ from datetime import datetime
694+ vals = {
695+ 'account_id': ref('wiz_test_acc2'),
696+ 'amount_currency': -2000.0,
697+ 'currency_id': ref('currency2'),
698+ 'credit': 1000.0,
699+ 'date': '%s-01-01' %(datetime.now().year),
700+ 'debit': 0.0,
701+ 'name': 'Increase balance',
702+ 'quantity': 0.0,
703+ 'move_id': ref('wiz_test_move2'),
704+ 'state': 'valid'
705+ }
706+ line_id = self.create(cr, uid, vals)
707+ assert line_id, "Account move line has not been created"
708+
709+-
710+ I Force my 2 move lines with a state to valid
711+-
712+ !python {model: account.move.line}: |
713+ cr.execute("UPDATE account_move_line SET state='valid' WHERE name = 'Increase balance'")
714+
715+-
716+ Launch the computing with the currency revaluation wizard on 20 january (using new rates)
717+-
718+ !python {model: wizard.currency.revaluation}: |
719+ from datetime import datetime
720+ # Enter wizard data
721+ wiz_data = {'revaluation_date': '%s-01-20' %(datetime.now().year),
722+ 'journal_id': ref('wiz_general_journal'),
723+ 'currency_type': ref('rate_type1'),
724+ 'label': '[%(account)s] wiz_test'}
725+ wiz_id = self.create(cr, uid, wiz_data)
726+ wiz = self.browse(cr, uid, wiz_id)
727+ # Call wizard computing
728+ result = wiz.revaluate_currency(context=context)
729+ assert result, "No result returned"
730+
731+-
732+ I check I have the 8 following entries
733+
734+ |---------------|--------|--------|
735+
736+ | Account | debit | credit |
737+
738+ |---------------|--------|--------|
739+
740+ | Prov P&L Loss | 0.0 | 1000.0 |
741+
742+ | Prov B.S Loss | 1000.0 | 0.0 |
743+
744+ | Reval Loss | 0.0 | 1000.0 |
745+
746+ | Account 1 | 1000.0 | 0.0 |
747+
748+ | Prov P&L Gain | 500.0 | 0.0 |
749+
750+ | Prov B.S Gain | 0.0 | 500.0 |
751+
752+ | Reval Gain | 500.0 | 0.0 |
753+
754+ | Account 2 | 0.0 | 500.0 |
755+-
756+ !python {model: account.move.line}: |
757+ label_search = "wiz_test"
758+ move_line_ids = self.search(cr, uid,
759+ [('name', 'like', label_search)])
760+ count_l = len(move_line_ids)
761+ assert count_l >= 8, "Some entries are missing found only %s on 8" %count_l
762+ lines = self.browse(cr, uid, move_line_ids)
763+ res = [(l.name, l.account_id.id, l.debit, l.credit) for l in lines]
764+ check_list = [(u'[acc1] wiz_test', ref('acc_prov_pl_loss'), 1000.0, 0.0),
765+ (u'[acc1] wiz_test', ref('acc_prov_bs_loss'), 0.0, 1000.0),
766+ (u'[acc1] wiz_test', ref('acc_reval_loss'), 1000.0, 0.0),
767+ (u'[acc1] wiz_test', ref('wiz_test_acc1'), 0.0, 1000.0),
768+ (u'[acc2] wiz_test', ref('acc_prov_pl_gain'), 0.0, 500.0),
769+ (u'[acc2] wiz_test', ref('acc_prov_bs_gain'), 500.0, 0.0),
770+ (u'[acc2] wiz_test', ref('acc_reval_gain'), 0.0, 500.0),
771+ (u'[acc2] wiz_test', ref('wiz_test_acc2'), 500.0, 0.0),]
772+ assert set(check_list) <= set(res), ("Those lines are missing\n"+"\n".join([el[0] + " " + str(el[1:]) for el in list(set(check_list) - set(res))]))
773
774=== added directory 'msf_currency_revaluation/wizard'
775=== added file 'msf_currency_revaluation/wizard/__init__.py'
776--- msf_currency_revaluation/wizard/__init__.py 1970-01-01 00:00:00 +0000
777+++ msf_currency_revaluation/wizard/__init__.py 2014-01-16 13:10:58 +0000
778@@ -0,0 +1,1 @@
779+from . import wizard_currency_revaluation
780
781=== added file 'msf_currency_revaluation/wizard/wizard_currency_revaluation.py'
782--- msf_currency_revaluation/wizard/wizard_currency_revaluation.py 1970-01-01 00:00:00 +0000
783+++ msf_currency_revaluation/wizard/wizard_currency_revaluation.py 2014-01-16 13:10:58 +0000
784@@ -0,0 +1,863 @@
785+# -*- coding: utf-8 -*-
786+##############################################################################
787+#
788+# Author: Yannick Vaucher, Guewen Baconnier
789+# Copyright 2012 Camptocamp SA
790+#
791+# This program is free software: you can redistribute it and/or modify
792+# it under the terms of the GNU Affero General Public License as
793+# published by the Free Software Foundation, either version 3 of the
794+# License, or (at your option) any later version.
795+#
796+# This program is distributed in the hope that it will be useful,
797+# but WITHOUT ANY WARRANTY; without even the implied warranty of
798+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
799+# GNU Affero General Public License for more details.
800+#
801+# You should have received a copy of the GNU Affero General Public License
802+# along with this program. If not, see <http://www.gnu.org/licenses/>.
803+#
804+##############################################################################
805+
806+import datetime
807+
808+from dateutil.relativedelta import relativedelta
809+
810+from osv import osv, fields
811+from tools.translate import _
812+
813+class WizardCurrencyrevaluation(osv.osv_memory):
814+ _name = 'wizard.currency.revaluation'
815+
816+ _columns = {'revaluation_date': fields.date(
817+ _('Revaluation Date')),
818+ 'revaluation_method': fields.selection(
819+ [('liquidity_month', _("Liquidity (Month-end)")),
820+ ('liquidity_year', _("Liquidity (Year-end)")),
821+ ('other_bs', _("Other B/S (Year-end)")),
822+ ],
823+ string=_("Revaluation method"), required=True),
824+ #'revaluation_year_ok': fields.boolean(
825+ # _("Year-end revaluation"),
826+ # help=_("In 'Liquidity' mode, you can choose to do a "
827+ # "year-end revaluation instead of month-end.")),
828+ 'fiscalyear_id': fields.many2one(
829+ 'account.fiscalyear', string=_("Fiscal year"),
830+ domain=[('state', '=', 'draft')],
831+ required=True),
832+ 'period_id': fields.many2one(
833+ 'account.period', string=_("Period"),
834+ domain="[('fiscalyear_id', '=', fiscalyear_id), ('state', '!=', ['created'])]"),
835+ 'currency_table_id': fields.many2one(
836+ 'res.currency.table', string=_("Currency table"),
837+ domain=[('state', '=', 'valid')]),
838+ 'journal_id': fields.many2one(
839+ 'account.journal', string=_("Entry journal"),
840+ #domain="[('type','=','general')]",
841+ help=_("Journal used for revaluation entries."),
842+ readonly=True),
843+ 'result_period_id': fields.many2one(
844+ 'account.period', string=_(u"Entry period"), required=True,
845+ domain="[('fiscalyear_id', '=', fiscalyear_id), ('state', '!=', 'created')]",
846+ help=_("Period used for revaluation entries.")),
847+ 'posting_date': fields.date(
848+ _('Entry date'), readonly=True,
849+ help=_("Revaluation entry date (document and posting date)")),
850+ 'label': fields.char(
851+ 'Entry description',
852+ size=100,
853+ help="This label will be inserted in entries description."
854+ " You can use %(account)s, %(currency)s"
855+ " and %(rate)s keywords.",
856+ required=True),
857+ }
858+
859+ #def _get_default_revaluation_date(self, cr, uid, context):
860+ # """Get stop date of the fiscal year."""
861+ # if context is None:
862+ # context = {}
863+ # #period_obj = self.pool.get('account.period')
864+ # #period_id = self._get_default_result_period_id(cr, uid, context=context)
865+ # #if period_id:
866+ # # period = period_obj.browse(cr, uid, period_id, context=context)
867+ # # return period.date_stop
868+ # #return False
869+ # fiscalyear_obj = self.pool.get('account.fiscalyear')
870+ # fiscalyear_id = self._get_default_fiscalyear_id(cr, uid, context=context)
871+ # if fiscalyear_id:
872+ # fiscalyear = fiscalyear_obj.browse(cr, uid, fiscalyear_id, context=context)
873+ # return fiscalyear.date_stop
874+ # return False
875+
876+ def _get_default_fiscalyear_id(self, cr, uid, context=None):
877+ """Get default fiscal year to process."""
878+ if context is None:
879+ context = {}
880+ user_obj = self.pool.get('res.users')
881+ cp = user_obj.browse(cr, uid, uid, context=context).company_id
882+ current_date = datetime.date.today().strftime('%Y-%m-%d')
883+ fiscalyear_obj = self.pool.get('account.fiscalyear')
884+ fiscalyear_ids = fiscalyear_obj.search(
885+ cr, uid,
886+ [('date_start', '<', current_date),
887+ ('date_stop', '>', current_date),
888+ ('company_id', '=', cp.id)],
889+ limit=1,
890+ context=context)
891+ return fiscalyear_ids and fiscalyear_ids[0] or False
892+
893+ _defaults = {
894+ 'label': "%(currency)s %(account)s %(rate)s",
895+ 'revaluation_method': lambda *args: 'liquidity_month',
896+ 'fiscalyear_id': _get_default_fiscalyear_id,
897+ }
898+
899+ def default_get(self, cr, uid, fields, context=None):
900+ """'default_get' method overridden."""
901+ res = super(WizardCurrencyrevaluation, self).default_get(
902+ cr, uid, fields, context=context)
903+ user_obj = self.pool.get('res.users')
904+ fiscalyear_obj = self.pool.get('account.fiscalyear')
905+ period_obj = self.pool.get('account.period')
906+ journal_obj = self.pool.get('account.journal')
907+ # Fiscalyear
908+ cp = user_obj.browse(cr, uid, uid, context=context).company_id
909+ current_date = datetime.date.today().strftime('%Y-%m-%d')
910+ fiscalyear_obj = self.pool.get('account.fiscalyear')
911+ fiscalyear_ids = fiscalyear_obj.search(
912+ cr, uid,
913+ [('date_start', '<', current_date),
914+ ('date_stop', '>', current_date),
915+ ('company_id', '=', cp.id)],
916+ limit=1,
917+ context=context)
918+ res['fiscalyear_id'] = fiscalyear_ids and fiscalyear_ids[0] or False
919+ # Revaluation date
920+ res['revaluation_date'] = False
921+ if res['fiscalyear_id']:
922+ fiscalyear = fiscalyear_obj.browse(
923+ cr, uid, res['fiscalyear_id'], context=context)
924+ res['revaluation_date'] = fiscalyear.date_stop
925+ # Period
926+ period_date = datetime.date.today()
927+ if period_date.month > 1:
928+ period_date = period_date - relativedelta(months=1)
929+ # NOTE: the method 'get_period_from_date()' supplied by the
930+ # 'account_tools' module is used here
931+ period_ids = period_obj.get_period_from_date(
932+ cr, uid, period_date.strftime('%Y-%m-%d'))
933+ res['period_id'] = period_ids and period_ids[0] or False
934+ # Journal
935+ journal_ids = journal_obj.search(
936+ cr, uid, [('code', '=', 'REVAL')], context=context)
937+ if not journal_ids:
938+ raise osv.except_osv(
939+ _(u"Error"),
940+ _(u"No revaluation journal found!"))
941+ res['journal_id'] = journal_ids and journal_ids[0] or False
942+ # Entry period
943+ res['result_period_id'] = False
944+ if res['fiscalyear_id']:
945+ period_ids = period_obj.search(
946+ cr, uid,
947+ [('number', '=', 13),
948+ ('fiscalyear_id', '=', res['fiscalyear_id']),
949+ ('state', '!=', 'created')],
950+ context=context)
951+ res['result_period_id'] = period_ids and period_ids[0] or False
952+ # Posting date
953+ res['posting_date'] = False
954+ if res['period_id']:
955+ period = period_obj.browse(
956+ cr, uid, res['period_id'], context=context)
957+ res['posting_date'] = period.date_stop
958+ return res
959+
960+ def on_change_revaluation_method(
961+ self, cr, uid, ids, method, fiscalyear_id, period_id):
962+ """'on_change' method for the 'revaluation_method', 'fiscalyear_id' and
963+ 'period_id' fields.
964+ """
965+ if not method or not fiscalyear_id:
966+ return {}
967+ value = {}
968+ warning = {}
969+ fiscalyear_obj = self.pool.get('account.fiscalyear')
970+ period_obj = self.pool.get('account.period')
971+ move_obj = self.pool.get('account.move')
972+ fiscalyear = fiscalyear_obj.browse(cr, uid, fiscalyear_id)
973+ # Check
974+ previous_fiscalyear_ids = fiscalyear_obj.search(
975+ cr, uid,
976+ [('date_stop', '<', fiscalyear.date_start),
977+ ('company_id', '=', fiscalyear.company_id.id)],
978+ limit=1)
979+ if previous_fiscalyear_ids:
980+ special_period_ids = [p.id for p in fiscalyear.period_ids
981+ if p.special == True]
982+ opening_move_ids = []
983+ if special_period_ids:
984+ opening_move_ids = move_obj.search(
985+ cr, uid, [('period_id', '=', special_period_ids[0])])
986+ if not opening_move_ids or not special_period_ids:
987+ warning = {
988+ 'title': _('Warning!'),
989+ 'message': _('No opening entries in opening period for this fiscal year')
990+ }
991+ # Set values according to the user input
992+ value['period_id'] = period_id
993+ value['revaluation_date'] = False
994+ if method == 'liquidity_month':
995+ #if period_id == 'no_period' and fiscalyear_id:
996+ # # If the current fiscal year is the actual one, we get the
997+ # # previous month as the right period (except for january)
998+ # if fiscalyear_id == self._get_default_fiscalyear_id(cr, uid):
999+ # period_date = datetime.date.today()
1000+ # if period_date.month > 1:
1001+ # period_date = period_date - relativedelta(months=1)
1002+ # # If the selected fiscal year is not the actual one, we get its
1003+ # # last period
1004+ # else:
1005+ # period_date = datetime.datetime.strptime(
1006+ # fiscalyear.date_stop, '%Y-%m-%d')
1007+ # # NOTE: the method 'get_period_from_date()' supplied by the
1008+ # # 'account_tools' module is used here
1009+ # period_ids = period_obj.get_period_from_date(
1010+ # cr, uid, period_date.strftime('%Y-%m-%d'))
1011+ # period_id = period_ids and period_ids[0] or False
1012+ # value['period_id'] = period_id
1013+ if period_id:
1014+ period = period_obj.browse(cr, uid, period_id)
1015+ value['revaluation_date'] = period.date_stop
1016+ else:
1017+ value['revaluation_date'] = fiscalyear.date_stop
1018+ value['posting_date'] = fiscalyear.date_stop
1019+ period_ids = period_obj.search(
1020+ cr, uid,
1021+ [('state', '!=', 'created'),
1022+ ('fiscalyear_id', '=', fiscalyear.id),
1023+ ('number', '=', 13)])
1024+ if period_ids:
1025+ value['result_period_id'] = period_ids[0]
1026+ res = {'value': value, 'warning': warning}
1027+ return res
1028+
1029+ def on_change_fiscalyear_id(self, cr, uid, ids, method, fiscalyear_id):
1030+ """'on_change' method for the 'fiscalyear_id' field."""
1031+ if not method or not fiscalyear_id:
1032+ return {}
1033+ value = {}
1034+ warning = {}
1035+ fiscalyear_obj = self.pool.get('account.fiscalyear')
1036+ period_obj = self.pool.get('account.period')
1037+ fiscalyear = fiscalyear_obj.browse(cr, uid, fiscalyear_id)
1038+ if method in ['liquidity_month', 'liquidity_year']:
1039+ if fiscalyear_id:
1040+ # If the current fiscal year is the actual one, we get the
1041+ # previous month as the right period (except for january)
1042+ if fiscalyear_id == self._get_default_fiscalyear_id(cr, uid):
1043+ period_date = datetime.date.today()
1044+ if period_date.month > 1:
1045+ period_date = period_date - relativedelta(months=1)
1046+ # If the selected fiscal year is not the actual one, we get its
1047+ # last period
1048+ else:
1049+ period_date = datetime.datetime.strptime(
1050+ fiscalyear.date_stop, '%Y-%m-%d')
1051+ # NOTE: the method 'get_period_from_date()' supplied by the
1052+ # 'account_tools' module is used here
1053+ period_ids = period_obj.get_period_from_date(
1054+ cr, uid, period_date.strftime('%Y-%m-%d'))
1055+ period_id = period_ids and period_ids[0] or False
1056+ value['period_id'] = period_id
1057+ value['result_period_id'] = period_id
1058+ period = period_obj.browse(cr, uid, period_id)
1059+ value['revaluation_date'] = period.date_stop
1060+ value['posting_date'] = period.date_stop
1061+ # Set the next period as the 'Entry period' + the entry date
1062+ #next_period_date = datetime.datetime.strptime(
1063+ # period.date_start, '%Y-%m-%d') + relativedelta(months=1)
1064+ #next_period_ids = period_obj.get_period_from_date(
1065+ # cr, uid, next_period_date.strftime('%Y-%m-%d'))
1066+ #value['result_period_id'] = \
1067+ # next_period_ids and next_period_ids[0] or False
1068+ elif method == 'other_bs':
1069+ value['revaluation_date'] = fiscalyear.date_stop
1070+ value['posting_date'] = fiscalyear.date_stop
1071+ period_ids = period_obj.search(
1072+ cr, uid,
1073+ [('state', '!=', 'created'),
1074+ ('fiscalyear_id', '=', fiscalyear.id),
1075+ ('number', '=', 13)])
1076+ if period_ids:
1077+ value['result_period_id'] = period_ids[0]
1078+ res = {'value': value, 'warning': warning}
1079+ return res
1080+
1081+ def on_change_result_period_id(self, cr, uid, ids, result_period_id, context=None):
1082+ """'on_change' method for the 'result_period_id' field."""
1083+ if context is None:
1084+ context = {}
1085+ value = {}
1086+ warning = {}
1087+ if result_period_id:
1088+ period_obj = self.pool.get('account.period')
1089+ period = period_obj.browse(cr, uid, result_period_id, context=context)
1090+ value['posting_date'] = period.date_stop
1091+ return {'value': value, 'warning': warning}
1092+
1093+ def _compute_unrealized_currency_gl(self, cr, uid,
1094+ currency_id,
1095+ balances,
1096+ form,
1097+ context=None):
1098+ """
1099+ Update data dict with the unrealized currency gain and loss
1100+ plus add 'currency_rate' which is the value used for rate in
1101+ computation
1102+
1103+ @param int currency_id: currency to revaluate
1104+ @param dict balances: contains foreign balance and balance
1105+
1106+ @return: updated data for foreign balance plus rate value used
1107+ """
1108+ context = context or {}
1109+
1110+ currency_obj = self.pool.get('res.currency')
1111+
1112+ # Compute unrealized gain loss
1113+ ctx_rate = context.copy()
1114+ ctx_rate['date'] = form.revaluation_date
1115+ user_obj = self.pool.get('res.users')
1116+ cp_currency_id = user_obj.browse(cr, uid, uid, context=context).company_id.currency_id.id
1117+
1118+ currency = currency_obj.browse(cr, uid, currency_id, context=ctx_rate)
1119+
1120+ foreign_balance = adjusted_balance = balances.get('foreign_balance', 0.0)
1121+ balance = balances.get('balance', 0.0)
1122+ unrealized_gain_loss = 0.0
1123+ # Check if reval_balance exists
1124+ if foreign_balance:
1125+ ctx_rate['revaluation'] = True
1126+ # Use reval_balance to fix booking balance problems
1127+ adjusted_balance = currency_obj.compute(
1128+ cr, uid, currency_id, cp_currency_id, foreign_balance,
1129+ context=ctx_rate)
1130+ # Substract reval lines from amount
1131+ unrealized_gain_loss = adjusted_balance - balance
1132+ else:
1133+ if balance:
1134+ if currency_id != cp_currency_id:
1135+ unrealized_gain_loss = 0.0 - balance
1136+ else:
1137+ unrealized_gain_loss = 0.0
1138+ else:
1139+ unrealized_gain_loss = 0.0
1140+ return {'unrealized_gain_loss': unrealized_gain_loss,
1141+ 'currency_rate': currency.rate,
1142+ 'revaluated_balance': adjusted_balance}
1143+
1144+ def _format_label(self, cr, uid, text, account_id, currency_id,
1145+ rate, context=None):
1146+ """
1147+ Return a text with replaced keywords by values
1148+
1149+ @param str text: label template, can use
1150+ %(account)s, %(currency)s, %(rate)s
1151+ @param int account_id: id of the account to display in label
1152+ @param int currency_id: id of the currency to display
1153+ @param float rate: rate to display
1154+ """
1155+ account_obj = self.pool.get('account.account')
1156+ currency_obj = self.pool.get('res.currency')
1157+ account = account_obj.browse(cr, uid,
1158+ account_id,
1159+ context=context)
1160+ currency = currency_obj.browse(cr, uid, currency_id, context=context)
1161+ data = {'account': account.code or False,
1162+ 'currency': currency.name or False,
1163+ 'rate': rate or False}
1164+ return text % data
1165+
1166+ def _write_adjust_balance(self, cr, uid, account_id, currency_id,
1167+ partner_id, amount, label, rate, form, sums,
1168+ context=None):
1169+ """
1170+ Generate entries to adjust balance in the revaluation accounts
1171+
1172+ @param account_id: ID of account to be reevaluated
1173+ @param amount: Amount to be written to adjust the balance
1174+ @param label: Label to be written on each entry
1175+ @param form: Wizard browse record containing data
1176+
1177+ @return: ids of created move_lines
1178+ """
1179+ if context is None:
1180+ context = {}
1181+
1182+ def create_move():
1183+ account = self.pool.get('account.account').browse(
1184+ cr, uid, account_id, context=context)
1185+ currency = self.pool.get('res.currency').browse(
1186+ cr, uid, currency_id, context=context)
1187+ base_move = {'name': label,
1188+ 'ref': "%s-%s-%s" % (currency.name, account.code, rate),
1189+ 'journal_id': form.journal_id.id,
1190+ 'period_id': form.result_period_id.id,
1191+ 'document_date': form.posting_date,
1192+ 'date': form.posting_date}
1193+ return move_obj.create(cr, uid, base_move, context=context)
1194+
1195+ def create_move_line(move_id, line_data, sums):
1196+ line_name = "Revaluation - %s" % form.fiscalyear_id.name
1197+ if form.revaluation_method == 'liquidity_month':
1198+ line_name = "Revaluation - %s" % form.period_id.name
1199+ base_line = {'name': line_name,
1200+ 'currency_id': currency_id,
1201+ 'amount_currency': 0.0,
1202+ 'document_date': form.posting_date,
1203+ 'date': form.posting_date,
1204+ 'is_revaluated_ok': True,
1205+ }
1206+ base_line.update(line_data)
1207+ # we can assume that keys should be equals columns name + gl_
1208+ # but it was not decide when the code was designed. So commented code may sucks
1209+ #for k, v in sums.items():
1210+ # line_data['gl_' + k] = v
1211+ base_line['gl_foreign_balance'] = sums.get('foreign_balance', 0.0)
1212+ base_line['gl_balance'] = sums.get('balance', 0.0)
1213+ base_line['gl_revaluated_balance'] = sums.get('revaluated_balance', 0.0)
1214+ base_line['gl_currency_rate'] = sums.get('currency_rate', 0.0)
1215+ return move_line_obj.create(cr, uid, base_line, context=context)
1216+
1217+ account_obj = self.pool.get('account.account')
1218+ move_obj = self.pool.get('account.move')
1219+ move_line_obj = self.pool.get('account.move.line')
1220+ #user_obj = self.pool.get('res.users')
1221+ distrib_obj = self.pool.get('analytic.distribution')
1222+ cc_distrib_obj = self.pool.get('cost.center.distribution.line')
1223+ fp_distrib_obj = self.pool.get('funding.pool.distribution.line')
1224+ account_ana_obj = self.pool.get('account.analytic.account')
1225+ model_data_obj = self.pool.get('ir.model.data')
1226+
1227+ # UF-2246: Use 6940 account as default for reevaluation line.
1228+ revaluation_account_ids = account_obj.search(cr, uid, [('code', '=', '6940')])
1229+ if not revaluation_account_ids:
1230+ raise osv.except_osv(_('Settings Error!'), _('G/L account 6940 is missing, please create it'))
1231+
1232+ revaluation_account_id = revaluation_account_ids[0]
1233+ revaluation_account = account_obj.browse(
1234+ cr, uid, revaluation_account_id, context=context)
1235+
1236+ # Prepare the analytic distribution for the account revaluation entry
1237+ # if the account has a 'expense' or 'income' type
1238+ distribution_id = False
1239+ if revaluation_account.user_type.code in ['expense', 'income']:
1240+ destination_id = model_data_obj.get_object_reference(
1241+ cr, uid, 'analytic_distribution', 'analytic_account_destination_support')[1]
1242+ #cost_center_id = model_data_obj.get_object_reference(
1243+ # cr, uid, 'analytic_distribution', 'analytic_account_project_intermission')[1]
1244+ cost_center_id = account_ana_obj.search(
1245+ cr, uid, [('for_fx_gain_loss', '=', True)], context=context)[0]
1246+ funding_pool_id = model_data_obj.get_object_reference(
1247+ cr, uid, 'analytic_distribution', 'analytic_account_msf_private_funds')[1]
1248+ distribution_id = distrib_obj.create(cr, uid, {}, context=context)
1249+ cc_distrib_obj.create(
1250+ cr, uid,
1251+ {'distribution_id': distribution_id,
1252+ 'analytic_id': cost_center_id,
1253+ 'destination_id': destination_id,
1254+ 'currency_id': currency_id,
1255+ 'percentage': 100.0,
1256+ 'source_date': form.posting_date,
1257+ },
1258+ context=context)
1259+ fp_distrib_obj.create(
1260+ cr, uid,
1261+ {'distribution_id': distribution_id,
1262+ 'analytic_id': funding_pool_id,
1263+ 'destination_id': destination_id,
1264+ 'cost_center_id': cost_center_id,
1265+ 'currency_id': currency_id,
1266+ 'percentage': 100.0,
1267+ 'source_date': form.posting_date,
1268+ },
1269+ context=context)
1270+
1271+ move_id = False
1272+ created_ids = []
1273+ # over revaluation
1274+ if amount >= 0.02:
1275+ if revaluation_account_id:
1276+ move_id = create_move()
1277+ # Create a move line to Debit account to be revaluated
1278+ line_data = {
1279+ 'debit': amount,
1280+ 'debit_currency': False,
1281+ 'move_id': move_id,
1282+ 'account_id': account_id,
1283+ }
1284+ created_ids.append(create_move_line(move_id, line_data, sums))
1285+ # Create a move line to Credit revaluation account
1286+ line_data = {
1287+ 'credit': amount,
1288+ 'credit_currency': False,
1289+ 'move_id': move_id,
1290+ 'account_id': revaluation_account_id,
1291+ 'analytic_distribution_id': distribution_id,
1292+ }
1293+ created_ids.append(create_move_line(move_id, line_data, sums))
1294+ # under revaluation
1295+ elif amount <= -0.02:
1296+ amount = -amount
1297+ if revaluation_account_id:
1298+ move_id = create_move()
1299+
1300+ # Create a move line to Debit revaluation loss account
1301+ line_data = {
1302+ 'debit': amount,
1303+ 'move_id': move_id,
1304+ 'account_id': revaluation_account_id,
1305+ 'analytic_distribution_id': distribution_id,
1306+ }
1307+
1308+ created_ids.append(create_move_line(move_id, line_data, sums))
1309+ # Create a move line to Credit account to be revaluated
1310+ line_data = {
1311+ 'credit': amount,
1312+ 'move_id': move_id,
1313+ 'account_id': account_id,
1314+ }
1315+ created_ids.append(create_move_line(move_id, line_data, sums))
1316+ # Hard post the move
1317+ if move_id:
1318+ move_obj.post(cr, uid, [move_id], context=context)
1319+ return move_id, created_ids
1320+
1321+ def revaluate_currency(self, cr, uid, ids, context=None):
1322+ """
1323+ Compute unrealized currency gain and loss and add entries to
1324+ adjust balances
1325+
1326+ @return: dict to open an Entries view filtered on generated move lines
1327+ """
1328+ if context is None:
1329+ context = {}
1330+ user_obj = self.pool.get('res.users')
1331+ period_obj = self.pool.get('account.period')
1332+ account_obj = self.pool.get('account.account')
1333+ #move_obj = self.pool.get('account.move')
1334+ currency_obj = self.pool.get('res.currency')
1335+ seq_obj = self.pool.get('ir.sequence')
1336+
1337+ company = user_obj.browse(cr, uid, uid).company_id
1338+
1339+ created_ids = []
1340+
1341+ if isinstance(ids, (int, long)):
1342+ ids = [ids]
1343+ form = self.browse(cr, uid, ids[0], context=context)
1344+
1345+ # Set the currency table in the context for later computations
1346+ if form.revaluation_method in ['liquidity_year', 'other_bs']:
1347+ context['currency_table_id'] = form.currency_table_id.id
1348+
1349+ # Get all currency names to map them with main currencies later
1350+ currency_codes_from_table = {}
1351+ if form.revaluation_method in ['liquidity_year', 'other_bs']:
1352+ for currency in form.currency_table_id.currency_ids:
1353+ # Check the revaluation date and dates in the currency table
1354+ #if currency.date != form.revaluation_date:
1355+ # raise osv.except_osv(
1356+ # _("Error"),
1357+ # _("The revaluation date seems to differ with the data of "
1358+ # "the currency table."))
1359+ currency_codes_from_table[currency.name] = currency.id
1360+
1361+ # Get posting date (as the field is readonly, its value is not sent
1362+ # to the server by the web client
1363+ form.posting_date = form.result_period_id and form.result_period_id.date_stop
1364+ #if form.revaluation_method == 'liquidity':
1365+ # form.revaluation_date = form.period_id and form.period_id.date_stop
1366+
1367+ # Search for accounts Balance Sheet or Liquidity to be eevaluated
1368+ account_ids = []
1369+ if form.revaluation_method in ['liquidity_month', 'liquidity_year']:
1370+ account_ids = account_obj.search(
1371+ cr, uid,
1372+ [('currency_revaluation', '=', True),
1373+ ('type', '=', 'liquidity'),
1374+ ('user_type_code', '=', 'cash')],
1375+ #('user_type.close_method', '!=', 'none'),
1376+ context=context)
1377+ elif form.revaluation_method == 'other_bs':
1378+ account_ids = account_obj.search(
1379+ cr, uid,
1380+ [('currency_revaluation', '=', True),
1381+ ('user_type_code', 'in', ['receivables', 'payables', 'asset', 'stock'])],
1382+ #('type', '!=', 'liquidity')],
1383+ context=context)
1384+ if not account_ids:
1385+ raise osv.except_osv(
1386+ _('Settings Error!'),
1387+ _("No account to be revaluated found. "
1388+ "Please check 'Included in revaluation' "
1389+ "for at least one account in account form."))
1390+
1391+ special_period_ids = [p.id for p in form.fiscalyear_id.period_ids if p.special == True]
1392+ if not special_period_ids:
1393+ raise osv.except_osv(_('Error!'),
1394+ _('No special period found for the fiscalyear %s') %
1395+ form.fiscalyear_id.code)
1396+
1397+ # FIXME
1398+ #opening_move_ids = []
1399+ #if special_period_ids:
1400+ # opening_move_ids = move_obj.search(
1401+ # cr, uid, [('period_id', '=', special_period_ids[0])])
1402+ # if not opening_move_ids:
1403+ # # if the first move is on this fiscalyear, this is the first
1404+ # # financial year
1405+ # first_move_id = move_obj.search(
1406+ # cr, uid, [('company_id', '=', company.id)],
1407+ # order='date', limit=1)
1408+ # if not first_move_id:
1409+ # raise osv.except_osv(
1410+ # _('Error!'),
1411+ # _('No fiscal entries found'))
1412+ # first_move = move_obj.browse(
1413+ # cr, uid, first_move_id[0], context=context)
1414+ # if fiscalyear.id != first_move.period_id.fiscalyear_id:
1415+ # raise osv.except_osv(
1416+ # _('Error!'),
1417+ # _('No opening entries in opening period for this fiscal year %s' % (
1418+ # fiscalyear.code,)))
1419+
1420+ period_ids = []
1421+ if form.revaluation_method == 'liquidity_month':
1422+ period_ids = [form.period_id.id]
1423+ else:
1424+ period_ids = []
1425+ for period in form.fiscalyear_id.period_ids:
1426+ if period.number < 13:
1427+ period_ids.append(period.id)
1428+ if not period_ids:
1429+ raise osv.except_osv(
1430+ _('Error!'),
1431+ _('No period found for the fiscalyear %s') % (
1432+ form.fiscalyear_id.code))
1433+ # Check periods state
1434+ periods_not_field_closed = []
1435+ for period in period_obj.browse(cr, uid, period_ids, context=context):
1436+ if period.state in ['created', 'draft']:
1437+ periods_not_field_closed.append(period.name)
1438+ if periods_not_field_closed:
1439+ raise osv.except_osv(
1440+ _(u"Error"),
1441+ _(u"Revaluation aborted, the following periods are not field-closed: %s" % (
1442+ ', '.join(periods_not_field_closed))))
1443+
1444+ # Get balance sums
1445+ account_sums = account_obj.compute_revaluations(
1446+ cr, uid, account_ids, period_ids, form.fiscalyear_id.id,
1447+ form.revaluation_date, form.revaluation_method, context=context)
1448+ for account_id, account_tree in account_sums.iteritems():
1449+ for currency_id, sums in account_tree.iteritems():
1450+ new_currency_id = currency_id
1451+ # If the method is 'other_bs' or 'liquidity_year', check if the
1452+ # account move currency is declared in the currency table and
1453+ # get it there
1454+ if form.revaluation_method in ['liquidity_year', 'other_bs']:
1455+ currency = currency_obj.browse(cr, uid, currency_id, context=context)
1456+ if currency.id != company.currency_id.id and currency.name not in currency_codes_from_table:
1457+ raise osv.except_osv(
1458+ _("Error"),
1459+ _("The currency %s is not declared in the currency table.") % currency.name)
1460+ new_currency_id = currency_codes_from_table[currency.name]
1461+ if not sums['balance']:
1462+ continue
1463+ # Update sums with compute amount currency balance
1464+ diff_balances = self._compute_unrealized_currency_gl(
1465+ cr, uid, new_currency_id, sums, form, context=context)
1466+ account_sums[account_id][currency_id].update(diff_balances)
1467+ # Create entries only after all computation have been done
1468+ for account_id, account_tree in account_sums.iteritems():
1469+ for currency_id, sums in account_tree.iteritems():
1470+ new_currency_id = currency_id
1471+ # If the method is 'other_bs' or 'liquidity_year', get the
1472+ # account move currency in the currency table
1473+ if form.revaluation_method in ['liquidity_year', 'other_bs']:
1474+ currency = currency_obj.browse(cr, uid, currency_id, context=context)
1475+ new_currency_id = currency_codes_from_table[currency.name]
1476+ adj_balance = sums.get('unrealized_gain_loss', 0.0)
1477+ if not adj_balance:
1478+ continue
1479+
1480+ rate = sums.get('currency_rate', 0.0)
1481+ #label = self._format_label(
1482+ # cr, uid, form.label, account_id, new_currency_id, rate)
1483+ # Generate the entry sequence
1484+ #seq = seq_obj.get_id(
1485+ # cr, uid, form.journal_id.sequence_id.id,
1486+ # context={'fiscalyear_id': form.fiscalyear_id.id})
1487+ #label = "%s-%s-%s" % (
1488+ # company.instance_id.move_prefix, form.journal_id.code, seq)
1489+ label = '/'
1490+
1491+ # Write an entry to adjust balance
1492+ move_id, new_ids = self._write_adjust_balance(
1493+ cr, uid,
1494+ account_id, currency_id, False, adj_balance,
1495+ label, rate, form, sums, context=context)
1496+ if move_id:
1497+ created_ids.extend(new_ids)
1498+ # Create a second journal entry that will offset the first one
1499+ # if the revaluation method is 'Other B/S'
1500+ if form.revaluation_method == 'other_bs':
1501+ move_id, rev_line_ids = self._reverse_other_bs_move_lines(
1502+ cr, uid, form, move_id, new_ids, context=context)
1503+ created_ids.extend(rev_line_ids)
1504+
1505+ if created_ids:
1506+ # Set all booking amount to 0 for revaluation lines
1507+ cr.execute('UPDATE account_move_line '
1508+ 'SET debit_currency = 0, credit_currency = 0, amount_currency = 0'
1509+ 'WHERE id IN %s', (tuple(created_ids),))
1510+ # Return the view
1511+ return {'domain': "[('id','in', %s)]" % (created_ids,),
1512+ 'name': _("Created revaluation lines"),
1513+ 'view_type': 'form',
1514+ 'view_mode': 'tree,form',
1515+ 'auto_search': True,
1516+ 'res_model': 'account.move.line',
1517+ 'view_id': False,
1518+ 'search_view_id': False,
1519+ 'type': 'ir.actions.act_window'}
1520+ else:
1521+ raise osv.except_osv(_("Warning"),
1522+ _("No revaluation accounting entry have been posted."))
1523+
1524+ def _get_next_fiscalyear_id(self, cr, uid, fiscalyear_id, context=None):
1525+ """Return the next fiscal year ID."""
1526+ if context is None:
1527+ context = {}
1528+ fiscalyear_obj = self.pool.get('account.fiscalyear')
1529+ fiscalyear = fiscalyear_obj.browse(
1530+ cr, uid, fiscalyear_id, context=context)
1531+ date_stop = datetime.datetime.strptime(
1532+ fiscalyear.date_stop, '%Y-%m-%d')
1533+ next_year_start = date_stop + relativedelta(years=1)
1534+ next_fiscalyear_ids = fiscalyear_obj.search(
1535+ cr, uid,
1536+ [('state', '=', 'draft'),
1537+ ('date_start', '<=', next_year_start.strftime('%Y-%m-%d')),
1538+ ('date_stop', '>=', next_year_start.strftime('%Y-%m-%d'))],
1539+ context=context)
1540+ if not next_fiscalyear_ids:
1541+ raise osv.except_osv(
1542+ _("Error"),
1543+ _("The next fiscal year does not exist."))
1544+ return next_fiscalyear_ids[0]
1545+
1546+ def _get_first_fiscalyear_period_id(self, cr, uid, fiscalyear_id, context=None):
1547+ """Return the first period ID of a fiscal year."""
1548+ if context is None:
1549+ context = {}
1550+ fiscalyear_obj = self.pool.get('account.fiscalyear')
1551+ period_obj = self.pool.get('account.period')
1552+ period_ids = period_obj.search(
1553+ cr, uid,
1554+ [('fiscalyear_id', '=', fiscalyear_id), ('number', '=', 1)],
1555+ context=context)
1556+ if not period_ids:
1557+ fiscalyear = fiscalyear_obj.browse(
1558+ cr, uid, fiscalyear_id, context=context)
1559+ raise osv.except_osv(
1560+ _("Error"),
1561+ _("No first period found in the fiscal year %s.") % (
1562+ fiscalyear.name))
1563+ return period_ids[0]
1564+
1565+ def _reverse_other_bs_move_lines(
1566+ self, cr, uid, form, move_id, line_ids, context=None):
1567+ """Reverse 'Other B/S' revaluation entries."""
1568+ if context is None:
1569+ context = {}
1570+ move_obj = self.pool.get('account.move')
1571+ line_obj = self.pool.get('account.move.line')
1572+ aal_obj = self.pool.get('account.analytic.line')
1573+ period_obj = self.pool.get('account.period')
1574+ # Get reserved move
1575+ rev_move = move_obj.browse(cr, uid, move_id, context=context)
1576+ # Compute the posting date:
1577+ # Get the start date of the first period of the next fiscal year
1578+ fiscalyear_id = self._get_next_fiscalyear_id(
1579+ cr, uid, form.fiscalyear_id.id, context=context)
1580+ period_id = self._get_first_fiscalyear_period_id(
1581+ cr, uid, fiscalyear_id, context=context)
1582+ period = period_obj.browse(cr, uid, period_id, context=context)
1583+ posting_date = period.date_start
1584+ # Create a new move
1585+ move_vals = {
1586+ 'journal_id': form.journal_id.id,
1587+ 'period_id': period_id,
1588+ 'date': posting_date,
1589+ 'ref': rev_move.ref,
1590+ }
1591+ move_id = move_obj.create(cr, uid, move_vals, context=context)
1592+ # Reverse lines + associate them to the newly created move
1593+ rev_line_ids = []
1594+ lines_to_reconcile = []
1595+ for line in line_obj.browse(cr, uid, line_ids, context=context):
1596+ # Prepare default value for new line
1597+ vals = {
1598+ 'move_id': move_id,
1599+ 'date': posting_date,
1600+ 'document_date': posting_date,
1601+ 'journal_id': form.journal_id.id,
1602+ 'period_id': period_id,
1603+ }
1604+ # Copy the line
1605+ rev_line_id = line_obj.copy(cr, uid, line.id, vals, context=context)
1606+ # Do the reverse
1607+ amt = -1 * line.amount_currency
1608+ vals.update({
1609+ 'debit': line.credit,
1610+ 'credit': line.debit,
1611+ 'amount_currency': amt,
1612+ 'journal_id': form.journal_id.id,
1613+ 'name': line_obj.join_without_redundancy(line.name, 'REV'),
1614+ 'reversal_line_id': line.id,
1615+ 'account_id': line.account_id.id,
1616+ 'source_date': line.date,
1617+ 'reversal': True,
1618+ 'reference': line.move_id and line.move_id.name or '',
1619+ 'ref': line.move_id and line.move_id.name or '',
1620+ })
1621+ line_obj.write(cr, uid, [rev_line_id], vals, context=context)
1622+ # Inform old line that it have been corrected
1623+ #line_obj.write(
1624+ # cr, uid, [line.id],
1625+ # {'corrected': True, 'have_an_historic': True},
1626+ # context=context)
1627+ # Keep lines to reconcile
1628+ if line.account_id.reconcile:
1629+ lines_to_reconcile.append((line.id, rev_line_id))
1630+ # Search analytic lines from first move line
1631+ aal_ids = aal_obj.search(cr, uid, [('move_id', '=', line.id)])
1632+ aal_obj.write(cr, uid, aal_ids, {'is_reallocated': True})
1633+ # Search analytic lines from reversed line and flag them as "is_reversal"
1634+ new_aal_ids = aal_obj.search(cr, uid, [('move_id', '=', rev_line_id)])
1635+ aal_obj.write(cr, uid, new_aal_ids, {'is_reversal': True,})
1636+ rev_line_ids.append(rev_line_id)
1637+ # Hard post the move
1638+ move_obj.post(cr, uid, [move_id], context=context)
1639+ # Reconcile lines
1640+ for line_id, rev_line_id in lines_to_reconcile:
1641+ line_obj.reconcile_partial(
1642+ cr, uid, [line_id, rev_line_id], context=context)
1643+ return move_id, rev_line_ids
1644+
1645+WizardCurrencyrevaluation()
1646+
1647+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
1648
1649=== added file 'msf_currency_revaluation/wizard/wizard_currency_revaluation_view.xml'
1650--- msf_currency_revaluation/wizard/wizard_currency_revaluation_view.xml 1970-01-01 00:00:00 +0000
1651+++ msf_currency_revaluation/wizard/wizard_currency_revaluation_view.xml 2014-01-16 13:10:58 +0000
1652@@ -0,0 +1,60 @@
1653+<?xml version="1.0" encoding="utf-8"?>
1654+<openerp>
1655+ <data>
1656+
1657+ <record id="view_account_currency_revaluation_wizard" model="ir.ui.view">
1658+ <field name="name">Revaluation</field>
1659+ <field name="model">wizard.currency.revaluation</field>
1660+ <field name="type">form</field>
1661+ <field name="arch" type="xml">
1662+ <form string="Revaluation" col="4">
1663+ <field name="revaluation_method"
1664+ on_change="on_change_revaluation_method(revaluation_method, fiscalyear_id, period_id)"/>
1665+ <newline/>
1666+ <newline/>
1667+ <field name="fiscalyear_id"
1668+ on_change="on_change_fiscalyear_id(revaluation_method, fiscalyear_id)"/>
1669+ <newline/>
1670+ <field name="period_id"
1671+ attrs="{'invisible': ['|', ('revaluation_method', '=', 'other_bs'), ('revaluation_method', '=', 'liquidity_year')],
1672+ 'required': [('revaluation_method', '=', 'liquidity_month')]}"
1673+ on_change="on_change_revaluation_method(revaluation_method, fiscalyear_id, period_id)"/>
1674+ <newline/>
1675+ <field name="currency_table_id"
1676+ attrs="{'invisible': [('revaluation_method', '=', 'liquidity_month')],
1677+ 'required': [('revaluation_method', 'in', ['liquidity_year', 'other_bs'])]}"/>
1678+ <field name="revaluation_date" invisible="1"/>
1679+ <newline/>
1680+ <separator string="" colspan="6"/>
1681+ <field name="result_period_id"
1682+ on_change="on_change_result_period_id(result_period_id)"/>
1683+ <newline/>
1684+ <field name="posting_date"/>
1685+ <newline/>
1686+ <field name="journal_id"/>
1687+ <newline/>
1688+ <field name="label" invisible="1"/>
1689+ <newline/>
1690+ <button special="cancel" string="Cancel" icon="gtk-cancel" />
1691+ <button name="revaluate_currency" string="Validate" type="object" icon="gtk-execute"/>
1692+ </form>
1693+ </field>
1694+ </record>
1695+
1696+ <record id="action_view_account_currency_revaluation_wizard" model="ir.actions.act_window">
1697+ <field name="name">Revaluation</field>
1698+ <field name="type">ir.actions.act_window</field>
1699+ <field name="res_model">wizard.currency.revaluation</field>
1700+ <field name="view_type">form</field>
1701+ <field name="view_mode">form</field>
1702+ <field name="target">new</field>
1703+ </record>
1704+
1705+ <menuitem
1706+ action="action_view_account_currency_revaluation_wizard"
1707+ id="menu_view_account_currency_revaluation_wizard"
1708+ parent="account.menu_finance_periodical_processing"/>
1709+
1710+ </data>
1711+</openerp>
1712+
1713
1714=== modified file 'msf_profile/__openerp__.py'
1715--- msf_profile/__openerp__.py 2013-12-19 15:10:23 +0000
1716+++ msf_profile/__openerp__.py 2014-01-16 13:10:58 +0000
1717@@ -116,6 +116,7 @@
1718 "msf_field_access_rights",
1719 "unifield_tests",
1720 "vertical_integration",
1721+ "msf_currency_revaluation",
1722 ],
1723 "update_xml": [
1724 "report.xml",
1725
1726=== modified file 'res_currency_functional/res_currency_rate_functional.py'
1727--- res_currency_functional/res_currency_rate_functional.py 2012-09-21 14:49:36 +0000
1728+++ res_currency_functional/res_currency_rate_functional.py 2014-01-16 13:10:58 +0000
1729@@ -36,7 +36,7 @@
1730 if currency is None:
1731 currency_obj = self.read(cr, uid, ids, ['currency_id'])[0]
1732 currency = currency_obj['currency_id'][0]
1733- move_line_search_params = [('currency_id', '=', currency)]
1734+ move_line_search_params = [('currency_id', '=', currency), ('is_revaluated_ok', '=', False)]
1735 if date is not None:
1736 move_line_search_params.append(('date', '>=', date))
1737

Subscribers

People subscribed via source and target branches