feat: add automated inter-company clearing move generation upon POS session validation
This commit is contained in:
parent
5caa96c1e3
commit
1f60af1e81
@ -8,8 +8,10 @@
|
|||||||
This module removes the standard restriction that prevents Chart of Accounts (COA) of type 'Bank and Cash' from being shared across multiple companies.
|
This module removes the standard restriction that prevents Chart of Accounts (COA) of type 'Bank and Cash' from being shared across multiple companies.
|
||||||
""",
|
""",
|
||||||
'author': 'Suherdy Yacob',
|
'author': 'Suherdy Yacob',
|
||||||
'depends': ['account'],
|
'depends': ['account', 'point_of_sale'],
|
||||||
'data': [],
|
'data': [
|
||||||
|
'views/pos_payment_method_views.xml',
|
||||||
|
],
|
||||||
'installable': True,
|
'installable': True,
|
||||||
'application': False,
|
'application': False,
|
||||||
'license': 'LGPL-3',
|
'license': 'LGPL-3',
|
||||||
|
|||||||
@ -1 +1,4 @@
|
|||||||
from . import account_account
|
from . import account_account
|
||||||
|
from . import pos_payment_method
|
||||||
|
from . import pos_session
|
||||||
|
|
||||||
|
|||||||
21
models/pos_payment_method.py
Normal file
21
models/pos_payment_method.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from odoo import models, fields
|
||||||
|
|
||||||
|
class PosPaymentMethod(models.Model):
|
||||||
|
_inherit = 'pos.payment.method'
|
||||||
|
|
||||||
|
intercompany_clearing_account_id = fields.Many2one(
|
||||||
|
'account.account',
|
||||||
|
string='Inter-Company Clearing Account',
|
||||||
|
domain="[('account_type', 'in', ['asset_receivable', 'liability_payable', 'asset_current'])]",
|
||||||
|
help="If specified, an automatic clearing entry will be generated when a POS session closes. "
|
||||||
|
"This is used to transfer the balance from a shared parent bank account to an inter-company account."
|
||||||
|
)
|
||||||
|
|
||||||
|
intercompany_clearing_journal_id = fields.Many2one(
|
||||||
|
'account.journal',
|
||||||
|
string='Clearing Journal',
|
||||||
|
domain="[('type', '=', 'general')]",
|
||||||
|
help="Journal to use for the automated inter-company clearing entries."
|
||||||
|
)
|
||||||
102
models/pos_session.py
Normal file
102
models/pos_session.py
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from odoo import models, fields, api, Command
|
||||||
|
import logging
|
||||||
|
|
||||||
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class PosSession(models.Model):
|
||||||
|
_inherit = 'pos.session'
|
||||||
|
|
||||||
|
def _validate_session(self, balancing_account=False, amount_to_balance=0, bank_payment_method_diffs=None):
|
||||||
|
res = super(PosSession, self)._validate_session(balancing_account, amount_to_balance, bank_payment_method_diffs)
|
||||||
|
|
||||||
|
# After the standard validation and account move creation, we create the inter-company clearing moves
|
||||||
|
self._create_intercompany_clearing_moves()
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
def _create_intercompany_clearing_moves(self):
|
||||||
|
for session in self:
|
||||||
|
if session.state != 'closed' or not session.move_id:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Dictionary to accumulate amounts per payment method
|
||||||
|
# Key: pos.payment.method, Value: float (amount)
|
||||||
|
clearing_amounts = {}
|
||||||
|
|
||||||
|
# Find all payments for this session
|
||||||
|
orders = session.get_session_orders()
|
||||||
|
payments = orders.payment_ids
|
||||||
|
|
||||||
|
for payment in payments:
|
||||||
|
pm = payment.payment_method_id
|
||||||
|
if pm.intercompany_clearing_account_id and pm.intercompany_clearing_journal_id:
|
||||||
|
if pm not in clearing_amounts:
|
||||||
|
clearing_amounts[pm] = 0.0
|
||||||
|
clearing_amounts[pm] += payment.amount
|
||||||
|
|
||||||
|
for pm, amount in clearing_amounts.items():
|
||||||
|
if session.currency_id.compare_amounts(amount, 0) <= 0:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# The outstanding account of the payment method is the Shared Bank Account
|
||||||
|
shared_bank_account = pm.outstanding_account_id or pm.journal_id.default_account_id
|
||||||
|
if not shared_bank_account:
|
||||||
|
_logger.warning("No outstanding account found on payment method %s, cannot create clearing entry.", pm.name)
|
||||||
|
continue
|
||||||
|
|
||||||
|
intercompany_account = pm.intercompany_clearing_account_id
|
||||||
|
clearing_journal = pm.intercompany_clearing_journal_id
|
||||||
|
|
||||||
|
# Convert amount to company currency if needed
|
||||||
|
amount_company_curr = amount
|
||||||
|
if session.currency_id != session.company_id.currency_id:
|
||||||
|
amount_company_curr = session.currency_id._convert(
|
||||||
|
amount, session.company_id.currency_id, session.company_id, fields.Date.context_today(session)
|
||||||
|
)
|
||||||
|
|
||||||
|
# We need to CREDIT the shared bank account (to clear it in the Branch)
|
||||||
|
# and DEBIT the intercompany account
|
||||||
|
|
||||||
|
move_vals = {
|
||||||
|
'journal_id': clearing_journal.id,
|
||||||
|
'date': fields.Date.context_today(session),
|
||||||
|
'ref': f"Inter-company clearing for {session.name} ({pm.name})",
|
||||||
|
'pos_session_id': session.id, # Link back to session if pos_session_id field exists on move
|
||||||
|
'line_ids': [
|
||||||
|
Command.create({
|
||||||
|
'name': f"Clearing: {pm.name}",
|
||||||
|
'account_id': shared_bank_account.id,
|
||||||
|
'credit': amount_company_curr,
|
||||||
|
'debit': 0.0,
|
||||||
|
'currency_id': session.currency_id.id,
|
||||||
|
'amount_currency': -amount if session.currency_id != session.company_id.currency_id else 0.0,
|
||||||
|
}),
|
||||||
|
Command.create({
|
||||||
|
'name': f"Due from Parent: {pm.name}",
|
||||||
|
'account_id': intercompany_account.id,
|
||||||
|
'credit': 0.0,
|
||||||
|
'debit': amount_company_curr,
|
||||||
|
'currency_id': session.currency_id.id,
|
||||||
|
'amount_currency': amount if session.currency_id != session.company_id.currency_id else 0.0,
|
||||||
|
})
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if 'pos_session_id' exists on account.move, if not remove it
|
||||||
|
if 'pos_session_id' not in self.env['account.move']._fields:
|
||||||
|
move_vals.pop('pos_session_id', None)
|
||||||
|
|
||||||
|
clearing_move = self.env['account.move'].sudo().with_company(session.company_id).create(move_vals)
|
||||||
|
clearing_move._post()
|
||||||
|
|
||||||
|
# Attempt to auto-reconcile the credit line with the debit line from the main POS move
|
||||||
|
try:
|
||||||
|
clearing_credit_line = clearing_move.line_ids.filtered(lambda l: l.account_id == shared_bank_account and l.credit > 0)
|
||||||
|
pos_debit_lines = session.move_id.line_ids.filtered(lambda l: l.account_id == shared_bank_account and l.debit > 0)
|
||||||
|
|
||||||
|
if clearing_credit_line and pos_debit_lines:
|
||||||
|
(clearing_credit_line + pos_debit_lines).reconcile()
|
||||||
|
except Exception as e:
|
||||||
|
_logger.warning("Could not auto-reconcile inter-company clearing lines for session %s: %s", session.name, e)
|
||||||
18
views/pos_payment_method_views.xml
Normal file
18
views/pos_payment_method_views.xml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
<record id="pos_payment_method_view_form_inherit_intercompany" model="ir.ui.view">
|
||||||
|
<field name="name">pos.payment.method.form.inherit.intercompany</field>
|
||||||
|
<field name="model">pos.payment.method</field>
|
||||||
|
<field name="inherit_id" ref="point_of_sale.pos_payment_method_view_form"/>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//group[@name='Payment methods']" position="after">
|
||||||
|
<group name="intercompany_clearing" string="Inter-Company Clearing">
|
||||||
|
<field name="intercompany_clearing_account_id"/>
|
||||||
|
<field name="intercompany_clearing_journal_id"
|
||||||
|
invisible="not intercompany_clearing_account_id"
|
||||||
|
required="intercompany_clearing_account_id"/>
|
||||||
|
</group>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
||||||
Loading…
Reference in New Issue
Block a user