trytond-account_payment_gat.../gateway.py

325 lines
11 KiB
Python

# This file is part account_payment_gateway module for Tryton.
# The COPYRIGHT file at the top level of this repository contains
# the full copyright notices and license terms.
from uuid import uuid4
from datetime import datetime
from trytond.model import ModelSQL, ModelView, Workflow, fields
from trytond.pool import Pool
from trytond.pyson import Eval, If
from trytond.transaction import Transaction
from trytond.i18n import gettext
from trytond.exceptions import UserError
__all__ = ['AccountPaymentGateway', 'AccountPaymentGatewayTransaction']
READONLY_IF_NOT_DRAFT = {'readonly': Eval('state') != 'draft'}
class AccountPaymentGateway(ModelSQL, ModelView):
"Account Payment Gateway"
__name__ = 'account.payment.gateway'
name = fields.Char('Name', required=True)
company = fields.Many2One('company.company', 'Company', required=True,
select=True, readonly=True, domain=[
('id', If(Eval('context', {}).contains('company'), '=', '!='),
Eval('context', {}).get('company', 0)),
])
active = fields.Boolean('Active')
method = fields.Selection('get_methods', 'Method', required=True)
mode = fields.Selection([
('live', 'Live'),
('sandbox', 'Sandbox'),
], 'Mode', required=True)
journal = fields.Many2One('account.journal', 'Journal', required=True)
journal_writeoff = fields.Many2One('account.journal', 'Write Off Journal',
required=True)
writeoff_amount_percent = fields.Numeric('Write Off (%)', digits=(8, 4),
required=True)
from_transactions = fields.DateTime('From Transactions',
help='This date is last import (filter)', required=True)
to_transactions = fields.DateTime('To Transactions',
help='This date is to import (filter)')
scheduler = fields.Boolean('Scheduler',
help='Import transactions from Gateway')
@classmethod
def __setup__(cls):
super(AccountPaymentGateway, cls).__setup__()
cls._buttons.update({
'import_transactions': {},
})
@staticmethod
def default_company():
return Transaction().context.get('company')
@staticmethod
def default_active():
return True
@staticmethod
def default_from_transactions():
return datetime.now()
@classmethod
def get_methods(cls):
return []
@staticmethod
def default_mode():
return 'live'
@classmethod
@ModelView.button
def import_transactions(self, gateways):
"""
Import Transactions from Gateway APP
"""
for gateway in gateways:
import_transaction = getattr(gateway, 'import_transactions_%s' %
gateway.method)
import_transaction()
@classmethod
def import_gateway(cls):
"""
Import gateways transactions:
"""
gateways = cls.search([
('scheduler', '=', True),
])
cls.import_transactions(gateways)
return True
class AccountPaymentGatewayTransaction(Workflow, ModelSQL, ModelView):
'''Account Payment Gateway Transaction'''
__name__ = 'account.payment.gateway.transaction'
_rec_name = 'uuid'
uuid = fields.Char('UUID', required=True, readonly=True)
description = fields.Char('Description', states=READONLY_IF_NOT_DRAFT,
depends=['state'])
origin = fields.Reference('Origin', selection='get_origin', select=True,
states=READONLY_IF_NOT_DRAFT, depends=['state'])
gateway = fields.Many2One('account.payment.gateway', 'Gateway',
required=True, states=READONLY_IF_NOT_DRAFT, depends=['state'],
ondelete='RESTRICT')
reference_gateway = fields.Char('Reference Gateway',
states=READONLY_IF_NOT_DRAFT, depends=['state'])
authorisation_code = fields.Char('Authorisation Code',
states=READONLY_IF_NOT_DRAFT, depends=['state'])
date = fields.Date('Date', required=True,
states=READONLY_IF_NOT_DRAFT, depends=['state'])
company = fields.Many2One('company.company', 'Company', required=True,
states=READONLY_IF_NOT_DRAFT, select=True,
domain=[
('id', If(Eval('context', {}).contains('company'), '=', '!='),
Eval('context', {}).get('company', -1)),
], depends=['state'])
party = fields.Many2One('party.party', 'Party', ondelete='RESTRICT',
depends=['state'], states=READONLY_IF_NOT_DRAFT)
amount = fields.Numeric('Amount', digits=(16, Eval('currency_digits', 2)),
required=True, depends=['state', 'currency_digits'],
states=READONLY_IF_NOT_DRAFT)
currency = fields.Many2One('currency.currency', 'Currency',
required=True, depends=['state'], states=READONLY_IF_NOT_DRAFT)
currency_digits = fields.Function(fields.Integer('Currency Digits'),
'on_change_with_currency_digits')
method = fields.Function(fields.Char('Payment Gateway Method'),
'get_method')
state = fields.Selection([
('draft', 'Draft'),
('pending', 'Pending'),
('failed', 'Failed'),
('authorized', 'Authorized'),
('done', 'Done'),
('cancelled', "Cancelled"),
('refunded', 'Refunded'),
], 'State', readonly=True)
log = fields.Text("Log", depends=['state'], states=READONLY_IF_NOT_DRAFT)
@classmethod
def __setup__(cls):
super(AccountPaymentGatewayTransaction, cls).__setup__()
cls._order.insert(0, ('date', 'DESC'))
cls._transitions |= set((
('draft', 'cancelled'),
('draft', 'pending'),
('draft', 'failed'),
('draft', 'authorized'),
('draft', 'done'),
('cancelled', 'draft'),
('failed', 'draft'),
('pending', 'cancelled'),
('pending', 'authorized'),
('pending', 'done'),
('authorized', 'cancelled'),
('authorized', 'done'),
('authorized', 'refunded'),
('done', 'cancelled'),
('done', 'refunded'),
))
cls._buttons.update({
'cancel': {
'invisible': ~Eval('state').in_([
'draft', 'pending', 'failed', 'authorized', 'done',
]),
},
'draft': {
'invisible': ~Eval('state').in_(['cancelled']),
},
'pending': {
'invisible': ~Eval('state').in_(['draft']),
},
'authorized': {
'invisible': ~Eval('state').in_(['draft', 'pending']),
},
'confirm': {
'invisible': ~Eval('state').in_([
'draft', 'pending', 'authorized',
]),
},
'refund': {
'invisible': ~Eval('state').in_([
'authorized', 'done',
]),
},
})
@classmethod
def __register__(cls, module_name):
cursor = Transaction().connection.cursor()
sql_table = cls.__table__()
super(AccountPaymentGatewayTransaction, cls).__register__(module_name)
# Migration from 5.6: rename state cancel to cancelled
cursor.execute(*sql_table.update(
[sql_table.state], ['cancelled'],
where=sql_table.state == 'cancel'))
@staticmethod
def default_uuid():
return uuid4()
@staticmethod
def default_date():
Date = Pool().get('ir.date')
return Date.today()
@staticmethod
def default_company():
return Transaction().context.get('company')
@staticmethod
def default_currency():
Company = Pool().get('company.company')
if Transaction().context.get('company'):
company = Company(Transaction().context['company'])
return company.currency.id
@staticmethod
def default_state():
return 'draft'
@classmethod
def _get_origin(cls):
'Return list of Model names for origin Reference'
return []
@classmethod
def get_origin(cls):
IrModel = Pool().get('ir.model')
models = cls._get_origin()
models = IrModel.search([('model', 'in', models)])
return [(None, '')] + [(m.model, m.name) for m in models]
@classmethod
def copy(cls, transactions, default=None):
if default is None:
default = {}
default = default.copy()
default['uuid'] = cls.default_uuid()
return super(AccountPaymentGatewayTransaction, cls).copy(
transactions, default=default)
@classmethod
def delete(cls, transactions):
# Cancel before delete
cls.cancel(transactions)
for transaction in transactions:
if transaction.state != 'cancelled':
raise UserError(gettext('account_payment_gateway.delete_cancel',
transaction=transaction.rec_name))
super(AccountPaymentGatewayTransaction, cls).delete(transactions)
@fields.depends('currency')
def on_change_with_currency_digits(self, name=None):
if self.currency:
return self.currency.digits
return 2
def get_method(self, name=None):
'Return the method based on the gateway'
return self.gateway.method
@classmethod
@ModelView.button
@Workflow.transition('cancelled')
def cancel(cls, transactions):
for transaction in transactions:
method_name = 'cancel_%s' % transaction.gateway.method
if hasattr(transaction, method_name):
getattr(transaction, method_name)()
pass
@classmethod
@ModelView.button
@Workflow.transition('draft')
def draft(cls, transactions):
for transaction in transactions:
method_name = 'draft_%s' % transaction.gateway.method
if hasattr(transaction, method_name):
getattr(transaction, method_name)()
pass
@classmethod
@ModelView.button
@Workflow.transition('pending')
def pending(cls, transactions):
for transaction in transactions:
method_name = 'pending_%s' % transaction.gateway.method
if hasattr(transaction, method_name):
getattr(transaction, method_name)()
pass
@classmethod
@ModelView.button
@Workflow.transition('authorized')
def authorized(cls, transactions):
for transaction in transactions:
method_name = 'authorized_%s' % transaction.gateway.method
if hasattr(transaction, method_name):
getattr(transaction, method_name)()
pass
@classmethod
@ModelView.button
@Workflow.transition('done')
def confirm(cls, transactions):
for transaction in transactions:
method_name = 'confirm_%s' % transaction.gateway.method
if hasattr(transaction, method_name):
getattr(transaction, method_name)()
pass
@classmethod
@ModelView.button
@Workflow.transition('refunded')
def refund(cls, transactions):
for transaction in transactions:
method_name = 'refund_%s' % transaction.gateway.method
if hasattr(transaction, method_name):
getattr(transaction, method_name)()
pass