-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
TA#66819 [16.0][MIG] account_negative_debit_credit (#190)
* TA#66819 [16.0][MIG] account_negative_debit_credit --------- Co-authored-by: Majda EL MARIOULI <[email protected]>
- Loading branch information
1 parent
116bd8c
commit b424a09
Showing
10 changed files
with
259 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
===================== | ||
Negative Debit/Credit | ||
===================== | ||
In accounting, the following logic is often repeated: | ||
|
||
* If my invoice line is positive, put the amount in the debit column. | ||
* Otherwise, put the inverse amount in the credit column. | ||
|
||
The Problem | ||
----------- | ||
The problem with that logic is that it is repeated almost everywhere an accounting entry is created | ||
(invoicing, payments, expenses, payroll, etc.). | ||
|
||
When an exception is raised because of a comparison error, the message is very nonspeaking to the user | ||
and very hard to debug for the developper. | ||
|
||
The Solution | ||
------------ | ||
What the system could do instead is the following: | ||
|
||
* Put the amount in the debit column. | ||
|
||
Then, in a lower layer of code, the system would apply the following logic: | ||
|
||
* If the debit is negative, put the inverse amount in the credit column. | ||
* If the credit is negative, put the inverse amount in the credit column. | ||
|
||
This is what this module does. It replaces the debit/credit amounts in the appropriate column | ||
when creating accounting entries. | ||
|
||
Contributors | ||
------------ | ||
* Numigi (tm) and all its contributors (https://bit.ly/numigiens) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Copyright 2024-today Numigi and all its contributors (https://bit.ly/numigiens) | ||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). | ||
|
||
from . import models |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# Copyright 2024-today Numigi and all its contributors (https://bit.ly/numigiens) | ||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). | ||
|
||
{ | ||
"name": "Negative Debit/Credit", | ||
"version": "16.0.1.0.0", | ||
"author": "Numigi", | ||
"maintainer": "Numigi", | ||
"website": "https://www.numigi.com", | ||
"license": "LGPL-3", | ||
"category": "Accounting", | ||
"summary": "Allow writing negative amounts in debit/credit columns.", | ||
"depends": ["account"], | ||
"installable": True, | ||
"application": False, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Copyright 2024-today Numigi and all its contributors (https://bit.ly/numigiens) | ||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). | ||
|
||
from . import account_move_line |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# Copyright 2024-today Numigi and all its contributors (https://bit.ly/numigiens) | ||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). | ||
|
||
from odoo import api, models | ||
|
||
|
||
class AccountMoveLine(models.Model): | ||
|
||
_inherit = "account.move.line" | ||
|
||
@api.model_create_multi | ||
def create(self, vals_list): | ||
for vals in vals_list: | ||
_update_vals_debit_credit(vals) | ||
return super().create(vals_list) | ||
|
||
def write(self, vals): | ||
_update_vals_debit_credit(vals) | ||
return super().write(vals) | ||
|
||
|
||
def _update_vals_debit_credit(vals): | ||
"""Update debit and credit fields in a values dictionnary. | ||
If either the debit or the credit is negative, permutate the two fields. | ||
:param vals: a dictionnary of values | ||
""" | ||
if vals.get("debit", 0) < 0 or vals.get("credit", 0) < 0: | ||
vals["debit"], vals["credit"] = -vals.get("credit", 0), -vals.get("debit", 0) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Copyright 2024-today Numigi and all its contributors (https://bit.ly/numigiens) | ||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). | ||
|
||
from . import test_account_move_line |
166 changes: 166 additions & 0 deletions
166
account_negative_debit_credit/tests/test_account_move_line.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
# Copyright 2024-today Numigi and all its contributors (https://bit.ly/numigiens) | ||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). | ||
|
||
from datetime import datetime | ||
from odoo.tests import common | ||
|
||
|
||
class TestAccountMoveLine(common.SavepointCase): | ||
@classmethod | ||
def setUpClass(cls): | ||
super().setUpClass() | ||
cls.journal = cls.env["account.journal"].create( | ||
{ | ||
"company_id": cls.env.user.company_id.id, | ||
"code": "TEST", | ||
"name": "Test Journal", | ||
"type": "general", | ||
} | ||
) | ||
|
||
cls.expense = cls.env["account.account"].create( | ||
{ | ||
"account_type": "expense", | ||
"name": "Revenus", | ||
"code": "400001", | ||
} | ||
) | ||
|
||
cls.asset = cls.env["account.account"].create( | ||
{ | ||
"account_type": "asset_current", | ||
"name": "Assets", | ||
"code": "100001", | ||
} | ||
) | ||
|
||
def _get_expense_line(self, move): | ||
return move.line_ids.filtered(lambda l: l.account_id == self.expense) | ||
|
||
def _get_asset_line(self, move): | ||
return move.line_ids.filtered(lambda l: l.account_id == self.asset) | ||
|
||
def test_negative_debit(self): | ||
move = self._create_move( | ||
[ | ||
( | ||
0, | ||
0, | ||
{ | ||
"account_id": self.expense.id, | ||
"debit": -10, | ||
}, | ||
), | ||
( | ||
0, | ||
0, | ||
{ | ||
"account_id": self.asset.id, | ||
"debit": 10, | ||
}, | ||
), | ||
] | ||
) | ||
|
||
line = move.line_ids[0] | ||
assert line.debit == 0 | ||
assert line.credit == 10 | ||
|
||
def test_negative_credit(self): | ||
move = self._create_move( | ||
[ | ||
( | ||
0, | ||
0, | ||
{ | ||
"account_id": self.expense.id, | ||
"credit": 10, | ||
}, | ||
), | ||
( | ||
0, | ||
0, | ||
{ | ||
"account_id": self.asset.id, | ||
"credit": -10, | ||
}, | ||
), | ||
] | ||
) | ||
|
||
line = move.line_ids[1] | ||
assert line.debit == 10 | ||
assert line.credit == 0 | ||
|
||
def test_negative_debit_and_credit(self): | ||
move = self._create_move( | ||
[ | ||
( | ||
0, | ||
0, | ||
{ | ||
"account_id": self.expense.id, | ||
"credit": 10, | ||
}, | ||
), | ||
( | ||
0, | ||
0, | ||
{ | ||
"account_id": self.asset.id, | ||
"credit": -10, | ||
}, | ||
), | ||
] | ||
) | ||
|
||
expense_line = move.line_ids[0] | ||
assert expense_line.debit == 0 | ||
assert expense_line.credit == 10 | ||
|
||
asset_line = move.line_ids[1] | ||
assert asset_line.debit == 10 | ||
assert asset_line.credit == 0 | ||
|
||
def test_write(self): | ||
move = self._create_move( | ||
[ | ||
( | ||
0, | ||
0, | ||
{ | ||
"account_id": self.expense.id, | ||
"debit": 10, | ||
}, | ||
), | ||
( | ||
0, | ||
0, | ||
{ | ||
"account_id": self.asset.id, | ||
"credit": 10, | ||
}, | ||
), | ||
] | ||
) | ||
lines = move.line_ids.sorted() | ||
move.write( | ||
{ | ||
"line_ids": [ | ||
(1, lines[0].id, {"credit": -10}), | ||
(1, lines[1].id, {"debit": -10}), | ||
], | ||
} | ||
) | ||
|
||
assert move.line_ids[1].credit == 10 | ||
assert move.line_ids[0].debit == 10 | ||
|
||
def _create_move(self, line_vals): | ||
return self.env["account.move"].create( | ||
{ | ||
"journal_id": self.journal.id, | ||
"date": datetime.now(), | ||
"line_ids": line_vals, | ||
} | ||
) |