[MERGE] forward port branch 9.0 up to 22ac4deb94
This commit is contained in:
@@ -755,7 +755,7 @@ class AccountBankStatementLine(models.Model):
|
||||
}
|
||||
|
||||
def _prepare_reconciliation_move_line(self, move, amount):
|
||||
""" Prepare the dict of values to create the move line from a statement line.
|
||||
""" Prepare the dict of values to balance the move.
|
||||
|
||||
:param recordset move: the account.move to link the move line
|
||||
:param float amount: the amount of transaction that wasn't already reconciled
|
||||
@@ -763,25 +763,29 @@ class AccountBankStatementLine(models.Model):
|
||||
company_currency = self.journal_id.company_id.currency_id
|
||||
statement_currency = self.journal_id.currency_id or company_currency
|
||||
st_line_currency = self.currency_id or statement_currency
|
||||
|
||||
amount_currency = False
|
||||
if statement_currency != company_currency or st_line_currency != company_currency:
|
||||
# First get the ratio total mount / amount not already reconciled
|
||||
if statement_currency == company_currency:
|
||||
total_amount = self.amount
|
||||
elif st_line_currency == company_currency:
|
||||
total_amount = self.amount_currency
|
||||
else:
|
||||
total_amount = statement_currency.with_context({'date': self.date}).compute(self.amount, company_currency, round=False)
|
||||
if float_compare(total_amount, amount, precision_digits=company_currency.rounding) == 0:
|
||||
ratio = 1.0
|
||||
else:
|
||||
ratio = total_amount / amount
|
||||
# Then use it to adjust the statement.line field that correspond to the move.line amount_currency
|
||||
if statement_currency != company_currency:
|
||||
amount_currency = self.amount * ratio
|
||||
elif st_line_currency != company_currency:
|
||||
amount_currency = self.amount_currency * ratio
|
||||
st_line_currency_rate = self.currency_id and (self.amount_currency / self.amount) or False
|
||||
# We have several use case here to compure the currency and amount currency of counterpart line to balance the move:
|
||||
if st_line_currency != company_currency and st_line_currency == statement_currency:
|
||||
# company in currency A, statement in currency B and transaction in currency B
|
||||
# counterpart line must have currency B and correct amount is inverse of already existing lines
|
||||
amount_currency = -sum([x.amount_currency for x in move.line_ids])
|
||||
elif st_line_currency != company_currency and statement_currency == company_currency:
|
||||
# company in currency A, statement in currency A and transaction in currency B
|
||||
# counterpart line must have currency B and correct amount is inverse of already existing lines
|
||||
amount_currency = -sum([x.amount_currency for x in move.line_ids])
|
||||
elif st_line_currency != company_currency and st_line_currency != statement_currency:
|
||||
# company in currency A, statement in currency B and transaction in currency C
|
||||
# counterpart line must have currency B and use rate between B and C to compute correct amount
|
||||
amount_currency = -sum([x.amount_currency for x in move.line_ids])/st_line_currency_rate
|
||||
elif st_line_currency == company_currency and statement_currency != company_currency:
|
||||
# company in currency A, statement in currency B and transaction in currency A
|
||||
# counterpart line must have currency B and amount is computed using the rate between A and B
|
||||
amount_currency = amount/st_line_currency_rate
|
||||
|
||||
# last case is company in currency A, statement in currency A and transaction in currency A
|
||||
# and in this case counterpart line does not need any second currency nor amount_currency
|
||||
|
||||
return {
|
||||
'name': self.name,
|
||||
'date': self.date,
|
||||
@@ -990,8 +994,7 @@ class AccountBankStatementLine(models.Model):
|
||||
|
||||
(new_aml | counterpart_move_line).reconcile()
|
||||
|
||||
# Create the move line for the statement line using the bank statement line as the remaining amount
|
||||
# This leaves out the amount already reconciled and avoids rounding errors from currency conversion
|
||||
# Balance the move
|
||||
st_line_amount = -sum([x.balance for x in move.line_ids])
|
||||
aml_dict = self._prepare_reconciliation_move_line(move, st_line_amount)
|
||||
aml_dict['payment_id'] = payment_id
|
||||
|
||||
@@ -74,7 +74,7 @@ class AccountInvoice(models.Model):
|
||||
@api.model
|
||||
def _default_currency(self):
|
||||
journal = self._default_journal()
|
||||
return journal.currency_id or journal.company_id.currency_id
|
||||
return journal.currency_id or journal.company_id.currency_id or self.env.user.company_id.currency_id
|
||||
|
||||
@api.model
|
||||
def _get_reference_type(self):
|
||||
|
||||
@@ -81,7 +81,7 @@ class account_abstract_payment(models.AbstractModel):
|
||||
|
||||
def _compute_total_invoices_amount(self):
|
||||
""" Compute the sum of the residual of invoices, expressed in the payment currency """
|
||||
payment_currency = self.currency_id or self.journal_id.currency_id or self.journal_id.company_id.currency_id
|
||||
payment_currency = self.currency_id or self.journal_id.currency_id or self.journal_id.company_id.currency_id or self.env.user.company_id.currency_id
|
||||
invoices = self._get_invoices()
|
||||
|
||||
if all(inv.currency_id == payment_currency for inv in invoices):
|
||||
|
||||
@@ -404,3 +404,75 @@ class TestReconciliation(AccountingTestCase):
|
||||
self.assertTrue(aml.reconciled, 'The journal item should be totally reconciled')
|
||||
self.assertEquals(aml.amount_residual, 0, 'The journal item should be totally reconciled')
|
||||
self.assertEquals(aml.amount_residual_currency, 0, 'The journal item should be totally reconciled')
|
||||
|
||||
def test_reconcile_bank_statement_with_payment_and_writeoff(self):
|
||||
# Use case:
|
||||
# Company is in EUR, create a bill for 80 USD and register payment of 80 USD.
|
||||
# create a bank statement in USD bank journal with a bank statement line of 85 USD
|
||||
# Reconcile bank statement with payment and put the remaining 5 USD in bank fees or another account.
|
||||
|
||||
invoice = self.create_invoice(type='out_invoice', invoice_amount=80, currency_id=self.currency_usd_id)
|
||||
# register payment on invoice
|
||||
payment = self.env['account.payment'].create({'payment_type': 'inbound',
|
||||
'payment_method_id': self.env.ref('account.account_payment_method_manual_in').id,
|
||||
'partner_type': 'customer',
|
||||
'partner_id': self.partner_agrolait_id,
|
||||
'amount': 80,
|
||||
'currency_id': self.currency_usd_id,
|
||||
'payment_date': time.strftime('%Y') + '-07-15',
|
||||
'journal_id': self.bank_journal_usd.id,
|
||||
})
|
||||
payment.post()
|
||||
payment_move_line = False
|
||||
bank_move_line = False
|
||||
for l in payment.move_line_ids:
|
||||
if l.account_id.id == self.account_rcv.id:
|
||||
payment_move_line = l
|
||||
else:
|
||||
bank_move_line = l
|
||||
invoice.register_payment(payment_move_line)
|
||||
|
||||
# create bank statement
|
||||
bank_stmt = self.acc_bank_stmt_model.create({
|
||||
'journal_id': self.bank_journal_usd.id,
|
||||
'date': time.strftime('%Y') + '-07-15',
|
||||
})
|
||||
|
||||
bank_stmt_line = self.acc_bank_stmt_line_model.create({'name': 'payment',
|
||||
'statement_id': bank_stmt.id,
|
||||
'partner_id': self.partner_agrolait_id,
|
||||
'amount': 85,
|
||||
'date': time.strftime('%Y') + '-07-15',})
|
||||
|
||||
#reconcile the statement with invoice and put remaining in another account
|
||||
bank_stmt_line.process_reconciliation(payment_aml_rec= bank_move_line, new_aml_dicts=[{
|
||||
'account_id': self.diff_income_account.id,
|
||||
'debit': 0,
|
||||
'credit': 5,
|
||||
'name': 'bank fees',
|
||||
}])
|
||||
|
||||
# Check that move lines associated to bank_statement are correct
|
||||
bank_stmt_aml = self.env['account.move.line'].search([('statement_id', '=', bank_stmt.id)])
|
||||
bank_stmt_aml |= bank_stmt_aml.mapped('move_id').mapped('line_ids')
|
||||
self.assertEquals(len(bank_stmt_aml), 4, "The bank statement should have 4 moves lines")
|
||||
lines = {
|
||||
self.account_usd.id: [
|
||||
{'debit': 3.27, 'credit': 0.0, 'amount_currency': 5, 'currency_id': self.currency_usd_id},
|
||||
{'debit': 52.33, 'credit': 0, 'amount_currency': 80, 'currency_id': self.currency_usd_id}
|
||||
],
|
||||
self.diff_income_account.id: {'debit': 0.0, 'credit': 3.27, 'amount_currency': -5, 'currency_id': self.currency_usd_id},
|
||||
self.account_rcv.id: {'debit': 0.0, 'credit': 52.33, 'amount_currency': -80, 'currency_id': self.currency_usd_id},
|
||||
}
|
||||
for aml in bank_stmt_aml:
|
||||
line = lines[aml.account_id.id]
|
||||
if type(line) == list:
|
||||
# find correct line inside the list
|
||||
if line[0]['debit'] == round(aml.debit, 2):
|
||||
line = line[0]
|
||||
else:
|
||||
line = line[1]
|
||||
self.assertEquals(round(aml.debit, 2), line['debit'])
|
||||
self.assertEquals(round(aml.credit, 2), line['credit'])
|
||||
self.assertEquals(round(aml.amount_currency, 2), line['amount_currency'])
|
||||
self.assertEquals(aml.currency_id.id, line['currency_id'])
|
||||
@@ -244,6 +244,7 @@ class AccountVoucher(models.Model):
|
||||
'date': self.date,
|
||||
'tax_ids': [(4,t.id) for t in line.tax_ids],
|
||||
'amount_currency': line.price_subtotal if current_currency != company_currency else 0.0,
|
||||
'currency_id': company_currency != current_currency and current_currency or False,
|
||||
}
|
||||
|
||||
self.env['account.move.line'].create(move_line)
|
||||
@@ -269,7 +270,7 @@ class AccountVoucher(models.Model):
|
||||
move = self.env['account.move'].create(voucher.account_move_get())
|
||||
# Get the name of the account_move just created
|
||||
# Create the first line of the voucher
|
||||
move_line = self.env['account.move.line'].with_context(ctx).create(voucher.first_move_line_get(move.id, company_currency, current_currency))
|
||||
move_line = self.env['account.move.line'].with_context(ctx).create(voucher.with_context(ctx).first_move_line_get(move.id, company_currency, current_currency))
|
||||
line_total = move_line.debit - move_line.credit
|
||||
if voucher.voucher_type == 'sale':
|
||||
line_total = line_total - voucher._convert_amount(voucher.tax_amount)
|
||||
|
||||
@@ -1185,15 +1185,6 @@ class product_product(osv.osv):
|
||||
args.append((('categ_id', 'child_of', context['search_default_categ_id'])))
|
||||
return super(product_product, self).search(cr, uid, args, offset=offset, limit=limit, order=order, context=context, count=count)
|
||||
|
||||
def open_product_template(self, cr, uid, ids, context=None):
|
||||
""" Utility method used to add an "Open Template" button in product views """
|
||||
product = self.browse(cr, uid, ids[0], context=context)
|
||||
return {'type': 'ir.actions.act_window',
|
||||
'res_model': 'product.template',
|
||||
'view_mode': 'form',
|
||||
'res_id': product.product_tmpl_id.id,
|
||||
'target': 'new'}
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
ctx = dict(context or {}, create_product_product=True)
|
||||
product_id = super(product_product, self).create(cr, uid, vals, context=ctx)
|
||||
|
||||
Reference in New Issue
Block a user