Files
odoo_source/addons/website_payment/models/payment.py
T
Joren Van Onder 65b1220008 [IMP] website_payment: when invoicing always ignore invoice policy
Sale orders created through the website that have to be automatically
invoiced should ignore the delivery invoicing policy.

Otherwise you can end up with either an invoice not being generated at
all. This means the user has to manually generate and add the payment to
it. Even worse is if only some purchased products have invoice policy
delivery. In this case a partial invoice would be generated to which the
payment would be added, leading to a mismatch between invoice total and
payment amount.
2016-06-17 13:09:18 +02:00

75 lines
4.0 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import logging
from odoo import api, fields, models
from odoo.tools import float_compare
_logger = logging.getLogger(__name__)
class PaymentAcquirer(models.Model):
_name = 'payment.acquirer'
_inherit = ['payment.acquirer','website.published.mixin']
class PaymentTransaction(models.Model):
_inherit = 'payment.transaction'
# link with the sale order
sale_order_id = fields.Many2one('sale.order', string='Sale Order')
def _generate_and_pay_invoice(self, tx, acquirer_name):
tx.sale_order_id._force_lines_to_invoice_policy_order()
created_invoice = tx.sale_order_id.action_invoice_create()
created_invoice = self.env['account.invoice'].browse(created_invoice)
if created_invoice:
_logger.info('<%s> transaction completed, auto-generated invoice %s (ID %s) for %s (ID %s)',
acquirer_name, created_invoice.name, created_invoice.id, tx.sale_order_id.name, tx.sale_order_id.id)
created_invoice.signal_workflow('invoice_open')
if tx.acquirer_id.journal_id:
created_invoice.pay_and_reconcile(tx.acquirer_id.journal_id, pay_amount=created_invoice.amount_total)
if created_invoice.payment_ids:
created_invoice.payment_ids[0].payment_transaction_id = tx
else:
_logger.warning('<%s> transaction completed, could not auto-generate payment for %s (ID %s) (no journal set on acquirer)',
acquirer_name, tx.sale_order_id.name, tx.sale_order_id.id)
else:
_logger.warning('<%s> transaction completed, could not auto-generate invoice for %s (ID %s)',
acquirer_name, tx.sale_order_id.name, tx.sale_order_id.id)
@api.model
def form_feedback(self, data, acquirer_name):
""" Override to confirm the sale order, if defined, and if the transaction
is done. """
tx = None
res = super(PaymentTransaction, self).form_feedback(data, acquirer_name)
# fetch the tx, check its state, confirm the potential SO
try:
tx_find_method_name = '_%s_form_get_tx_from_data' % acquirer_name
if hasattr(self, tx_find_method_name):
tx = getattr(self, tx_find_method_name)(data)
_logger.info('<%s> transaction processed: tx ref:%s, tx amount: %s', acquirer_name, tx.reference if tx else 'n/a', tx.amount if tx else 'n/a')
if tx and tx.sale_order_id and tx.sale_order_id.state in ['draft', 'sent']:
# verify SO/TX match, excluding tx.fees which are currently not included in SO
amount_matches = float_compare(tx.amount, tx.sale_order_id.amount_total, 2) == 0
if amount_matches:
if tx.state == 'done' and tx.acquirer_id.auto_confirm in ['confirm_so', 'generate_and_pay_invoice']:
_logger.info('<%s> transaction completed, auto-confirming order %s (ID %s)', acquirer_name, tx.sale_order_id.name, tx.sale_order_id.id)
tx.sale_order_id.with_context(send_email=True).action_confirm()
if tx.acquirer_id.auto_confirm == 'generate_and_pay_invoice':
self._generate_and_pay_invoice(tx, acquirer_name)
elif tx.state not in ['cancel', 'error'] and tx.sale_order_id.state == 'draft':
_logger.info('<%s> transaction pending/to confirm manually, sending quote email for order %s (ID %s)', acquirer_name, tx.sale_order_id.name, tx.sale_order_id.id)
tx.sale_order_id.force_quotation_send()
else:
_logger.warning('<%s> transaction MISMATCH for order %s (ID %s)', acquirer_name, tx.sale_order_id.name, tx.sale_order_id.id)
except Exception:
_logger.exception('Fail to confirm the order or send the confirmation email%s', tx and ' for the transaction %s' % tx.reference or '')
return res