def register_transaction(registrant, amount, currency, action, provider=None, data=None): """Creates a new transaction for a certain transaction action. :param registrant: the `Registrant` of the transaction :param amount: the (strictly positive) amount of the transaction :param currency: the currency used for the transaction :param action: the `TransactionAction` of the transaction :param provider: the payment method name of the transaction, or '_manual' if no payment method has been used :param data: arbitrary JSON-serializable data specific to the transaction's provider """ new_transaction, double_payment = PaymentTransaction.create_next( registrant=registrant, amount=amount, currency=currency, action=action, provider=provider, data=data) if new_transaction: db.session.add(new_transaction) db.session.flush() if double_payment: notify_double_payment(registrant) if new_transaction.status == TransactionStatus.successful: notify_payment_confirmation(registrant, amount) return new_transaction
def _create_transaction(status, **params): params.setdefault('amount', 10) params.setdefault('currency', 'USD') params.setdefault('provider', '_manual') params.setdefault('data', {}) transaction = PaymentTransaction(event_id=dummy_event.getId(), registrant_id=dummy_registrant.getId(), status=status, **params) db.session.add(transaction) db.session.flush() return transaction
def test_create_next_with_exception(caplog, mocker, creation_params, exception): mocker.patch.object(TransactionStatusTransition, 'next') TransactionStatusTransition.next.side_effect = exception('TEST_EXCEPTION') transaction, double_payment = PaymentTransaction.create_next(**creation_params) log = extract_logs(caplog, one=True, name='indico.payment') assert transaction is None assert double_payment is None assert 'TEST_EXCEPTION' in log.message if log.exc_info: assert log.exc_info[0] == exception
def register_transaction(registrant, amount, currency, action, provider=None, data=None): """Creates a new transaction for a certain transaction action. :param registrant: the `Registrant` of the transaction :param amount: the (strictly positive) amount of the transaction :param currency: the currency used for the transaction :param action: the `TransactionAction` of the transaction :param provider: the payment method name of the transaction, or '_manual' if no payment method has been used :param data: arbitrary JSON-serializable data specific to the transaction's provider """ new_transaction, double_payment = PaymentTransaction.create_next(registrant=registrant, amount=amount, currency=currency, action=action, provider=provider, data=data) if new_transaction: db.session.add(new_transaction) db.session.flush() if double_payment: notify_double_payment(registrant) if new_transaction.status == TransactionStatus.successful: notify_payment_confirmation(registrant, amount) return new_transaction
def has_data(self): return bool(PaymentTransaction.find().count())
def migrate_transactions(self): self.messages.append(cformat("%{magenta!} - Payment Transactions:")) print cformat("%{white!}migrating payment transactions") count = 0 errors = 0 warnings = 0 for event, registrant, transaction in committing_iterator( self._iter_transactions()): try: data = self._get_transaction_data(transaction, event) except ValueError as e: print cformat("%{red!}{0} (evt: {1}, reg: {2})").format( e, event.id, registrant._id) errors += 1 continue if data['provider'] == '_manual' and data['amount'] == 0.0: print cformat( "%{yellow!}Skipping {0[provider]} transaction (evt: {1}, reg: {2}) " "with zero amount: {0[amount]} {0[currency]}").format( data, event.id, registrant._id) warnings += 1 continue elif data['amount'] < 0.0: print cformat( "%{yellow!}Skipping {0[provider]} transaction (evt: {1}, reg: {2}) " "with negative amount: {0[amount]} {0[currency]}").format( data, event.id, registrant._id) warnings += 1 continue pt = PaymentTransaction(event_id=int(event.id), registrant_id=int(registrant._id), status=TransactionStatus.successful, **data) count += 1 print cformat("%{cyan}{0}").format(pt) db.session.add(pt) if warnings: warning_msg = cformat( "%{yellow!}There were {0} warnings during the migration " "of the payment transactions.").format(warnings) self.messages.append(' ' + warning_msg) print warning_msg if errors: msg = cformat( "%{red!}There were some errors during the migration of the payment transactions.\n" "{0} transactions were not migrated and will be lost.\n" ).format(errors) else: msg = cformat( "%{green!}migration of {0} payment transactions successful\n" ).format(count) self.messages.append(' ' + '\n '.join(msg.split('\n'))) print msg
def test_find_latest_for_registrant(create_transaction, dummy_registrant): t1 = create_transaction(TransactionStatus.successful) t2 = create_transaction(TransactionStatus.successful) assert t1 != t2 assert PaymentTransaction.find_latest_for_registrant(dummy_registrant) == t2
def test_create_next_double_payment(caplog, create_transaction, creation_params): create_transaction(TransactionStatus.successful) _, double_payment = PaymentTransaction.create_next(**creation_params) log = extract_logs(caplog, one=True, name='indico.payment').message assert 'already paid' in log assert double_payment
def test_create_next(creation_params): transaction, double_payment = PaymentTransaction.create_next(**creation_params) assert isinstance(transaction, PaymentTransaction) assert not double_payment