split_pendapatan_payment/models/pos_session.py
2025-08-16 11:46:03 +07:00

141 lines
6.6 KiB
Python

# -*- coding: utf-8 -*-
from collections import defaultdict
from odoo import models, fields, api, _
from odoo.exceptions import UserError
from odoo.tools import float_is_zero, float_compare
class PosSession(models.Model):
_inherit = 'pos.session'
def _accumulate_amounts(self, data):
# Call the original method to get all the standard accumulations
data = super(PosSession, self)._accumulate_amounts(data)
# Get all orders in this session
closed_orders = self._get_closed_orders()
# If no orders, return original data
if not closed_orders:
return data
# Get the original sales data
sales = data.get('sales', {})
if not sales:
return data
# Create new sales data structure split by payment method
split_sales = defaultdict(lambda: {'amount': 0.0, 'amount_converted': 0.0, 'tax_amount': 0.0})
# For each sale entry, we need to distribute it across payment methods
for sale_key, sale_amounts in sales.items():
# Skip if this is a tax key (we only want to split actual sales)
if len(sale_key) < 4: # Not a standard sales key
continue
total_amount = sale_amounts['amount']
total_amount_converted = sale_amounts['amount_converted']
tax_amount = sale_amounts.get('tax_amount', 0.0) # Get tax amount if it exists
if float_is_zero(total_amount, precision_rounding=self.currency_id.rounding):
continue
# Distribute this sales amount across all orders based on their payment methods
total_payment_amount = sum(sum(payment.amount for payment in order.payment_ids) for order in closed_orders)
if float_is_zero(total_payment_amount, precision_rounding=self.currency_id.rounding):
continue
# Distribute the sales amount across all orders proportionally to their payments
for order in closed_orders:
if order.is_invoiced:
continue # Skip invoiced orders
order_payments = order.payment_ids
order_payment_total = sum(payment.amount for payment in order_payments)
if float_is_zero(order_payment_total, precision_rounding=order.currency_id.rounding):
continue
# For each payment in this order, create a split sales entry
for payment in order_payments:
# Calculate the proportion of this payment relative to all payments
payment_proportion = payment.amount / total_payment_amount
payment_amount = total_amount * payment_proportion
payment_amount_converted = total_amount_converted * payment_proportion
payment_tax_amount = tax_amount * payment_proportion
if float_is_zero(payment_amount, precision_rounding=self.currency_id.rounding):
continue
# Use the payment method's income account if specified, otherwise use original account
income_account_id = sale_key[0] # default account
if payment.payment_method_id.income_account_id and payment.payment_method_id.income_account_id.id:
income_account_id = payment.payment_method_id.income_account_id.id
# Ensure we have a valid account ID
if not income_account_id:
continue
# Create a new key that includes the payment method
new_sale_key = (
# account (use payment method account if specified)
income_account_id,
# sign (same as original)
sale_key[1],
# payment method
payment.payment_method_id.id,
# for taxes (same as original)
sale_key[2],
# base tags (same as original)
sale_key[3],
)
# Update the split sales data
split_sales[new_sale_key]['amount'] += payment_amount
split_sales[new_sale_key]['amount_converted'] += payment_amount_converted
split_sales[new_sale_key]['tax_amount'] += payment_tax_amount
# Replace the original sales data with our split sales data
data['sales'] = split_sales
return data
def _get_sale_vals(self, key, amount, amount_converted):
""" Override to add payment method information to the sales line description """
# Check if this key includes payment method information
if len(key) >= 5 and isinstance(key[2], int): # Has payment method ID
account_id, sign, payment_method_id, tax_keys, base_tag_ids = key
# Try to get the payment method name
try:
payment_method = self.env['pos.payment.method'].browse(payment_method_id)
payment_method_name = payment_method.name
except:
payment_method_name = "Unknown Payment"
else:
# Original format
account_id, sign, tax_keys, base_tag_ids = key
payment_method_name = None
tax_ids = set(tax[0] for tax in tax_keys) if tax_keys else set()
applied_taxes = self.env['account.tax'].browse(tax_ids)
title = _('Sales') if sign == 1 else _('Refund')
# Create name with payment method information
if payment_method_name:
name = _('%s - %s', title, payment_method_name)
if applied_taxes:
name = _('%s with %s - %s', title, ', '.join([tax.name for tax in applied_taxes]), payment_method_name)
else:
name = _('%s untaxed', title)
if applied_taxes:
name = _('%s with %s', title, ', '.join([tax.name for tax in applied_taxes]))
partial_vals = {
'name': name,
'account_id': account_id,
'move_id': self.move_id.id,
'tax_ids': [(6, 0, tax_ids)],
'tax_tag_ids': [(6, 0, base_tag_ids)] if base_tag_ids else [],
}
return self._credit_amounts(partial_vals, amount, amount_converted)