refactor: remove redundant accounting logic and configurations for POS loyalty discounts

This commit is contained in:
Suherdy Yacob 2026-04-27 14:13:03 +07:00
parent a7c6781af5
commit b2964f66ec
7 changed files with 3 additions and 138 deletions

View File

@ -8,7 +8,7 @@ This module modifies the loyalty reward discount calculation in POS to apply dis
2. **Tax-Exclusive Display**: Discount values are displayed as tax-exclusive in the POS receipt. 2. **Tax-Exclusive Display**: Discount values are displayed as tax-exclusive in the POS receipt.
3. **Proper Accounting Entries**: Accounting entries are created with tax only on the credit side, ensuring compliance with accounting standards.
## Technical Changes ## Technical Changes
@ -17,12 +17,7 @@ This module modifies the loyalty reward discount calculation in POS to apply dis
- Modified `static/src/overrides/models/loyalty.js` to calculate discounts on tax-exclusive amounts - Modified `static/src/overrides/models/loyalty.js` to calculate discounts on tax-exclusive amounts
- Ensured discount line values are tax-exclusive for display purposes - Ensured discount line values are tax-exclusive for display purposes
### Backend Changes
- Created `models/pos_order.py` to handle accounting entries for loyalty discounts
- Created `models/loyalty_reward.py` to ensure discount products are properly configured
- Created `models/account_move.py` to ensure discount lines in account moves are tax-exclusive
- Created `models/pos_session.py` to handle session-level accounting for loyalty discounts
## Installation ## Installation

View File

@ -8,9 +8,7 @@
This module modifies the loyalty reward discount calculation in POS to apply discounts before tax calculation. This module modifies the loyalty reward discount calculation in POS to apply discounts before tax calculation.
""", """,
"depends": ["point_of_sale", "pos_loyalty"], "depends": ["point_of_sale", "pos_loyalty"],
"data": [ "data": [],
"views/res_config_settings_views.xml",
],
"assets": { "assets": {
"point_of_sale._assets_pos": [ "point_of_sale._assets_pos": [
'pos_loyalty_discount_before_tax/static/src/overrides/models/loyalty.js', 'pos_loyalty_discount_before_tax/static/src/overrides/models/loyalty.js',

View File

@ -1,3 +1 @@
from . import pos_config # Empty init as redundant accounting logic was removed
from . import pos_session
from . import res_config_settings

View File

@ -1,17 +0,0 @@
from odoo import fields, models
class PosConfig(models.Model):
_inherit = 'pos.config'
discount_100_income_account_id = fields.Many2one(
'account.account',
string='100% Discount Income Account',
help='Account used for Income when an order has a 100% discount (0 total).',
domain="[('deprecated', '=', False)]"
)
discount_100_expense_account_id = fields.Many2one(
'account.account',
string='100% Discount Expense Account',
help='Account used for Expense/Discount when an order has a 100% discount (0 total).',
domain="[('deprecated', '=', False)]"
)

View File

@ -1,74 +0,0 @@
from odoo import models, _
from odoo.tools import float_is_zero
class PosSession(models.Model):
_inherit = 'pos.session'
def _create_account_move(self, balancing_account=False, amount_to_balance=0, bank_payment_method_diffs=None):
"""
Extend _create_account_move to generate additional journal entry lines
for 100% discount orders (where total amount is 0).
"""
# 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')
if not MoveLine:
# Depending on Odoo 19's internal structure changes, fallback / ensure MoveLine exists. Odoo 17 returns a dict with 'MoveLine'.
MoveLine = self.env['account.move.line']
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 the exact discount amount applied by loyalty rewards
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 and self.move_id:
MoveLine.with_context(check_move_validity=False).create(zero_value_moves)
return data

View File

@ -1,13 +0,0 @@
from odoo import fields, models
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
pos_discount_100_income_account_id = fields.Many2one(
related='pos_config_id.discount_100_income_account_id',
readonly=False,
)
pos_discount_100_expense_account_id = fields.Many2one(
related='pos_config_id.discount_100_expense_account_id',
readonly=False,
)

View File

@ -1,22 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="res_config_settings_view_form" model="ir.ui.view">
<field name="name">res.config.settings.view.form.inherit.pos.loyalty.discount.100</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="point_of_sale.res_config_settings_view_form"/>
<field name="arch" type="xml">
<xpath expr="//block[@id='pos_accounting_section']" position="inside">
<setting id="discount_100_account" title="Accounting entries for 100% discount orders" string="100% Discount Accounting">
<div class="row">
<label string="Income Account" for="pos_discount_100_income_account_id" class="col-lg-3 o_light_label"/>
<field name="pos_discount_100_income_account_id"/>
</div>
<div class="row">
<label string="Expense/Discount Account" for="pos_discount_100_expense_account_id" class="col-lg-3 o_light_label"/>
<field name="pos_discount_100_expense_account_id"/>
</div>
</setting>
</xpath>
</field>
</record>
</odoo>