[REF] sale_payment: clean code related to so confirmation and invoice generation

Indeed this code is difficult to understand and uses unnecessary
variables. Both confirm_so and generate_and_pay_invoice methods now work
on payment.transaction records as they belong to that model. Finally
less code is put in the try/except of confirm_so to avoid hiding real
errors and issues.

One interesting thing would be to correctly manage so confirmation errors
and mail sending errors. This is currently not done and will maybe be
done in future commits.
This commit is contained in:
Thibault Delavallée
2017-06-06 11:04:34 +02:00
parent b5146643b5
commit 8e733b22f8
+33 -33
View File
@@ -33,61 +33,61 @@ class PaymentTransaction(models.Model):
if tx:
# Auto-confirm SO if necessary
tx._confirm_so(acquirer_name=acquirer_name)
tx._confirm_so()
return res
def _confirm_so(self, acquirer_name=False):
def _confirm_so(self):
for tx in self:
# check tx state, confirm the potential SO
if not tx.sale_order_id or tx.sale_order_id.state not in ['draft', 'sent']:
# _logger.warning('<%s> transaction incorrect sale order %s (ID %s, state %s)', tx.acquirer_id.provider, tx.sale_order_id.name, tx.sale_order_id.id, tx.sale_order_id.state)
continue
if not float_compare(tx.amount, tx.sale_order_id.amount_total, 2) == 0:
_logger.warning('<%s> transaction MISMATCH for order %s (ID %s)', tx.acquirer_id.provider, tx.sale_order_id.name, tx.sale_order_id.id)
continue
try:
# check tx state, confirm the potential SO
if 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 not acquirer_name:
acquirer_name = tx.sale_order_id.payment_acquirer_id.provider or 'unknown'
if tx.state == 'authorized' and tx.acquirer_id.capture_manually:
_logger.info('<%s> transaction authorized, 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.state == 'done':
_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()
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)
if tx.state == 'authorized' and tx.acquirer_id.capture_manually:
_logger.info('<%s> transaction authorized, auto-confirming order %s (ID %s)', tx.acquirer_id.provider, tx.sale_order_id.name, tx.sale_order_id.id)
tx.sale_order_id.with_context(send_email=True).action_confirm()
if tx.state == 'done':
_logger.info('<%s> transaction completed, auto-confirming order %s (ID %s)', tx.acquirer_id.provider, tx.sale_order_id.name, tx.sale_order_id.id)
tx.sale_order_id.with_context(send_email=True).action_confirm()
tx._generate_and_pay_invoice()
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)', tx.acquirer_id.provider, 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)', tx.acquirer_id.provider, 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 '')
def _generate_and_pay_invoice(self, tx, acquirer_name):
tx.sale_order_id._force_lines_to_invoice_policy_order()
def _generate_and_pay_invoice(self):
self.sale_order_id._force_lines_to_invoice_policy_order()
# force company to ensure journals/accounts etc. are correct
# company_id needed for default_get on account.journal
# force_company needed for company_dependent fields
ctx_company = {'company_id': tx.sale_order_id.company_id.id,
'force_company': tx.sale_order_id.company_id.id}
created_invoice = tx.sale_order_id.with_context(**ctx_company).action_invoice_create()
ctx_company = {'company_id': self.sale_order_id.company_id.id,
'force_company': self.sale_order_id.company_id.id}
created_invoice = self.sale_order_id.with_context(**ctx_company).action_invoice_create()
created_invoice = self.env['account.invoice'].browse(created_invoice).with_context(**ctx_company)
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)
self.acquirer_id.provider, created_invoice.name, created_invoice.id, self.sale_order_id.name, self.sale_order_id.id)
created_invoice.action_invoice_open()
if not tx.acquirer_id.journal_id:
if not self.acquirer_id.journal_id:
default_journal = self.env['account.journal'].search([('type', '=', 'bank')], limit=1)
if not default_journal:
_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)
tx.acquirer_id.journal_id = default_journal
created_invoice.pay_and_reconcile(tx.acquirer_id.journal_id, pay_amount=created_invoice.amount_total)
self.acquirer_id.provider, self.sale_order_id.name, self.sale_order_id.id)
self.acquirer_id.journal_id = default_journal
created_invoice.pay_and_reconcile(self.acquirer_id.journal_id, pay_amount=created_invoice.amount_total)
if created_invoice.payment_ids:
created_invoice.payment_ids[0].payment_transaction_id = tx
created_invoice.payment_ids[0].payment_transaction_id = self
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)
self.acquirer_id.provider, self.sale_order_id.name, self.sale_order_id.id)