141 lines
6.6 KiB
Python
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)
|