Refactor 100% discount accounting by removing custom journal entries from pos_session and implementing dynamic account mapping in pos_order_line.
This commit is contained in:
parent
6640b0bc98
commit
d975966b70
@ -24,8 +24,8 @@ This module modifies the loyalty reward discount calculation in POS to apply dis
|
|||||||
|
|
||||||
### Backend Changes
|
### Backend Changes
|
||||||
|
|
||||||
- Extended `pos.session` (`models/pos_session.py`) to generate additional journal entry lines for 0-value orders.
|
- Extended `pos.order.line` (`models/pos_order_line.py`) to override `_get_income_account`. For 100% discount orders, this dynamically maps standard item lines to the custom Income Account and discount reward lines to the custom Expense Account during standard POS session aggregation, preventing double journal entries.
|
||||||
- Extended `res.config.settings` to allow configuration of Income and Expense accounts for 100% discounts.
|
- Extended `res.config.settings` (`models/res_config_settings.py`) to allow configuration of Income and Expense accounts for 100% discounts.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
from . import pos_config
|
from . import pos_config
|
||||||
from . import pos_session
|
from . import pos_session
|
||||||
from . import res_config_settings
|
from . import res_config_settings
|
||||||
|
from . import pos_order_line
|
||||||
|
|||||||
32
models/pos_order_line.py
Normal file
32
models/pos_order_line.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from odoo import models, api
|
||||||
|
from odoo.tools import float_is_zero
|
||||||
|
|
||||||
|
class PosOrderLine(models.Model):
|
||||||
|
_inherit = 'pos.order.line'
|
||||||
|
|
||||||
|
def _get_income_account(self, **kwargs):
|
||||||
|
"""
|
||||||
|
Dynamically route the income account for 100% discount orders
|
||||||
|
if the custom discount_100 accounts are configured.
|
||||||
|
"""
|
||||||
|
self.ensure_one()
|
||||||
|
|
||||||
|
# If the whole order is essentially 0 (100% discount):
|
||||||
|
if float_is_zero(self.order_id.amount_total, precision_rounding=self.order_id.currency_id.rounding):
|
||||||
|
# Check if custom accounts are configured
|
||||||
|
income_account = self.order_id.config_id.discount_100_income_account_id
|
||||||
|
expense_account = self.order_id.config_id.discount_100_expense_account_id
|
||||||
|
|
||||||
|
if income_account and expense_account:
|
||||||
|
# If this line is an income/product line (positive value)
|
||||||
|
if self.price_subtotal > 0:
|
||||||
|
return income_account
|
||||||
|
|
||||||
|
# If this line is the discount/reward line (negative value)
|
||||||
|
elif self.price_subtotal < 0:
|
||||||
|
return expense_account
|
||||||
|
|
||||||
|
# Fallback to standard Odoo logic
|
||||||
|
return super(PosOrderLine, self)._get_income_account(**kwargs)
|
||||||
@ -4,77 +4,7 @@ from odoo.tools import float_is_zero
|
|||||||
class PosSession(models.Model):
|
class PosSession(models.Model):
|
||||||
_inherit = 'pos.session'
|
_inherit = 'pos.session'
|
||||||
|
|
||||||
def _create_account_move(self, balancing_account=False, amount_to_balance=0, bank_payment_method_diffs=None):
|
# The manual creation of journal entries for 100% discount orders
|
||||||
"""
|
# has been removed because it duplicates the aggregated entries that
|
||||||
Extend _create_account_move to generate additional journal entry lines
|
# Odoo POS natively creates when closing a session. The mapping is
|
||||||
for 100% discount orders (where total amount is 0).
|
# instead handled at the pos.order.line level dynamically.
|
||||||
"""
|
|
||||||
# Call super to generate the standard move
|
|
||||||
data = super(PosSession, self)._create_account_move(balancing_account, amount_to_balance, bank_payment_method_diffs)
|
|
||||||
|
|
||||||
if not self.config_id.discount_100_income_account_id or not self.config_id.discount_100_expense_account_id:
|
|
||||||
return data
|
|
||||||
|
|
||||||
# Identify orders with 0 absolute paid amount but non-zero gross amount
|
|
||||||
# We look for orders where amount_total is near zero.
|
|
||||||
# Note: 100% discount orders have amount_total = 0.
|
|
||||||
|
|
||||||
MoveLine = data.get('MoveLine')
|
|
||||||
income_account = self.config_id.discount_100_income_account_id
|
|
||||||
expense_account = self.config_id.discount_100_expense_account_id
|
|
||||||
|
|
||||||
# Helper to convert amount to company currency if needed, similar to Odoo's internals
|
|
||||||
def _get_amounts(amount, date):
|
|
||||||
return self._update_amounts({'amount': 0, 'amount_converted': 0}, {'amount': amount}, date)
|
|
||||||
|
|
||||||
zero_value_moves = []
|
|
||||||
|
|
||||||
for order in self._get_closed_orders():
|
|
||||||
if float_is_zero(order.amount_total, precision_rounding=self.currency_id.rounding):
|
|
||||||
# Calculate gross amount (price before discount logic applied, or sum of positive lines)
|
|
||||||
# Since it's 100% discount, the "Gross Value" we want to record is roughly the sum
|
|
||||||
# of the products' prices *before* they were wiped out.
|
|
||||||
# However, in our new line-by-line strategy, we have:
|
|
||||||
# Item A: $100
|
|
||||||
# Discount A: -$100
|
|
||||||
# Net: $0
|
|
||||||
# We want to record: Credit Income $100, Debit Expense $100.
|
|
||||||
|
|
||||||
# Calculate the exact discount amount applied by loyalty rewards
|
|
||||||
# This avoids treating downpayments or refunds as "100% Discount Income"
|
|
||||||
discount_amount = sum(
|
|
||||||
abs(line.price_subtotal)
|
|
||||||
for line in order.lines
|
|
||||||
if line.price_subtotal < 0 and (getattr(line, 'is_reward_line', False) or getattr(line, 'reward_id', False))
|
|
||||||
)
|
|
||||||
|
|
||||||
if float_is_zero(discount_amount, precision_rounding=self.currency_id.rounding):
|
|
||||||
continue
|
|
||||||
|
|
||||||
amounts = _get_amounts(discount_amount, order.date_order)
|
|
||||||
|
|
||||||
# Create Credit Line (Income)
|
|
||||||
# We use _credit_amounts helper logic style manually
|
|
||||||
credit_vals = {
|
|
||||||
'name': _('100%% Discount Income: %s') % order.name,
|
|
||||||
'account_id': income_account.id,
|
|
||||||
'move_id': self.move_id.id,
|
|
||||||
'partner_id': order.partner_id.id or False,
|
|
||||||
}
|
|
||||||
credit_vals.update(self._credit_amounts(credit_vals, amounts['amount'], amounts['amount_converted']))
|
|
||||||
zero_value_moves.append(credit_vals)
|
|
||||||
|
|
||||||
# Create Debit Line (Expense/Discount)
|
|
||||||
debit_vals = {
|
|
||||||
'name': _('100%% Discount Expense: %s') % order.name,
|
|
||||||
'account_id': expense_account.id,
|
|
||||||
'move_id': self.move_id.id,
|
|
||||||
'partner_id': order.partner_id.id or False,
|
|
||||||
}
|
|
||||||
debit_vals.update(self._debit_amounts(debit_vals, amounts['amount'], amounts['amount_converted']))
|
|
||||||
zero_value_moves.append(debit_vals)
|
|
||||||
|
|
||||||
if zero_value_moves:
|
|
||||||
MoveLine.create(zero_value_moves)
|
|
||||||
|
|
||||||
return data
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user