diff --git a/pos_transfer_account/README.rst b/pos_transfer_account/README.rst new file mode 100644 index 0000000000..5888947ba4 --- /dev/null +++ b/pos_transfer_account/README.rst @@ -0,0 +1,99 @@ +================================ +Point of Sale - Transfer Account +================================ + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:1303b980905367f42847d08584f9170f6e81941decb7c87800789196c99c4c7b + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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/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%2Fpos-lightgray.png?logo=github + :target: https://github.com/OCA/pos/tree/18.0/pos_transfer_account + :alt: OCA/pos +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/pos-18-0/pos-18-0-pos_transfer_account + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/pos&target_branch=18.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module was written to extend the functionality of odoo Point Of +Sale about suspense account. + +This module is usefull only in a multi Point of Sale context of multi +company context. + +With this module, it is now allowed to define for each PoS config a +suspense account. + +If this account is set, it will be used when user realizes "Cash In" or +Cash Out" operation, instead of the default one set in 'Invoicing' / +'Configuration' / 'Journals'. ("Suspense Account" field) + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +- Go to 'Point of Sale' / 'Configuration' / 'Point of Sale' +- Edit your PoS Config and add a suspense account + +|Suspense account| + +.. |Suspense account| image:: https://raw.githubusercontent.com/OCA/pos/18.0/pos_transfer_account/static/description/pos_config.png + +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 +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* La Louve + +Contributors +------------ + +- `Trobz `__ + + - Phan Hong Phuc + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +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. + +This module is part of the `OCA/pos `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/pos_transfer_account/__init__.py b/pos_transfer_account/__init__.py new file mode 100644 index 0000000000..0650744f6b --- /dev/null +++ b/pos_transfer_account/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/pos_transfer_account/__manifest__.py b/pos_transfer_account/__manifest__.py new file mode 100644 index 0000000000..3ba1d32a7a --- /dev/null +++ b/pos_transfer_account/__manifest__.py @@ -0,0 +1,21 @@ +# Copyright (C) 2016-Today: La Louve () +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{ + "name": "Point of Sale - Transfer Account", + "version": "18.0.1.0.0", + "category": "Point Of Sale", + "author": "La Louve, Odoo Community Association (OCA)", + "license": "AGPL-3", + "website": "https://github.com/OCA/pos", + "depends": [ + "point_of_sale", + ], + "data": ["views/view_pos_config.xml", "views/res_config_settings_view.xml"], + "demo": [ + "demo/account_account.xml", + "demo/pos_config.xml", + ], + "installable": True, +} diff --git a/pos_transfer_account/demo/account_account.xml b/pos_transfer_account/demo/account_account.xml new file mode 100644 index 0000000000..03b3c163c2 --- /dev/null +++ b/pos_transfer_account/demo/account_account.xml @@ -0,0 +1,9 @@ + + + + Demo PoS Liquidity Suspense Account + 101710 + asset_current + + + diff --git a/pos_transfer_account/demo/pos_config.xml b/pos_transfer_account/demo/pos_config.xml new file mode 100644 index 0000000000..f70baa8418 --- /dev/null +++ b/pos_transfer_account/demo/pos_config.xml @@ -0,0 +1,8 @@ + + + + Point Of Sale with Specific Transfer Account + + + + diff --git a/pos_transfer_account/i18n/fr.po b/pos_transfer_account/i18n/fr.po new file mode 100644 index 0000000000..6c756979ae --- /dev/null +++ b/pos_transfer_account/i18n/fr.po @@ -0,0 +1,43 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * pos_transfer_account +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2025-11-19 08:37+0000\n" +"PO-Revision-Date: 2025-11-19 08:37+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: pos_transfer_account +#: model:ir.model,name:pos_transfer_account.model_res_config_settings +msgid "Config Settings" +msgstr "Paramètres de configuration" + +#. module: pos_transfer_account +#: model:account.account,name:pos_transfer_account.account_pos_transfer_account +msgid "Demo PoS Liquidity Transfers" +msgstr "Démo : Transferts de liquidités PoS" + +#. module: pos_transfer_account +#: model:ir.model,name:pos_transfer_account.model_pos_config +msgid "Point of Sale Configuration" +msgstr "Configuration du point de vente" + +#. module: pos_transfer_account +#: model:ir.model,name:pos_transfer_account.model_pos_session +msgid "Point of Sale Session" +msgstr "Session du point de vente" + +#. module: pos_transfer_account +#: model:ir.model.fields,field_description:pos_transfer_account.field_pos_config__suspense_account_id +#: model:ir.model.fields,field_description:pos_transfer_account.field_res_config_settings__pos_suspense_account_id +#: model_terms:ir.ui.view,arch_db:pos_transfer_account.pos_config_view_form +msgid "Suspense Account" +msgstr "Compte d'attente" diff --git a/pos_transfer_account/i18n/pos_transfer_account.pot b/pos_transfer_account/i18n/pos_transfer_account.pot new file mode 100644 index 0000000000..756ee970c6 --- /dev/null +++ b/pos_transfer_account/i18n/pos_transfer_account.pot @@ -0,0 +1,43 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * pos_transfer_account +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2025-11-19 08:39+0000\n" +"PO-Revision-Date: 2025-11-19 08:39+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: pos_transfer_account +#: model:ir.model,name:pos_transfer_account.model_res_config_settings +msgid "Config Settings" +msgstr "" + +#. module: pos_transfer_account +#: model:account.account,name:pos_transfer_account.account_pos_transfer_account +msgid "Demo PoS Liquidity Transfers" +msgstr "" + +#. module: pos_transfer_account +#: model:ir.model,name:pos_transfer_account.model_pos_config +msgid "Point of Sale Configuration" +msgstr "" + +#. module: pos_transfer_account +#: model:ir.model,name:pos_transfer_account.model_pos_session +msgid "Point of Sale Session" +msgstr "" + +#. module: pos_transfer_account +#: model:ir.model.fields,field_description:pos_transfer_account.field_pos_config__suspense_account_id +#: model:ir.model.fields,field_description:pos_transfer_account.field_res_config_settings__pos_suspense_account_id +#: model_terms:ir.ui.view,arch_db:pos_transfer_account.pos_config_view_form +msgid "Suspense Account" +msgstr "" diff --git a/pos_transfer_account/models/__init__.py b/pos_transfer_account/models/__init__.py new file mode 100644 index 0000000000..b8f2c52acc --- /dev/null +++ b/pos_transfer_account/models/__init__.py @@ -0,0 +1,4 @@ +from . import pos_config +from . import pos_session +from . import res_config_settings +from . import account_bank_statement_line diff --git a/pos_transfer_account/models/account_bank_statement_line.py b/pos_transfer_account/models/account_bank_statement_line.py new file mode 100644 index 0000000000..4754f15252 --- /dev/null +++ b/pos_transfer_account/models/account_bank_statement_line.py @@ -0,0 +1,13 @@ +from odoo import api, models + + +class AccountBankStatementLine(models.Model): + _inherit = "account.bank.statement.line" + + @api.model_create_multi + def create(self, vals_list): + counterpart_id = self.env.context.get("counterpart_account_id", False) + if counterpart_id: + for vals in vals_list: + vals["counterpart_account_id"] = counterpart_id + return super().create(vals_list) diff --git a/pos_transfer_account/models/pos_config.py b/pos_transfer_account/models/pos_config.py new file mode 100644 index 0000000000..0735c106b1 --- /dev/null +++ b/pos_transfer_account/models/pos_config.py @@ -0,0 +1,12 @@ +# Copyright (C) 2016-Today: La Louve () +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + + +from odoo import fields, models + + +class PosConfig(models.Model): + _inherit = "pos.config" + + suspense_account_id = fields.Many2one(comodel_name="account.account") diff --git a/pos_transfer_account/models/pos_session.py b/pos_transfer_account/models/pos_session.py new file mode 100644 index 0000000000..b8c77d07ea --- /dev/null +++ b/pos_transfer_account/models/pos_session.py @@ -0,0 +1,37 @@ +from odoo import models + + +class PosSession(models.Model): + _inherit = "pos.session" + + def _prepare_account_bank_statement_line_vals( + self, session, sign, amount, reason, extras + ): + res = super()._prepare_account_bank_statement_line_vals( + session, sign, amount, reason, extras + ) + if extras.get("counterpart_account_id"): + res["counterpart_account_id"] = extras["counterpart_account_id"] + return res + + def try_cash_in_out(self, _type, amount, reason, extras): + extras = extras or {} + if self.config_id.suspense_account_id: + counterpart_account = self.config_id.suspense_account_id + else: + counterpart_account = self.config_id.company_id.transfer_account_id + extras["counterpart_account_id"] = counterpart_account.id + return super().try_cash_in_out(_type, amount, reason, extras) + + def show_cash_register(self): + action = super().show_cash_register() + if self.config_id.suspense_account_id: + counterpart_account = self.config_id.suspense_account_id + else: + counterpart_account = self.config_id.company_id.transfer_account_id + action["context"] = { + "default_pos_session_id": self.id, + "counterpart_account_id": counterpart_account.id, + "default_journal_id": self.cash_journal_id.id, + } + return action diff --git a/pos_transfer_account/models/res_config_settings.py b/pos_transfer_account/models/res_config_settings.py new file mode 100644 index 0000000000..b90a16ed68 --- /dev/null +++ b/pos_transfer_account/models/res_config_settings.py @@ -0,0 +1,11 @@ +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + _inherit = "res.config.settings" + + pos_suspense_account_id = fields.Many2one( + "account.account", + related="pos_config_id.suspense_account_id", + readonly=False, + ) diff --git a/pos_transfer_account/pyproject.toml b/pos_transfer_account/pyproject.toml new file mode 100644 index 0000000000..4231d0cccb --- /dev/null +++ b/pos_transfer_account/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/pos_transfer_account/readme/CONFIGURE.md b/pos_transfer_account/readme/CONFIGURE.md new file mode 100644 index 0000000000..2255306838 --- /dev/null +++ b/pos_transfer_account/readme/CONFIGURE.md @@ -0,0 +1,4 @@ +* Go to 'Point of Sale' / 'Configuration' / 'Point of Sale' +* Edit your PoS Config and add a suspense account + +![Suspense account](./static/description/pos_config.png) diff --git a/pos_transfer_account/readme/CONTRIBUTORS.md b/pos_transfer_account/readme/CONTRIBUTORS.md new file mode 100644 index 0000000000..561f5bcc8c --- /dev/null +++ b/pos_transfer_account/readme/CONTRIBUTORS.md @@ -0,0 +1,2 @@ +- [Trobz](https://trobz.com) + - Phan Hong Phuc \<\> diff --git a/pos_transfer_account/readme/DESCRIPTION.md b/pos_transfer_account/readme/DESCRIPTION.md new file mode 100644 index 0000000000..8f0d2d5115 --- /dev/null +++ b/pos_transfer_account/readme/DESCRIPTION.md @@ -0,0 +1,12 @@ +This module was written to extend the functionality of odoo Point Of Sale about +suspense account. + +This module is usefull only in a multi Point of Sale context of multi company +context. + +With this module, it is now allowed to define for each PoS config a suspense +account. + +If this account is set, it will be used when user realizes "Cash In" or +Cash Out" operation, instead of the default one set in 'Invoicing' / +'Configuration' / 'Journals'. ("Suspense Account" field) \ No newline at end of file diff --git a/pos_transfer_account/static/description/icon.png b/pos_transfer_account/static/description/icon.png new file mode 100644 index 0000000000..769e99823a Binary files /dev/null and b/pos_transfer_account/static/description/icon.png differ diff --git a/pos_transfer_account/static/description/index.html b/pos_transfer_account/static/description/index.html new file mode 100644 index 0000000000..469883838e --- /dev/null +++ b/pos_transfer_account/static/description/index.html @@ -0,0 +1,443 @@ + + + + + +Point of Sale - Transfer Account + + + +
+

Point of Sale - Transfer Account

+ + +

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

+

This module was written to extend the functionality of odoo Point Of +Sale about suspense account.

+

This module is usefull only in a multi Point of Sale context of multi +company context.

+

With this module, it is now allowed to define for each PoS config a +suspense account.

+

If this account is set, it will be used when user realizes “Cash In” or +Cash Out” operation, instead of the default one set in ‘Invoicing’ / +‘Configuration’ / ‘Journals’. (“Suspense Account” field)

+

Table of contents

+ +
+

Configuration

+
    +
  • Go to ‘Point of Sale’ / ‘Configuration’ / ‘Point of Sale’
  • +
  • Edit your PoS Config and add a suspense account
  • +
+

Suspense account

+
+
+

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 +feedback.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • La Louve
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

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.

+

This module is part of the OCA/pos project on GitHub.

+

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

+
+
+
+ + diff --git a/pos_transfer_account/static/description/pos_config.png b/pos_transfer_account/static/description/pos_config.png new file mode 100644 index 0000000000..11e2e867ef Binary files /dev/null and b/pos_transfer_account/static/description/pos_config.png differ diff --git a/pos_transfer_account/tests/__init__.py b/pos_transfer_account/tests/__init__.py new file mode 100644 index 0000000000..aae0557e76 --- /dev/null +++ b/pos_transfer_account/tests/__init__.py @@ -0,0 +1 @@ +from . import test_pos_transfer_account diff --git a/pos_transfer_account/tests/test_pos_transfer_account.py b/pos_transfer_account/tests/test_pos_transfer_account.py new file mode 100644 index 0000000000..deefeb21fa --- /dev/null +++ b/pos_transfer_account/tests/test_pos_transfer_account.py @@ -0,0 +1,97 @@ +from odoo.tests.common import TransactionCase, tagged + + +@tagged("post_install", "-at_install") +class TestPosTransferAccount(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + # Create suspense account + cls.suspense_account = cls.env["account.account"].create( + { + "name": "Suspense Account Test", + "code": "123456", + "account_type": "asset_current", + } + ) + + # Create cash journal first (required by payment method) + cash_journal = cls.env["account.journal"].create( + { + "name": "POS Cash", + "code": "POSC", + "type": "cash", + "company_id": cls.env.company.id, + } + ) + + # Create cash payment method for POS + cls.cash_method = cls.env["pos.payment.method"].create( + { + "name": "Cash", + "type": "cash", + "journal_id": cash_journal.id, + "company_id": cls.env.company.id, + } + ) + + # Now create POS config including the cash method + cls.pos_config = cls.env["pos.config"].create( + { + "name": "Test POS", + "suspense_account_id": cls.suspense_account.id, + "payment_method_ids": [(6, 0, [cls.cash_method.id])], + } + ) + + # Open session + cls.session = cls.env["pos.session"].create( + { + "config_id": cls.pos_config.id, + } + ) + cls.session.action_pos_session_open() + + def test_suspense_account_used_in_cash_in(self): + # Perform cash in + cash_in_amount = 789 + extras = { + "translatedType": "in", + } + self.session.try_cash_in_out( + "in", + cash_in_amount, + "Test Cash In", + extras, + ) + self.session.action_pos_session_close() + # Check the account.move.line for the cash in + aml = self.env["account.move.line"].search( + [ + ("credit", "=", cash_in_amount), + ("account_id", "=", self.suspense_account.id), + ] + ) + self.assertTrue(aml, "Suspense account should be used in cash in operation") + + def test_suspense_account_used_in_cash_out(self): + # Perform cash out + cash_out_amount = 456 + extras = { + "translatedType": "out", + } + self.session.try_cash_in_out( + "out", + cash_out_amount, + "Test Cash Out", + extras, + ) + self.session.action_pos_session_close() + # Check the account.move.line for the cash out + aml = self.env["account.move.line"].search( + [ + ("debit", "=", cash_out_amount), + ("account_id", "=", self.suspense_account.id), + ] + ) + self.assertTrue(aml, "Suspense account should be used in cash out operation") diff --git a/pos_transfer_account/views/res_config_settings_view.xml b/pos_transfer_account/views/res_config_settings_view.xml new file mode 100644 index 0000000000..c369811185 --- /dev/null +++ b/pos_transfer_account/views/res_config_settings_view.xml @@ -0,0 +1,15 @@ + + + + res.config.settings.form.view + res.config.settings + + + + + + + + + + diff --git a/pos_transfer_account/views/view_pos_config.xml b/pos_transfer_account/views/view_pos_config.xml new file mode 100644 index 0000000000..0dea53ea40 --- /dev/null +++ b/pos_transfer_account/views/view_pos_config.xml @@ -0,0 +1,19 @@ + + + + + pos.config + + + + + + + + + +