You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
294 lines
12 KiB
Python
294 lines
12 KiB
Python
import logging
|
|
import odoo.tests
|
|
import time
|
|
from odoo.addons.account.tests.common import TestAccountReconciliationCommon
|
|
from odoo import fields
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
@odoo.tests.tagged('post_install', '-at_install')
|
|
class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
|
|
def test_reconciliation_process_move_lines_with_mixed_currencies(self):
|
|
# Delete any old rate - to make sure that we use the ones we need.
|
|
old_rates = self.env['res.currency.rate'].search(
|
|
[('currency_id', '=', self.currency_usd_id)])
|
|
old_rates.unlink()
|
|
|
|
self.env['res.currency.rate'].create({
|
|
'currency_id': self.currency_usd_id,
|
|
'name': time.strftime('%Y') + '-01-01',
|
|
'rate': 2,
|
|
})
|
|
|
|
move_product = self.env['account.move'].create({
|
|
'ref': 'move product',
|
|
})
|
|
move_product_lines = self.env['account.move.line'].create([
|
|
{
|
|
'name': 'line product',
|
|
'move_id': move_product.id,
|
|
'account_id': self.env['account.account'].search([
|
|
('account_type', '=', 'income'),
|
|
('company_id', '=', self.company.id)
|
|
], limit=1).id,
|
|
'debit': 20,
|
|
'credit': 0,
|
|
},
|
|
{
|
|
'name': 'line receivable',
|
|
'move_id': move_product.id,
|
|
'account_id': self.account_rcv.id,
|
|
'debit': 0,
|
|
'credit': 20,
|
|
}
|
|
])
|
|
move_product.action_post()
|
|
|
|
move_payment = self.env['account.move'].create({
|
|
'ref': 'move payment',
|
|
})
|
|
liquidity_account = self.env['account.account'].search([
|
|
('account_type', '=', 'asset_cash'),
|
|
('company_id', '=', self.company.id)], limit=1)
|
|
move_payment_lines = self.env['account.move.line'].create([
|
|
{
|
|
'name': 'line product',
|
|
'move_id': move_payment.id,
|
|
'account_id': liquidity_account.id,
|
|
'debit': 10.0,
|
|
'credit': 0,
|
|
'amount_currency': 20,
|
|
'currency_id': self.currency_usd_id,
|
|
},
|
|
{
|
|
'name': 'line product',
|
|
'move_id': move_payment.id,
|
|
'account_id': self.account_rcv.id,
|
|
'debit': 0,
|
|
'credit': 10.0,
|
|
'amount_currency': -20,
|
|
'currency_id': self.currency_usd_id,
|
|
}
|
|
])
|
|
move_payment.action_post()
|
|
|
|
# We are reconciling a move line in currency A with a move line in currency B and putting
|
|
# the rest in a writeoff, this test ensure that the debit/credit value of the writeoff is
|
|
# correctly computed in company currency.
|
|
self.env['account.reconciliation.widget'].process_move_lines([{
|
|
'id': False,
|
|
'type': False,
|
|
'mv_line_ids': [move_payment_lines[1].id, move_product_lines[1].id],
|
|
'new_mv_line_dicts': [{
|
|
'account_id': liquidity_account.id,
|
|
'analytic_distribution': False,
|
|
'credit': 0,
|
|
'date': time.strftime('%Y') + '-01-01',
|
|
'debit': 15.0,
|
|
'journal_id': self.env['account.journal'].search([('type', '=', 'sale'), ('company_id', '=', self.company.id)], limit=1).id,
|
|
'name': 'writeoff',
|
|
}],
|
|
}])
|
|
|
|
writeoff_line = self.env['account.move.line'].search([('name', '=', 'writeoff'), ('company_id', '=', self.company.id)])
|
|
self.assertEqual(writeoff_line.credit, 15.0)
|
|
|
|
def test_writeoff_single_entry(self):
|
|
""" Test writeoff are grouped by journal and date in common journal entries"""
|
|
today = fields.Date.today().strftime('%Y-07-15')
|
|
invoice = self.env['account.move'].create({
|
|
'move_type': 'out_invoice',
|
|
'partner_id': self.partner_a.id,
|
|
'invoice_date': '2019-01-21',
|
|
'date': '2019-01-21',
|
|
'invoice_line_ids': [(0, 0, {
|
|
'product_id': self.product_a.id,
|
|
'price_unit': 1000.0,
|
|
'tax_ids': [(6, 0, self.tax_purchase_a.ids)],
|
|
})]
|
|
})
|
|
invoice.action_post()
|
|
|
|
payment = self.env['account.payment'].create({
|
|
'date': invoice.date,
|
|
'partner_id': self.partner_a.id,
|
|
'amount': 1161.5,
|
|
'payment_type': 'inbound',
|
|
'partner_type': 'customer',
|
|
})
|
|
payment.action_post()
|
|
|
|
# Create a write-off for the residual amount.
|
|
account = self.company_data['default_account_receivable']
|
|
lines = (invoice + payment.move_id).line_ids.filtered(lambda line: line.account_id == account)
|
|
|
|
self.env['account.reconciliation.widget'].process_move_lines([{
|
|
'type': 'other',
|
|
'mv_line_ids': lines.ids,
|
|
'new_mv_line_dicts': [
|
|
{
|
|
'name': 'TEST',
|
|
'journal_id': self.company_data['default_journal_misc'].id,
|
|
'account_id': self.company_data['default_account_revenue'].id,
|
|
'balance': 10,
|
|
'date': today,
|
|
'tax_ids': [(6, 0, self.tax_purchase_a.ids)],
|
|
},
|
|
{
|
|
'name': 'TEST TAX',
|
|
'journal_id': self.company_data['default_journal_misc'].id,
|
|
'account_id': self.company_data['default_account_tax_sale'].id,
|
|
'date': today,
|
|
'balance': 1.5,
|
|
'tax_base_amount': -10,
|
|
'tax_repartition_line_id': self.tax_purchase_a.invoice_repartition_line_ids.filtered('account_id').id
|
|
}
|
|
]}])
|
|
|
|
self.assertTrue(all(line.reconciled for line in lines))
|
|
|
|
write_off = lines.full_reconcile_id.reconciled_line_ids.move_id - lines.move_id
|
|
|
|
self.assertEqual(len(write_off), 1, "It should create only a single journal entry")
|
|
|
|
self.assertRecordValues(write_off.line_ids.sorted('balance'), [
|
|
{
|
|
'partner_id': self.partner_a.id,
|
|
'debit': 0.0,
|
|
'credit': 10,
|
|
},
|
|
{
|
|
'partner_id': self.partner_a.id,
|
|
'debit': 0.0,
|
|
'credit': 1.5,
|
|
},
|
|
{
|
|
'partner_id': self.partner_a.id,
|
|
'debit': 1.5,
|
|
'credit': 0.0,
|
|
},
|
|
{
|
|
'partner_id': self.partner_a.id,
|
|
'debit': 10,
|
|
'credit': 0.0,
|
|
},
|
|
])
|
|
|
|
def test_prepare_writeoff_moves_multi_currency(self):
|
|
for invoice_type, payment_type, partner_type in (
|
|
('out_invoice', 'inbound', 'customer'),
|
|
('in_invoice', 'outbound', 'supplier'),
|
|
):
|
|
# Create an invoice at rate 1:2.
|
|
invoice = self.env['account.move'].create({
|
|
'move_type': invoice_type,
|
|
'partner_id': self.partner_a.id,
|
|
'currency_id': self.currency_data['currency'].id,
|
|
'invoice_date': '2019-01-21',
|
|
'date': '2019-01-21',
|
|
'invoice_line_ids': [(0, 0, {
|
|
'product_id': self.product_a.id,
|
|
'price_unit': 1000.0,
|
|
'tax_ids': [],
|
|
})]
|
|
})
|
|
invoice.action_post()
|
|
|
|
# Create a payment at rate 1:2.
|
|
payment = self.env['account.payment'].create({
|
|
'date': invoice.date,
|
|
'partner_id': self.partner_a.id,
|
|
'amount': 800.0,
|
|
'currency_id': self.currency_data['currency'].id,
|
|
'payment_type': payment_type,
|
|
'partner_type': partner_type,
|
|
})
|
|
payment.action_post()
|
|
|
|
# Create a write-off for the residual amount.
|
|
account = invoice.line_ids\
|
|
.filtered(lambda line: line.account_id.account_type in ('asset_receivable', 'liability_payable')).account_id
|
|
lines = (invoice + payment.move_id).line_ids.filtered(lambda line: line.account_id.account_type in ('asset_receivable', 'liability_payable'))
|
|
write_off_vals = self.env['account.reconciliation.widget']._prepare_writeoff_moves(lines, {
|
|
'journal_id': self.company_data['default_journal_misc'].id,
|
|
'account_id': self.company_data['default_account_revenue'].id,
|
|
})
|
|
write_off = self.env['account.move'].create(write_off_vals)
|
|
write_off.action_post()
|
|
|
|
self.assertRecordValues(write_off.line_ids.sorted('balance'), [
|
|
{
|
|
'partner_id': self.partner_a.id,
|
|
'currency_id': self.currency_data['currency'].id,
|
|
'debit': 0.0,
|
|
'credit': 100.0,
|
|
'amount_currency': -200.0,
|
|
},
|
|
{
|
|
'partner_id': self.partner_a.id,
|
|
'currency_id': self.currency_data['currency'].id,
|
|
'debit': 100.0,
|
|
'credit': 0.0,
|
|
'amount_currency': 200.0,
|
|
},
|
|
])
|
|
|
|
# Reconcile.
|
|
all_lines = (invoice + payment.move_id + write_off).line_ids.filtered(lambda line: line.account_id == account)
|
|
all_lines.reconcile()
|
|
|
|
for line in all_lines:
|
|
self.assertTrue(line.reconciled)
|
|
|
|
def test_with_reconciliation_model(self):
|
|
bank_fees = self.env['account.reconcile.model'].create({
|
|
'name': 'Bank Fees',
|
|
'line_ids': [(0, 0, {
|
|
'account_id': self.company_data['default_account_expense'].id,
|
|
'journal_id': self.company_data['default_journal_misc'].id,
|
|
'amount_type': 'fixed',
|
|
'amount_string': '50',
|
|
})],
|
|
})
|
|
|
|
customer = self.partner_a
|
|
|
|
invoice = self.env['account.move'].create({
|
|
'move_type': 'out_invoice',
|
|
'partner_id': customer.id,
|
|
'invoice_date': '2021-05-12',
|
|
'date': '2021-05-12',
|
|
'invoice_line_ids': [(0, 0, {
|
|
'product_id': self.product_a.id,
|
|
'price_unit': 1000.0,
|
|
'tax_ids': [],
|
|
})],
|
|
})
|
|
invoice.action_post()
|
|
inv_receivable = invoice.line_ids.filtered(lambda l: l.account_id.account_type == 'asset_receivable')
|
|
|
|
payment = self.env['account.payment'].create({
|
|
'partner_id': customer.id,
|
|
'amount': 600,
|
|
})
|
|
payment.action_post()
|
|
payment_receivable = payment.line_ids.filtered(lambda l: l.account_id.account_type == 'asset_receivable')
|
|
|
|
self.env['account.reconciliation.widget'].process_move_lines([{
|
|
'id': None,
|
|
'type': None,
|
|
'mv_line_ids': (inv_receivable + payment_receivable).ids,
|
|
'new_mv_line_dicts': [{
|
|
'name': 'SuperLabel',
|
|
'balance': -bank_fees.line_ids.amount,
|
|
'analytic_distribution': False,
|
|
'account_id': bank_fees.line_ids.account_id.id,
|
|
'journal_id': bank_fees.line_ids.journal_id.id,
|
|
'reconcile_model_id': bank_fees.id}
|
|
]
|
|
}])
|
|
|
|
self.assertEqual(invoice.amount_residual, 350)
|