Merge branch 'main' into rollback

This commit is contained in:
Suherdy Yacob 2025-08-25 16:45:00 +07:00
commit 2ae9be1d68
4 changed files with 46 additions and 23 deletions

View File

@ -19,7 +19,7 @@
'version': '17.0.1.0.0', 'version': '17.0.1.0.0',
# any module necessary for this one to work correctly # any module necessary for this one to work correctly
'depends': ['point_of_sale'], 'depends': ['point_of_sale', 'pos_discount'],
# always loaded # always loaded
'data': [ 'data': [

View File

@ -11,3 +11,10 @@ class PosPaymentMethod(models.Model):
domain=[('deprecated', '=', False)], domain=[('deprecated', '=', False)],
help='Account used for income lines when splitting by payment method. ' help='Account used for income lines when splitting by payment method. '
'If empty, the default income account from the product will be used.') 'If empty, the default income account from the product will be used.')
discount_account_id = fields.Many2one(
'account.account',
string='Discount Account',
domain=[('deprecated', '=', False)],
help='Account used for discount product lines when splitting by payment method. '
'If empty, the default discount account from the product will be used.')

View File

@ -11,52 +11,55 @@ class PosSession(models.Model):
def _accumulate_amounts(self, data): def _accumulate_amounts(self, data):
# Call the original method to get all the standard accumulations # Call the original method to get all the standard accumulations
data = super(PosSession, self)._accumulate_amounts(data) data = super(PosSession, self)._accumulate_amounts(data)
# Get all orders in this session # Get all orders in this session
closed_orders = self._get_closed_orders() closed_orders = self._get_closed_orders()
# If no orders, return original data # If no orders, return original data
if not closed_orders: if not closed_orders:
return data return data
# Get the original sales data # Get the original sales data
sales = data.get('sales', {}) sales = data.get('sales', {})
if not sales: if not sales:
return data return data
# Create new sales data structure split by payment method # Create new sales data structure split by payment method
split_sales = defaultdict(lambda: {'amount': 0.0, 'amount_converted': 0.0, 'tax_amount': 0.0}) split_sales = defaultdict(lambda: {'amount': 0.0, 'amount_converted': 0.0, 'tax_amount': 0.0})
# Get discount product ID from config
discount_product_id = self.config_id.discount_product_id.id if self.config_id.discount_product_id else None
# For each sale entry, we need to distribute it across payment methods # For each sale entry, we need to distribute it across payment methods
for sale_key, sale_amounts in sales.items(): for sale_key, sale_amounts in sales.items():
# Skip if this is a tax key (we only want to split actual sales) # Skip if this is a tax key (we only want to split actual sales)
if len(sale_key) < 4: # Not a standard sales key if len(sale_key) < 4: # Not a standard sales key
continue continue
total_amount = sale_amounts['amount'] total_amount = sale_amounts['amount']
total_amount_converted = sale_amounts['amount_converted'] total_amount_converted = sale_amounts['amount_converted']
tax_amount = sale_amounts.get('tax_amount', 0.0) # Get tax amount if it exists 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): if float_is_zero(total_amount, precision_rounding=self.currency_id.rounding):
continue continue
# Distribute this sales amount across all orders based on their payment methods # 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) 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): if float_is_zero(total_payment_amount, precision_rounding=self.currency_id.rounding):
continue continue
# Distribute the sales amount across all orders proportionally to their payments # Distribute the sales amount across all orders proportionally to their payments
for order in closed_orders: for order in closed_orders:
if order.is_invoiced: if order.is_invoiced:
continue # Skip invoiced orders continue # Skip invoiced orders
order_payments = order.payment_ids order_payments = order.payment_ids
order_payment_total = sum(payment.amount for payment in order_payments) order_payment_total = sum(payment.amount for payment in order_payments)
if float_is_zero(order_payment_total, precision_rounding=order.currency_id.rounding): if float_is_zero(order_payment_total, precision_rounding=order.currency_id.rounding):
continue continue
# For each payment in this order, create a split sales entry # For each payment in this order, create a split sales entry
for payment in order_payments: for payment in order_payments:
# Calculate the proportion of this payment relative to all payments # Calculate the proportion of this payment relative to all payments
@ -64,19 +67,31 @@ class PosSession(models.Model):
payment_amount = total_amount * payment_proportion payment_amount = total_amount * payment_proportion
payment_amount_converted = total_amount_converted * payment_proportion payment_amount_converted = total_amount_converted * payment_proportion
payment_tax_amount = tax_amount * payment_proportion payment_tax_amount = tax_amount * payment_proportion
if float_is_zero(payment_amount, precision_rounding=self.currency_id.rounding): if float_is_zero(payment_amount, precision_rounding=self.currency_id.rounding):
continue continue
# Use the payment method's income account if specified, otherwise use original account # Determine the account to use based on whether this is a discount product
income_account_id = sale_key[0] # default 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 # Check if this sale key corresponds to a discount product
# We need to check if the account in the sale_key matches the discount product account
if discount_product_id:
# Get the discount product's income account
discount_product = self.env['product.product'].browse(discount_product_id)
discount_account = discount_product._get_product_accounts()['income']
if discount_account and discount_account.id == sale_key[0]:
# This is a discount product, use discount account if configured
if payment.payment_method_id.discount_account_id:
income_account_id = payment.payment_method_id.discount_account_id.id
elif payment.payment_method_id.income_account_id:
# This is a regular product, use income account if configured
income_account_id = payment.payment_method_id.income_account_id.id
# Ensure we have a valid account ID # Ensure we have a valid account ID
if not income_account_id: if not income_account_id:
continue continue
# Create a new key that includes the payment method # Create a new key that includes the payment method
new_sale_key = ( new_sale_key = (
# account (use payment method account if specified) # account (use payment method account if specified)
@ -90,12 +105,12 @@ class PosSession(models.Model):
# base tags (same as original) # base tags (same as original)
sale_key[3], sale_key[3],
) )
# Update the split sales data # Update the split sales data
split_sales[new_sale_key]['amount'] += payment_amount split_sales[new_sale_key]['amount'] += payment_amount
split_sales[new_sale_key]['amount_converted'] += payment_amount_converted split_sales[new_sale_key]['amount_converted'] += payment_amount_converted
split_sales[new_sale_key]['tax_amount'] += payment_tax_amount split_sales[new_sale_key]['tax_amount'] += payment_tax_amount
# Replace the original sales data with our split sales data # Replace the original sales data with our split sales data
data['sales'] = split_sales data['sales'] = split_sales
return data return data

View File

@ -7,6 +7,7 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//group[@name='Payment methods']/group" position="inside"> <xpath expr="//group[@name='Payment methods']/group" position="inside">
<field name="income_account_id" domain="[('deprecated', '=', False)]"/> <field name="income_account_id" domain="[('deprecated', '=', False)]"/>
<field name="discount_account_id" domain="[('deprecated', '=', False)]"/>
</xpath> </xpath>
</field> </field>
</record> </record>