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') 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. # We can sum the positive lines to get the "Sale Value". gross_amount = sum( line.price_subtotal_incl for line in order.lines if line.price_subtotal_incl > 0 ) if float_is_zero(gross_amount, precision_rounding=self.currency_id.rounding): continue amounts = _get_amounts(gross_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