Exemplo n.º 1
0
    def setUp(self):
        super().setUp()
        self.admin = User.objects.create_superuser('admin',
                                                   '*****@*****.**',
                                                   'password')
        self.request_factory = RequestFactory()

        self.account = get_account(account_name='My Account')
        self.account.save()
        self.imported_payment = get_payment(
            identifier='My Payment 1',
            account=self.account,
            state=PaymentState.READY_TO_PROCESS,
            variable_symbol='VAR1',
            transaction_date=date(2019, 1, 1),
        )
        self.imported_payment.save()
        self.processed_payment = get_payment(
            identifier='My Payment 2',
            account=self.account,
            state=PaymentState.PROCESSED,
            variable_symbol='VAR2',
            processor='dummy',
            processing_error=PaymentProcessingError.DUPLICITY,
        )
        self.processed_payment.save()
        self.invoice = get_invoice(number='INV111222')
        self.invoice.save()
        self.invoice.payments.add(self.processed_payment)
        self.payment_client = get_client(handle='HANDLE',
                                         payment=self.processed_payment)
        self.payment_client.save()
Exemplo n.º 2
0
    def test_payments_from_to(self):
        """Test from/to parameters."""
        payment = get_payment(identifier='PAYMENT_1', account=self.account, state=PaymentState.INITIALIZED,
                              card_handler='dummy')
        payment.save()
        payment2 = get_payment(identifier='PAYMENT_2', account=self.account, state=PaymentState.INITIALIZED,
                               card_handler='dummy', create_time=datetime.date(2010, 1, 1))
        payment2.save()
        payment3 = get_payment(identifier='PAYMENT_3', account=self.account, state=PaymentState.INITIALIZED,
                               card_handler='dummy')
        payment3.save()

        # auto_add fields must be changed after first save:
        payment.create_time = datetime.date(2000, 1, 1)
        payment.save()
        payment2.create_time = datetime.date(2010, 1, 1)
        payment2.save()
        payment3.create_time = datetime.date(2020, 1, 1)
        payment3.save()

        call_command('get_card_payments_states', '--from', '2009-01-01 00:00', '--to', '2017-01-02 00:00')

        self.assertQuerysetEqual(BankPayment.objects.values_list('identifier', 'state').order_by('identifier'),
                                 [('PAYMENT_1', PaymentState.INITIALIZED.value),
                                  ('PAYMENT_2', PaymentState.READY_TO_PROCESS.value),
                                  ('PAYMENT_3', PaymentState.INITIALIZED.value)],
                                 transform=tuple)
Exemplo n.º 3
0
 def parse(self, bank_statement) -> List[BankPayment]:
     account = BankAccount.objects.get(account_number='123456/7890')
     return [
         get_payment(identifier='PAYMENT_1',
                     account=account,
                     variable_symbol='1234'),
         get_payment(identifier='PAYMENT_2',
                     account=account,
                     amount=Money('370.00', 'CZK')),
     ]
Exemplo n.º 4
0
 def test_card_payments_defferred(self):
     get_payment(identifier='PAYMENT_2',
                 account=self.account,
                 state=PaymentState.READY_TO_PROCESS,
                 payment_type=PaymentType.CARD_PAYMENT,
                 counter_account_number='',
                 processor='dummy_error',
                 transaction_date=date(2018, 5, 10)).save()
     get_payment(identifier='PAYMENT_3',
                 account=self.account,
                 state=PaymentState.READY_TO_PROCESS,
                 payment_type=PaymentType.CARD_PAYMENT,
                 counter_account_number='',
                 processor='dummy',
                 transaction_date=date(2018, 5, 11)).save()
     with override_settings(PAIN_PROCESS_PAYMENTS_LOCK_FILE=os.path.join(
             self.tempdir.path, 'test.lock')):
         call_command('process_payments')
         self.assertQuerysetEqual(
             BankPayment.objects.values_list('identifier', 'state',
                                             'processor'),
             [('PAYMENT_1', PaymentState.PROCESSED, 'dummy'),
              ('PAYMENT_2', PaymentState.DEFERRED, 'dummy_error'),
              ('PAYMENT_3', PaymentState.PROCESSED, 'dummy')],
             transform=tuple,
             ordered=False)
         self.assertEqual(BankPayment.objects.first().objective,
                          'True objective')
         self.log_handler.check(
             ('django_pain.management.commands.process_payments', 'INFO',
              'Command process_payments started.'),
             ('django_pain.management.commands.process_payments', 'INFO',
              'Lock acquired.'),
             ('django_pain.management.commands.process_payments', 'INFO',
              'Processing 3 unprocessed payments.'),
             ('django_pain.management.commands.process_payments', 'INFO',
              'Processing card payments.'),
             ('django_pain.management.commands.process_payments', 'INFO',
              'Processing card payments with processor dummy.'),
             ('django_pain.management.commands.process_payments', 'INFO',
              'Processing card payments with processor dummy_error.'),
             ('django_pain.management.commands.process_payments', 'INFO',
              'Saving payment %s as DEFERRED with error PaymentProcessingError.DUPLICITY.'
              % BankPayment.objects.get(identifier='PAYMENT_2').uuid),
             ('django_pain.management.commands.process_payments', 'INFO',
              'Processing payments with processor dummy.'),
             ('django_pain.management.commands.process_payments', 'INFO',
              'Marking 0 unprocessed payments as DEFERRED.'),
             ('django_pain.management.commands.process_payments', 'INFO',
              'Command process_payments finished.'),
         )
Exemplo n.º 5
0
    def test_retrieve_exists(self):
        account = get_account(account_number='123456', currency='CZK')
        account.save()
        payment = get_payment(identifier='1',
                              account=account,
                              counter_account_number='',
                              payment_type=PaymentType.CARD_PAYMENT,
                              state=PaymentState.INITIALIZED,
                              card_handler='csob')
        payment.save()

        result_mock = Mock()
        result_mock.payload = {
            'paymentStatus': CSOB.PAYMENT_STATUS_CANCELLED,
            'resultCode': CSOB.RETURN_CODE_OK
        }

        card_payment_hadler = get_card_payment_handler_instance(
            payment.card_handler)
        with patch.object(card_payment_hadler,
                          '_client') as gateway_client_mock:
            gateway_client_mock.payment_status.return_value = result_mock
            response = self.client.get('/api/private/bankpayment/{}/'.format(
                payment.uuid))

        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.data['state'], ExternalPaymentState.CANCELED)
Exemplo n.º 6
0
    def test_get_state(self):
        account = get_account(account_number='123456', currency='CZK')
        payment = get_payment(identifier='1', account=account, counter_account_name='Account one',
                              state=PaymentState.PROCESSED)

        serializer = BankPaymentSerializer()
        self.assertEqual(serializer.get_state(payment), ExternalPaymentState.PAID)
Exemplo n.º 7
0
 def setUp(self):
     super().setUp()
     self.account = get_account()
     self.account.save()
     self.payment = get_payment(account=self.account,
                                state=PaymentState.READY_TO_PROCESS)
     self.payment.save()
Exemplo n.º 8
0
 def test_credit_card_summary_payment(self):
     payment = get_payment(
         counter_account_number='None/None',
         constant_symbol='1176',
     )
     with self.assertRaises(ValidationError):
         payment = skip_credit_card_transaction_summary(payment)
Exemplo n.º 9
0
 def setUp(self):
     self.account = BankAccount(account_number='123456/7890',
                                currency='CZK')
     self.account.save()
     self.payment = get_payment(identifier='PAYMENT_1',
                                account=self.account,
                                state=PaymentState.IMPORTED)
     self.payment.save()
Exemplo n.º 10
0
 def parse(self, bank_statement) -> List[BankPayment]:
     account = BankAccount.objects.get(account_number='123456/7890')
     return [
         get_payment(identifier='PAYMENT_3',
                     account=account,
                     counter_account_number='None/None',
                     constant_symbol='1176'),
     ]
Exemplo n.º 11
0
 def test_format_payment(self):
     """Test format_payment."""
     payment = get_payment(identifier='ID', create_time=datetime(2018, 1, 1, 12, 0, 0),
                           amount=Money('42.00', 'CZK'), description='Memo...',
                           counter_account_name='Acc')
     self.assertRegex(
         format_payment(payment),
         r'^ID\s+2018-01-01T12:00:00\s+amount:\s+42.00 Kč\s+account_memo: Memo...\s+account_name: Acc$'
     )
Exemplo n.º 12
0
    def test_processing_does_not_overwrite_locked_rows(self):
        get_payment(identifier='PAYMENT_1', transaction_date=datetime.date(2018, 5, 2), account=self.account,
                    state=PaymentState.INITIALIZED, card_handler='dummy').save()
        get_payment(identifier='PAYMENT_2', transaction_date=datetime.date(2018, 4, 1), account=self.account,
                    state=PaymentState.INITIALIZED, card_handler='dummy').save()

        processing_finished = threading.Event()
        query_finished = threading.Event()

        def target_processing():
            query_finished.wait()
            try:
                call_command('get_card_payments_states')
            except Exception as e:  # pragma: no cover
                self.errors.put(e)
                raise e
            finally:
                processing_finished.set()
                close_old_connections()

        def target_query():
            try:
                with transaction.atomic():
                    BankPayment.objects.select_for_update().filter(identifier='PAYMENT_1').get()
                    query_finished.set()
                    processing_finished.wait()
            except Exception as e:  # pragma: no cover
                self.errors.put(e)
                raise e
            finally:
                query_finished.set()
                close_old_connections()

        threads = [threading.Thread(target=target_processing), threading.Thread(target=target_query)]
        for t in threads:
            t.start()
        for t in threads:
            t.join()

        self.assertTrue(self.errors.empty())
        self.assertQuerysetEqual(BankPayment.objects.values_list('identifier', 'state').order_by('identifier'),
                                 [('PAYMENT_1', PaymentState.INITIALIZED.value),
                                  ('PAYMENT_2', PaymentState.READY_TO_PROCESS.value)],
                                 transform=tuple)
Exemplo n.º 13
0
    def test_normal_run(self):
        payment = get_payment(identifier='PAYMENT_1', account=self.account, state=PaymentState.INITIALIZED,
                              card_handler='dummy')
        payment.save()
        payment2 = get_payment(identifier='PAYMENT_2', account=self.account, state=PaymentState.READY_TO_PROCESS,
                               card_handler='dummy')
        payment2.save()

        call_command('get_card_payments_states')

        self.log_handler.check(
            ('django_pain.management.commands.get_card_payments_states', 'INFO',
             'Command get_card_payments_states started.'),
            ('django_pain.management.commands.get_card_payments_states', 'INFO', 'Getting state of 1 payment(s).'),
        )
        self.assertQuerysetEqual(BankPayment.objects.values_list('identifier', 'state').order_by('identifier'),
                                 [('PAYMENT_1', PaymentState.READY_TO_PROCESS.value),
                                  ('PAYMENT_2', PaymentState.READY_TO_PROCESS.value)],
                                 transform=tuple)
Exemplo n.º 14
0
    def test_not_empty(self):
        account = BankAccount(account_number='123456789/0123', currency='CZK')
        account.save()
        payment1 = get_payment(identifier='PAYMENT_1', account=account)
        payment1.save()
        payment2 = get_payment(identifier='PAYMENT_2', account=account)
        payment2.save()

        result = self.client.get(reverse('payments-list'))
        self.assertQuerysetEqual(result.context['payments'].values_list(
            'identifier', 'account', 'counter_account_number',
            'transaction_date'), [
                (payment1.identifier, payment1.account.pk,
                 payment1.counter_account_number, payment1.transaction_date),
                (payment2.identifier, payment2.account.pk,
                 payment2.counter_account_number, payment2.transaction_date),
            ],
                                 transform=tuple,
                                 ordered=False)
Exemplo n.º 15
0
 def test_format_payment_with_processing_error(self):
     """Test format_payment with processing_error."""
     payment = get_payment(identifier='ID', create_time=datetime(2018, 1, 1, 12, 0, 0),
                           amount=Money('42.00', 'CZK'), description='Memo...',
                           counter_account_name='Acc', processing_error=PaymentProcessingError.DUPLICITY)
     self.assertRegex(
         format_payment(payment),
         r'^ID\s+2018-01-01T12:00:00\s+amount:\s+42.00 Kč\s+'
         r'account_memo: Memo...\s+account_name: Acc\s+processing_error: Duplicate payment$'
     )
Exemplo n.º 16
0
 def setUp(self):
     self.tempdir = TempDirectory()
     self.account_in = BankAccount(account_number='123456/7890',
                                   currency='CZK')
     self.account_ex = BankAccount(account_number='987654/3210',
                                   currency='CZK')
     self.account_in.save()
     self.account_ex.save()
     get_payment(identifier='PAYMENT_1',
                 account=self.account_in,
                 state=PaymentState.READY_TO_PROCESS).save()
     get_payment(identifier='PAYMENT_2',
                 account=self.account_ex,
                 state=PaymentState.READY_TO_PROCESS).save()
     self.log_handler = LogCapture(
         'django_pain.management.commands.process_payments',
         propagate=False)
     # Exception in a threads does not fail the test - wee need to collect it somemehow
     self.errors = Queue()  # type: Queue
Exemplo n.º 17
0
 def setUp(self):
     super().setUp()
     self.tempdir = TempDirectory()
     self.account = BankAccount(account_number='123456/7890',
                                currency='CZK')
     self.account.save()
     payment = get_payment(identifier='PAYMENT_1',
                           account=self.account,
                           state=PaymentState.READY_TO_PROCESS)
     payment.save()
     self.log_handler = LogCapture(
         'django_pain.management.commands.process_payments',
         propagate=False)
Exemplo n.º 18
0
    def test_error(self):
        payment = get_payment(identifier='PAYMENT_1', account=self.account, state=PaymentState.INITIALIZED,
                              card_handler='dummy_exc')
        payment.save()

        call_command('get_card_payments_states')
        self.log_handler.check(
            ('django_pain.management.commands.get_card_payments_states', 'INFO',
             'Command get_card_payments_states started.'),
            ('django_pain.management.commands.get_card_payments_states', 'INFO', 'Getting state of 1 payment(s).'),
            ('django_pain.management.commands.get_card_payments_states', 'ERROR',
             'Error while updating state of payment identifier=PAYMENT_1')
        )
Exemplo n.º 19
0
 def setUp(self):
     self.request_factory = RequestFactory()
     self.admin = User.objects.create_superuser('admin',
                                                '*****@*****.**',
                                                'password')
     account = BankAccount(account_number='123456/7890', currency='CZK')
     account.save()
     get_payment(identifier='PAYMENT_1',
                 account=account,
                 state=PaymentState.INITIALIZED).save()
     get_payment(identifier='PAYMENT_2',
                 account=account,
                 state=PaymentState.READY_TO_PROCESS).save()
     get_payment(identifier='PAYMENT_3',
                 account=account,
                 state=PaymentState.DEFERRED).save()
     get_payment(identifier='PAYMENT_4',
                 account=account,
                 state=PaymentState.PROCESSED).save()
     get_payment(identifier='PAYMENT_5',
                 account=account,
                 state=PaymentState.CANCELED).save()
Exemplo n.º 20
0
 def test_payment_admin_locking(self):
     account = get_account(account_name='My Account')
     account.save()
     instance = get_payment(
         identifier='My Payment 1',
         account=account,
         state=PaymentState.READY_TO_PROCESS,
         variable_symbol='VAR1',
         transaction_date=date(2019, 1, 1),
     )
     viewname = 'admin:django_pain_bankpayment_changelist'
     find_in_response = 'VAR1'
     model_class = BankPayment
     self._test_admin_locking(instance, viewname, find_in_response,
                              model_class)
Exemplo n.º 21
0
    def test_inclusion_in_payment_processing(self):
        """Test including accounts from payment processing"""
        account2 = BankAccount(account_number='987654/3210', currency='CZK')
        account2.save()
        get_payment(identifier='PAYMENT_2',
                    account=self.account,
                    state=PaymentState.READY_TO_PROCESS).save()
        get_payment(identifier='PAYMENT_3',
                    account=account2,
                    state=PaymentState.READY_TO_PROCESS).save()
        with override_settings(PAIN_PROCESS_PAYMENTS_LOCK_FILE=os.path.join(
                self.tempdir.path, 'test.lock')):
            out = StringIO()
            err = StringIO()
            call_command('process_payments',
                         '--include-accounts',
                         '123456/7890',
                         stdout=out,
                         stderr=err)

            self.assertEqual(out.getvalue(), '')
            self.assertEqual(err.getvalue(), '')
            self.log_handler.check(
                ('django_pain.management.commands.process_payments', 'INFO',
                 'Command process_payments started.'),
                ('django_pain.management.commands.process_payments', 'INFO',
                 'Lock acquired.'),
                ('django_pain.management.commands.process_payments', 'INFO',
                 'Processing 2 unprocessed payments.'),
                ('django_pain.management.commands.process_payments', 'INFO',
                 'Processing payments with processor dummy.'),
                ('django_pain.management.commands.process_payments', 'INFO',
                 'Marking 0 unprocessed payments as DEFERRED.'),
                ('django_pain.management.commands.process_payments', 'INFO',
                 'Command process_payments finished.'),
            )
Exemplo n.º 22
0
    def test_update_payment_state_connection_error(self):
        account = get_account(account_number='123456', currency='CZK')
        account.save()
        payment = get_payment(identifier='1',
                              account=account,
                              counter_account_number='',
                              payment_type=PaymentType.CARD_PAYMENT,
                              state=PaymentState.INITIALIZED,
                              card_handler='csob')
        payment.save()

        handler = CSOBCardPaymentHandler('csob')
        with patch.object(handler, '_client') as gateway_client_mock:
            gateway_client_mock.payment_status.side_effect = requests.ConnectionError(
            )

            self.assertRaises(PaymentHandlerConnectionError,
                              handler.update_payments_state, payment)
Exemplo n.º 23
0
    def test_update_payment_state_not_ok(self):
        account = get_account(account_number='123456', currency='CZK')
        account.save()
        payment = get_payment(identifier='1',
                              account=account,
                              counter_account_number='',
                              payment_type=PaymentType.CARD_PAYMENT,
                              state=PaymentState.INITIALIZED,
                              card_handler='csob')
        payment.save()

        result_mock = Mock()
        result_mock.payload = {'resultCode': CSOB.RETURN_CODE_MERCHANT_BLOCKED}

        handler = CSOBCardPaymentHandler('csob')
        with patch.object(handler, '_client') as gateway_client_mock:
            gateway_client_mock.payment_status.return_value = result_mock
            self.assertRaisesRegex(PaymentHandlerError,
                                   'payment_status resultCode != OK',
                                   handler.update_payments_state, payment)
        self.assertEqual(payment.state, PaymentState.INITIALIZED)
Exemplo n.º 24
0
    def test_retrieve_gateway_connection_error(self):
        account = get_account(account_number='123456', currency='CZK')
        account.save()
        payment = get_payment(identifier='1',
                              account=account,
                              counter_account_number='',
                              payment_type=PaymentType.CARD_PAYMENT,
                              state=PaymentState.READY_TO_PROCESS,
                              card_handler='csob')
        payment.save()

        card_payment_hadler = get_card_payment_handler_instance(
            payment.card_handler)
        with patch.object(card_payment_hadler,
                          '_client') as gateway_client_mock:
            gateway_client_mock.payment_status.side_effect = PaymentHandlerConnectionError(
            )
            response = self.client.get('/api/private/bankpayment/{}/'.format(
                payment.uuid))

        self.assertEqual(response.status_code, 503)
Exemplo n.º 25
0
    def test_update_payment_state_no_update_not_initialized(self):
        account = get_account(account_number='123456', currency='CZK')
        account.save()
        payment = get_payment(identifier='1',
                              account=account,
                              counter_account_number='',
                              payment_type=PaymentType.CARD_PAYMENT,
                              state=PaymentState.PROCESSED,
                              card_handler='csob')
        payment.save()

        result_mock = Mock()
        result_mock.payload = {
            'paymentStatus': CSOB.PAYMENT_STATUS_CANCELLED,
            'resultCode': CSOB.RETURN_CODE_OK
        }

        handler = CSOBCardPaymentHandler('csob')
        with patch.object(handler, '_client') as gateway_client_mock:
            gateway_client_mock.payment_status.return_value = result_mock

            handler.update_payments_state(payment)

        self.assertEqual(payment.state, PaymentState.PROCESSED)
Exemplo n.º 26
0
 def setUp(self):
     super().setUp()
     self.payment = get_payment()
Exemplo n.º 27
0
 def setUpTestData(cls):
     account1 = get_account(account_number='123456', currency='CZK')
     account1.save()
     account2 = get_account(account_number='654321', currency='CZK')
     account2.save()
     get_payment(identifier='1', account=account1, counter_account_name='Account one',
                 state=PaymentState.READY_TO_PROCESS).save()
     get_payment(identifier='2', account=account2, counter_account_name='Account two',
                 state=PaymentState.READY_TO_PROCESS).save()
     get_payment(identifier='3', account=account1, counter_account_name='Account three',
                 state=PaymentState.PROCESSED).save()
     get_payment(identifier='4', account=account2, counter_account_name='Account four',
                 description='I am your father!', state=PaymentState.PROCESSED).save()
     get_payment(identifier='5', account=account1, counter_account_name='Account five',
                 state=PaymentState.DEFERRED).save()
     get_payment(identifier='6', account=account1, counter_account_name='Account six',
                 description='May the force be with you', state=PaymentState.DEFERRED).save()
     get_payment(identifier='7', account=account2, counter_account_name='Account seven',
                 state=PaymentState.DEFERRED).save()
Exemplo n.º 28
0
    def test_processed_rows_not_overwritten(self):
        processing_started = threading.Event()
        query_finished = threading.Event()

        p1 = get_payment(identifier='PAYMENT_1', account=self.account, state=PaymentState.INITIALIZED,
                         card_handler='dummy')
        p2 = get_payment(identifier='PAYMENT_2', account=self.account, state=PaymentState.INITIALIZED,
                         card_handler='dummy')
        p1.save()
        p2.save()

        p1.create_time = datetime.datetime(2018, 5, 2)
        p2.create_time = datetime.datetime(2018, 4, 1)
        p1.save()
        p2.save()

        def mock_update_state(payment):
            processing_started.set()
            query_finished.wait()
            payment.state = PaymentState.READY_TO_PROCESS
            payment.save()

        def target_processing():
            try:
                # cache may prevent mocking
                get_card_payment_handler_instance.cache_clear()
                get_card_payment_handler_class.cache_clear()
                with patch('django_pain.tests.utils.DummyCardPaymentHandler') as MockClass:
                    instance = MockClass.return_value
                    instance.update_payments_state = mock_update_state
                    call_command('get_card_payments_states', '--from', datetime.datetime(2018, 5, 1))
            except Exception as e:  # pragma: no cover
                self.errors.put(e)
                raise e
            finally:
                processing_started.set()
                close_old_connections()
                # mock might be cached
                get_card_payment_handler_instance.cache_clear()
                get_card_payment_handler_class.cache_clear()

        def target_query():
            processing_started.wait()
            try:
                with transaction.atomic():
                    payments = BankPayment.objects.select_for_update(skip_locked=True).all()
                    for p in payments:
                        p.state = PaymentState.PROCESSED
                        p.save()
            except Exception as e:  # pragma: no cover
                self.errors.put(e)
                raise e
            finally:
                query_finished.set()
                close_old_connections()

        threads = [threading.Thread(target=target_processing), threading.Thread(target=target_query)]
        for t in threads:
            t.start()
        for t in threads:
            t.join()

        self.assertTrue(self.errors.empty())
        self.assertQuerysetEqual(BankPayment.objects.values_list('identifier', 'state').order_by('identifier'),
                                 [('PAYMENT_1', PaymentState.READY_TO_PROCESS.value),
                                  ('PAYMENT_2', PaymentState.PROCESSED.value)],
                                 transform=tuple)
Exemplo n.º 29
0
 def test_normal_payment(self):
     payment = get_payment()
     payment = skip_credit_card_transaction_summary(payment)
     self.assertEqual(payment.state, PaymentState.READY_TO_PROCESS)
Exemplo n.º 30
0
 def setUp(self):
     self.processor = IgnorePaymentProcessor()
     self.payment = get_payment()