From 25b36b599a25463fb9ca89ea2bca8fea4405e51f Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Tue, 22 Nov 2011 17:55:37 +0100 Subject: [PATCH 01/19] [IMP] account_voucher: multi currency handling bzr revid: qdp-launchpad@openerp.com-20111122165537-2c8a9ov2qjklq2wj --- addons/account_voucher/account_voucher.py | 140 ++++++++++++++---- .../account_voucher/test/account_voucher.yml | 1 - addons/account_voucher/test/sales_receipt.yml | 1 - .../voucher_payment_receipt_view.xml | 53 +++---- 4 files changed, 136 insertions(+), 59 deletions(-) diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py index fd6dac9f90d..4b099eedc66 100644 --- a/addons/account_voucher/account_voucher.py +++ b/addons/account_voucher/account_voucher.py @@ -90,6 +90,17 @@ class account_voucher(osv.osv): return tax_id return False + def _get_payment_rate_currency(self, cr, uid, context=None): + if context is None: context = {} + journal_pool = self.pool.get('account.journal') + journal_id = context.get('journal_id', False) + if journal_id: + journal = journal_pool.browse(cr, uid, journal_id, context=context) + if journal.currency: + return journal.currency.id + #no journal given in the context, use company currency as default + return self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.currency_id.id + def _get_currency(self, cr, uid, context=None): if context is None: context = {} journal_pool = self.pool.get('account.journal') @@ -143,11 +154,21 @@ class account_voucher(osv.osv): res = super(account_voucher, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu) doc = etree.XML(res['arch']) - nodes = doc.xpath("//field[@name='partner_id']") + + # replace the label of the field payment_rate + currency_obj = self.pool.get('res.currency') + base_currency_id = currency_obj.search(cr, uid, [('rate','=',1.0),('rate_ids','=',1.0)], context=context) + symbol = base_currency_id and currency_obj.name_get(cr, uid, base_currency_id, context=context)[0][1] + string = _("Rate for this operation: 1 %s is") % symbol + payment_rate_field = doc.xpath("//field[@name='payment_rate']") + for field in payment_rate_field: + field.set('string', string) + if context.get('type', 'sale') in ('purchase', 'payment'): + nodes = doc.xpath("//field[@name='partner_id']") for node in nodes: node.set('domain', "[('supplier', '=', True)]") - res['arch'] = etree.tostring(doc) + res['arch'] = etree.tostring(doc) return res def _compute_writeoff_amount(self, cr, uid, line_dr_ids, line_cr_ids, amount): @@ -184,7 +205,10 @@ class account_voucher(osv.osv): res = {} debit = credit = 0.0 for voucher in self.browse(cr, uid, ids, context=context): - res[voucher.id] = voucher.amount / voucher.payment_rate + rate = voucher.currency_id.rate or voucher.company_id.currency_id.rate + if voucher.currency_id == voucher.payment_rate_currency_id: + rate = voucher.payment_rate + res[voucher.id] = voucher.amount / rate * voucher.company_id.currency_id.rate return res _name = 'account.voucher' @@ -247,8 +271,9 @@ class account_voucher(osv.osv): 'comment': fields.char('Counterpart Comment', size=64, required=True, readonly=True, states={'draft': [('readonly', False)]}), 'analytic_id': fields.many2one('account.analytic.account','Write-Off Analytic Account', readonly=True, states={'draft': [('readonly', False)]}), 'writeoff_amount': fields.function(_get_writeoff_amount, string='Reconcile Amount', type='float', readonly=True), + 'payment_rate_currency_id': fields.many2one('res.currency', 'Payment Rate Currency', required=True, readonly=True, states={'draft':[('readonly',False)]}), 'payment_rate': fields.float('Payment Rate', digits=(12,6), required=True, readonly=True, states={'draft': [('readonly', False)]}, - help='The rate between the journal currency and the company currency for this particular payment.'), + help='The specific rate that will be used for this voucher for the selected currency.'), 'paid_amount_in_company_currency': fields.function(_paid_amount_in_company_currency, string='Paid Amount in Company Currency', type='float', readonly=True), } _defaults = { @@ -269,6 +294,7 @@ class account_voucher(osv.osv): 'payment_option': 'without_writeoff', 'comment': _('Write-Off'), 'payment_rate': 1.0, + 'payment_rate_currency_id': _get_payment_rate_currency, } def compute_tax(self, cr, uid, ids, context=None): @@ -374,7 +400,7 @@ class account_voucher(osv.osv): }) return {'value':default} - def onchange_journal_voucher(self, cr, uid, ids, line_ids=False, tax_id=False, price=0.0, partner_id=False, journal_id=False, ttype=False, context=None): + def onchange_journal_voucher(self, cr, uid, ids, line_ids=False, tax_id=False, price=0.0, partner_id=False, journal_id=False, ttype=False, company_id=False, context=None): """price Returns a dict that contains new values and context @@ -413,20 +439,25 @@ class account_voucher(osv.osv): default['value']['account_id'] = account_id default['value']['type'] = ttype or tr_type - vals = self.onchange_journal(cr, uid, ids, journal_id, line_ids, tax_id, partner_id, context) + vals = self.onchange_journal(cr, uid, ids, journal_id, line_ids, tax_id, partner_id, company_id, context) default['value'].update(vals.get('value')) return default - def onchange_rate(self, cr, uid, ids, rate, amount, context=None): - res = {'value': {'paid_amount_in_company_currency': 0.0}} - if rate and amount: - res['value']['paid_amount_in_company_currency'] = amount / rate + def onchange_rate(self, cr, uid, ids, rate, amount, currency_id, payment_rate_currency_id, company_id, context=None): + res = {'value': {}} + if rate and amount and currency_id and currency_id == payment_rate_currency_id: + company_rate = self.pool.get('res.company').browse(cr, uid, company_id, context=context).currency_id.rate + res['value']['paid_amount_in_company_currency'] = amount / rate * company_rate return res - def onchange_amount(self, cr, uid, ids, amount, rate, partner_id, journal_id, currency_id, ttype, date, context=None): + def onchange_amount(self, cr, uid, ids, amount, rate, partner_id, journal_id, currency_id, ttype, date, payment_rate_currency_id, company_id, context=None): + if context is None: + context = {} res = self.onchange_partner_id(cr, uid, ids, partner_id, journal_id, amount, currency_id, ttype, date, context=context) - vals = self.onchange_rate(cr, uid, ids, rate, amount, context=context) + ctx = context.copy() + ctx.update({'date': date}) + vals = self.onchange_rate(cr, uid, ids, rate, amount, currency_id, payment_rate_currency_id, company_id, context=ctx) for key in vals.keys(): res[key].update(vals[key]) return res @@ -582,7 +613,22 @@ class account_voucher(osv.osv): default['value']['writeoff_amount'] = self._compute_writeoff_amount(cr, uid, default['value']['line_dr_ids'], default['value']['line_cr_ids'], price) return default - def onchange_date(self, cr, uid, ids, date, currency_id, amount, context=None): + def onchange_payment_rate_currency(self, cr, uid, ids, currency_id, payment_rate_currency_id, date, amount, company_id, context=None): + if context is None: + context = {} + res = {'value': {}} + #set the default payment rate of the voucher and compute the paid amount in company currency + if currency_id and currency_id == payment_rate_currency_id: + ctx = context.copy() + ctx.update({'date': date}) + payment_rate = self.pool.get('res.currency').browse(cr, uid, currency_id, context=ctx).rate + res['value'].update({'payment_rate': payment_rate}) + vals = self.onchange_rate(cr, uid, ids, payment_rate, amount, currency_id, payment_rate_currency_id, company_id, context=ctx) + for key in vals.keys(): + res[key].update(vals[key]) + return res + + def onchange_date(self, cr, uid, ids, date, currency_id, payment_rate_currency_id, amount, company_id, context=None): """ @param date: latest value from user input for field date @param args: other arguments @@ -590,22 +636,19 @@ class account_voucher(osv.osv): @return: Returns a dict which contains new values, and context """ res = {'value': {}} + #FIXME: use find() hereunder + #set the period of the voucher period_pool = self.pool.get('account.period') pids = period_pool.search(cr, uid, [('date_start', '<=', date), ('date_stop', '>=', date)]) if pids: res['value'].update({'period_id':pids[0]}) - #set the default payment rate of the voucher and compute the paid amount in company currency - payment_rate = 1.0 - if currency_id: - payment_rate = self.pool.get('res.currency').browse(cr, uid, currency_id, context={'date': date}).rate - res['value'].update({'payment_rate': payment_rate}) - vals = self.onchange_rate(cr, uid, ids, payment_rate, amount, context=context) + vals = self.onchange_payment_rate_currency(cr, uid, ids, currency_id, payment_rate_currency_id, date, amount, company_id, context=context) for key in vals.keys(): res[key].update(vals[key]) return res - def onchange_journal(self, cr, uid, ids, journal_id, line_ids, tax_id, partner_id, date, amount, ttype, context=None): + def onchange_journal(self, cr, uid, ids, journal_id, line_ids, tax_id, partner_id, date, amount, ttype, company_id, context=None): if not journal_id: return False journal_pool = self.pool.get('account.journal') @@ -620,12 +663,16 @@ class account_voucher(osv.osv): currency_id = False if journal.currency: currency_id = journal.currency.id - payment_rate = self.pool.get('res.currency').browse(cr, uid, currency_id, context={'date': date}).rate + ctx = context.copy() + ctx.update({'date': date}) + payment_rate = self.pool.get('res.currency').browse(cr, uid, currency_id, context=ctx).rate vals['value'].update({'payment_rate': payment_rate}) - res = self.onchange_rate(cr, uid, ids, payment_rate, amount, context=context) + res = self.onchange_rate(cr, uid, ids, payment_rate, amount, currency_id, currency_id, company_id, context=ctx) for key in res.keys(): vals[key].update(res[key]) - vals['value'].update({'currency_id': currency_id}) + if currency_id: + vals['value'].update({'currency_id': currency_id}) + vals['value'].update({'payment_rate_currency_id': currency_id}) res = self.onchange_partner_id(cr, uid, ids, partner_id, journal_id, amount, currency_id, ttype, date, context) for key in res.keys(): vals[key].update(res[key]) @@ -730,9 +777,9 @@ class account_voucher(osv.osv): # TODO: Make this logic available. # -for sale, purchase we have but for the payment and receipt we do not have as based on the bank/cash journal we can not know its payment or receipt if voucher_brw.type in ('purchase', 'payment'): - credit = voucher_brw.amount / voucher_brw.payment_rate + credit = voucher_brw.paid_amount_in_company_currency#voucher_brw.amount / voucher_brw.payment_rate * voucher_brw.company_id.currency_id.rate elif voucher_brw.type in ('sale', 'receipt'): - debit = voucher_brw.amount / voucher_brw.payment_rate + debit = voucher_brw.paid_amount_in_company_currency#amount / voucher_brw.payment_rate * voucher_brw.company_id.currency_id.rate if debit < 0: credit = -debit; debit = 0.0 if credit < 0: debit = -credit; credit = 0.0 sign = debit - credit < 0 and -1 or 1 @@ -831,6 +878,24 @@ class account_voucher(osv.osv): } return (move_line, move_line_counterpart) + def _convert_amount(self, cr, uid, amount, voucher_id, context=None): + #TODO: doccument me + currency_obj = self.pool.get('res.currency') + voucher = self.browse(cr, uid, voucher_id, context=context) + res = amount + if voucher.payment_rate_currency_id.id == voucher.company_id.currency_id.id: + rate_between_voucher_and_base = voucher.currency_id.rate or 1.0 + rate_between_base_and_company = voucher.payment_rate or 1.0 + res = amount / rate_between_voucher_and_base * rate_between_base_and_company + elif voucher.payment_rate_currency_id.id == voucher.currency_id.id: + rate_between_base_and_company = voucher.company_id.currency_id.rate or 1.0 + rate_between_voucher_and_base = voucher.payment_rate or 1.0 + res = amount / rate_between_voucher_and_base * rate_between_base_and_company + else: + res = currency_obj.compute(cr, uid, voucher.currency_id.id, voucher.company_id.currency_id.id, amount, context=ctx) + print 'res', res + return res + def voucher_move_line_create(self, cr, uid, voucher_id, line_total, move_id, company_currency, current_currency, context=None): ''' Create one account move line, on the given account move, per voucher line where amount is not 0.0. @@ -843,24 +908,32 @@ class account_voucher(osv.osv): :param company_currency: id of currency of the company to which the voucher belong :param current_currency: id of currency of the voucher :return: Tuple build as (remaining amount not allocated on voucher lines, list of account_move_line created in this method) - :rtype: tuple(int, list of int) + :rtype: tuple(float, list of int) ''' + if context is None: + context = {} move_line_obj = self.pool.get('account.move.line') currency_obj = self.pool.get('res.currency') tot_line = line_total rec_lst_ids = [] - voucher_brw = self.pool.get('account.voucher').browse(cr,uid,voucher_id,context) + voucher_brw = self.pool.get('account.voucher').browse(cr, uid, voucher_id, context) + ctx = context.copy() + ctx.update({'date': voucher_brw.date}) for line in voucher_brw.line_ids: #create one move line per voucher line where amount is not 0.0 if not line.amount: continue - #we check if the voucher line is fully paid or not and create a move line to balance the payment and initial invoice if needed + #TODO: comment me + amount = self._convert_amount(cr, uid, line.untax_amount or line.amount, voucher_brw.id, context=ctx) + #residual amount in company currency + #amount_residual = line.move_line_id.amount_residual - amount + #TODO: remove me if line.amount == line.amount_unreconciled: - amount = (line.untax_amount or line.amount) / voucher_brw.payment_rate + # amount = (line.untax_amount or line.amount) / voucher_brw.payment_rate amount_residual = line.move_line_id.amount_residual - amount #residual amount in company currency else: - amount = (line.untax_amount or line.amount) / voucher_brw.payment_rate + # amount = (line.untax_amount or line.amount) / voucher_brw.payment_rate amount_residual = 0.0 move_line = { 'journal_id': voucher_brw.journal_id.id, @@ -997,6 +1070,9 @@ class account_voucher(osv.osv): for voucher in self.browse(cr, uid, ids, context=context): if voucher.move_id: continue + #TODO: -need to check- Can't we just use the context returned by _sel_context? + ctx = context.copy() + ctx.update({'date': voucher.date}) company_currency = self._get_company_currency(cr, uid, voucher.id, context) current_currency = self._get_current_currency(cr, uid, voucher.id, context) context = self._sel_context(cr, uid, voucher.id, context) @@ -1010,9 +1086,9 @@ class account_voucher(osv.osv): line_total = move_line_brw.debit - move_line_brw.credit rec_list_ids = [] if voucher.type == 'sale': - line_total = line_total - (voucher.tax_amount / voucher.payment_rate) + line_total = line_total - self._convert_amount(cr, uid, voucher.tax_amount, voucher.id, context=ctx) elif voucher.type == 'purchase': - line_total = line_total + (voucher.tax_amount / voucher.payment_rate) + line_total = line_total + self._convert_amount(cr, uid, voucher.tax_amount, voucher.id, context=ctx) #create one move line per voucher line where amount is not 0.0 line_total, rec_list_ids = self.voucher_move_line_create(cr, uid, voucher.id, line_total, move_id, company_currency, current_currency, context) diff --git a/addons/account_voucher/test/account_voucher.yml b/addons/account_voucher/test/account_voucher.yml index 33ae609e3f3..7e5482aa931 100644 --- a/addons/account_voucher/test/account_voucher.yml +++ b/addons/account_voucher/test/account_voucher.yml @@ -5,7 +5,6 @@ account_id: account.cash amount: 1000.0 company_id: base.main_company - currency_id: base.EUR journal_id: account.bank_journal name: Voucher for Axelor narration: Basic Pc diff --git a/addons/account_voucher/test/sales_receipt.yml b/addons/account_voucher/test/sales_receipt.yml index d3fd720ec6d..7ea4f7d1c55 100644 --- a/addons/account_voucher/test/sales_receipt.yml +++ b/addons/account_voucher/test/sales_receipt.yml @@ -5,7 +5,6 @@ account_id: account.a_recv amount: 30000.0 company_id: base.main_company - currency_id: base.EUR journal_id: account.sales_journal line_cr_ids: - account_id: account.a_sale diff --git a/addons/account_voucher/voucher_payment_receipt_view.xml b/addons/account_voucher/voucher_payment_receipt_view.xml index 46720b2732c..4adebed8a1a 100644 --- a/addons/account_voucher/voucher_payment_receipt_view.xml +++ b/addons/account_voucher/voucher_payment_receipt_view.xml @@ -75,13 +75,13 @@
- + - + - - - - - - + + + + + + + @@ -140,14 +141,14 @@ - + - + @@ -188,12 +189,13 @@ - - + + - - + domain="[('type','=','other')]" colspan="4"/> + + + @@ -289,14 +291,14 @@ + on_change="onchange_amount(amount, payment_rate, partner_id, journal_id, currency_id, type, date, payment_rate_currency_id, company_id, context)"/> - + @@ -337,12 +339,13 @@ - - + + - - + domain="[('type','=','other')]" colspan="4"/> + + + From 7393886d18ab5274cd5a1911e1280c8b3a9ce2b1 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 23 Nov 2011 14:38:14 +0100 Subject: [PATCH 02/19] [FIX] account_voucher: small fixes in account_voucher.py due to last commit and updating of yaml files to have them compliant with last changes bzr revid: qdp-launchpad@openerp.com-20111123133814-w2vsqmklajtyonxk --- addons/account_voucher/account_voucher.py | 5 +- addons/account_voucher/test/case1_usd_usd.yml | 113 +++++++++-------- .../test/case2_suppl_usd_eur.yml | 114 +++++++++--------- .../test/case2_usd_eur_debtor_in_eur.yml | 114 +++++++++--------- .../test/case2_usd_eur_debtor_in_usd.yml | 114 +++++++++--------- addons/account_voucher/test/case3_eur_eur.yml | 113 ++++++++--------- addons/account_voucher/test/case4_cad_chf.yml | 57 ++++----- 7 files changed, 314 insertions(+), 316 deletions(-) diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py index 4b099eedc66..b2c87a53672 100644 --- a/addons/account_voucher/account_voucher.py +++ b/addons/account_voucher/account_voucher.py @@ -600,7 +600,6 @@ class account_voucher(osv.osv): rs['amount'] = amount total_credit -= amount - default['value']['line_ids'].append(rs) if rs['type'] == 'cr': default['value']['line_cr_ids'].append(rs) else: @@ -880,6 +879,7 @@ class account_voucher(osv.osv): def _convert_amount(self, cr, uid, amount, voucher_id, context=None): #TODO: doccument me + #TODO: rounding errors currency_obj = self.pool.get('res.currency') voucher = self.browse(cr, uid, voucher_id, context=context) res = amount @@ -892,8 +892,7 @@ class account_voucher(osv.osv): rate_between_voucher_and_base = voucher.payment_rate or 1.0 res = amount / rate_between_voucher_and_base * rate_between_base_and_company else: - res = currency_obj.compute(cr, uid, voucher.currency_id.id, voucher.company_id.currency_id.id, amount, context=ctx) - print 'res', res + res = currency_obj.compute(cr, uid, voucher.currency_id.id, voucher.company_id.currency_id.id, amount, context=context) return res def voucher_move_line_create(self, cr, uid, voucher_id, line_total, move_id, company_currency, current_currency, context=None): diff --git a/addons/account_voucher/test/case1_usd_usd.yml b/addons/account_voucher/test/case1_usd_usd.yml index e19e7e3ee46..96a0e07f70d 100644 --- a/addons/account_voucher/test/case1_usd_usd.yml +++ b/addons/account_voucher/test/case1_usd_usd.yml @@ -131,39 +131,41 @@ assert (move_line.debit - move_line.credit == 80), "Invoice move is not correct for debtors account" - - I create the first voucher of payment - + I set the context that will be used for the encoding of all the vouchers of this file +- + !context + 'type': 'receipt' +- + I create the first voucher of payment with values 240 USD, journal USD, +- + !record {model: account.voucher, id: account_voucher_1_case1, view: view_vendor_receipt_form}: + account_id: account.cash + amount: 240.0 + company_id: base.main_company + journal_id: bank_journal_USD + name: 'First payment: Case 1 USD/USD' + partner_id: base.res_partner_seagate + period_id: account.period_3 + date: !eval time.strftime("%Y-03-01") + payment_option: 'with_writeoff' + writeoff_acc_id: account.a_expense + comment: 'Write Off' + +- + I fill amounts 180 for the invoice of 200$ and 70 for the invoice of 100$> - !python {model: account.voucher}: | import netsvc, time vals = {} - res = self.onchange_partner_id(cr, uid, [], ref("base.res_partner_seagate"), ref('bank_journal_USD'), 240.00, 2, ttype='receipt', date=False) - vals = { - 'account_id': ref('account.cash'), - 'amount': 240.00, - 'company_id': ref('base.main_company'), - 'currency_id': ref('base.USD'), - 'journal_id': ref('bank_journal_USD'), - 'partner_id': ref('base.res_partner_seagate'), - 'period_id': ref('account.period_3'), - 'type': 'receipt', - 'date': time.strftime("%Y-%m-%d"), - 'payment_option': 'with_writeoff', - 'writeoff_acc_id': ref('account.a_expense'), - 'comment': 'Write Off', - 'name': 'First payment: Case 1 USD/USD', - } - vals.update(self.onchange_date(cr, uid, [], time.strftime('%Y-03-01'), ref('base.USD'), 240)['value']) - if not res['value']['line_cr_ids']: - res['value']['line_cr_ids'] = [{'type': 'cr', 'account_id': ref('account.a_recv'),}] - for item in res['value']['line_cr_ids']: - if item['amount_unreconciled'] == 200.00: - item['amount'] = 180.00 + voucher_id = self.browse(cr, uid, ref('account_voucher_1_case1')) + data = [] + for item in voucher_id.line_cr_ids: + if item.amount_unreconciled == 200.00: + data += [(item.id, 180.0)] else: - item['amount'] = 70.00 - vals['line_cr_ids'] = [(0,0,i) for i in res['value']['line_cr_ids']] - id = self.create(cr, uid, vals) - voucher_id = self.browse(cr, uid, id) + data += [(item.id, 70.0)] + for line_id, amount in data: + self.pool.get('account.voucher.line').write(cr, uid, [line_id], {'amount': amount}) assert (voucher_id.state=='draft'), "Voucher is not in draft state" - I check that writeoff amount computed is 10.0 @@ -228,41 +230,36 @@ move_line = move_line_obj.browse(cr, uid, move_lines[0]) assert (move_line.amount_residual_currency == 30.0) , "Residual amount is not correct for first Invoice" - - I create the second voucher of payment - - + I create the second voucher of payment with values 45 USD, journal USD, +- + !record {model: account.voucher, id: account_voucher_2_case1}: + account_id: account.cash + amount: 45.0 + company_id: base.main_company + journal_id: bank_journal_USD + name: 'Second payment: Case 1' + partner_id: base.res_partner_seagate + period_id: account.period_3 + date: !eval time.strftime("%Y-04-01") + payment_option: 'with_writeoff' + writeoff_acc_id: account.a_expense + exchange_acc_id: account.o_expense + comment: 'Write Off' +- + I fill amounts 20 for the invoice of 200$ and 30 for the invoice of 100$ - !python {model: account.voucher}: | import netsvc, time vals = {} - res = self.onchange_partner_id(cr, uid, [], ref("base.res_partner_seagate"), ref('bank_journal_USD'), 45.00, 2, ttype='receipt', date=False) - vals = { - 'account_id': ref('account.cash'), - 'amount': 45.00, - 'exchange_acc_id': ref('account.o_expense'), - 'company_id': ref('base.main_company'), - 'currency_id': ref('base.USD'), - 'journal_id': ref('bank_journal_USD'), - 'partner_id': ref('base.res_partner_seagate'), - 'period_id': ref('account.period_3'), - 'type': 'receipt', - 'date': time.strftime("%Y-%m-%d"), - 'payment_option': 'with_writeoff', - 'writeoff_acc_id': ref('account.a_expense'), - 'comment': 'Write Off', - 'name': 'Second payment: Case 1', - } - vals.update(self.onchange_date(cr, uid, [], time.strftime('%Y-04-01'), ref('base.USD'), 45.0)['value']) - if not res['value']['line_cr_ids']: - res['value']['line_cr_ids'] = [{'type': 'cr', 'account_id': ref('account.a_recv'),}] - for item in res['value']['line_cr_ids']: - if item['amount_unreconciled'] == 20.00: - item['amount'] = 20.00 + voucher_id = self.browse(cr, uid, ref('account_voucher_2_case1')) + data = [] + for item in voucher_id.line_cr_ids: + if item.amount_unreconciled == 20.00: + data += [(item.id, 20.0)] else: - item['amount'] = 30.00 - vals['line_cr_ids'] = [(0,0,i) for i in res['value']['line_cr_ids']] - id = self.create(cr, uid, vals) - voucher_id = self.browse(cr, uid, id) + data += [(item.id, 30.0)] + for line_id, amount in data: + self.pool.get('account.voucher.line').write(cr, uid, [line_id], {'amount': amount}) assert (voucher_id.state=='draft'), "Voucher is not in draft state" - I check that writeoff amount computed is 5.0 diff --git a/addons/account_voucher/test/case2_suppl_usd_eur.yml b/addons/account_voucher/test/case2_suppl_usd_eur.yml index 23f11d28803..6d6f71b943e 100644 --- a/addons/account_voucher/test/case2_suppl_usd_eur.yml +++ b/addons/account_voucher/test/case2_suppl_usd_eur.yml @@ -104,38 +104,41 @@ move_line = move_line_obj.browse(cr, uid, move_lines[0]) assert (move_line.debit - move_line.credit == -80), "Invoice move is incorrect for debtors account" - - I create the first voucher of payment - + I set the context that will be used for the encoding of all the vouchers of this file +- + !context + 'type': 'payment' +- + I create the first voucher of payment with values 240 EUR, journal EUR +- + !record {model: account.voucher, id: account_voucher_1_case2_suppl, view: view_vendor_payment_form}: + account_id: account.cash + amount: 240.0 + company_id: base.main_company + journal_id: bank_journal_EUR + name: 'First payment: Case 2 SUPPL USD/EUR', + partner_id: base.res_partner_seagate + period_id: account.period_3 + date: !eval time.strftime("%Y-03-01") + payment_option: 'with_writeoff' + writeoff_acc_id: account.a_expense + comment: 'Write Off' + +- + I fill amounts 180 for the invoice of 200$ and 70 for the invoice of 100$ - !python {model: account.voucher}: | import netsvc, time vals = {} - res = self.onchange_partner_id(cr, uid, [], ref("base.res_partner_seagate"), ref('bank_journal_EUR'), 240.0, 2, ttype='payment', date=False) - vals = { - 'account_id': ref('account.cash'), - 'amount': 240.0, - 'company_id': ref('base.main_company'), - 'currency_id': ref('base.EUR'), - 'journal_id': ref('bank_journal_EUR'), - 'partner_id': ref('base.res_partner_seagate'), - 'period_id': ref('account.period_3'), - 'type': 'payment', - 'date': time.strftime("%Y-03-01"), - 'payment_option': 'with_writeoff', - 'writeoff_acc_id': ref('account.a_expense'), - 'comment': 'Write Off', - 'name': 'First payment: Case 2 SUPPL USD/EUR', - } - if not res['value']['line_dr_ids']: - res['value']['line_dr_ids'] = [{'type': 'dr', 'account_id': ref('account.a_pay'),}] - for item in res['value']['line_dr_ids']: - if item['amount_unreconciled'] == 200.00: - item['amount'] = 180.00 + voucher_id = self.browse(cr, uid, ref('account_voucher_1_case2_suppl')) + data = [] + for item in voucher_id.line_cr_ids: + if item.amount_unreconciled == 200.00: + data += [(item.id, 180.0)] else: - item['amount'] = 70.00 - vals['line_dr_ids'] = [(0,0,i) for i in res['value']['line_dr_ids']] - id = self.create(cr, uid, vals) - voucher_id = self.browse(cr, uid, id) + data += [(item.id, 70.0)] + for line_id, amount in data: + self.pool.get('account.voucher.line').write(cr, uid, [line_id], {'amount': amount}) assert (voucher_id.state=='draft'), "Voucher is not in draft state" - I check that writeoff amount computed is -15.0 @@ -201,7 +204,7 @@ move_lines = move_line_obj.search(cr, uid, [('move_id', '=', invoice_id.move_id.id), ('invoice', '=', invoice_id.id), ('account_id', '=', invoice_id.account_id.id)]) move_line = move_line_obj.browse(cr, uid, move_lines[0]) assert (move_line.amount_residual_currency == 20.0 and move_line.amount_residual == 15) , "Residual amount is not correct for first Invoice" -- +- I check the residual amuont of Invoice2, should be 30 in residual currency and 24 in amount_residual - !python {model: account.invoice}: | @@ -210,40 +213,37 @@ move_lines = move_line_obj.search(cr, uid, [('move_id', '=', invoice_id.move_id.id), ('invoice', '=', invoice_id.id), ('account_id', '=', invoice_id.account_id.id)]) move_line = move_line_obj.browse(cr, uid, move_lines[0]) assert (move_line.amount_residual_currency == 30 and move_line.amount_residual == 24) , "Residual amount is not correct for second Invoice" -- - I create the second voucher of payment - +- + I create the second voucher of payment with values 45 USD, journal USD, +- + !record {model: account.voucher, id: account_voucher_2_case2_suppl, view: view_vendor_payment_form}: + account_id: account.cash + amount: 45.0 + company_id: base.main_company + journal_id: bank_journal_USD + partner_id: base.res_partner_seagate + period_id: account.period_3 + date: !eval time.strftime("%Y-04-01") + payment_option: 'with_writeoff' + writeoff_acc_id: account.a_expense + comment: 'Write Off' + name: 'Second payment: Case 2 SUPPL USD/EUR' + +- + I fill amounts 20 for the invoice of 200$ and 30 for the invoice of 100$> - !python {model: account.voucher}: | import netsvc, time vals = {} - res = self.onchange_partner_id(cr, uid, [], ref("base.res_partner_seagate"), ref('bank_journal_EUR'), 45.0, 2, ttype='payment', date=False) - vals = { - 'account_id': ref('account.cash'), - 'amount': 45.0, - 'company_id': ref('base.main_company'), - 'currency_id': ref('base.USD'), - 'journal_id': ref('bank_journal_USD'), - 'partner_id': ref('base.res_partner_seagate'), - 'period_id': ref('account.period_3'), - 'type': 'payment', - 'date': time.strftime("%Y-%m-%d"), - 'payment_option': 'with_writeoff', - 'writeoff_acc_id': ref('account.a_expense'), - 'comment': 'Write Off', - 'name': 'Second payment: Case 2 SUPPL USD/EUR', - } - vals.update(self.onchange_date(cr, uid, [], time.strftime('%Y-04-01'), ref('base.USD'), 45.0)['value']) - if not res['value']['line_dr_ids']: - res['value']['line_dr_ids'] = [{'type': 'dr', 'account_id': ref('account.a_pay'),}] - for item in res['value']['line_dr_ids']: - if item['amount_unreconciled'] == 20.00: - item['amount'] = 20.00 + voucher_id = self.browse(cr, uid, ref('account_voucher_2_case2_suppl')) + data = [] + for item in voucher_id.line_cr_ids: + if item.amount_unreconciled == 20.00: + data += [(item.id, 20.0)] else: - item['amount'] = 30.00 - vals['line_dr_ids'] = [(0,0,i) for i in res['value']['line_dr_ids']] - id = self.create(cr, uid, vals) - voucher_id = self.browse(cr, uid, id) + data += [(item.id, 30.0)] + for line_id, amount in data: + self.pool.get('account.voucher.line').write(cr, uid, [line_id], {'amount': amount}) assert (voucher_id.state=='draft'), "Voucher is not in draft state" - I check that writeoff amount computed is -5.0 diff --git a/addons/account_voucher/test/case2_usd_eur_debtor_in_eur.yml b/addons/account_voucher/test/case2_usd_eur_debtor_in_eur.yml index 67287591778..fa87fc1289b 100644 --- a/addons/account_voucher/test/case2_usd_eur_debtor_in_eur.yml +++ b/addons/account_voucher/test/case2_usd_eur_debtor_in_eur.yml @@ -136,38 +136,41 @@ move_line = move_line_obj.browse(cr, uid, move_lines[0]) assert (move_line.debit - move_line.credit == 80), "Invoice move is incorrect for debtors account" - - I create the first voucher of payment - + I set the context that will be used for the encoding of all the vouchers of this file +- + !context + 'type': 'receipt' +- + I create the first voucher of payment with values 200 EUR, journal EUR +- + !record {model: account.voucher, id: account_voucher_1_case2a, view: view_vendor_receipt_form}: + account_id: account.cash + amount: 200.0 + company_id: base.main_company + journal_id: bank_journal_EUR + partner_id: base.res_partner_seagate + period_id: account.period_3 + date: !eval time.strftime("%Y-03-01") + payment_option: 'with_writeoff' + writeoff_acc_id: account.a_expense + comment: 'Write Off' + name: 'First payment: Case 2 USD/EUR DR EUR' + +- + I fill amounts 130 for the invoice of 200$ and 70 for the invoice of 100$ - !python {model: account.voucher}: | import netsvc, time vals = {} - res = self.onchange_partner_id(cr, uid, [], ref("base.res_partner_seagate"), ref('bank_journal_EUR'), 240.0, False, ttype='receipt', date=False) - vals = { - 'account_id': ref('account.cash'), - 'amount': 200.0, - 'company_id': ref('base.main_company'), - 'currency_id': False, - 'journal_id': ref('bank_journal_EUR'), - 'partner_id': ref('base.res_partner_seagate'), - 'period_id': ref('account.period_3'), - 'type': 'receipt', - 'date': time.strftime("%Y-03-01"), - 'payment_option': 'with_writeoff', - 'writeoff_acc_id': ref('account.a_expense'), - 'comment': 'Write Off', - 'name': 'First payment: Case 2 USD/EUR DR EUR', - } - if not res['value']['line_cr_ids']: - res['value']['line_cr_ids'] = [{'type': 'cr', 'account_id': ref('account.a_recv'),}] - for item in res['value']['line_cr_ids']: - if item['amount_unreconciled'] == 150.00: - item['amount'] = 130.00 + voucher_id = self.browse(cr, uid, ref('account_voucher_1_case2a')) + data = [] + for item in voucher_id.line_cr_ids: + if item.amount_unreconciled == 150.00: + data += [(item.id, 130.0)] else: - item['amount'] = 70.00 - vals['line_cr_ids'] = [(0,0,i) for i in res['value']['line_cr_ids']] - id = self.create(cr, uid, vals) - voucher_id = self.browse(cr, uid, id) + data += [(item.id, 70.0)] + for line_id, amount in data: + self.pool.get('account.voucher.line').write(cr, uid, [line_id], {'amount': amount}) assert (voucher_id.state=='draft'), "Voucher is not in draft state" - I confirm the voucher @@ -217,41 +220,38 @@ move_lines = move_line_obj.search(cr, uid, [('move_id', '=', invoice_id.move_id.id), ('invoice', '=', invoice_id.id), ('account_id', '=', invoice_id.account_id.id)]) move_line = move_line_obj.browse(cr, uid, move_lines[0]) assert (move_line.amount_residual_currency == 22.22 and move_line.amount_residual == 10) , "Residual amount is not correct for second Invoice" -- - I create the second voucher of payment - +- + I create the second voucher of payment with values 80 USD, journal USD +- + !record {model: account.voucher, id: account_voucher_2_case2a, view: view_vendor_receipt_form}: + account_id: account.cash + amount: 80 + company_id: base.main_company + journal_id: bank_journal_USD + partner_id: base.res_partner_seagate + period_id: account.period_3 + date: !eval time.strftime("%Y-04-01") + payment_option: 'with_writeoff' + writeoff_acc_id: account.a_expense + exchange_acc_id: account.o_expense + comment: 'Write Off' + name: 'Second payment: Case 2 SUPPL USD/EUR DR EUR' + +- + and I fully reconcile the 2 previous invoices - !python {model: account.voucher}: | import netsvc, time vals = {} - res = self.onchange_partner_id(cr, uid, [], ref("base.res_partner_seagate"), ref('bank_journal_USD'), 80.0, 2, ttype='receipt', date=False) - vals = { - 'account_id': ref('account.cash'), - 'amount': 80.0, - 'company_id': ref('base.main_company'), - 'currency_id': ref('base.USD'), - 'journal_id': ref('bank_journal_USD'), - 'partner_id': ref('base.res_partner_seagate'), - 'period_id': ref('account.period_3'), - 'type': 'receipt', - 'date': time.strftime("%Y-%m-%d"), - 'payment_option': 'with_writeoff', - 'writeoff_acc_id': ref('account.a_expense'), - 'exchange_acc_id': ref('account.o_expense'), - 'comment': 'Write Off', - 'name': 'Second payment: Case 2 SUPPL USD/EUR DR EUR', - } - vals.update(self.onchange_date(cr, uid, [], time.strftime('%Y-04-01'), ref('base.USD'), 80.0)['value']) - if not res['value']['line_cr_ids']: - res['value']['line_cr_ids'] = [{'type': 'cr', 'account_id': ref('account.a_recv'),}] - for item in res['value']['line_cr_ids']: - if item['amount_unreconciled'] == 55.56: - item['amount'] = 55.56 + voucher_id = self.browse(cr, uid, ref('account_voucher_2_case2a')) + data = [] + for item in voucher_id.line_cr_ids: + if item.amount_unreconciled == 55.56: + data += [(item.id, 55.56)] else: - item['amount'] = 22.22 - vals['line_cr_ids'] = [(0,0,i) for i in res['value']['line_cr_ids']] - id = self.create(cr, uid, vals) - voucher_id = self.browse(cr, uid, id) + data += [(item.id, 22.22)] + for line_id, amount in data: + self.pool.get('account.voucher.line').write(cr, uid, [line_id], {'amount': amount}) assert (voucher_id.state=='draft'), "Voucher is not in draft state" - I check that writeoff amount computed is 2.22 diff --git a/addons/account_voucher/test/case2_usd_eur_debtor_in_usd.yml b/addons/account_voucher/test/case2_usd_eur_debtor_in_usd.yml index ec4d653c8ab..43c00a9f798 100644 --- a/addons/account_voucher/test/case2_usd_eur_debtor_in_usd.yml +++ b/addons/account_voucher/test/case2_usd_eur_debtor_in_usd.yml @@ -136,38 +136,41 @@ move_line = move_line_obj.browse(cr, uid, move_lines[0]) assert (move_line.debit - move_line.credit == 80), "Invoice move is incorrect for debtors account" - - I create the first voucher of payment - + I set the context that will be used for the encoding of all the vouchers of this file +- + !context + 'type': 'receipt' +- + I create the first voucher of payment with values 200 EUR, journal EUR +- + !record {model: account.voucher, id: account_voucher_1_case2b, view: view_vendor_receipt_form}: + account_id: account.cash + amount: 200.0 + company_id: base.main_company + journal_id: bank_journal_EUR + partner_id: base.res_partner_seagate + period_id: account.period_3 + date: !eval time.strftime("%Y-03-01") + payment_option: 'with_writeoff' + writeoff_acc_id: account.a_expense + comment: 'Write Off' + name: 'First payment: Case 2 USD/EUR DR USD' + +- + I fill amounts 130 for the invoice of 200$ and 70 for the invoice of 100$> - !python {model: account.voucher}: | import netsvc, time vals = {} - res = self.onchange_partner_id(cr, uid, [], ref("base.res_partner_seagate"), ref('bank_journal_EUR'), 200.0, False, ttype='receipt', date=False) - vals = { - 'account_id': ref('account.cash'), - 'amount': 200.0, - 'company_id': ref('base.main_company'), - 'currency_id': ref('base.EUR'), - 'journal_id': ref('bank_journal_EUR'), - 'partner_id': ref('base.res_partner_seagate'), - 'period_id': ref('account.period_3'), - 'type': 'receipt', - 'date': time.strftime("%Y-03-01"), - 'payment_option': 'with_writeoff', - 'writeoff_acc_id': ref('account.a_expense'), - 'comment': 'Write Off', - 'name': 'First payment: Case 2 USD/EUR DR USD', - } - if not res['value']['line_cr_ids']: - res['value']['line_cr_ids'] = [{'type': 'cr', 'account_id': ref('account.a_recv'),}] - for item in res['value']['line_cr_ids']: - if item['amount_unreconciled'] == 150.00: - item['amount'] = 130.00 + voucher_id = self.browse(cr, uid, ref('account_voucher_1_case2b')) + data = [] + for item in voucher_id.line_cr_ids: + if item.amount_unreconciled == 150.00: + data += [(item.id, 130.0)] else: - item['amount'] = 70.00 - vals['line_cr_ids'] = [(0,0,i) for i in res['value']['line_cr_ids']] - id = self.create(cr, uid, vals) - voucher_id = self.browse(cr, uid, id) + data += [(item.id, 70.0)] + for line_id, amount in data: + self.pool.get('account.voucher.line').write(cr, uid, [line_id], {'amount': amount}) assert (voucher_id.state=='draft'), "Voucher is not in draft state" - I confirm the voucher @@ -220,41 +223,38 @@ move_lines = move_line_obj.search(cr, uid, [('move_id', '=', invoice_id.move_id.id), ('invoice', '=', invoice_id.id), ('account_id', '=', invoice_id.account_id.id)]) move_line = move_line_obj.browse(cr, uid, move_lines[0]) assert (move_line.amount_residual_currency == 22.22 and move_line.amount_residual == 10) , "Residual amount is not correct for second Invoice" -- - I create the second voucher of payment - +- + I create the second voucher of payment with values 80 USD, journal USD +- + !record {model: account.voucher, id: account_voucher_2_case2b, view: view_vendor_receipt_form}: + account_id: account.cash + amount: 80.0 + company_id: base.main_company + journal_id: bank_journal_USD + partner_id: base.res_partner_seagate + period_id: account.period_3 + date: !eval time.strftime("%Y-04-01") + payment_option: 'with_writeoff' + writeoff_acc_id: account.a_expense + exchange_acc_id: account.o_expense + comment: 'Write Off' + name: 'Second payment: Case 2 SUPPL USD/EUR DR USD' + +- + and I fully reconcil the 2 previous invoices - !python {model: account.voucher}: | import netsvc, time vals = {} - res = self.onchange_partner_id(cr, uid, [], ref("base.res_partner_seagate"), ref('bank_journal_USD'), 80.0, ref('base.USD'), ttype='receipt', date=False) - vals = { - 'account_id': ref('account.cash'), - 'amount': 80.0, - 'company_id': ref('base.main_company'), - 'currency_id': ref('base.USD'), - 'journal_id': ref('bank_journal_USD'), - 'partner_id': ref('base.res_partner_seagate'), - 'period_id': ref('account.period_3'), - 'type': 'receipt', - 'date': time.strftime("%Y-%m-%d"), - 'payment_option': 'with_writeoff', - 'writeoff_acc_id': ref('account.a_expense'), - 'exchange_acc_id': ref('account.o_expense'), - 'comment': 'Write Off', - 'name': 'Second payment: Case 2 SUPPL USD/EUR DR USD', - } - vals.update(self.onchange_date(cr, uid, [], time.strftime('%Y-04-01'), ref('base.USD'), 80.0)['value']) - if not res['value']['line_cr_ids']: - res['value']['line_cr_ids'] = [{'type': 'cr', 'account_id': ref('account.a_recv'),}] - for item in res['value']['line_cr_ids']: - if item['amount_unreconciled'] == 55.56: - item['amount'] = 55.56 + voucher_id = self.browse(cr, uid, ref('account_voucher_2_case2b')) + data = [] + for item in voucher_id.line_cr_ids: + if item.amount_unreconciled == 55.56: + data += [(item.id, 55.56)] else: - item['amount'] = 22.22 - vals['line_cr_ids'] = [(0,0,i) for i in res['value']['line_cr_ids']] - id = self.create(cr, uid, vals) - voucher_id = self.browse(cr, uid, id) + data += [(item.id, 22.22)] + for line_id, amount in data: + self.pool.get('account.voucher.line').write(cr, uid, [line_id], {'amount': amount}) assert (voucher_id.state=='draft'), "Voucher is not in draft state" - I check that writeoff amount computed is 2.22 diff --git a/addons/account_voucher/test/case3_eur_eur.yml b/addons/account_voucher/test/case3_eur_eur.yml index 09034fadf51..a2fc39e1844 100644 --- a/addons/account_voucher/test/case3_eur_eur.yml +++ b/addons/account_voucher/test/case3_eur_eur.yml @@ -99,38 +99,41 @@ move_line = move_line_obj.browse(cr, uid, move_lines[0]) assert (move_line.debit - move_line.credit == 80.00), "Invoice move is incorrect for debtors account" - - I create the first voucher of payment - + I set the context that will be used for the encoding of all the vouchers of this file +- + !context + 'type': 'receipt' +- + I create the first voucher of payment with values 120 EUR, journal EUR +- + !record {model: account.voucher, id: account_voucher_1_case3, view: view_vendor_receipt_form}: + account_id: account.cash + amount: 120.0 + company_id: base.main_company + journal_id: bank_journal_EUR + partner_id: base.res_partner_seagate + period_id: account.period_3 + date: !eval time.strftime("%Y-03-01") + payment_option: 'with_writeoff' + writeoff_acc_id: account.a_expense + comment: 'Write Off' + name: 'First payment: Case 3' + +- + I fill amounts 100 for the invoice of 150€ and 20 for the invoice of 80€ - !python {model: account.voucher}: | import netsvc, time vals = {} - res = self.onchange_partner_id(cr, uid, [], ref("base.res_partner_seagate"), ref('bank_journal_EUR'), 120.00, False, ttype='receipt', date=False) - vals = { - 'account_id': ref('account.cash'), - 'amount': 120.00, - 'company_id': ref('base.main_company'), - 'currency_id': ref('base.EUR'), - 'journal_id': ref('bank_journal_EUR'), - 'partner_id': ref('base.res_partner_seagate'), - 'period_id': ref('account.period_3'), - 'type': 'receipt', - 'date': time.strftime("%Y-03-01"), - 'payment_option': 'with_writeoff', - 'writeoff_acc_id': ref('account.a_expense'), - 'comment': 'Write Off', - 'name': 'First payment: Case 3', - } - if not res['value']['line_cr_ids']: - res['value']['line_cr_ids'] = [{'type': 'cr', 'account_id': ref('account.a_recv'),}] - for item in res['value']['line_cr_ids']: - if item['amount_unreconciled'] == 150.00: - item['amount'] = 100.00 + voucher_id = self.browse(cr, uid, ref('account_voucher_1_case3')) + data = [] + for item in voucher_id.line_cr_ids: + if item.amount_unreconciled == 150.00: + data += [(item.id, 100.0)] else: - item['amount'] = 20.00 - vals['line_cr_ids'] = [(0,0,i) for i in res['value']['line_cr_ids']] - id = self.create(cr, uid, vals) - voucher_id = self.browse(cr, uid, id) + data += [(item.id, 20.0)] + for line_id, amount in data: + self.pool.get('account.voucher.line').write(cr, uid, [line_id], {'amount': amount}) assert (voucher_id.state=='draft'), "Voucher is not in draft state" - I check that writeoff amount computed is 0.00 @@ -181,7 +184,7 @@ move_lines = move_line_obj.search(cr, uid, [('move_id', '=', invoice_id.move_id.id), ('invoice', '=', invoice_id.id), ('account_id', '=', invoice_id.account_id.id)]) move_line = move_line_obj.browse(cr, uid, move_lines[0]) assert (move_line.amount_residual_currency == 50.0 and move_line.amount_residual == 50.0) , "Residual amount is not correct for first Invoice" -- +- I check the residual amuont of Invoice2 is 60 - !python {model: account.invoice}: | @@ -191,38 +194,36 @@ move_line = move_line_obj.browse(cr, uid, move_lines[0]) assert (move_line.amount_residual_currency == 60.0 and move_line.amount_residual == 60.0) , "Residual amount is not correct for second Invoice" - - I create the second voucher of payment and check to let open the debtor overpaid amount. - + I create the second voucher of payment with values 120€, journal EUR, and check to let open the debtor overpaid amount +- + !record {model: account.voucher, id: account_voucher_2_case3, view: view_vendor_receipt_form}: + account_id: account.cash + amount: 120.0 + company_id: base.main_company + journal_id: bank_journal_EUR + partner_id: base.res_partner_seagate + period_id: account.period_3 + date: !eval time.strftime("%Y-04-01") + payment_option: 'with_writeoff' + writeoff_acc_id: account.a_expense + comment: 'Write Off' + name: 'Second payment: Case 3' + +- + I fill amounts 50 for the invoice of 150€ and 70 for the invoice of 80€ - !python {model: account.voucher}: | import netsvc, time vals = {} - res = self.onchange_partner_id(cr, uid, [], ref("base.res_partner_seagate"), ref('bank_journal_EUR'), 120.00, False, ttype='receipt', date=False) - vals = { - 'account_id': ref('account.cash'), - 'amount': 120.00, - 'company_id': ref('base.main_company'), - 'currency_id': ref('base.EUR'), - 'journal_id': ref('bank_journal_EUR'), - 'partner_id': ref('base.res_partner_seagate'), - 'period_id': ref('account.period_3'), - 'type': 'receipt', - 'date': time.strftime("%Y-04-01"), - 'payment_option': 'with_writeoff', - 'writeoff_acc_id': ref('account.a_expense'), - 'comment': 'Write Off', - 'name': 'Second payment: Case 3', - } - if not res['value']['line_cr_ids']: - res['value']['line_cr_ids'] = [{'type': 'cr', 'account_id': ref('account.a_recv'),}] - for item in res['value']['line_cr_ids']: - if item['amount_unreconciled'] == 50.00: - item['amount'] = 50.00 - elif item['amount_unreconciled'] == 60.00: - item['amount'] = 70.00 - vals['line_cr_ids'] = [(0,0,i) for i in res['value']['line_cr_ids']] - id = self.create(cr, uid, vals) - voucher_id = self.browse(cr, uid, id) + voucher_id = self.browse(cr, uid, ref('account_voucher_2_case3')) + data = [] + for item in voucher_id.line_cr_ids: + if item.amount_unreconciled == 50.00: + data += [(item.id, 50.0)] + elif item.amount_unreconciled == 60.00: + data += [(item.id, 70.00)] + for line_id, amount in data: + self.pool.get('account.voucher.line').write(cr, uid, [line_id], {'amount': amount}) assert (voucher_id.state=='draft'), "Voucher is not in draft state" - I check that writeoff amount computed is 0.00 diff --git a/addons/account_voucher/test/case4_cad_chf.yml b/addons/account_voucher/test/case4_cad_chf.yml index b3abbb25e01..2fe43b57fd3 100644 --- a/addons/account_voucher/test/case4_cad_chf.yml +++ b/addons/account_voucher/test/case4_cad_chf.yml @@ -89,38 +89,39 @@ move_line = move_line_obj.browse(cr, uid, move_lines[0]) assert (move_line.debit - move_line.credit == 149.39), "Invoice move is incorrect for debtors account" - - I create the first voucher of payment - + I set the context that will be used for the encoding of all the vouchers of this file +- + !context + 'type': 'receipt' +- + I create the first voucher of payment with values 200 CHF, journal CHF +- + !record {model: account.voucher, id: account_voucher_1_case4, view: view_vendor_receipt_form}: + account_id: account.cash + amount: 200 + company_id: base.main_company + journal_id: bank_journal_CHF + partner_id: base.res_partner_seagate + period_id: account.period_3 + date: !eval time.strftime("%Y-03-01") + payment_option: 'with_writeoff' + writeoff_acc_id: account.a_expense + exchange_acc_id: account.o_expense + comment: 'Write Off' + name: 'First payment: Case 4' +- + I completly pay the invoice of 200 CAD - !python {model: account.voucher}: | import netsvc, time vals = {} - res = self.onchange_partner_id(cr, uid, [], ref("base.res_partner_seagate"), ref('bank_journal_CHF'), 200.00, ref('base.CHF'), ttype='receipt', date=False) - vals = { - 'account_id': ref('account.cash'), - 'amount': 200.00, - 'company_id': ref('base.main_company'), - 'currency_id': ref('base.CHF'), - 'journal_id': ref('bank_journal_CHF'), - 'partner_id': ref('base.res_partner_seagate'), - 'period_id': ref('account.period_3'), - 'type': 'receipt', - 'date': time.strftime("%Y-%m-%d"), - 'payment_option': 'with_writeoff', - 'writeoff_acc_id': ref('account.a_expense'), - 'exchange_acc_id': ref('account.o_expense'), - 'comment': 'Write Off', - 'name': 'First payment: Case 4', - } - vals.update(self.onchange_date(cr, uid, [], time.strftime('%Y-03-01'), ref('base.CHF'), 200.0)['value']) - if not res['value']['line_cr_ids']: - res['value']['line_cr_ids'] = [{'type': 'cr', 'account_id': ref('account.a_recv'),}] - for item in res['value']['line_cr_ids']: - if item['amount_unreconciled'] == 186.74: - item['amount'] = 186.74 - vals['line_cr_ids'] = [(0,0,i) for i in res['value']['line_cr_ids']] - id = self.create(cr, uid, vals) - voucher_id = self.browse(cr, uid, id) + voucher_id = self.browse(cr, uid, ref('account_voucher_1_case4')) + data = [] + for item in voucher_id.line_cr_ids: + if item.amount_unreconciled == 186.74: + data += [(item.id, 186.74)] + for line_id, amount in data: + self.pool.get('account.voucher.line').write(cr, uid, [line_id], {'amount': amount}) assert (voucher_id.state=='draft'), "Voucher is not in draft state" - I check that writeoff amount computed is 13.26 From e9051fabdb42caf291e6055b1cf957dd74290ee9 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 23 Nov 2011 15:32:22 +0100 Subject: [PATCH 03/19] [IMP] account_voucher: added a a column 'full reconcile' on the voucher lines bzr revid: qdp-launchpad@openerp.com-20111123143222-xuj8dfjw0ne85dfb --- addons/account_voucher/account_voucher.py | 19 ++++++++++++++++++- .../voucher_payment_receipt_view.xml | 6 ++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py index b2c87a53672..3c12db84a40 100644 --- a/addons/account_voucher/account_voucher.py +++ b/addons/account_voucher/account_voucher.py @@ -600,6 +600,9 @@ class account_voucher(osv.osv): rs['amount'] = amount total_credit -= amount + if rs['amount_unreconciled'] == rs['amount']: + rs['reconcile'] = True + if rs['type'] == 'cr': default['value']['line_cr_ids'].append(rs) else: @@ -1165,6 +1168,7 @@ class account_voucher_line(osv.osv): 'partner_id':fields.related('voucher_id', 'partner_id', type='many2one', relation='res.partner', string='Partner'), 'untax_amount':fields.float('Untax Amount'), 'amount':fields.float('Amount', digits_compute=dp.get_precision('Account')), + 'reconcile': fields.boolean('Full Reconcile'), 'type':fields.selection([('dr','Debit'),('cr','Credit')], 'Dr/Cr'), 'account_analytic_id': fields.many2one('account.analytic.account', 'Analytic Account'), 'move_line_id': fields.many2one('account.move.line', 'Journal Item'), @@ -1175,9 +1179,22 @@ class account_voucher_line(osv.osv): 'company_id': fields.related('voucher_id','company_id', relation='res.company', type='many2one', string='Company', store=True, readonly=True), } _defaults = { - 'name': '' + 'name': '', + 'reconcile': False, } + def onchange_reconcile(self, cr, uid, ids, reconcile, amount, amount_unreconciled, context=None): + vals = { 'amount': 0.0} + if reconcile: + vals = { 'amount': amount_unreconciled} + return {'value': vals} + + def onchange_amount(self, cr, uid, ids, amount, amount_unreconciled, context=None): + vals = {} + if amount: + vals['reconcile'] = (amount == amount_unreconciled) + return {'value': vals} + def onchange_move_line_id(self, cr, user, ids, move_line_id, context=None): """ Returns a dict that contains new values and context diff --git a/addons/account_voucher/voucher_payment_receipt_view.xml b/addons/account_voucher/voucher_payment_receipt_view.xml index 4adebed8a1a..6265abf1c7d 100644 --- a/addons/account_voucher/voucher_payment_receipt_view.xml +++ b/addons/account_voucher/voucher_payment_receipt_view.xml @@ -172,7 +172,8 @@ - + + @@ -322,7 +323,8 @@ - + + From e346d6c8ad4c13bea210174c36fb0c6c5a8f38db Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 23 Nov 2011 17:22:34 +0100 Subject: [PATCH 04/19] [IMP] account_voucher: changed logic when paying an invoice in a secondary currency => now we always write the amount_currency (and in the same currency) bzr revid: qdp-launchpad@openerp.com-20111123162234-nr685qp729btv19c --- addons/account_voucher/account_voucher.py | 17 ++++++++++++++--- .../test/case2_usd_eur_debtor_in_eur.yml | 12 ------------ addons/account_voucher/test/case4_cad_chf.yml | 4 ++-- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py index 3c12db84a40..e47038de03b 100644 --- a/addons/account_voucher/account_voucher.py +++ b/addons/account_voucher/account_voucher.py @@ -882,7 +882,7 @@ class account_voucher(osv.osv): def _convert_amount(self, cr, uid, amount, voucher_id, context=None): #TODO: doccument me - #TODO: rounding errors + #TODO: check: rounding errors ? currency_obj = self.pool.get('res.currency') voucher = self.browse(cr, uid, voucher_id, context=context) res = amount @@ -944,7 +944,7 @@ class account_voucher(osv.osv): 'account_id': line.account_id.id, 'move_id': move_id, 'partner_id': voucher_brw.partner_id.id, - 'currency_id': company_currency <> current_currency and current_currency or False, + 'currency_id': line.move_line_id and (company_currency <> line.move_line_id.currency_id.id and line.move_line_id.currency_id.id) or False, 'analytic_account_id': line.account_analytic_id and line.account_analytic_id.id or False, 'quantity': 1, 'credit': 0.0, @@ -976,7 +976,18 @@ class account_voucher(osv.osv): raise osv.except_osv(_('No Account Base Code and Account Tax Code!'),_("You have to configure account base code and account tax code on the '%s' tax!") % (tax_data.name)) sign = (move_line['debit'] - move_line['credit']) < 0 and -1 or 1 - move_line['amount_currency'] = company_currency <> current_currency and sign * line.amount or False + #TODO: comment me + amount_currency = False + if line.move_line_id: + if line.move_line_id.currency_id and line.move_line_id.currency_id.id != company_currency: + if line.move_line_id.currency_id.id == current_currency: + amount_currency = sign * (line.amount) + elif line.move_line_id.currency_id.id == voucher_brw.payment_rate_currency_id.id: + amount_currency = (move_line['debit'] - move_line['credit']) * voucher_brw.payment_rate + else: + amount_currency = currency_obj.compute(cr, uid, company_currency, line.move_line_id.currency_id.id, move_line['debit']-move_line['credit'], context=ctx) + + move_line['amount_currency'] = amount_currency voucher_line = move_line_obj.create(cr, uid, move_line) rec_ids = [voucher_line, line.move_line_id.id] diff --git a/addons/account_voucher/test/case2_usd_eur_debtor_in_eur.yml b/addons/account_voucher/test/case2_usd_eur_debtor_in_eur.yml index fa87fc1289b..5aadc93be13 100644 --- a/addons/account_voucher/test/case2_usd_eur_debtor_in_eur.yml +++ b/addons/account_voucher/test/case2_usd_eur_debtor_in_eur.yml @@ -190,18 +190,6 @@ move_lines = move_line_obj.search(cr, uid, [('move_id', '=', voucher_id.move_id.id)]) for move_line in move_line_obj.browse(cr, uid, move_lines): assert move_line.state == 'valid', "Voucher move is not valid" -- - I check that my debtor account is correct -- - I check that the debtor account has 2 new lines with 0 in amount_currency columns and their credit columns are 130 and 70 -- - !python {model: account.voucher}: | - voucher = self.search(cr, uid, [('name', '=', 'First payment: Case 2 USD/EUR DR EUR'), ('partner_id', '=', ref('base.res_partner_seagate'))]) - voucher_id = self.browse(cr, uid, voucher[0]) - move_line_obj = self.pool.get('account.move.line') - move_lines = move_line_obj.search(cr, uid, [('move_id', '=', voucher_id.move_id.id)]) - for move_line in move_line_obj.browse(cr, uid, move_lines): - assert move_line.amount_currency == 0.00, "A line has the 'amount_currency' column filled" - I check the residual amount of Invoice1, should be 55.56 in residual currency and 20 in amount_residual - diff --git a/addons/account_voucher/test/case4_cad_chf.yml b/addons/account_voucher/test/case4_cad_chf.yml index 2fe43b57fd3..bb9bda9126c 100644 --- a/addons/account_voucher/test/case4_cad_chf.yml +++ b/addons/account_voucher/test/case4_cad_chf.yml @@ -152,7 +152,7 @@ - I check that my debtor account is correct - - I check that the debtor account has 1 new line with -186.74 as amount_currency columns and 149.39 of credit and currency is CHF. + I check that the debtor account has 1 new line with -298.78 as amount_currency columns and 149.39 of credit and currency is CAD. - I check that my currency rate difference is correct. 0 in debit with no amount_currency - @@ -166,7 +166,7 @@ for move_line in move_line_obj.browse(cr, uid, move_lines): if move_line.amount_currency == 200: assert move_line.debit == 160.00, "Bank account has wrong entry." - elif move_line.amount_currency == -186.74: + elif move_line.amount_currency == -298.78: assert move_line.credit == 149.39, "Debtor account has wrong entry." elif move_line.debit == 0.00 and move_line.credit == 0.00: assert move_line.amount_currency == 0.00, "Incorrect Currency Difference." From d92d56dc6f4d22e622382030e787b7ae96c6e1ef Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 23 Nov 2011 17:24:18 +0100 Subject: [PATCH 05/19] [IMP] account_followup: changing again the way to group lines in followup report in multi currency cases bzr revid: qdp-launchpad@openerp.com-20111123162418-9qcdfw1sswxi2pc1 --- addons/account_followup/report/account_followup_print.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/account_followup/report/account_followup_print.py b/addons/account_followup/report/account_followup_print.py index f2cf476e674..56004cebde3 100644 --- a/addons/account_followup/report/account_followup_print.py +++ b/addons/account_followup/report/account_followup_print.py @@ -64,9 +64,9 @@ class report_rappel(report_sxw.rml_parse): line_cur = {base_currency.id: {'line': []}} for line in movelines: - if line.account_id.currency_id and (not line.account_id.currency_id.id in line_cur): - line_cur[line.account_id.currency_id.id] = {'line': []} - currency = line.account_id.currency_id or line.company_id.currency_id + if line.currency_id and (not line.currency_id.id in line_cur): + line_cur[line.currency_id.id] = {'line': []} + currency = line.currency_id or line.company_id.currency_id line_data = { 'name': line.move_id.name, 'ref': line.ref, From 3440aa70f4bec5f2679aeb874260ca07eb6faef4 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 23 Nov 2011 17:33:43 +0100 Subject: [PATCH 06/19] [IMP] account_voucher: usabilty small improvements bzr revid: qdp-launchpad@openerp.com-20111123163343-v4nhltzvcd7r5ob3 --- .../voucher_payment_receipt_view.xml | 63 +++++++++++-------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/addons/account_voucher/voucher_payment_receipt_view.xml b/addons/account_voucher/voucher_payment_receipt_view.xml index 6265abf1c7d..17216ed5f21 100644 --- a/addons/account_voucher/voucher_payment_receipt_view.xml +++ b/addons/account_voucher/voucher_payment_receipt_view.xml @@ -108,10 +108,15 @@ - - - - + + + + + + @@ -157,6 +162,7 @@ invisible="True"/> + @@ -165,7 +171,7 @@ @@ -178,11 +184,18 @@ - - - - - + + + + + + + + @@ -211,11 +224,6 @@ - - - - - @@ -223,6 +231,7 @@ + @@ -316,7 +325,7 @@ @@ -329,11 +338,18 @@ - - - - - + + + + + + + + @@ -362,10 +378,6 @@ - - - - @@ -373,6 +385,7 @@ + From d7827b9215321a91fc1e6330a40d4f6545207e52 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 23 Nov 2011 17:36:43 +0100 Subject: [PATCH 07/19] [IMP] account_voucher: removed reference to voucher print report bzr revid: qdp-launchpad@openerp.com-20111123163643-k1pqx4u7d66gfuk7 --- addons/account_voucher/account_voucher_report.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/addons/account_voucher/account_voucher_report.xml b/addons/account_voucher/account_voucher_report.xml index 8af204efbbe..97de2b89f3a 100644 --- a/addons/account_voucher/account_voucher_report.xml +++ b/addons/account_voucher/account_voucher_report.xml @@ -11,13 +11,14 @@ header = "False" menu="True"/> --> - + From bc07877f642a68abd57c78c1fc541abfd9ea9bcc Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 23 Nov 2011 17:48:34 +0100 Subject: [PATCH 08/19] [FIX] account_voucher: fixed onchange_payment_rate_currency bzr revid: qdp-launchpad@openerp.com-20111123164834-m4tjfjtxpp8j2iew --- addons/account_voucher/account_voucher.py | 4 +--- .../account_voucher/voucher_payment_receipt_view.xml | 12 ++++++------ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py index e47038de03b..b759387b590 100644 --- a/addons/account_voucher/account_voucher.py +++ b/addons/account_voucher/account_voucher.py @@ -615,7 +615,7 @@ class account_voucher(osv.osv): default['value']['writeoff_amount'] = self._compute_writeoff_amount(cr, uid, default['value']['line_dr_ids'], default['value']['line_cr_ids'], price) return default - def onchange_payment_rate_currency(self, cr, uid, ids, currency_id, payment_rate_currency_id, date, amount, company_id, context=None): + def onchange_payment_rate_currency(self, cr, uid, ids, currency_id, payment_rate, payment_rate_currency_id, date, amount, company_id, context=None): if context is None: context = {} res = {'value': {}} @@ -623,8 +623,6 @@ class account_voucher(osv.osv): if currency_id and currency_id == payment_rate_currency_id: ctx = context.copy() ctx.update({'date': date}) - payment_rate = self.pool.get('res.currency').browse(cr, uid, currency_id, context=ctx).rate - res['value'].update({'payment_rate': payment_rate}) vals = self.onchange_rate(cr, uid, ids, payment_rate, amount, currency_id, payment_rate_currency_id, company_id, context=ctx) for key in vals.keys(): res[key].update(vals[key]) diff --git a/addons/account_voucher/voucher_payment_receipt_view.xml b/addons/account_voucher/voucher_payment_receipt_view.xml index 17216ed5f21..4b6817d77ef 100644 --- a/addons/account_voucher/voucher_payment_receipt_view.xml +++ b/addons/account_voucher/voucher_payment_receipt_view.xml @@ -128,8 +128,8 @@ - - + + @@ -208,8 +208,8 @@ - - + + @@ -362,8 +362,8 @@ - - + + From 6cee9eb3a93d9d239213cf29bf52d1c5d3d0ffbd Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Thu, 24 Nov 2011 12:41:03 +0100 Subject: [PATCH 09/19] [IMP] account_voucher: code cleaning and bugfixes bzr revid: qdp-launchpad@openerp.com-20111124114103-95pr374r2fqmc7np --- addons/account_voucher/account_voucher.py | 83 ++++++++++++++--------- 1 file changed, 52 insertions(+), 31 deletions(-) diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py index b759387b590..e03f45396a5 100644 --- a/addons/account_voucher/account_voucher.py +++ b/addons/account_voucher/account_voucher.py @@ -635,17 +635,23 @@ class account_voucher(osv.osv): @param context: context arguments, like lang, time zone @return: Returns a dict which contains new values, and context """ + if context is None: + context ={} res = {'value': {}} - #FIXME: use find() hereunder - #set the period of the voucher period_pool = self.pool.get('account.period') - pids = period_pool.search(cr, uid, [('date_start', '<=', date), ('date_stop', '>=', date)]) + ctx = context.copy() + ctx.update({'company_id': company_id}) + pids = period_pool.find(cr, uid, date, context=ctx) if pids: res['value'].update({'period_id':pids[0]}) - vals = self.onchange_payment_rate_currency(cr, uid, ids, currency_id, payment_rate_currency_id, date, amount, company_id, context=context) - for key in vals.keys(): - res[key].update(vals[key]) + if payment_rate_currency_id: + ctx.update({'date': date}) + payment_rate = self.pool.get('res.currency').browse(cr, uid, payment_rate_currency_id, context=ctx).rate + vals = self.onchange_payment_rate_currency(cr, uid, ids, currency_id, payment_rate, payment_rate_currency_id, date, amount, company_id, context=context) + vals['value'].update({'payment_rate': payment_rate}) + for key in vals.keys(): + res[key].update(vals[key]) return res def onchange_journal(self, cr, uid, ids, journal_id, line_ids, tax_id, partner_id, date, amount, ttype, company_id, context=None): @@ -777,9 +783,9 @@ class account_voucher(osv.osv): # TODO: Make this logic available. # -for sale, purchase we have but for the payment and receipt we do not have as based on the bank/cash journal we can not know its payment or receipt if voucher_brw.type in ('purchase', 'payment'): - credit = voucher_brw.paid_amount_in_company_currency#voucher_brw.amount / voucher_brw.payment_rate * voucher_brw.company_id.currency_id.rate + credit = voucher_brw.paid_amount_in_company_currency elif voucher_brw.type in ('sale', 'receipt'): - debit = voucher_brw.paid_amount_in_company_currency#amount / voucher_brw.payment_rate * voucher_brw.company_id.currency_id.rate + debit = voucher_brw.paid_amount_in_company_currency if debit < 0: credit = -debit; debit = 0.0 if credit < 0: debit = -credit; credit = 0.0 sign = debit - credit < 0 and -1 or 1 @@ -879,20 +885,32 @@ class account_voucher(osv.osv): return (move_line, move_line_counterpart) def _convert_amount(self, cr, uid, amount, voucher_id, context=None): - #TODO: doccument me - #TODO: check: rounding errors ? + ''' + This function convert the amount given in company currency. It takes either the rate in the voucher (if the + payment_rate_currency_id is relevant) either the rate encoded in the system. + + :param amount: float. The amount to convert + :param voucher: id of the voucher on which we want the conversion + :param context: to context to use for the conversion. It may contain the key 'date' set to the voucher date + field in order to select the good rate to use. + :return: the amount in the currency of the voucher's company + :rtype: float + ''' currency_obj = self.pool.get('res.currency') voucher = self.browse(cr, uid, voucher_id, context=context) res = amount if voucher.payment_rate_currency_id.id == voucher.company_id.currency_id.id: + # the rate specified on the voucher is for the company currency rate_between_voucher_and_base = voucher.currency_id.rate or 1.0 rate_between_base_and_company = voucher.payment_rate or 1.0 res = amount / rate_between_voucher_and_base * rate_between_base_and_company elif voucher.payment_rate_currency_id.id == voucher.currency_id.id: + # the rate specified on the voucher is for the voucher currency rate_between_base_and_company = voucher.company_id.currency_id.rate or 1.0 rate_between_voucher_and_base = voucher.payment_rate or 1.0 res = amount / rate_between_voucher_and_base * rate_between_base_and_company else: + # the rate specified on the voucher is not relevant, we use all the rates in the system res = currency_obj.compute(cr, uid, voucher.currency_id.id, voucher.company_id.currency_id.id, amount, context=context) return res @@ -924,17 +942,14 @@ class account_voucher(osv.osv): #create one move line per voucher line where amount is not 0.0 if not line.amount: continue - #TODO: comment me + # convert the amount set on the voucher line into the currency of the voucher's company amount = self._convert_amount(cr, uid, line.untax_amount or line.amount, voucher_brw.id, context=ctx) - #residual amount in company currency - #amount_residual = line.move_line_id.amount_residual - amount - #TODO: remove me + # if the amount encoded in voucher is equal to the amount unreconciled, we need to compute the + # currency rate difference if line.amount == line.amount_unreconciled: - # amount = (line.untax_amount or line.amount) / voucher_brw.payment_rate - amount_residual = line.move_line_id.amount_residual - amount #residual amount in company currency + currency_rate_difference = line.move_line_id.amount_residual - amount else: - # amount = (line.untax_amount or line.amount) / voucher_brw.payment_rate - amount_residual = 0.0 + currency_rate_difference = 0.0 move_line = { 'journal_id': voucher_brw.journal_id.id, 'period_id': voucher_brw.period_id.id, @@ -973,25 +988,30 @@ class account_voucher(osv.osv): if not (tax_data.base_code_id and tax_data.tax_code_id): raise osv.except_osv(_('No Account Base Code and Account Tax Code!'),_("You have to configure account base code and account tax code on the '%s' tax!") % (tax_data.name)) - sign = (move_line['debit'] - move_line['credit']) < 0 and -1 or 1 - #TODO: comment me + # compute the amount in foreign currency. amount_currency = False if line.move_line_id: + # We want to set it on the account move line as soon as the original line had a foreign currency if line.move_line_id.currency_id and line.move_line_id.currency_id.id != company_currency: + # we compute the amount in that foreign currency. if line.move_line_id.currency_id.id == current_currency: + # if the voucher and the voucher line share the same currency, there is no computation to do + sign = (move_line['debit'] - move_line['credit']) < 0 and -1 or 1 amount_currency = sign * (line.amount) elif line.move_line_id.currency_id.id == voucher_brw.payment_rate_currency_id.id: + # if the rate is specified on the voucher, we must use it amount_currency = (move_line['debit'] - move_line['credit']) * voucher_brw.payment_rate else: + # otherwise we use the rates of the system (giving the voucher date in the context) amount_currency = currency_obj.compute(cr, uid, company_currency, line.move_line_id.currency_id.id, move_line['debit']-move_line['credit'], context=ctx) move_line['amount_currency'] = amount_currency voucher_line = move_line_obj.create(cr, uid, move_line) rec_ids = [voucher_line, line.move_line_id.id] - if amount_residual: + if currency_rate_difference: # Change difference entry - exch_lines = self._get_exchange_lines(cr, uid, line, move_id, amount_residual, company_currency, current_currency, context=context) + exch_lines = self._get_exchange_lines(cr, uid, line, move_id, currency_rate_difference, company_currency, current_currency, context=context) new_id = move_line_obj.create(cr, uid, exch_lines[0],context) move_line_obj.create(cr, uid, exch_lines[1], context) rec_ids.append(new_id) @@ -1081,17 +1101,18 @@ class account_voucher(osv.osv): for voucher in self.browse(cr, uid, ids, context=context): if voucher.move_id: continue - #TODO: -need to check- Can't we just use the context returned by _sel_context? - ctx = context.copy() - ctx.update({'date': voucher.date}) company_currency = self._get_company_currency(cr, uid, voucher.id, context) current_currency = self._get_current_currency(cr, uid, voucher.id, context) + # we select the context to use accordingly if it's a multicurrency case or not context = self._sel_context(cr, uid, voucher.id, context) - #Create the account move record. + # But for the operations made by _convert_amount, we always need to give the date in the context + ctx = context.copy() + ctx.update({'date': voucher.date}) + # Create the account move record. move_id = move_pool.create(cr, uid, self.account_move_get(cr, uid, voucher.id, context=context), context=context) # Get the name of the account_move just created name = move_pool.browse(cr, uid, move_id, context=context).name - #Create the first line of the voucher + # Create the first line of the voucher move_line_id = move_line_pool.create(cr, uid, self.first_move_line_get(cr,uid,voucher.id, move_id, company_currency, current_currency, context), context) move_line_brw = move_line_pool.browse(cr, uid, move_line_id, context=context) line_total = move_line_brw.debit - move_line_brw.credit @@ -1100,14 +1121,14 @@ class account_voucher(osv.osv): line_total = line_total - self._convert_amount(cr, uid, voucher.tax_amount, voucher.id, context=ctx) elif voucher.type == 'purchase': line_total = line_total + self._convert_amount(cr, uid, voucher.tax_amount, voucher.id, context=ctx) - #create one move line per voucher line where amount is not 0.0 + # Create one move line per voucher line where amount is not 0.0 line_total, rec_list_ids = self.voucher_move_line_create(cr, uid, voucher.id, line_total, move_id, company_currency, current_currency, context) - #create the writeoff line if needed + # Create the writeoff line if needed ml_writeoff = self.writeoff_move_line_get(cr, uid, voucher.id, line_total, move_id, name, company_currency, current_currency, context) if ml_writeoff: ml_writeoff_id = move_line_pool.create(cr, uid, ml_writeoff, context) - #We post the voucher. + # We post the voucher. self.write(cr, uid, [voucher.id], { 'move_id': move_id, 'state': 'posted', @@ -1115,7 +1136,7 @@ class account_voucher(osv.osv): }) if voucher.journal_id.entry_posted: move_pool.post(cr, uid, [move_id], context={}) - #We automatically reconcile the account move lines. + # We automatically reconcile the account move lines. for rec_ids in rec_list_ids: if len(rec_ids) >= 2: move_line_pool.reconcile_partial(cr, uid, rec_ids, writeoff_acc_id=voucher.exchange_acc_id.id, writeoff_period_id=voucher.period_id.id, writeoff_journal_id=voucher.journal_id.id) From 07d143d74ddc359d664f7ca3fb8b7ed58b950076 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Thu, 24 Nov 2011 13:26:48 +0100 Subject: [PATCH 10/19] [FIX] account_voucher: fixed the views for sales and purchases receipt bzr revid: qdp-launchpad@openerp.com-20111124122648-vl2xtgkpfji1v644 --- addons/account_voucher/voucher_sales_purchase_view.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/account_voucher/voucher_sales_purchase_view.xml b/addons/account_voucher/voucher_sales_purchase_view.xml index db21b4ce86a..03c462780bf 100644 --- a/addons/account_voucher/voucher_sales_purchase_view.xml +++ b/addons/account_voucher/voucher_sales_purchase_view.xml @@ -83,8 +83,8 @@ - - + + @@ -210,8 +210,8 @@ - - + + From 62398c5cba3a821b24cf7cd30875c9fd286fb7e6 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Thu, 24 Nov 2011 16:42:16 +0100 Subject: [PATCH 11/19] [IMP + FIX] account_voucher: fixed few remaining bugs and improved the code in order to remove the field ecxhange_acc_id from the voucher. We now will use fields on the company bzr revid: qdp-launchpad@openerp.com-20111124154216-ivne5w0q9cwhn12r --- addons/account_voucher/account_voucher.py | 34 ++++++++++++++++--- .../account_voucher/account_voucher_view.xml | 14 ++++++++ addons/account_voucher/test/case1_usd_usd.yml | 10 +++++- .../test/case2_suppl_usd_eur.yml | 9 +++++ .../test/case2_usd_eur_debtor_in_eur.yml | 10 +++++- .../test/case2_usd_eur_debtor_in_usd.yml | 10 +++++- addons/account_voucher/test/case4_cad_chf.yml | 10 +++++- .../voucher_payment_receipt_view.xml | 12 +++---- 8 files changed, 92 insertions(+), 17 deletions(-) diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py index e03f45396a5..6860665f71d 100644 --- a/addons/account_voucher/account_voucher.py +++ b/addons/account_voucher/account_voucher.py @@ -91,6 +91,10 @@ class account_voucher(osv.osv): return False def _get_payment_rate_currency(self, cr, uid, context=None): + ''' + Return the default value for field payment_rate_currency_id: the currency of the journal + if there is one, otherwise the currency of the user's company + ''' if context is None: context = {} journal_pool = self.pool.get('account.journal') journal_id = context.get('journal_id', False) @@ -266,7 +270,6 @@ class account_voucher(osv.osv): ('without_writeoff', 'Keep Open'), ('with_writeoff', 'Reconcile Payment Balance'), ], 'Payment Difference', required=True, readonly=True, states={'draft': [('readonly', False)]}), - 'exchange_acc_id': fields.many2one('account.account', 'Exchange Diff. Account', readonly=True, states={'draft': [('readonly', False)]}), 'writeoff_acc_id': fields.many2one('account.account', 'Counterpart Account', readonly=True, states={'draft': [('readonly', False)]}), 'comment': fields.char('Counterpart Comment', size=64, required=True, readonly=True, states={'draft': [('readonly', False)]}), 'analytic_id': fields.many2one('account.analytic.account','Write-Off Analytic Account', readonly=True, states={'draft': [('readonly', False)]}), @@ -851,8 +854,14 @@ class account_voucher(osv.osv): :return: the account move line and its counterpart to create, depicted as mapping between fieldname and value :rtype: tuple of dict ''' - if not line.voucher_id.exchange_acc_id.id: - raise osv.except_osv(_('Error!'), _('You must provide an account for the exchange difference.')) + if amount_residual > 0: + account_id = line.voucher_id.company_id.expense_currency_exchange_account_id + if not account_id: + raise osv.except_osv(_('Warning'),_("Unable to create accounting entry for currency rate difference. You have to configure the field 'Income Currency Rate' on the company! ")) + else: + account_id = line.voucher_id.company_id.income_currency_exchange_account_id + if not account_id: + raise osv.except_osv(_('Warning'),_("Unable to create accounting entry for currency rate difference. You have to configure the field 'Expense Currency Rate' on the company! ")) move_line = { 'journal_id': line.voucher_id.journal_id.id, @@ -872,7 +881,7 @@ class account_voucher(osv.osv): 'journal_id': line.voucher_id.journal_id.id, 'period_id': line.voucher_id.period_id.id, 'name': _('change')+': '+(line.name or '/'), - 'account_id': line.voucher_id.exchange_acc_id.id, + 'account_id': account_id.id, 'move_id': move_id, 'amount_currency': 0.0, 'partner_id': line.voucher_id.partner_id.id, @@ -1139,7 +1148,7 @@ class account_voucher(osv.osv): # We automatically reconcile the account move lines. for rec_ids in rec_list_ids: if len(rec_ids) >= 2: - move_line_pool.reconcile_partial(cr, uid, rec_ids, writeoff_acc_id=voucher.exchange_acc_id.id, writeoff_period_id=voucher.period_id.id, writeoff_journal_id=voucher.journal_id.id) + move_line_pool.reconcile_partial(cr, uid, rec_ids, writeoff_acc_id=voucher.writeoff_acc_id.id, writeoff_period_id=voucher.period_id.id, writeoff_journal_id=voucher.journal_id.id) return True def copy(self, cr, uid, id, default={}, context=None): @@ -1390,4 +1399,19 @@ def resolve_o2m_operations(cr, uid, target_osv, operations, fields, context): results.append(result) return results +class res_company(osv.osv): + _inherit = "res.company" + _columns = { + 'income_currency_exchange_account_id': fields.many2one( + 'account.account', + string="Income Currency Rate", + domain="[('type', '=', 'other')]",), + 'expense_currency_exchange_account_id': fields.many2one( + 'account.account', + string="Expense Currency Rate", + domain="[('type', '=', 'other')]",), + } + +res_company() + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_voucher/account_voucher_view.xml b/addons/account_voucher/account_voucher_view.xml index 4e218e04714..cbe35b5fc5f 100644 --- a/addons/account_voucher/account_voucher_view.xml +++ b/addons/account_voucher/account_voucher_view.xml @@ -259,5 +259,19 @@ + + + res.company.form.inherit + + res.company + form + + + + + + + + diff --git a/addons/account_voucher/test/case1_usd_usd.yml b/addons/account_voucher/test/case1_usd_usd.yml index 96a0e07f70d..3432d3cf27b 100644 --- a/addons/account_voucher/test/case1_usd_usd.yml +++ b/addons/account_voucher/test/case1_usd_usd.yml @@ -1,6 +1,15 @@ - In order to check the Account_voucher module with multi-currency in OpenERP, I create 2 Invoices in USD and make 2 Payments in USD based on the currency rating on that particular date +- + I set the income and expense currency accounts on the main company +- + !python {model: res.company}: | + from datetime import datetime + vals = { + 'income_currency_exchange_account_id': ref('account.o_expense'), + 'expense_currency_exchange_account_id': ref('account.o_expense')} + self.write(cr, uid, ref('base.main_company'), vals) - I create currency USD in OpenERP for January of 1.333333 Rate - @@ -243,7 +252,6 @@ date: !eval time.strftime("%Y-04-01") payment_option: 'with_writeoff' writeoff_acc_id: account.a_expense - exchange_acc_id: account.o_expense comment: 'Write Off' - I fill amounts 20 for the invoice of 200$ and 30 for the invoice of 100$ diff --git a/addons/account_voucher/test/case2_suppl_usd_eur.yml b/addons/account_voucher/test/case2_suppl_usd_eur.yml index 6d6f71b943e..0ad523b8004 100644 --- a/addons/account_voucher/test/case2_suppl_usd_eur.yml +++ b/addons/account_voucher/test/case2_suppl_usd_eur.yml @@ -1,6 +1,15 @@ - In order to check the Account_voucher module with multi-currency in OpenERP, I create 2 Invoices in USD and make 2 Payments one in USD and another in EUR, based on the currency rating on that particular date +- + I set the income and expense currency accounts on the main company +- + !python {model: res.company}: | + from datetime import datetime + vals = { + 'income_currency_exchange_account_id': ref('account.o_expense'), + 'expense_currency_exchange_account_id': ref('account.o_expense')} + self.write(cr, uid, ref('base.main_company'), vals) - I create a bank journal with EUR as currency - diff --git a/addons/account_voucher/test/case2_usd_eur_debtor_in_eur.yml b/addons/account_voucher/test/case2_usd_eur_debtor_in_eur.yml index 5aadc93be13..ac77aef622d 100644 --- a/addons/account_voucher/test/case2_usd_eur_debtor_in_eur.yml +++ b/addons/account_voucher/test/case2_usd_eur_debtor_in_eur.yml @@ -1,6 +1,15 @@ - In order to check the Account_voucher module with multi-currency in OpenERP, I create 2 Invoices in USD and make 2 Payments one in USD and another in EUR, based on the currency rating on that particular date +- + I set the income and expense currency accounts on the main company +- + !python {model: res.company}: | + from datetime import datetime + vals = { + 'income_currency_exchange_account_id': ref('account.o_expense'), + 'expense_currency_exchange_account_id': ref('account.o_expense')} + self.write(cr, uid, ref('base.main_company'), vals) - I modify the debtor account in order to make sure there is no currency_id linked - @@ -221,7 +230,6 @@ date: !eval time.strftime("%Y-04-01") payment_option: 'with_writeoff' writeoff_acc_id: account.a_expense - exchange_acc_id: account.o_expense comment: 'Write Off' name: 'Second payment: Case 2 SUPPL USD/EUR DR EUR' diff --git a/addons/account_voucher/test/case2_usd_eur_debtor_in_usd.yml b/addons/account_voucher/test/case2_usd_eur_debtor_in_usd.yml index 43c00a9f798..326ba6989d7 100644 --- a/addons/account_voucher/test/case2_usd_eur_debtor_in_usd.yml +++ b/addons/account_voucher/test/case2_usd_eur_debtor_in_usd.yml @@ -1,6 +1,15 @@ - In order to check the Account_voucher module with multi-currency in OpenERP, I create 2 Invoices in USD and make 2 Payments one in USD and another in EUR, based on the currency rating on that particular date +- + I set the income and expense currency accounts on the main company +- + !python {model: res.company}: | + from datetime import datetime + vals = { + 'income_currency_exchange_account_id': ref('account.o_expense'), + 'expense_currency_exchange_account_id': ref('account.o_expense')} + self.write(cr, uid, ref('base.main_company'), vals) - I modify the debtor account in order to set the currency_id = USD - @@ -236,7 +245,6 @@ date: !eval time.strftime("%Y-04-01") payment_option: 'with_writeoff' writeoff_acc_id: account.a_expense - exchange_acc_id: account.o_expense comment: 'Write Off' name: 'Second payment: Case 2 SUPPL USD/EUR DR USD' diff --git a/addons/account_voucher/test/case4_cad_chf.yml b/addons/account_voucher/test/case4_cad_chf.yml index bb9bda9126c..7c0f9274ff8 100644 --- a/addons/account_voucher/test/case4_cad_chf.yml +++ b/addons/account_voucher/test/case4_cad_chf.yml @@ -1,6 +1,15 @@ - In order to check the Account_voucher module with multi-currency in OpenERP, I create an invoice in CAD and make its Payment in CHF based on the currency rating on that particular date. +- + I set the income and expense currency accounts on the main company +- + !python {model: res.company}: | + from datetime import datetime + vals = { + 'income_currency_exchange_account_id': ref('account.o_expense'), + 'expense_currency_exchange_account_id': ref('account.o_expense')} + self.write(cr, uid, ref('base.main_company'), vals) - I create currency CAD in OpenERP for January of 1.338800 Rate - @@ -106,7 +115,6 @@ date: !eval time.strftime("%Y-03-01") payment_option: 'with_writeoff' writeoff_acc_id: account.a_expense - exchange_acc_id: account.o_expense comment: 'Write Off' name: 'First payment: Case 4' - diff --git a/addons/account_voucher/voucher_payment_receipt_view.xml b/addons/account_voucher/voucher_payment_receipt_view.xml index 4b6817d77ef..db7c9d9ec54 100644 --- a/addons/account_voucher/voucher_payment_receipt_view.xml +++ b/addons/account_voucher/voucher_payment_receipt_view.xml @@ -171,7 +171,7 @@ @@ -187,7 +187,7 @@ @@ -205,8 +205,6 @@ - @@ -325,7 +323,7 @@ @@ -341,7 +339,7 @@ @@ -359,8 +357,6 @@ - From bb67abe9140d73f6c8ad4c25eefc9d38be777485 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 30 Nov 2011 11:11:10 +0100 Subject: [PATCH 12/19] [IMP] account_voucher: improvements inj usability + changed the semantic of the payment_rate, which now depicts the rate of the payment_rate_currency_id against the voucher currency (instead of the main currency) bzr revid: qdp-launchpad@openerp.com-20111130101110-p19ujgsaqgfnuv1r --- addons/account_voucher/account_voucher.py | 100 +++++++++++------- .../test/account_voucher_report.yml | 4 +- addons/account_voucher/test/case4_cad_chf.yml | 2 + .../voucher_payment_receipt_view.xml | 18 ++-- 4 files changed, 76 insertions(+), 48 deletions(-) diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py index 6860665f71d..22824cb8db0 100644 --- a/addons/account_voucher/account_voucher.py +++ b/addons/account_voucher/account_voucher.py @@ -159,15 +159,6 @@ class account_voucher(osv.osv): res = super(account_voucher, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu) doc = etree.XML(res['arch']) - # replace the label of the field payment_rate - currency_obj = self.pool.get('res.currency') - base_currency_id = currency_obj.search(cr, uid, [('rate','=',1.0),('rate_ids','=',1.0)], context=context) - symbol = base_currency_id and currency_obj.name_get(cr, uid, base_currency_id, context=context)[0][1] - string = _("Rate for this operation: 1 %s is") % symbol - payment_rate_field = doc.xpath("//field[@name='payment_rate']") - for field in payment_rate_field: - field.set('string', string) - if context.get('type', 'sale') in ('purchase', 'payment'): nodes = doc.xpath("//field[@name='partner_id']") for node in nodes: @@ -183,17 +174,25 @@ class account_voucher(osv.osv): credit += l['amount'] return abs(amount - abs(credit - debit)) - def onchange_line_ids(self, cr, uid, ids, line_dr_ids, line_cr_ids, amount, context=None): + def onchange_line_ids(self, cr, uid, ids, line_dr_ids, line_cr_ids, amount, voucher_currency, context=None): context = context or {} if not line_dr_ids and not line_cr_ids: return {'value':{}} line_osv = self.pool.get("account.voucher.line") line_dr_ids = resolve_o2m_operations(cr, uid, line_osv, line_dr_ids, ['amount'], context) line_cr_ids = resolve_o2m_operations(cr, uid, line_osv, line_cr_ids, ['amount'], context) - return {'value': {'writeoff_amount': self._compute_writeoff_amount(cr, uid, line_dr_ids, line_cr_ids, amount)}} + + #loop into the lines to see if there is an amount allocated on a voucher line with a currency different than the voucher currency + is_multi_currency = False + for voucher_line in line_dr_ids+line_cr_ids: + if voucher_line.get('currency_id',False) != voucher_currency: + is_multi_currency = True + break + return {'value': {'writeoff_amount': self._compute_writeoff_amount(cr, uid, line_dr_ids, line_cr_ids, amount), 'is_multi_currency': is_multi_currency}} def _get_writeoff_amount(self, cr, uid, ids, name, args, context=None): if not ids: return {} + currency_obj = self.pool.get('res.currency') res = {} debit = credit = 0.0 for voucher in self.browse(cr, uid, ids, context=context): @@ -201,18 +200,24 @@ class account_voucher(osv.osv): debit += l.amount for l in voucher.line_cr_ids: credit += l.amount - res[voucher.id] = abs(voucher.amount - abs(credit - debit)) + currency = voucher.currency_id or voucher.company_id.currency_id + res[voucher.id] = currency_obj.round(cr, uid, currency, abs(voucher.amount - abs(credit - debit))) return res def _paid_amount_in_company_currency(self, cr, uid, ids, name, args, context=None): if not ids: return {} res = {} - debit = credit = 0.0 + voucher_rate = company_currency_rate = 1.0 for voucher in self.browse(cr, uid, ids, context=context): - rate = voucher.currency_id.rate or voucher.company_id.currency_id.rate - if voucher.currency_id == voucher.payment_rate_currency_id: - rate = voucher.payment_rate - res[voucher.id] = voucher.amount / rate * voucher.company_id.currency_id.rate + if voucher.currency_id: + ctx = context.copy() + ctx.update({'date': voucher.date}) + voucher_rate = self.browse(cr, uid, voucher.id, context=ctx).currency_id.rate + if voucher.company_id.currency_id.id == voucher.payment_rate_currency_id.id: + company_currency_rate = voucher.payment_rate + else: + company_currency_rate = voucher.company_id.currency_id.rate + res[voucher.id] = voucher.amount / voucher_rate * company_currency_rate return res _name = 'account.voucher' @@ -275,9 +280,10 @@ class account_voucher(osv.osv): 'analytic_id': fields.many2one('account.analytic.account','Write-Off Analytic Account', readonly=True, states={'draft': [('readonly', False)]}), 'writeoff_amount': fields.function(_get_writeoff_amount, string='Reconcile Amount', type='float', readonly=True), 'payment_rate_currency_id': fields.many2one('res.currency', 'Payment Rate Currency', required=True, readonly=True, states={'draft':[('readonly',False)]}), - 'payment_rate': fields.float('Payment Rate', digits=(12,6), required=True, readonly=True, states={'draft': [('readonly', False)]}, - help='The specific rate that will be used for this voucher for the selected currency.'), + 'payment_rate': fields.float('Exchange Rate', digits=(12,6), required=True, readonly=True, states={'draft': [('readonly', False)]}, + help='The specific rate that will be used, in this voucher, between the selected currency (in \'Payment Rate Currency\' field) and the voucher currency.'), 'paid_amount_in_company_currency': fields.function(_paid_amount_in_company_currency, string='Paid Amount in Company Currency', type='float', readonly=True), + 'is_multi_currency': fields.boolean('Multi Currency Voucher', help='Fields with internal purpose only that depicts if the voucher is a multi currency one or not'), } _defaults = { 'period_id': _get_period, @@ -448,10 +454,15 @@ class account_voucher(osv.osv): return default def onchange_rate(self, cr, uid, ids, rate, amount, currency_id, payment_rate_currency_id, company_id, context=None): - res = {'value': {}} - if rate and amount and currency_id and currency_id == payment_rate_currency_id: - company_rate = self.pool.get('res.company').browse(cr, uid, company_id, context=context).currency_id.rate - res['value']['paid_amount_in_company_currency'] = amount / rate * company_rate + res = {'value': {'paid_amount_in_company_currency': amount}} + company_currency = self.pool.get('res.company').browse(cr, uid, company_id, context=context).currency_id + if rate and amount and currency_id:# and currency_id == payment_rate_currency_id: + voucher_rate = self.pool.get('res.currency').browse(cr, uid, currency_id, context).rate + if company_currency.id == payment_rate_currency_id: + company_rate = rate + else: + company_rate = self.pool.get('res.company').browse(cr, uid, company_id, context=context).currency_id.rate + res['value']['paid_amount_in_company_currency'] = amount / voucher_rate * company_rate return res def onchange_amount(self, cr, uid, ids, amount, rate, partner_id, journal_id, currency_id, ttype, date, payment_rate_currency_id, company_id, context=None): @@ -578,6 +589,7 @@ class account_voucher(osv.osv): else: amount_original = currency_pool.compute(cr, uid, company_currency, currency_id, line.credit or line.debit or 0.0) amount_unreconciled = currency_pool.compute(cr, uid, company_currency, currency_id, abs(line.amount_residual)) + currency_id = line.currency_id and line.currency_id.id or line.company_id.currency_id.id rs = { 'name':line.move_id.name, 'type': line.credit and 'dr' or 'cr', @@ -588,6 +600,7 @@ class account_voucher(osv.osv): 'date_original':line.date, 'date_due':line.date_maturity, 'amount_unreconciled': amount_unreconciled, + 'currency_id': currency_id, } #split voucher amount by most old first, but only for lines in the same currency @@ -650,7 +663,9 @@ class account_voucher(osv.osv): res['value'].update({'period_id':pids[0]}) if payment_rate_currency_id: ctx.update({'date': date}) - payment_rate = self.pool.get('res.currency').browse(cr, uid, payment_rate_currency_id, context=ctx).rate + payment_rate = 1.0 + if payment_rate_currency_id != currency_id: + payment_rate = self.pool.get('res.currency').browse(cr, uid, payment_rate_currency_id, context=ctx).rate vals = self.onchange_payment_rate_currency(cr, uid, ids, currency_id, payment_rate, payment_rate_currency_id, date, amount, company_id, context=context) vals['value'].update({'payment_rate': payment_rate}) for key in vals.keys(): @@ -674,12 +689,13 @@ class account_voucher(osv.osv): currency_id = journal.currency.id ctx = context.copy() ctx.update({'date': date}) - payment_rate = self.pool.get('res.currency').browse(cr, uid, currency_id, context=ctx).rate - vals['value'].update({'payment_rate': payment_rate}) + #on change of the journal, we need to TODO coment me + payment_rate = 1.0 + res = self.onchange_rate(cr, uid, ids, payment_rate, amount, currency_id, currency_id, company_id, context=ctx) for key in res.keys(): vals[key].update(res[key]) - if currency_id: + vals['value'].update({'payment_rate': payment_rate}) vals['value'].update({'currency_id': currency_id}) vals['value'].update({'payment_rate_currency_id': currency_id}) res = self.onchange_partner_id(cr, uid, ids, partner_id, journal_id, amount, currency_id, ttype, date, context) @@ -912,12 +928,7 @@ class account_voucher(osv.osv): # the rate specified on the voucher is for the company currency rate_between_voucher_and_base = voucher.currency_id.rate or 1.0 rate_between_base_and_company = voucher.payment_rate or 1.0 - res = amount / rate_between_voucher_and_base * rate_between_base_and_company - elif voucher.payment_rate_currency_id.id == voucher.currency_id.id: - # the rate specified on the voucher is for the voucher currency - rate_between_base_and_company = voucher.company_id.currency_id.rate or 1.0 - rate_between_voucher_and_base = voucher.payment_rate or 1.0 - res = amount / rate_between_voucher_and_base * rate_between_base_and_company + res = currency_obj.round(cr, uid, voucher.company_id.currency_id, (amount / rate_between_voucher_and_base * rate_between_base_and_company)) else: # the rate specified on the voucher is not relevant, we use all the rates in the system res = currency_obj.compute(cr, uid, voucher.currency_id.id, voucher.company_id.currency_id.id, amount, context=context) @@ -997,7 +1008,7 @@ class account_voucher(osv.osv): if not (tax_data.base_code_id and tax_data.tax_code_id): raise osv.except_osv(_('No Account Base Code and Account Tax Code!'),_("You have to configure account base code and account tax code on the '%s' tax!") % (tax_data.name)) - # compute the amount in foreign currency. + # compute the amount in foreign currency amount_currency = False if line.move_line_id: # We want to set it on the account move line as soon as the original line had a foreign currency @@ -1200,6 +1211,20 @@ class account_voucher_line(osv.osv): rs_data[line.id] = res return rs_data + def _currency_id(self, cr, uid, ids, name, args, context=None): + ''' + This function returns the currency id of a voucher line. It's either the currency of the + associated move line (if any) or the currency of the voucher or the company currency. + ''' + res = {} + for line in self.browse(cr, uid, ids, context=context): + move_line = line.move_line_id + if move_line: + res[line.id] = move_line.currency_id and move_line.currency_id.id or move_line.company_id.currency_id.id + else: + res[line.id] = line.voucher_id.currency_id and line.voucher_id.currency_id.id or line.voucher_id.company_id.currency_id.id + return res + _columns = { 'voucher_id':fields.many2one('account.voucher', 'Voucher', required=1, ondelete='cascade'), 'name':fields.char('Description', size=256), @@ -1216,6 +1241,7 @@ class account_voucher_line(osv.osv): 'amount_original': fields.function(_compute_balance, multi='dc', type='float', string='Original Amount', store=True), 'amount_unreconciled': fields.function(_compute_balance, multi='dc', type='float', string='Open Balance', store=True), 'company_id': fields.related('voucher_id','company_id', relation='res.company', type='many2one', string='Company', store=True, readonly=True), + 'currency_id': fields.function(_currency_id, string='Currency', type='many2one', relation='res.currency', readonly=True), } _defaults = { 'name': '', @@ -1252,10 +1278,10 @@ class account_voucher_line(osv.osv): ttype = 'dr' else: ttype = 'cr' - account_id = move_line.account_id.id res.update({ - 'account_id':account_id, - 'type': ttype + 'account_id': move_line.account_id.id, + 'type': ttype, + 'currency_id': move_line.currency_id and move_line.currency_id.id or move_line.company_id.currency_id.id, }) return { 'value':res, diff --git a/addons/account_voucher/test/account_voucher_report.yml b/addons/account_voucher/test/account_voucher_report.yml index b41c33e4470..85432f747aa 100644 --- a/addons/account_voucher/test/account_voucher_report.yml +++ b/addons/account_voucher/test/account_voucher_report.yml @@ -1,7 +1,7 @@ - Demo for Account Voucher - - !record {model: account.voucher, id: account_voucher_voucheraxelor0}: + !record {model: account.voucher, id: account_voucher_voucheraxelor0again}: account_id: account.cash company_id: base.main_company journal_id: account.bank_journal @@ -19,6 +19,6 @@ - !python {model: account.voucher}: | import netsvc, tools, os - (data, format) = netsvc.LocalService('report.voucher.cash_receipt.drcr').create(cr, uid, [ref("account_voucher_voucheraxelor0")], {}, {}) + (data, format) = netsvc.LocalService('report.voucher.cash_receipt.drcr').create(cr, uid, [ref("account_voucher_voucheraxelor0again")], {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'account_voucher-report.'+format), 'wb+').write(data) diff --git a/addons/account_voucher/test/case4_cad_chf.yml b/addons/account_voucher/test/case4_cad_chf.yml index 7c0f9274ff8..f31a7393a8e 100644 --- a/addons/account_voucher/test/case4_cad_chf.yml +++ b/addons/account_voucher/test/case4_cad_chf.yml @@ -128,6 +128,8 @@ for item in voucher_id.line_cr_ids: if item.amount_unreconciled == 186.74: data += [(item.id, 186.74)] + else: + data += [(item.id, 0.0)] for line_id, amount in data: self.pool.get('account.voucher.line').write(cr, uid, [line_id], {'amount': amount}) assert (voucher_id.state=='draft'), "Voucher is not in draft state" diff --git a/addons/account_voucher/voucher_payment_receipt_view.xml b/addons/account_voucher/voucher_payment_receipt_view.xml index db7c9d9ec54..6ed7ab0fe7c 100644 --- a/addons/account_voucher/voucher_payment_receipt_view.xml +++ b/addons/account_voucher/voucher_payment_receipt_view.xml @@ -92,7 +92,7 @@ - + - + - + @@ -203,11 +203,11 @@ - + - + @@ -318,7 +318,7 @@ - + - + - + - + From 832436c1487ca6accf074da8e73ce5cccda51c48 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 30 Nov 2011 14:30:08 +0100 Subject: [PATCH 13/19] [IMP] account_voucher: usability changes bzr revid: qdp-launchpad@openerp.com-20111130133008-lki16nzzlz78s0h8 --- addons/account_voucher/account_voucher.py | 6 ++--- .../voucher_payment_receipt_view.xml | 24 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py index 22824cb8db0..999de8dfbf4 100644 --- a/addons/account_voucher/account_voucher.py +++ b/addons/account_voucher/account_voucher.py @@ -274,11 +274,11 @@ class account_voucher(osv.osv): 'payment_option':fields.selection([ ('without_writeoff', 'Keep Open'), ('with_writeoff', 'Reconcile Payment Balance'), - ], 'Payment Difference', required=True, readonly=True, states={'draft': [('readonly', False)]}), + ], 'Payment Difference', required=True, readonly=True, states={'draft': [('readonly', False)]}, help="This field helps you to choose what you want to do with the eventual difference between the paid amount and the sum of allocated amounts. You can either choose to keep open this difference on the partner's account, or reconcile it with the payment(s)"), 'writeoff_acc_id': fields.many2one('account.account', 'Counterpart Account', readonly=True, states={'draft': [('readonly', False)]}), 'comment': fields.char('Counterpart Comment', size=64, required=True, readonly=True, states={'draft': [('readonly', False)]}), 'analytic_id': fields.many2one('account.analytic.account','Write-Off Analytic Account', readonly=True, states={'draft': [('readonly', False)]}), - 'writeoff_amount': fields.function(_get_writeoff_amount, string='Reconcile Amount', type='float', readonly=True), + 'writeoff_amount': fields.function(_get_writeoff_amount, string='Difference Amount', type='float', readonly=True, help="Computed as the difference between the amount stated in the voucher and the sum of allocation on the voucher lines."), 'payment_rate_currency_id': fields.many2one('res.currency', 'Payment Rate Currency', required=True, readonly=True, states={'draft':[('readonly',False)]}), 'payment_rate': fields.float('Exchange Rate', digits=(12,6), required=True, readonly=True, states={'draft': [('readonly', False)]}, help='The specific rate that will be used, in this voucher, between the selected currency (in \'Payment Rate Currency\' field) and the voucher currency.'), @@ -1231,7 +1231,7 @@ class account_voucher_line(osv.osv): 'account_id':fields.many2one('account.account','Account', required=True), 'partner_id':fields.related('voucher_id', 'partner_id', type='many2one', relation='res.partner', string='Partner'), 'untax_amount':fields.float('Untax Amount'), - 'amount':fields.float('Amount', digits_compute=dp.get_precision('Account')), + 'amount':fields.float('Allocation', digits_compute=dp.get_precision('Account')), 'reconcile': fields.boolean('Full Reconcile'), 'type':fields.selection([('dr','Debit'),('cr','Credit')], 'Dr/Cr'), 'account_analytic_id': fields.many2one('account.analytic.account', 'Analytic Account'), diff --git a/addons/account_voucher/voucher_payment_receipt_view.xml b/addons/account_voucher/voucher_payment_receipt_view.xml index 6ed7ab0fe7c..e2060a04533 100644 --- a/addons/account_voucher/voucher_payment_receipt_view.xml +++ b/addons/account_voucher/voucher_payment_receipt_view.xml @@ -102,8 +102,8 @@ - - + + @@ -116,8 +116,8 @@ - - + + @@ -177,9 +177,9 @@ - + - + @@ -193,9 +193,9 @@ - + - + @@ -329,9 +329,9 @@ - + - + @@ -345,9 +345,9 @@ - + - + From 8dcc7aac7ae32007795cf9c44f4a725a2c248404 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 30 Nov 2011 14:33:11 +0100 Subject: [PATCH 14/19] [IMP] account_voucher: usability changes bzr revid: qdp-launchpad@openerp.com-20111130133311-8t4sxrikywrkkkhh --- addons/account_voucher/voucher_payment_receipt_view.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/account_voucher/voucher_payment_receipt_view.xml b/addons/account_voucher/voucher_payment_receipt_view.xml index e2060a04533..13cbaa74688 100644 --- a/addons/account_voucher/voucher_payment_receipt_view.xml +++ b/addons/account_voucher/voucher_payment_receipt_view.xml @@ -252,7 +252,7 @@