226 lines
9.6 KiB
Python
226 lines
9.6 KiB
Python
# -*- 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, we create the parent mirror entries
|
|
self._create_intercompany_parent_moves()
|
|
|
|
return res
|
|
|
|
def _create_bank_payment_moves(self, data):
|
|
"""Override to skip account.payment creation for intercompany payment methods,
|
|
and append the clearing lines directly to the POS session move."""
|
|
intercompany_pms = self.payment_method_ids.filtered(
|
|
lambda pm: pm.intercompany_clearing_account_id and pm.intercompany_clearing_journal_id
|
|
)
|
|
|
|
if not intercompany_pms:
|
|
return super()._create_bank_payment_moves(data)
|
|
|
|
combine_receivables_bank = data.get('combine_receivables_bank', {})
|
|
MoveLine = data.get('MoveLine')
|
|
|
|
# Split the data into intercompany and standard
|
|
standard_combine = {}
|
|
intercompany_combine = {}
|
|
|
|
for pm, amounts in combine_receivables_bank.items():
|
|
if pm in intercompany_pms:
|
|
intercompany_combine[pm] = amounts
|
|
else:
|
|
standard_combine[pm] = amounts
|
|
|
|
# Call super with only standard payments
|
|
data['combine_receivables_bank'] = standard_combine
|
|
res_data = super()._create_bank_payment_moves(data)
|
|
|
|
# Restore original data
|
|
data['combine_receivables_bank'] = combine_receivables_bank
|
|
|
|
# Manually handle intercompany ones: create the line in main move but skip account.payment
|
|
for pm, amounts in intercompany_combine.items():
|
|
# 1. Create the standard Debit AR In Transit line
|
|
combine_receivable_line = MoveLine.create(self._get_combine_receivable_vals(pm, amounts['amount'], amounts['amount_converted']))
|
|
|
|
# 2. Create the Intercompany Clearing Lines (Credit AR In Transit, Debit Hubungan RK)
|
|
receivable_account = self._get_receivable_account(pm)
|
|
intercompany_account = pm.intercompany_clearing_account_id
|
|
|
|
amount = amounts['amount']
|
|
amount_company_curr = amounts['amount_converted']
|
|
|
|
credit_transit_line = MoveLine.create({
|
|
'name': f"Clearing - {pm.name}",
|
|
'account_id': receivable_account.id,
|
|
'move_id': self.move_id.id,
|
|
'credit': amount_company_curr,
|
|
'debit': 0.0,
|
|
'currency_id': self.currency_id.id,
|
|
'amount_currency': -amount,
|
|
})
|
|
|
|
debit_rk_line = MoveLine.create({
|
|
'name': f"Due from Parent - {pm.name}",
|
|
'account_id': intercompany_account.id,
|
|
'move_id': self.move_id.id,
|
|
'credit': 0.0,
|
|
'debit': amount_company_curr,
|
|
'currency_id': self.currency_id.id,
|
|
'amount_currency': amount,
|
|
})
|
|
|
|
# Add both AR In Transit lines to the data dict so standard Odoo reconciles them!
|
|
res_data['payment_method_to_receivable_lines'][pm] = combine_receivable_line | credit_transit_line
|
|
|
|
return res_data
|
|
|
|
def _create_intercompany_parent_moves(self):
|
|
for session in self:
|
|
if session.state != 'closed' or not session.move_id:
|
|
continue
|
|
|
|
# Accumulate amounts per payment method
|
|
clearing_amounts = {}
|
|
for order in session.order_ids:
|
|
for payment in order.payment_ids:
|
|
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
|
|
|
|
if not clearing_amounts:
|
|
continue
|
|
|
|
pm_level_data = []
|
|
for pm, amount in clearing_amounts.items():
|
|
if session.currency_id.is_zero(amount):
|
|
continue
|
|
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, session.stop_at or fields.Date.context_today(session)
|
|
)
|
|
pm_level_data.append({
|
|
'pm': pm,
|
|
'amount': amount,
|
|
'amount_company_curr': amount_company_curr,
|
|
})
|
|
|
|
if pm_level_data:
|
|
self._create_aggregated_parent_mirror_move(session, pm_level_data)
|
|
|
|
def _create_aggregated_parent_mirror_move(self, session, pm_level_data):
|
|
"""Create a single mirror journal entry in the parent company, with separate lines per PM.
|
|
|
|
For each PM:
|
|
Debit: Outstanding receipt account of the parent bank journal
|
|
Credit: Hubungan RK liability (229101) in the parent
|
|
"""
|
|
parent_groups = {}
|
|
for data in pm_level_data:
|
|
pm = data['pm']
|
|
parent_company = pm.parent_company_id or session.company_id.parent_id
|
|
if not parent_company:
|
|
continue
|
|
|
|
parent_bank_journal = pm.parent_bank_journal_id
|
|
parent_rk_account = pm.parent_intercompany_account_id
|
|
parent_clearing_journal = pm.parent_clearing_journal_id
|
|
|
|
if not parent_bank_journal or not parent_rk_account or not parent_clearing_journal:
|
|
continue
|
|
|
|
outstanding_receipt_account = None
|
|
for pml in parent_bank_journal.inbound_payment_method_line_ids:
|
|
if pml.payment_account_id:
|
|
outstanding_receipt_account = pml.payment_account_id
|
|
break
|
|
|
|
if not outstanding_receipt_account:
|
|
continue
|
|
|
|
group_key = (parent_company.id, parent_clearing_journal.id)
|
|
if group_key not in parent_groups:
|
|
parent_groups[group_key] = {
|
|
'parent_company': parent_company,
|
|
'parent_clearing_journal': parent_clearing_journal,
|
|
'lines_data': []
|
|
}
|
|
|
|
parent_groups[group_key]['lines_data'].append({
|
|
'pm': pm,
|
|
'amount': data['amount'],
|
|
'amount_company_curr': data['amount_company_curr'],
|
|
'outstanding_receipt_account': outstanding_receipt_account,
|
|
'parent_rk_account': parent_rk_account,
|
|
})
|
|
|
|
entry_date = session.stop_at or fields.Date.context_today(session)
|
|
|
|
for group_key, group_data in parent_groups.items():
|
|
parent_company = group_data['parent_company']
|
|
parent_clearing_journal = group_data['parent_clearing_journal']
|
|
|
|
line_ids = []
|
|
|
|
for line_data in group_data['lines_data']:
|
|
pm = line_data['pm']
|
|
amount = line_data['amount']
|
|
|
|
parent_currency = parent_company.currency_id
|
|
if session.currency_id != parent_currency:
|
|
amount_parent_curr = session.currency_id._convert(
|
|
amount, parent_currency, parent_company, entry_date
|
|
)
|
|
else:
|
|
amount_parent_curr = amount
|
|
|
|
line_ids.append(Command.create({
|
|
'name': f"POS Receipt: {pm.name} ({session.company_id.name})",
|
|
'account_id': line_data['outstanding_receipt_account'].id,
|
|
'debit': amount_parent_curr,
|
|
'credit': 0.0,
|
|
'currency_id': session.currency_id.id,
|
|
'amount_currency': amount,
|
|
}))
|
|
|
|
line_ids.append(Command.create({
|
|
'name': f"Due to Branch: {pm.name} ({session.company_id.name})",
|
|
'account_id': line_data['parent_rk_account'].id,
|
|
'debit': 0.0,
|
|
'credit': amount_parent_curr,
|
|
'currency_id': session.currency_id.id,
|
|
'amount_currency': -amount,
|
|
}))
|
|
|
|
if not line_ids:
|
|
continue
|
|
|
|
parent_move_vals = {
|
|
'journal_id': parent_clearing_journal.id,
|
|
'date': entry_date,
|
|
'ref': f"POS Mirror: {session.name} - {session.company_id.name}",
|
|
'move_type': 'entry',
|
|
'company_id': parent_company.id,
|
|
'line_ids': line_ids,
|
|
}
|
|
|
|
try:
|
|
parent_move = self.env['account.move'].sudo().with_company(parent_company).create(parent_move_vals)
|
|
parent_move._post()
|
|
except Exception as e:
|
|
_logger.error(
|
|
"Failed to create aggregated parent mirror entry for session %s in company %s: %s",
|
|
session.name, parent_company.name, e
|
|
)
|