diff --git a/hr_expense_advance_clearing/README.rst b/hr_expense_advance_clearing/README.rst index b22dbcbda..4e1a2f92a 100644 --- a/hr_expense_advance_clearing/README.rst +++ b/hr_expense_advance_clearing/README.rst @@ -1,7 +1,3 @@ -.. image:: https://odoo-community.org/readme-banner-image - :target: https://odoo-community.org/get-involved?utm_source=readme - :alt: Odoo Community Association - ============================= Employee Advance and Clearing ============================= @@ -17,7 +13,7 @@ Employee Advance and Clearing .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png :target: https://odoo-community.org/page/development-status :alt: Beta -.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fhr--expense-lightgray.png?logo=github @@ -71,6 +67,19 @@ Note: - Employee Advance account code, if not already exists, you can create one. Use type = Current Asset and check Allow Reconciliation. +**Clearing Journal** + +Clearing entries are posted as journal entries (move_type 'entry'), +which only allow Miscellaneous (general) journals. By default Odoo picks +the first general journal it finds. To control it: + +1. Go to Settings > Expenses > Accounting. +2. Set the "Default Clearing Journal" to the Miscellaneous journal that + should receive the clearing entries. + +The clearing journal can also be set per clearing report on the report's +"Clearing Journal" field, which defaults to the company setting above. + Usage ===== @@ -175,10 +184,13 @@ promote its widespread use. .. |maintainer-kittiu| image:: https://github.com/kittiu.png?size=40px :target: https://github.com/kittiu :alt: kittiu +.. |maintainer-Saran440| image:: https://github.com/Saran440.png?size=40px + :target: https://github.com/Saran440 + :alt: Saran440 -Current `maintainer `__: +Current `maintainers `__: -|maintainer-kittiu| +|maintainer-kittiu| |maintainer-Saran440| This module is part of the `OCA/hr-expense `_ project on GitHub. diff --git a/hr_expense_advance_clearing/__manifest__.py b/hr_expense_advance_clearing/__manifest__.py index d3921dc66..36f5a5858 100644 --- a/hr_expense_advance_clearing/__manifest__.py +++ b/hr_expense_advance_clearing/__manifest__.py @@ -11,11 +11,12 @@ "depends": ["hr_expense"], "data": [ "data/advance_product.xml", + "views/res_config_settings_views.xml", "views/account_payment_view.xml", "views/hr_expense_views.xml", "views/hr_employee_views.xml", "views/hr_employee_public_views.xml", ], "installable": True, - "maintainers": ["kittiu"], + "maintainers": ["kittiu", "Saran440"], } diff --git a/hr_expense_advance_clearing/models/__init__.py b/hr_expense_advance_clearing/models/__init__.py index 581c2d85d..5d5c8a3cd 100644 --- a/hr_expense_advance_clearing/models/__init__.py +++ b/hr_expense_advance_clearing/models/__init__.py @@ -5,3 +5,5 @@ from . import hr_employee_base from . import account_move from . import account_payment +from . import res_company +from . import res_config_settings diff --git a/hr_expense_advance_clearing/models/hr_expense_sheet.py b/hr_expense_advance_clearing/models/hr_expense_sheet.py index ca40a5d82..29ba85550 100644 --- a/hr_expense_advance_clearing/models/hr_expense_sheet.py +++ b/hr_expense_advance_clearing/models/hr_expense_sheet.py @@ -56,6 +56,21 @@ class HrExpenseSheet(models.Model): compute="_compute_amount_payable", help="Final regiter payment amount even after advance clearing", ) + clearing_journal_id = fields.Many2one( + comodel_name="account.journal", + string="Clearing Journal", + check_company=True, + domain="[('type', '=', 'general')]", + compute="_compute_clearing_journal_id", + store=True, + readonly=False, + help="Miscellaneous journal used to post the clearing journal entry.", + ) + + @api.depends("company_id", "advance_sheet_id") + def _compute_clearing_journal_id(self): + for sheet in self: + sheet.clearing_journal_id = sheet.company_id.clearing_journal_id @api.constrains("advance_sheet_id", "expense_line_ids") def _check_advance_expense(self): @@ -250,6 +265,7 @@ def _prepare_bills_vals(self): res.update( { "move_type": "entry", + "journal_id": self.clearing_journal_id.id, "line_ids": [ Command.create(vals) for vals in self._get_move_line_vals() ], diff --git a/hr_expense_advance_clearing/models/res_company.py b/hr_expense_advance_clearing/models/res_company.py new file mode 100644 index 000000000..bd140fdbc --- /dev/null +++ b/hr_expense_advance_clearing/models/res_company.py @@ -0,0 +1,17 @@ +# Copyright 2026 Ecosoft Co., Ltd. (https://ecosoft.co.th) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + + +class ResCompany(models.Model): + _inherit = "res.company" + + clearing_journal_id = fields.Many2one( + comodel_name="account.journal", + string="Default Clearing Journal", + check_company=True, + domain="[('type', '=', 'general')]", + help="Default Miscellaneous journal used when posting the advance " + "clearing journal entry.", + ) diff --git a/hr_expense_advance_clearing/models/res_config_settings.py b/hr_expense_advance_clearing/models/res_config_settings.py new file mode 100644 index 000000000..83ab910e9 --- /dev/null +++ b/hr_expense_advance_clearing/models/res_config_settings.py @@ -0,0 +1,16 @@ +# Copyright 2026 Ecosoft Co., Ltd. (https://ecosoft.co.th) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + _inherit = "res.config.settings" + + clearing_journal_id = fields.Many2one( + comodel_name="account.journal", + related="company_id.clearing_journal_id", + check_company=True, + domain="[('type', '=', 'general')]", + readonly=False, + ) diff --git a/hr_expense_advance_clearing/readme/CONFIGURE.md b/hr_expense_advance_clearing/readme/CONFIGURE.md index b24c274eb..9f5a5722e 100644 --- a/hr_expense_advance_clearing/readme/CONFIGURE.md +++ b/hr_expense_advance_clearing/readme/CONFIGURE.md @@ -12,3 +12,17 @@ Note: data - Employee Advance account code, if not already exists, you can create one. Use type = Current Asset and check Allow Reconciliation. + +**Clearing Journal** + +Clearing entries are posted as journal entries (move_type 'entry'), which +only allow Miscellaneous (general) journals. By default Odoo picks the +first general journal it finds. To control it: + +1. Go to Settings \> Expenses \> Accounting. +2. Set the "Default Clearing Journal" to the Miscellaneous journal that + should receive the clearing entries. + +The clearing journal can also be set per clearing report on the report's +"Clearing Journal" field, which defaults to the company setting above. + diff --git a/hr_expense_advance_clearing/static/description/index.html b/hr_expense_advance_clearing/static/description/index.html index d6ff189aa..edac5d9c1 100644 --- a/hr_expense_advance_clearing/static/description/index.html +++ b/hr_expense_advance_clearing/static/description/index.html @@ -3,7 +3,7 @@ -README.rst +Employee Advance and Clearing -
+
+

Employee Advance and Clearing

- - -Odoo Community Association - -
-

Employee Advance and Clearing

-

Beta License: AGPL-3 OCA/hr-expense Translate me on Weblate Try me on Runboat

+

Beta License: AGPL-3 OCA/hr-expense Translate me on Weblate Try me on Runboat

Standard Expenses module allow employee to do the expense reimbursement only after the expense has been made. In other world, employee will need to pay first and reimburse later.

@@ -404,7 +399,7 @@

Employee Advance and Clearing

-

Configuration

+

Configuration

This module will create a new product “Employee Advance” automatically. You will need to setup the Expense Account of this product to your Employee Advance account manually.

@@ -420,9 +415,20 @@

Configuration

  • Employee Advance account code, if not already exists, you can create one. Use type = Current Asset and check Allow Reconciliation.
  • +

    Clearing Journal

    +

    Clearing entries are posted as journal entries (move_type ‘entry’), +which only allow Miscellaneous (general) journals. By default Odoo picks +the first general journal it finds. To control it:

    +
      +
    1. Go to Settings > Expenses > Accounting.
    2. +
    3. Set the “Default Clearing Journal” to the Miscellaneous journal that +should receive the clearing entries.
    4. +
    +

    The clearing journal can also be set per clearing report on the report’s +“Clearing Journal” field, which defaults to the company setting above.

    -

    Usage

    +

    Usage

    To use this module, you must configure product “Employee Advance” with account type = Current Asset and check Allow Reconciliation. After that, you can step following:

    @@ -484,7 +490,7 @@

    Usage

    -

    Bug Tracker

    +

    Bug Tracker

    Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed @@ -492,15 +498,15 @@

    Bug Tracker

    Do not contact contributors directly about support or help with technical issues.

    -

    Credits

    +

    Credits

    -

    Authors

    +

    Authors

    • Ecosoft
    -

    Contributors

    +

    Contributors

    -

    Maintainers

    +

    Maintainers

    This module is maintained by the OCA.

    Odoo Community Association @@ -516,13 +522,12 @@

    Maintainers

    OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use.

    -

    Current maintainer:

    -

    kittiu

    +

    Current maintainers:

    +

    kittiu Saran440

    This module is part of the OCA/hr-expense project on GitHub.

    You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

    -
    diff --git a/hr_expense_advance_clearing/tests/test_hr_expense_advance_clearing.py b/hr_expense_advance_clearing/tests/test_hr_expense_advance_clearing.py index 8d1802061..bd377f559 100644 --- a/hr_expense_advance_clearing/tests/test_hr_expense_advance_clearing.py +++ b/hr_expense_advance_clearing/tests/test_hr_expense_advance_clearing.py @@ -20,6 +20,17 @@ def setUpClass(cls): cls.emp_advance = cls.env.ref("hr_expense_advance_clearing.product_emp_advance") cls.emp_advance.property_account_expense_id = advance_account cls.product_a.standard_price = 0 + # Create journal clearing + cls.other_misc = cls.env["account.journal"].create( + { + "name": "Clearing Other", + "code": "CLRO", + "type": "general", + "company_id": cls.company_data["company"].id, + } + ) + # Configure a clearing journal on the company. + cls.company_data["company"].clearing_journal_id = cls.other_misc # Create advance expense 1,000 cls.advance = cls._create_expense_sheet( cls, @@ -187,6 +198,10 @@ def test_1_clear_equal_advance(self): self.clearing_equal.action_sheet_move_post() # Equal amount, state change to Paid and advance is cleared self.assertEqual(self.clearing_equal.state, "done") + # Fallback: no company clearing journal configured, move uses a general journal + clearing_move = self.clearing_equal.account_move_ids + self.assertEqual(clearing_move.move_type, "entry") + self.assertEqual(clearing_move.journal_id.type, "general") self.assertEqual(self.clearing_equal.advance_sheet_residual, 0.0) # Clear this with previous advance is done self.clearing_more.advance_sheet_id = self.advance @@ -229,12 +244,17 @@ def test_2_clear_more_than_advance(self): # Clear this with previous advance self.clearing_more.advance_sheet_id = self.advance self.assertEqual(self.clearing_more.advance_sheet_residual, 1000.0) + self.clearing_more.clearing_journal_id = self.other_misc self.clearing_more.action_submit_sheet() self.clearing_more.action_approve_expense_sheets() self.clearing_more.action_sheet_move_post() # More amount, state not changed to paid, and has to pay 200 more self.assertEqual(self.clearing_more.state, "post") self.assertEqual(self.clearing_more.amount_payable, 200.0) + # Verify clearing move used the overridden journal + clearing_move = self.clearing_more.account_move_ids + self.assertEqual(clearing_move.journal_id, self.other_misc) + self.assertEqual(clearing_move.move_type, "entry") self._register_payment(self.clearing_more.account_move_ids, 200.0) self.assertEqual(self.clearing_more.state, "done") diff --git a/hr_expense_advance_clearing/views/hr_expense_views.xml b/hr_expense_advance_clearing/views/hr_expense_views.xml index 800a93864..486631973 100644 --- a/hr_expense_advance_clearing/views/hr_expense_views.xml +++ b/hr_expense_advance_clearing/views/hr_expense_views.xml @@ -203,6 +203,13 @@ name="advance_sheet_residual" invisible="not advance_sheet_id" /> + diff --git a/hr_expense_advance_clearing/views/res_config_settings_views.xml b/hr_expense_advance_clearing/views/res_config_settings_views.xml new file mode 100644 index 000000000..81686189e --- /dev/null +++ b/hr_expense_advance_clearing/views/res_config_settings_views.xml @@ -0,0 +1,20 @@ + + + + res.config.settings.view.form.inherit.hr.expense.advance.clearing + res.config.settings + + + + + + + + + +