[IMP] account_netting: black, isort
This commit is contained in:
parent
331ad070d1
commit
3845e23d36
@ -3,19 +3,14 @@
|
|||||||
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
|
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
|
||||||
|
|
||||||
{
|
{
|
||||||
'name': 'Account netting',
|
"name": "Account netting",
|
||||||
'version': '12.0.1.0.0',
|
"version": "12.0.1.0.0",
|
||||||
'summary': 'Compensate AR/AP accounts from the same partner',
|
"summary": "Compensate AR/AP accounts from the same partner",
|
||||||
'category': 'Accounting & Finance',
|
"category": "Accounting & Finance",
|
||||||
'author': 'Tecnativa, '
|
"author": "Tecnativa, " "Odoo Community Association (OCA)",
|
||||||
'Odoo Community Association (OCA)',
|
"license": "AGPL-3",
|
||||||
'license': 'AGPL-3',
|
"website": "https://github.com/OCA/account-financial-tools/",
|
||||||
'website': 'https://github.com/OCA/account-financial-tools/',
|
"depends": ["account",],
|
||||||
'depends': [
|
"data": ["wizards/account_move_make_netting_view.xml",],
|
||||||
'account',
|
"installable": True,
|
||||||
],
|
|
||||||
'data': [
|
|
||||||
'wizards/account_move_make_netting_view.xml',
|
|
||||||
],
|
|
||||||
'installable': True,
|
|
||||||
}
|
}
|
||||||
|
@ -9,209 +9,288 @@ class TestAccountNetting(common.SavepointCase):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
super(TestAccountNetting, cls).setUpClass()
|
super(TestAccountNetting, cls).setUpClass()
|
||||||
cls.partner = cls.env['res.partner'].create({
|
cls.partner = cls.env["res.partner"].create(
|
||||||
'supplier': True,
|
{"supplier": True, "customer": True, "name": "Supplier/Customer",}
|
||||||
'customer': True,
|
)
|
||||||
'name': "Supplier/Customer",
|
cls.partner1 = cls.env["res.partner"].create(
|
||||||
})
|
{"supplier": True, "customer": True, "name": "Supplier/Customer 1",}
|
||||||
cls.partner1 = cls.env['res.partner'].create({
|
)
|
||||||
'supplier': True,
|
res_users_account_manager = cls.env.ref("account.group_account_manager")
|
||||||
'customer': True,
|
partner_manager = cls.env.ref("base.group_partner_manager")
|
||||||
'name': "Supplier/Customer 1",
|
cls.env.user.write(
|
||||||
})
|
{"groups_id": [(6, 0, [res_users_account_manager.id, partner_manager.id])],}
|
||||||
res_users_account_manager = cls.env.ref(
|
)
|
||||||
'account.group_account_manager')
|
|
||||||
partner_manager = cls.env.ref('base.group_partner_manager')
|
|
||||||
cls.env.user.write({
|
|
||||||
'groups_id': [
|
|
||||||
(6, 0, [res_users_account_manager.id, partner_manager.id])
|
|
||||||
],
|
|
||||||
})
|
|
||||||
# only adviser can create an account
|
# only adviser can create an account
|
||||||
cls.account_receivable = cls.env['account.account'].create({
|
cls.account_receivable = cls.env["account.account"].create(
|
||||||
'code': 'cust_acc',
|
{
|
||||||
'name': 'customer account',
|
"code": "cust_acc",
|
||||||
'user_type_id': cls.env.ref(
|
"name": "customer account",
|
||||||
'account.data_account_type_receivable').id,
|
"user_type_id": cls.env.ref("account.data_account_type_receivable").id,
|
||||||
'reconcile': True,
|
"reconcile": True,
|
||||||
})
|
}
|
||||||
cls.account_payable = cls.env['account.account'].create({
|
)
|
||||||
'code': 'supp_acc',
|
cls.account_payable = cls.env["account.account"].create(
|
||||||
'name': 'supplier account',
|
{
|
||||||
'user_type_id': cls.env.ref(
|
"code": "supp_acc",
|
||||||
'account.data_account_type_payable').id,
|
"name": "supplier account",
|
||||||
'reconcile': True,
|
"user_type_id": cls.env.ref("account.data_account_type_payable").id,
|
||||||
})
|
"reconcile": True,
|
||||||
cls.account_revenue = cls.env['account.account'].search([
|
}
|
||||||
('user_type_id', '=', cls.env.ref(
|
)
|
||||||
'account.data_account_type_revenue').id)
|
cls.account_revenue = cls.env["account.account"].search(
|
||||||
], limit=1)
|
[
|
||||||
cls.account_expense = cls.env['account.account'].search([
|
(
|
||||||
('user_type_id', '=', cls.env.ref(
|
"user_type_id",
|
||||||
'account.data_account_type_expenses').id)
|
"=",
|
||||||
], limit=1)
|
cls.env.ref("account.data_account_type_revenue").id,
|
||||||
cls.journal = cls.env['account.journal'].create({
|
)
|
||||||
'name': 'Test sale journal',
|
],
|
||||||
'type': 'sale',
|
limit=1,
|
||||||
'code': 'TEST',
|
)
|
||||||
})
|
cls.account_expense = cls.env["account.account"].search(
|
||||||
cls.expenses_journal = cls.env['account.journal'].create({
|
[
|
||||||
'name': 'Test expense journal',
|
(
|
||||||
'type': 'purchase',
|
"user_type_id",
|
||||||
'code': 'EXP',
|
"=",
|
||||||
})
|
cls.env.ref("account.data_account_type_expenses").id,
|
||||||
cls.miscellaneous_journal = cls.env['account.journal'].create({
|
)
|
||||||
'name': 'Miscellaneus journal',
|
],
|
||||||
'type': 'general',
|
limit=1,
|
||||||
'code': 'OTHER',
|
)
|
||||||
})
|
cls.journal = cls.env["account.journal"].create(
|
||||||
cls.customer_invoice = cls.env['account.invoice'].create({
|
{"name": "Test sale journal", "type": "sale", "code": "TEST",}
|
||||||
'journal_id': cls.journal.id,
|
)
|
||||||
'type': 'out_invoice',
|
cls.expenses_journal = cls.env["account.journal"].create(
|
||||||
'partner_id': cls.partner.id,
|
{"name": "Test expense journal", "type": "purchase", "code": "EXP",}
|
||||||
'account_id': cls.account_receivable.id,
|
)
|
||||||
'invoice_line_ids': [(0, 0, {
|
cls.miscellaneous_journal = cls.env["account.journal"].create(
|
||||||
'name': 'Test',
|
{"name": "Miscellaneus journal", "type": "general", "code": "OTHER",}
|
||||||
'price_unit': 100.0,
|
)
|
||||||
'account_id': cls.account_revenue.id,
|
cls.customer_invoice = cls.env["account.invoice"].create(
|
||||||
})],
|
{
|
||||||
})
|
"journal_id": cls.journal.id,
|
||||||
|
"type": "out_invoice",
|
||||||
|
"partner_id": cls.partner.id,
|
||||||
|
"account_id": cls.account_receivable.id,
|
||||||
|
"invoice_line_ids": [
|
||||||
|
(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
{
|
||||||
|
"name": "Test",
|
||||||
|
"price_unit": 100.0,
|
||||||
|
"account_id": cls.account_revenue.id,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
cls.customer_invoice.action_invoice_open()
|
cls.customer_invoice.action_invoice_open()
|
||||||
customer_move = cls.customer_invoice.move_id
|
customer_move = cls.customer_invoice.move_id
|
||||||
cls.move_line_1 = customer_move.line_ids.filtered(
|
cls.move_line_1 = customer_move.line_ids.filtered(
|
||||||
lambda x: x.account_id == cls.account_receivable)
|
lambda x: x.account_id == cls.account_receivable
|
||||||
cls.supplier_invoice = cls.env['account.invoice'].create({
|
)
|
||||||
'journal_id': cls.expenses_journal.id,
|
cls.supplier_invoice = cls.env["account.invoice"].create(
|
||||||
'type': 'in_invoice',
|
{
|
||||||
'partner_id': cls.partner.id,
|
"journal_id": cls.expenses_journal.id,
|
||||||
'account_id': cls.account_payable.id,
|
"type": "in_invoice",
|
||||||
'invoice_line_ids': [(0, 0, {
|
"partner_id": cls.partner.id,
|
||||||
'name': 'Test',
|
"account_id": cls.account_payable.id,
|
||||||
'price_unit': 1200.0,
|
"invoice_line_ids": [
|
||||||
'account_id': cls.account_expense.id,
|
(
|
||||||
})],
|
0,
|
||||||
})
|
0,
|
||||||
|
{
|
||||||
|
"name": "Test",
|
||||||
|
"price_unit": 1200.0,
|
||||||
|
"account_id": cls.account_expense.id,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
cls.supplier_invoice.action_invoice_open()
|
cls.supplier_invoice.action_invoice_open()
|
||||||
supplier_move = cls.supplier_invoice.move_id
|
supplier_move = cls.supplier_invoice.move_id
|
||||||
cls.move_line_2 = supplier_move.line_ids.filtered(
|
cls.move_line_2 = supplier_move.line_ids.filtered(
|
||||||
lambda x: x.account_id == cls.account_payable)
|
lambda x: x.account_id == cls.account_payable
|
||||||
|
)
|
||||||
cls.move_line_3 = supplier_move.line_ids.filtered(
|
cls.move_line_3 = supplier_move.line_ids.filtered(
|
||||||
lambda x: x.account_id == cls.account_expense)
|
lambda x: x.account_id == cls.account_expense
|
||||||
cls.supplier_invoice = cls.env['account.invoice'].create({
|
)
|
||||||
'journal_id': cls.expenses_journal.id,
|
cls.supplier_invoice = cls.env["account.invoice"].create(
|
||||||
'type': 'in_invoice',
|
{
|
||||||
'partner_id': cls.partner1.id,
|
"journal_id": cls.expenses_journal.id,
|
||||||
'account_id': cls.account_payable.id,
|
"type": "in_invoice",
|
||||||
'invoice_line_ids': [(0, 0, {
|
"partner_id": cls.partner1.id,
|
||||||
'name': 'Test',
|
"account_id": cls.account_payable.id,
|
||||||
'price_unit': 200.0,
|
"invoice_line_ids": [
|
||||||
'account_id': cls.account_expense.id,
|
(
|
||||||
})],
|
0,
|
||||||
})
|
0,
|
||||||
|
{
|
||||||
|
"name": "Test",
|
||||||
|
"price_unit": 200.0,
|
||||||
|
"account_id": cls.account_expense.id,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
cls.supplier_invoice.action_invoice_open()
|
cls.supplier_invoice.action_invoice_open()
|
||||||
supplier_move = cls.supplier_invoice.move_id
|
supplier_move = cls.supplier_invoice.move_id
|
||||||
cls.move_line_4 = supplier_move.line_ids.filtered(
|
cls.move_line_4 = supplier_move.line_ids.filtered(
|
||||||
lambda x: x.account_id == cls.account_payable)
|
lambda x: x.account_id == cls.account_payable
|
||||||
cls.supplier_invoice = cls.env['account.invoice'].create({
|
)
|
||||||
'journal_id': cls.expenses_journal.id,
|
cls.supplier_invoice = cls.env["account.invoice"].create(
|
||||||
'type': 'in_refund',
|
{
|
||||||
'partner_id': cls.partner1.id,
|
"journal_id": cls.expenses_journal.id,
|
||||||
'account_id': cls.account_payable.id,
|
"type": "in_refund",
|
||||||
'invoice_line_ids': [(0, 0, {
|
"partner_id": cls.partner1.id,
|
||||||
'name': 'Test',
|
"account_id": cls.account_payable.id,
|
||||||
'price_unit': 200.0,
|
"invoice_line_ids": [
|
||||||
'account_id': cls.account_expense.id,
|
(
|
||||||
})],
|
0,
|
||||||
})
|
0,
|
||||||
|
{
|
||||||
|
"name": "Test",
|
||||||
|
"price_unit": 200.0,
|
||||||
|
"account_id": cls.account_expense.id,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
cls.supplier_invoice.action_invoice_open()
|
cls.supplier_invoice.action_invoice_open()
|
||||||
supplier_move = cls.supplier_invoice.move_id
|
supplier_move = cls.supplier_invoice.move_id
|
||||||
cls.move_line_5 = supplier_move.line_ids.filtered(
|
cls.move_line_5 = supplier_move.line_ids.filtered(
|
||||||
lambda x: x.account_id == cls.account_payable)
|
lambda x: x.account_id == cls.account_payable
|
||||||
cls.supplier_invoice = cls.env['account.invoice'].create({
|
)
|
||||||
'journal_id': cls.expenses_journal.id,
|
cls.supplier_invoice = cls.env["account.invoice"].create(
|
||||||
'type': 'in_refund',
|
{
|
||||||
'partner_id': cls.partner1.id,
|
"journal_id": cls.expenses_journal.id,
|
||||||
'account_id': cls.account_payable.id,
|
"type": "in_refund",
|
||||||
'invoice_line_ids': [(0, 0, {
|
"partner_id": cls.partner1.id,
|
||||||
'name': 'Test',
|
"account_id": cls.account_payable.id,
|
||||||
'price_unit': 200.0,
|
"invoice_line_ids": [
|
||||||
'account_id': cls.account_expense.id,
|
(
|
||||||
})],
|
0,
|
||||||
})
|
0,
|
||||||
|
{
|
||||||
|
"name": "Test",
|
||||||
|
"price_unit": 200.0,
|
||||||
|
"account_id": cls.account_expense.id,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
cls.supplier_invoice.action_invoice_open()
|
cls.supplier_invoice.action_invoice_open()
|
||||||
supplier_move = cls.supplier_invoice.move_id
|
supplier_move = cls.supplier_invoice.move_id
|
||||||
cls.move_line_6 = supplier_move.line_ids.filtered(
|
cls.move_line_6 = supplier_move.line_ids.filtered(
|
||||||
lambda x: x.account_id == cls.account_payable)
|
lambda x: x.account_id == cls.account_payable
|
||||||
|
)
|
||||||
|
|
||||||
def test_compensation(self):
|
def test_compensation(self):
|
||||||
# Test exception line 33 from account_move_make_netting
|
# Test exception line 33 from account_move_make_netting
|
||||||
obj = self.env['account.move.make.netting'].with_context(
|
obj = self.env["account.move.make.netting"].with_context(
|
||||||
active_ids=[self.move_line_1.id])
|
active_ids=[self.move_line_1.id]
|
||||||
|
)
|
||||||
with self.assertRaises(Exception):
|
with self.assertRaises(Exception):
|
||||||
wizard = obj.create(
|
wizard = obj.create(
|
||||||
{'move_line_ids': [(6, 0, [self.move_line_1.id])],
|
{
|
||||||
'journal_id': self.miscellaneous_journal.id})
|
"move_line_ids": [(6, 0, [self.move_line_1.id])],
|
||||||
|
"journal_id": self.miscellaneous_journal.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
# Test exception line 39 from account_move_make_netting
|
# Test exception line 39 from account_move_make_netting
|
||||||
obj = self.env['account.move.make.netting'].with_context(
|
obj = self.env["account.move.make.netting"].with_context(
|
||||||
active_ids=[self.move_line_1.id, self.move_line_3.id])
|
active_ids=[self.move_line_1.id, self.move_line_3.id]
|
||||||
|
)
|
||||||
with self.assertRaises(Exception):
|
with self.assertRaises(Exception):
|
||||||
wizard = obj.create(
|
wizard = obj.create(
|
||||||
{'move_line_ids': [(6, 0, [self.move_line_1.id,
|
{
|
||||||
self.move_line_3.id])],
|
"move_line_ids": [
|
||||||
'journal_id': self.miscellaneous_journal.id})
|
(6, 0, [self.move_line_1.id, self.move_line_3.id])
|
||||||
|
],
|
||||||
|
"journal_id": self.miscellaneous_journal.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
# Test exception line 45 from account_move_make_netting
|
# Test exception line 45 from account_move_make_netting
|
||||||
obj = self.env['account.move.make.netting'].with_context(
|
obj = self.env["account.move.make.netting"].with_context(
|
||||||
active_ids=[self.move_line_4.id, self.move_line_5.id])
|
active_ids=[self.move_line_4.id, self.move_line_5.id]
|
||||||
|
)
|
||||||
with self.assertRaises(Exception):
|
with self.assertRaises(Exception):
|
||||||
wizard = obj.create(
|
wizard = obj.create(
|
||||||
{'move_line_ids': [(6, 0, [self.move_line_4.id,
|
{
|
||||||
self.move_line_5.id])],
|
"move_line_ids": [
|
||||||
'journal_id': self.miscellaneous_journal.id})
|
(6, 0, [self.move_line_4.id, self.move_line_5.id])
|
||||||
|
],
|
||||||
|
"journal_id": self.miscellaneous_journal.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
# Test exception line 42 from account_move_make_netting
|
# Test exception line 42 from account_move_make_netting
|
||||||
moves = self.env['account.move.line'].browse([self.move_line_4.id,
|
moves = self.env["account.move.line"].browse(
|
||||||
self.move_line_5.id])
|
[self.move_line_4.id, self.move_line_5.id]
|
||||||
|
)
|
||||||
moves.reconcile()
|
moves.reconcile()
|
||||||
obj = self.env['account.move.make.netting'].with_context(
|
obj = self.env["account.move.make.netting"].with_context(
|
||||||
active_ids=[self.move_line_4.id, self.move_line_5.id])
|
active_ids=[self.move_line_4.id, self.move_line_5.id]
|
||||||
|
)
|
||||||
with self.assertRaises(Exception):
|
with self.assertRaises(Exception):
|
||||||
wizard = obj.create(
|
wizard = obj.create(
|
||||||
{'move_line_ids': [(6, 0, [self.move_line_4.id,
|
{
|
||||||
self.move_line_5.id])],
|
"move_line_ids": [
|
||||||
'journal_id': self.miscellaneous_journal.id})
|
(6, 0, [self.move_line_4.id, self.move_line_5.id])
|
||||||
|
],
|
||||||
|
"journal_id": self.miscellaneous_journal.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
# Test exception line 52 from account_move_make_netting
|
# Test exception line 52 from account_move_make_netting
|
||||||
obj = self.env['account.move.make.netting'].with_context(
|
obj = self.env["account.move.make.netting"].with_context(
|
||||||
active_ids=[self.move_line_1.id, self.move_line_6.id])
|
active_ids=[self.move_line_1.id, self.move_line_6.id]
|
||||||
|
)
|
||||||
with self.assertRaises(Exception):
|
with self.assertRaises(Exception):
|
||||||
wizard = obj.create(
|
wizard = obj.create(
|
||||||
{'move_line_ids': [(6, 0, [self.move_line_1.id,
|
{
|
||||||
self.move_line_6.id])],
|
"move_line_ids": [
|
||||||
'journal_id': self.miscellaneous_journal.id})
|
(6, 0, [self.move_line_1.id, self.move_line_6.id])
|
||||||
obj = self.env['account.move.make.netting'].with_context(
|
],
|
||||||
active_ids=[self.move_line_1.id, self.move_line_2.id])
|
"journal_id": self.miscellaneous_journal.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
obj = self.env["account.move.make.netting"].with_context(
|
||||||
|
active_ids=[self.move_line_1.id, self.move_line_2.id]
|
||||||
|
)
|
||||||
wizard = obj.create(
|
wizard = obj.create(
|
||||||
{'move_line_ids': [(6, 0, [self.move_line_1.id,
|
{
|
||||||
self.move_line_2.id])],
|
"move_line_ids": [(6, 0, [self.move_line_1.id, self.move_line_2.id])],
|
||||||
'journal_id': self.miscellaneous_journal.id})
|
"journal_id": self.miscellaneous_journal.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
res = wizard.button_compensate()
|
res = wizard.button_compensate()
|
||||||
move = self.env['account.move'].browse(res['res_id'])
|
move = self.env["account.move"].browse(res["res_id"])
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
len(move.line_ids), 2,
|
len(move.line_ids), 2, "AR/AP netting move has an incorrect line number"
|
||||||
'AR/AP netting move has an incorrect line number')
|
)
|
||||||
move_line_receivable = move.line_ids.filtered(
|
move_line_receivable = move.line_ids.filtered(
|
||||||
lambda x: x.account_id == self.account_receivable)
|
lambda x: x.account_id == self.account_receivable
|
||||||
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
move_line_receivable.credit, 100,
|
move_line_receivable.credit,
|
||||||
'Incorrect credit amount for receivable move line')
|
100,
|
||||||
|
"Incorrect credit amount for receivable move line",
|
||||||
|
)
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
move_line_receivable.reconciled and
|
move_line_receivable.reconciled and move_line_receivable.full_reconcile_id,
|
||||||
move_line_receivable.full_reconcile_id,
|
"Receivable move line should be totally reconciled",
|
||||||
'Receivable move line should be totally reconciled')
|
)
|
||||||
move_line_payable = move.line_ids.filtered(
|
move_line_payable = move.line_ids.filtered(
|
||||||
lambda x: x.account_id == self.account_payable)
|
lambda x: x.account_id == self.account_payable
|
||||||
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
move_line_payable.debit, 100,
|
move_line_payable.debit, 100, "Incorrect debit amount for payable move line"
|
||||||
'Incorrect debit amount for payable move line')
|
)
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
move_line_payable.reconciled and not
|
move_line_payable.reconciled and not move_line_payable.full_reconcile_id,
|
||||||
move_line_payable.full_reconcile_id,
|
"Receivable move line should be partially reconciled",
|
||||||
'Receivable move line should be partially reconciled')
|
)
|
||||||
|
@ -7,83 +7,85 @@ from odoo import _, api, exceptions, fields, models
|
|||||||
|
|
||||||
class AccountMoveMakeNetting(models.TransientModel):
|
class AccountMoveMakeNetting(models.TransientModel):
|
||||||
_name = "account.move.make.netting"
|
_name = "account.move.make.netting"
|
||||||
_description = 'Wizard to generate account moves for netting'
|
_description = "Wizard to generate account moves for netting"
|
||||||
|
|
||||||
journal_id = fields.Many2one(
|
journal_id = fields.Many2one(
|
||||||
comodel_name="account.journal",
|
comodel_name="account.journal",
|
||||||
required=True,
|
required=True,
|
||||||
domain="[('type', '=', 'general')]",
|
domain="[('type', '=', 'general')]",
|
||||||
)
|
)
|
||||||
move_line_ids = fields.Many2many(
|
move_line_ids = fields.Many2many(comodel_name="account.move.line",)
|
||||||
comodel_name="account.move.line",
|
balance = fields.Float(readonly=True,)
|
||||||
)
|
|
||||||
balance = fields.Float(
|
|
||||||
readonly=True,
|
|
||||||
)
|
|
||||||
balance_type = fields.Selection(
|
balance_type = fields.Selection(
|
||||||
selection=[
|
selection=[("pay", "To pay"), ("receive", "To receive"),], readonly=True,
|
||||||
('pay', 'To pay'),
|
|
||||||
('receive', 'To receive'),
|
|
||||||
],
|
|
||||||
readonly=True,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def default_get(self, fields_list):
|
def default_get(self, fields_list):
|
||||||
if len(self.env.context.get('active_ids', [])) < 2:
|
if len(self.env.context.get("active_ids", [])) < 2:
|
||||||
raise exceptions.ValidationError(
|
raise exceptions.ValidationError(
|
||||||
_("You should compensate at least 2 journal entries."))
|
_("You should compensate at least 2 journal entries.")
|
||||||
move_lines = self.env['account.move.line'].browse(
|
)
|
||||||
self.env.context['active_ids'])
|
move_lines = self.env["account.move.line"].browse(
|
||||||
if (any(x not in ('payable', 'receivable') for
|
self.env.context["active_ids"]
|
||||||
x in move_lines.mapped('account_id.user_type_id.type'))):
|
)
|
||||||
|
if any(
|
||||||
|
x not in ("payable", "receivable")
|
||||||
|
for x in move_lines.mapped("account_id.user_type_id.type")
|
||||||
|
):
|
||||||
raise exceptions.ValidationError(
|
raise exceptions.ValidationError(
|
||||||
_("All entries must have a receivable or payable account"))
|
_("All entries must have a receivable or payable account")
|
||||||
if any(move_lines.mapped('reconciled')):
|
)
|
||||||
|
if any(move_lines.mapped("reconciled")):
|
||||||
|
raise exceptions.ValidationError(_("All entries mustn't been reconciled"))
|
||||||
|
if len(move_lines.mapped("account_id")) == 1:
|
||||||
raise exceptions.ValidationError(
|
raise exceptions.ValidationError(
|
||||||
_("All entries mustn't been reconciled"))
|
_(
|
||||||
if len(move_lines.mapped('account_id')) == 1:
|
"The 'Compensate' function is intended to balance "
|
||||||
|
"operations on different accounts for the same partner.\n"
|
||||||
|
"In this case all selected entries belong to the same "
|
||||||
|
"account.\n Please use the 'Reconcile' function."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if len(move_lines.mapped("partner_id")) != 1:
|
||||||
raise exceptions.ValidationError(
|
raise exceptions.ValidationError(
|
||||||
_("The 'Compensate' function is intended to balance "
|
_(
|
||||||
"operations on different accounts for the same partner.\n"
|
"All entries should have a partner and the partner must "
|
||||||
"In this case all selected entries belong to the same "
|
"be the same for all."
|
||||||
"account.\n Please use the 'Reconcile' function."))
|
)
|
||||||
if len(move_lines.mapped('partner_id')) != 1:
|
)
|
||||||
raise exceptions.ValidationError(
|
|
||||||
_("All entries should have a partner and the partner must "
|
|
||||||
"be the same for all."))
|
|
||||||
res = super(AccountMoveMakeNetting, self).default_get(fields_list)
|
res = super(AccountMoveMakeNetting, self).default_get(fields_list)
|
||||||
res['move_line_ids'] = [(6, 0, move_lines.ids)]
|
res["move_line_ids"] = [(6, 0, move_lines.ids)]
|
||||||
debit_move_lines_debit = move_lines.filtered('debit')
|
debit_move_lines_debit = move_lines.filtered("debit")
|
||||||
credit_move_lines_debit = move_lines.filtered('credit')
|
credit_move_lines_debit = move_lines.filtered("credit")
|
||||||
balance = (abs(sum(debit_move_lines_debit.mapped('amount_residual'))) -
|
balance = abs(sum(debit_move_lines_debit.mapped("amount_residual"))) - abs(
|
||||||
abs(sum(credit_move_lines_debit.mapped('amount_residual'))))
|
sum(credit_move_lines_debit.mapped("amount_residual"))
|
||||||
res['balance'] = abs(balance)
|
)
|
||||||
res['balance_type'] = 'pay' if balance < 0 else 'receive'
|
res["balance"] = abs(balance)
|
||||||
|
res["balance_type"] = "pay" if balance < 0 else "receive"
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def button_compensate(self):
|
def button_compensate(self):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
# Create account move
|
# Create account move
|
||||||
move = self.env['account.move'].create({
|
move = self.env["account.move"].create(
|
||||||
'ref': _('AR/AP netting'),
|
{"ref": _("AR/AP netting"), "journal_id": self.journal_id.id,}
|
||||||
'journal_id': self.journal_id.id,
|
)
|
||||||
})
|
|
||||||
# Group amounts by account
|
# Group amounts by account
|
||||||
account_groups = self.move_line_ids.read_group(
|
account_groups = self.move_line_ids.read_group(
|
||||||
[('id', 'in', self.move_line_ids.ids)],
|
[("id", "in", self.move_line_ids.ids)],
|
||||||
['account_id', 'amount_residual'],
|
["account_id", "amount_residual"],
|
||||||
['account_id'],
|
["account_id"],
|
||||||
)
|
)
|
||||||
debtors = []
|
debtors = []
|
||||||
creditors = []
|
creditors = []
|
||||||
total_debtors = 0
|
total_debtors = 0
|
||||||
total_creditors = 0
|
total_creditors = 0
|
||||||
for account_group in account_groups:
|
for account_group in account_groups:
|
||||||
balance = account_group['amount_residual']
|
balance = account_group["amount_residual"]
|
||||||
group_vals = {
|
group_vals = {
|
||||||
'account_id': account_group['account_id'][0],
|
"account_id": account_group["account_id"][0],
|
||||||
'balance': abs(balance),
|
"balance": abs(balance),
|
||||||
}
|
}
|
||||||
if balance > 0:
|
if balance > 0:
|
||||||
debtors.append(group_vals)
|
debtors.append(group_vals)
|
||||||
@ -93,36 +95,37 @@ class AccountMoveMakeNetting(models.TransientModel):
|
|||||||
total_creditors += abs(balance)
|
total_creditors += abs(balance)
|
||||||
# Create move lines
|
# Create move lines
|
||||||
netting_amount = min(total_creditors, total_debtors)
|
netting_amount = min(total_creditors, total_debtors)
|
||||||
field_map = {1: 'debit', 0: 'credit'}
|
field_map = {1: "debit", 0: "credit"}
|
||||||
move_lines = []
|
move_lines = []
|
||||||
for i, group in enumerate([debtors, creditors]):
|
for i, group in enumerate([debtors, creditors]):
|
||||||
available_amount = netting_amount
|
available_amount = netting_amount
|
||||||
for account_group in group:
|
for account_group in group:
|
||||||
if account_group['balance'] > available_amount:
|
if account_group["balance"] > available_amount:
|
||||||
amount = available_amount
|
amount = available_amount
|
||||||
else:
|
else:
|
||||||
amount = account_group['balance']
|
amount = account_group["balance"]
|
||||||
move_line_vals = {
|
move_line_vals = {
|
||||||
field_map[i]: amount,
|
field_map[i]: amount,
|
||||||
'partner_id': self.move_line_ids[0].partner_id.id,
|
"partner_id": self.move_line_ids[0].partner_id.id,
|
||||||
'name': move.ref,
|
"name": move.ref,
|
||||||
'account_id': account_group['account_id'],
|
"account_id": account_group["account_id"],
|
||||||
}
|
}
|
||||||
move_lines.append((0, 0, move_line_vals))
|
move_lines.append((0, 0, move_line_vals))
|
||||||
available_amount -= account_group['balance']
|
available_amount -= account_group["balance"]
|
||||||
if available_amount <= 0:
|
if available_amount <= 0:
|
||||||
break
|
break
|
||||||
if move_lines:
|
if move_lines:
|
||||||
move.write({'line_ids': move_lines})
|
move.write({"line_ids": move_lines})
|
||||||
# Make reconciliation
|
# Make reconciliation
|
||||||
for move_line in move.line_ids:
|
for move_line in move.line_ids:
|
||||||
to_reconcile = move_line + self.move_line_ids.filtered(
|
to_reconcile = move_line + self.move_line_ids.filtered(
|
||||||
lambda x: x.account_id == move_line.account_id)
|
lambda x: x.account_id == move_line.account_id
|
||||||
|
)
|
||||||
to_reconcile.reconcile()
|
to_reconcile.reconcile()
|
||||||
# Open created move
|
# Open created move
|
||||||
action = self.env.ref('account.action_move_journal_line').read()[0]
|
action = self.env.ref("account.action_move_journal_line").read()[0]
|
||||||
action['view_mode'] = 'form'
|
action["view_mode"] = "form"
|
||||||
del action['views']
|
del action["views"]
|
||||||
del action['view_id']
|
del action["view_id"]
|
||||||
action['res_id'] = move.id
|
action["res_id"] = move.id
|
||||||
return action
|
return action
|
||||||
|
@ -1,33 +1,38 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
|
<act_window
|
||||||
<act_window name="Compensate"
|
name="Compensate"
|
||||||
res_model="account.move.make.netting"
|
res_model="account.move.make.netting"
|
||||||
src_model="account.move.line"
|
src_model="account.move.line"
|
||||||
view_mode="form"
|
view_mode="form"
|
||||||
target="new"
|
target="new"
|
||||||
key2="client_action_multi"
|
key2="client_action_multi"
|
||||||
multi="True"
|
multi="True"
|
||||||
id="act_account_move_make_netting"/>
|
id="act_account_move_make_netting"
|
||||||
|
/>
|
||||||
<record id="view_account_move_make_netting_form" model="ir.ui.view">
|
<record id="view_account_move_make_netting_form" model="ir.ui.view">
|
||||||
<field name="name">Compensate entries</field>
|
<field name="name">Compensate entries</field>
|
||||||
<field name="model">account.move.make.netting</field>
|
<field name="model">account.move.make.netting</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="Compensate entries">
|
<form string="Compensate entries">
|
||||||
<p>This operation will generate account entries that are counterpart of the receivable/payable accounts selected, and reconcile each other, letting this balance in the partner.</p>
|
<p
|
||||||
|
>This operation will generate account entries that are counterpart of the receivable/payable accounts selected, and reconcile each other, letting this balance in the partner.</p>
|
||||||
<group>
|
<group>
|
||||||
<field name="balance"/>
|
<field name="balance" />
|
||||||
<field name="balance_type"/>
|
<field name="balance_type" />
|
||||||
<field name="journal_id"/>
|
<field name="journal_id" />
|
||||||
</group>
|
</group>
|
||||||
<footer>
|
<footer>
|
||||||
<button name="button_compensate" string="Compensate" type="object" default_focus="1" class="btn-primary"/>
|
<button
|
||||||
|
name="button_compensate"
|
||||||
|
string="Compensate"
|
||||||
|
type="object"
|
||||||
|
default_focus="1"
|
||||||
|
class="btn-primary"
|
||||||
|
/>
|
||||||
<button string="Cancel" class="btn-default" special="cancel" />
|
<button string="Cancel" class="btn-default" special="cancel" />
|
||||||
</footer>
|
</footer>
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
Loading…
Reference in New Issue
Block a user