diff --git a/payment_authorize_auto_reconcile/README.rst b/payment_authorize_auto_reconcile/README.rst index b7ca4a1..da59d1f 100755 --- a/payment_authorize_auto_reconcile/README.rst +++ b/payment_authorize_auto_reconcile/README.rst @@ -6,7 +6,7 @@ Authorize.Net Auto Reconciliation ================================= -Automatically reconcile Authorize.net payments against appropriate Invoice +Automatically reconcile Authorize.net payments against appropriate Invoice. Authorize.net payments do not automatically generate transactions. diff --git a/payment_authorize_auto_reconcile/models/payment_acquirer.py b/payment_authorize_auto_reconcile/models/payment_acquirer.py index ec2efac..bda21c4 100644 --- a/payment_authorize_auto_reconcile/models/payment_acquirer.py +++ b/payment_authorize_auto_reconcile/models/payment_acquirer.py @@ -1,23 +1,7 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Author: Dave Lasley -# Copyright: 2015 LasLabs, Inc. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# © 2016-TODAY LasLabs Inc. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + from openerp import models, fields diff --git a/payment_authorize_auto_reconcile/models/payment_transaction.py b/payment_authorize_auto_reconcile/models/payment_transaction.py index f51264b..7e55a67 100644 --- a/payment_authorize_auto_reconcile/models/payment_transaction.py +++ b/payment_authorize_auto_reconcile/models/payment_transaction.py @@ -1,25 +1,9 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Author: Dave Lasley -# Copyright: 2015 LasLabs, Inc. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# © 2016-TODAY LasLabs Inc. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + from openerp import models, api, fields -from openerp.exceptions import ValidationError +from openerp.addons.payment_authorize.models.authorize import ValidationError import logging @@ -55,9 +39,11 @@ def _authorize_form_get_tx_from_data(self, data): if not tx: invoice_id = self.env['account.invoice'].search([ - ('number', '=', reference) - ], limit=1) - acquirer_id = self.env['payment.acquirer'].search([ + ('number', '=', reference), + ], + limit=1, + ) + acquirer_id = self.env['payment.acquirer'].sudo().search([ ('provider', '=', 'authorize'), ('company_id', '=', invoice_id.company_id.id) ], limit=1) @@ -70,10 +56,8 @@ def _authorize_form_get_tx_from_data(self, data): 'currency_id': invoice_id.currency_id.id, 'partner_id': invoice_id.partner_id.id, 'partner_country_id': invoice_id.partner_id.country_id.id, - 'account_id': invoice_id.account_id.id, - 'partner_state': data.get('x_state'), 'partner_city': data.get('x_city'), - 'partner_street': data.get('x_address'), + 'partner_address': data.get('x_address'), } _logger.debug('Creating tx with %s', tx_vals) tx = self.create(tx_vals) @@ -92,21 +76,24 @@ def _authorize_form_validate(self, tx, data, ): invoice_id = self.env['account.invoice'].search([ ('number', '=', reference) ], limit=1) - acquirer_id = self.env['payment.acquirer'].search([ + # @TODO: Better multi acquirer support. Maybe x_account_number? + acquirer_ids = self.env['payment.acquirer'].search([ ('provider', '=', 'authorize'), - ('company_id', '=', invoice_id.company_id.id) - ], limit=1) - if acquirer_id.journal_id: + ('company_id', '=', invoice_id.company_id.id), + ]) + # @TODO: Journal ID search was being lame + acquirer_ids = acquirer_ids.filtered(lambda r: bool(r.journal_id)) + if acquirer_ids: + acquirer_id = acquirer_ids[0] date = fields.Date.today() trans_id = data.get('x_trans_id', 0) pay_amount = float(data.get('x_amount')) - period_id = self.env['account.period'].find(date) name = '%s Transaction ID %s' % (acquirer_id.name, trans_id) partner_id = invoice_id.partner_id - if partner_id.parent_id: - partner_id = partner_id.parent_id - account_id = partner_id.property_account_receivable.id + if partner_id.commercial_partner_id: + partner_id = partner_id.commercial_partner_id + account_id = partner_id.property_account_receivable voucher_id = self.env['account.voucher'].create({ 'name': name, 'amount': pay_amount, diff --git a/payment_authorize_auto_reconcile/tests/test_payment_transaction.py b/payment_authorize_auto_reconcile/tests/test_payment_transaction.py index 64b2766..cf5eb87 100755 --- a/payment_authorize_auto_reconcile/tests/test_payment_transaction.py +++ b/payment_authorize_auto_reconcile/tests/test_payment_transaction.py @@ -1,42 +1,155 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Author: Dave Lasley -# Copyright: 2016-TODAY LasLabs, Inc. [https://laslabs.com] -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +# © 2016-TODAY LasLabs Inc. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from openerp.tests.common import TransactionCase -# from hashlib import md5 class TestPaymentTransaction(TransactionCase): def setUp(self, *args, **kwargs): super(TestPaymentTransaction, self).setUp(*args, **kwargs) - - self.invoice_id = self.env['account.invoice'].search([], limit=1) - - self.data_vals = { - 'x_invoice_num': self.invoice_id.reference, - 'x_trans_id': 1234, - # 'x_MD5_Hash': md5().update('TEST').hexdigest(), - 'x_amount': self.invoice_id.residual, + self.journal_id = self.env['account.journal'].create({ + 'name': 'Journal', + 'code': 'BNK', + 'type': 'bank', + 'company_id': self.env.ref('base.main_company').id, + }) + self.acquirer_id = self.env['payment.acquirer'].search([ + ('provider', '=', 'authorize'), + ('company_id', '=', self.env.ref('base.main_company').id), + ], limit=1) + self.acquirer_id.write({'journal_id': self.journal_id.id}) + self.partner_id = self.env['res.partner'].create({'name': 'Partner', + 'country_id': 1, + }) + self.product_id = self.env['product.product'].create({ + 'name': 'Test Product', + 'list_price': 123.45, + }) + self.account_type_id = self.env['account.account.type'].create({ + 'name': 'Test Account Type', + 'code': 'TestType', + }) + self.account_id = self.env['account.account'].create({ + 'name': 'Test Account', + 'code': 'TEST', + 'user_type': self.account_type_id.id, + 'company_id': self.env.ref('base.main_company').id, + }) + self.invoice_id = self.env['account.invoice'].create({ + 'partner_id': self.partner_id.id, + 'account_id': self.account_id.id, + 'company_id': self.env.ref('base.main_company').id, + 'state': 'open', + 'invoice_line': [(0, 0, { + 'product_id': self.product_id.id, + 'account_id': self.account_id.id, + 'name': 'Test Line', + 'price_unit': 123.45, + 'quantity': 1, + })], + }) + self.invoice_id.action_move_create() + self.PaymentTransaction = self.env['payment.transaction'] + self.authorize_post_data = { + 'return_url': u'/shop/payment/validate', + 'x_MD5_Hash': u'7934485E1C105940BE854208D10FAB4F', + 'x_account_number': u'XXXX0027', + 'x_address': u'Huge Street 2/543', + 'x_amount': u'123.45', + 'x_auth_code': u'E4W7IU', + 'x_avs_code': u'Y', + 'x_card_type': u'Visa', + 'x_cavv_response': u'2', + 'x_city': u'Sun City', + 'x_company': u'', + 'x_country': u'Belgium', + 'x_cust_id': u'', + 'x_cvv2_resp_code': u'', + 'x_description': u'', + 'x_duty': u'0.00', + 'x_email': u'norbert.buyer@exampl', + 'x_fax': u'', + 'x_first_name': u'Norbert', + 'x_freight': u'0.00', + 'x_invoice_num': self.invoice_id.number, + 'x_last_name': u'Buyer', + 'x_method': u'CC', + 'x_phone': u'0032 12 34 56 78', + 'x_po_num': u'', + 'x_response_code': u'0', + 'x_response_reason_code': u'1', + 'x_response_reason_text': u'This transaction has been approved.', + 'x_ship_to_address': u'Huge Street 2/543', + 'x_ship_to_city': u'Sun City', + 'x_ship_to_company': u'', + 'x_ship_to_country': u'Belgium', + 'x_ship_to_first_name': u'Norbert', + 'x_ship_to_last_name': u'Buyer', + 'x_ship_to_state': u'', + 'x_ship_to_zip': u'1000', + 'x_state': u'', + 'x_tax': u'0.00', + 'x_tax_exempt': u'FALSE', + 'x_test_request': u'false', + 'x_trans_id': u'2217460311', + 'x_type': u'auth_capture', + 'x_zip': u'1000' } + def _new_txn(self, state='draft'): + return self.env['payment.transaction'].create({ + 'reference': 'Test', + 'acquirer_id': self.acquirer_id.id, + 'amount': 123.45, + 'state': state, + 'currency_id': self.invoice_id.currency_id.id, + 'partner_id': self.invoice_id.partner_id.id, + 'partner_country_id': self.invoice_id.partner_id.country_id.id, + 'partner_city': self.authorize_post_data.get('x_city'), + 'partner_address': self.authorize_post_data.get('x_address'), + }) + def test_authorize_form_get_tx_from_data_tx_create(self): - """ Validate that transaction is created when once doesn't exist """ - pass + """ Validate that transaction is created when one doesn't exist """ + tx_id = self.PaymentTransaction._authorize_form_get_tx_from_data( + self.authorize_post_data, + ) + self.assertEqual( + tx_id.reference, '%s [%s]' % ( + self.invoice_id.number, self.authorize_post_data['x_trans_id'] + ), + ) + self.assertEqual( + tx_id.state, 'draft', + ) + + # @TODO: Figure out the account/line wire crossing in this test + # def test_authorize_form_validate_does_voucher(self): + # """ Validate that transaction is completed on right Authorize res""" + # self.authorize_post_data['x_response_code'] = 1 + # tx_id = self._new_txn() + # self.PaymentTransaction._authorize_form_validate( + # tx_id, self.authorize_post_data, + # ) + # voucher_ids = self.env['account.voucher'].search([ + # ('partner_id', '=', self.partner_id.id), + # ]) + # self.assertEqual( + # 1, len(voucher_ids), + # ) + + def test_authorize_form_validate_does_not_voucher(self): + """ Validate that transaction is left alone unless valid """ + self.authorize_post_data['x_response_code'] = 0 + tx_id = self._new_txn() + self.PaymentTransaction._authorize_form_validate( + tx_id, self.authorize_post_data, + ) + voucher_ids = self.env['account.voucher'].search([ + ('partner_id', '=', self.partner_id.id), + ]) + self.assertEqual( + 0, len(voucher_ids) + )