예제 #1
0
class CardRewardTest(TestCase):
    """
    Test case for the ``CardRewardView`` API view.

    Rewards must be performed by following this schema:

    1 - The business transfers the reward amount to the consumer.
    2 - A fixed percentage (by default the 40%) of that amount is deducted
    for the consumer cause.
    3 - The consumer transfers that percentage of the reward amount to the
    cause.

    Then, two transactions must be performed and also logged to the system.
    """
    @skipIf(not 'cc3.rewards' in settings.INSTALLED_APPS,
            u'Skipped as cc3.rewards app not enabled')
    def setUp(self):
        self.backend = DummyCyclosBackend()
        set_backend(self.backend)

        self.group_1 = CyclosGroupFactory.create(initial=True)
        self.groupset = CyclosGroupSetFactory.create(
            groups=[self.group_1, ])
        self.community = CC3CommunityFactory.create(
            groupsets=[self.groupset], code='TST')

        # Create business with its terminal.
        self.user_1 = UserFactory.create()
        self.terminal_1 = TerminalFactory.create(business=self.user_1)
        self.token_1 = Token.objects.create(user=self.user_1)
        self.operator_1 = OperatorFactory(business=self.user_1)
        self.cc3profile_1 = CC3ProfileFactory.create(
            user=self.user_1, first_name='Test', last_name='Business',
            community=self.community, cyclos_group=self.group_1)
        self.business_settings = BusinessCauseSettingsFactory.create(
            user=self.user_1)

        # Create card users.
        self.user_2 = UserFactory.create()
        self.cc3profile_2 = CC3ProfileFactory.create(
            user=self.user_2, first_name='Test', last_name='User',
            community=self.community, cyclos_group=self.group_1)
        self.user_cause = UserCauseFactory.create(consumer=self.user_2)

        self.community_2 = CC3CommunityFactory.create(
            groupsets=[self.groupset], code='TST')

        self.user_3 = UserFactory.create()
        self.cc3profile_3 = CC3ProfileFactory.create(
            user=self.user_3, first_name='Test', last_name='User',
            community=self.community_2, cyclos_group=self.group_1)

        self.user_4 = UserFactory.create()
        self.terminal_4 = TerminalFactory.create(business=self.user_4)
        self.token_4 = Token.objects.create(user=self.user_4)
        self.operator_4 = OperatorFactory(business=self.user_4)

        self.client = self.client_class(HTTP_AUTHORIZATION='Token {0}'.format(
            self.token_1.key))
        self.card_2 = CardFactory.create(owner=self.user_2)
        self.card_3 = CardFactory.create(owner=self.user_3)

        self.url = reverse(
            'api_cards_card_reward', args=[self.card_2.number.uid_number])

        self.post_data = {
            'terminal_name': self.terminal_1.name,
            'operator_name': self.operator_1.name,
            'sender_id': self.operator_1.business.id,
            'receiver_id': self.card_2.owner.id,
            'amount': '100',
            'description': 'Reward to good cause {0}'.format(
                self.user_cause.cause)
        }

    @skipIf(not 'cc3.rewards' in settings.INSTALLED_APPS,
            u'Skipped as cc3.rewards app not enabled')
    @override_settings(INTER_COMMUNITIES_TRANSACTIONS=True)
    def test_card_reward_business_to_consumer_transaction(self):
        """
        Tests the transaction from business to consumer performed during a
        successful reward operation.
        """
        response = self.client.post(
            self.url, data=json.dumps(self.post_data),
            content_type='application/json')

        self.assertEqual(response.status_code, HTTP_200_OK)

        data = json.loads(response.content)

        self.assertEqual(data['card_transaction_id'],
                         self.backend.transactions()[0].transfer_id)

        # Check the transaction from business to consumer.
        trans = self.backend.transactions()[0]
        self.assertEqual(trans.amount, 100)
        self.assertEqual(trans.sender, self.terminal_1.business)
        self.assertEqual(trans.recipient, self.card_2.owner)
        self.assertEqual(trans.description, self.post_data['description'])

    @skipIf(not 'cc3.rewards' in settings.INSTALLED_APPS,
            u'Skipped as cc3.rewards app not enabled')
    @override_settings(INTER_COMMUNITIES_TRANSACTIONS=True)
    def test_card_reward_consumer_to_cause_transaction(self):
        """
        Tests the transaction from consumer to cause performed during a
        successful reward operation.
        """
        response = self.client.post(
            self.url, data=json.dumps(self.post_data),
            content_type='application/json')

        self.assertEqual(response.status_code, HTTP_200_OK)

        data = json.loads(response.content)

        self.assertEqual(data['reward_transaction_id'],
                         self.backend.transactions()[1].transfer_id)

        # Check the transaction from consumer to cause.
        # It must be the 40% of the initial transaction.
        trans = self.backend.transactions()[1]
        self.assertEqual(trans.amount, 40)
        self.assertEqual(trans.sender, self.card_2.owner)
        self.assertEqual(trans.recipient, self.user_cause.cause)
        self.assertEqual(trans.description, _('Cause donation'))

    @skipIf(not 'cc3.rewards' in settings.INSTALLED_APPS,
            u'Skipped as cc3.rewards app not enabled')
    @override_settings(INTER_COMMUNITIES_TRANSACTIONS=True)
    def test_card_reward_transaction_logged(self):
        """
        Tests the creation of ``Transaction`` objects to log the rewarding.

        There must be 2 ``Transaction``s logged: one from the business to the
        consumer and another one from the consumer to the cause.
        """
        response = self.client.post(
            self.url, data=json.dumps(self.post_data),
            content_type='application/json')

        self.assertEqual(response.status_code, HTTP_200_OK)

        transactions = CardTransaction.objects.all()
        self.assertEqual(len(transactions), 2)

    @skipIf(not 'cc3.rewards' in settings.INSTALLED_APPS,
            u'Skipped as cc3.rewards app not enabled')
    @override_settings(INTER_COMMUNITIES_TRANSACTIONS=True)
    def test_card_reward_invalid_terminal(self):
        """ Test wrong terminal name when performing a reward """
        self.post_data['terminal_name'] = 'invalid'

        response = self.client.post(
            self.url, data=json.dumps(self.post_data),
            content_type='application/json')
        self.assertEqual(response.status_code, HTTP_400_BAD_REQUEST)

    @skipIf(not 'cc3.rewards' in settings.INSTALLED_APPS,
            u'Skipped as cc3.rewards app not enabled')
    @override_settings(INTER_COMMUNITIES_TRANSACTIONS=True)
    def test_card_reward_invalid_operator(self):
        """ Test wrong operator name when performing a reward """
        self.post_data['operator_name'] = 'invalid'

        response = self.client.post(
            self.url, data=json.dumps(self.post_data),
            content_type='application/json')
        self.assertEqual(response.status_code, HTTP_400_BAD_REQUEST)

# TODO, test to check community and user values are used appropriately
    #@override_settings(INTER_COMMUNITIES_TRANSACTIONS=True,
    #                   REWARDS_FIXED_PERCENTAGE=None)
    #@skipIf(not 'cc3.rewards' in settings.INSTALLED_APPS,
    #        u'Skipped as cc3.rewards app not enabled')
    #def test_card_reward_fixed_percentage_setting(self):
    #    """
    #    Test automatic fallback when ``REWARDS_FIXED_PERCENTAGE`` setting is
    #    missing.
    #    """
    #    # Delete the setting.
    #    del settings.REWARDS_FIXED_PERCENTAGE
    #
    #    response = self.client.post(
    #        self.url, data=json.dumps(self.post_data),
    #        content_type='application/json')
    #
    #    self.assertEqual(response.status_code, HTTP_200_OK)
    #
    #    data = json.loads(response.content)
    #
    #    self.assertEqual(data['reward_transaction_id'],
    #                     self.backend.transactions()[1].transfer_id)
    #
    #    # Check the transaction from consumer to cause.
    #    # It must be the 40% of the initial transaction.
    #    trans = self.backend.transactions()[1]
    #    self.assertEqual(trans.amount, 40)
    #    self.assertEqual(trans.sender, self.card_2.owner)
    #    self.assertEqual(trans.recipient, self.user_cause.cause)
    #    self.assertEqual(trans.description, _('Cause donation'))

    @skipIf(not 'cc3.rewards' in settings.INSTALLED_APPS,
            u'Skipped as cc3.rewards app not enabled')
    @override_settings(INTER_COMMUNITIES_TRANSACTIONS=True)
    def test_card_reward_no_cause_available(self):
        """
        Tests that the request returns a 400 error when the user has no
        charity cause configured.
        """
        url = reverse(
            'api_cards_card_reward', args=[self.card_3.number.uid_number])

        post_data = {
            'terminal_name': self.terminal_1.name,
            'operator_name': self.operator_1.name,
            'sender_id': self.operator_1.business.id,
            'receiver_id': self.card_3.owner.id,
            'amount': '100',
            'description': 'Reward to good cause {0}'.format(
                self.user_cause.cause)
        }

        response = self.client.post(
            url, data=json.dumps(post_data), content_type='application/json')

        self.assertEqual(response.status_code, HTTP_200_OK)

        data = json.loads(response.content)

        self.assertIsNone(data['reward_transaction_id'])

    @skipIf(not 'cc3.rewards' in settings.INSTALLED_APPS,
            u'Skipped as cc3.rewards app not enabled')
    @override_settings(INTER_COMMUNITIES_TRANSACTIONS=False)
    def test_card_reward_inter_community_fails(self):
        """
        Tests that the request returns a 400 error when the reward is attempted
        to a business and/or cause in a different community.

        NB this relies on the fact that all users in these
        tests are in different communities
        """
        url = reverse(
            'api_cards_card_reward', args=[self.card_3.number.uid_number])

        post_data = {
            'terminal_name': self.terminal_1.name,
            'operator_name': self.operator_1.name,
            'sender_id': self.operator_1.business.id,
            'receiver_id': self.card_3.owner.id,
            'amount': '100',
            'description': 'Reward to good cause {0}'.format(
                self.user_cause.cause)
        }

        response = self.client.post(
            url, data=json.dumps(post_data), content_type='application/json')

        self.assertEqual(response.status_code, HTTP_400_BAD_REQUEST)
예제 #2
0
class CardPaymentTest(TestCase):
    def setUp(self):
        self.backend = DummyCyclosBackend()
        set_backend(self.backend)

        self.group_1 = CyclosGroupFactory.create(initial=True)
        self.groupset = CyclosGroupSetFactory.create(
            groups=[self.group_1, ])
        self.community = CC3CommunityFactory.create(
            groupsets=[self.groupset], code='TST')

        self.user_1 = UserFactory.create()
        self.terminal_1 = TerminalFactory.create(business=self.user_1)
        self.token_1 = Token.objects.create(user=self.user_1)
        self.operator_1 = OperatorFactory(business=self.user_1)
        self.cc3profile_1 = CC3ProfileFactory.create(
            user=self.user_1, first_name='Test', last_name='Business',
            community=self.community, cyclos_group=self.group_1)
        self.user_2 = UserFactory.create()
        self.cc3profile_2 = CC3ProfileFactory.create(
            user=self.user_2, first_name='Test', last_name='User',
            community=self.community, cyclos_group=self.group_1)

        self.user_3 = UserFactory.create()

        self.user_4 = UserFactory.create()
        self.terminal_4 = TerminalFactory.create(business=self.user_4)
        self.token_4 = Token.objects.create(user=self.user_4)
        self.operator_4 = OperatorFactory(business=self.user_4)

        self.client = self.client_class(HTTP_AUTHORIZATION='Token {0}'.format(
            self.token_1.key))
        self.card_2 = CardFactory.create(owner=self.user_2)
        self.card_3 = CardFactory.create(owner=self.user_3)

        self.community_5 = CC3CommunityFactory.create(
            groupsets=[self.groupset])
        self.user_5 = UserFactory.create()
        self.cc3profile_5 = CC3ProfileFactory.create(
            user=self.user_5, first_name='Test', last_name='User5',
            community=self.community_5, cyclos_group=self.group_1)
        self.card_5 = CardFactory.create(owner=self.user_5)
        self.blocked_card = CardFactory.create(owner=self.user_2)
        self.blocked_card.block_card()

        self.url = reverse(
            'api_cards_card_payment', args=[self.card_2.number.uid_number])

    def test_card_pay_successful(self):
        """ Test a payment from a user/card-holder to the business owner """
        data = {
            'terminal_name': self.terminal_1.name,
            'operator_name': self.operator_1.name,
            'sender_id': self.card_2.owner.id,
            'receiver_id': self.operator_1.business.id,
            'amount': '50',
            'description': 'My transaction'
        }

        response = self.client.post(
            self.url, data=json.dumps(data), content_type='application/json')
        self.assertEqual(response.status_code, HTTP_200_OK)
        data = json.loads(response.content)
        self.assertEqual(data['transaction_id'],
                         self.backend.transactions()[0].transfer_id)
        trans = self.backend.transactions()[0]
        self.assertEqual(trans.amount, 50)
        self.assertEqual(trans.sender, self.card_2.owner)
        self.assertEqual(trans.recipient, self.operator_1.business)
        self.assertEqual(trans.description, 'My transaction')

    def test_card_pay_successful_decimal(self):
        """ Test a decimal payment from a user/card-holder to business owner """
        data = {
            'terminal_name': self.terminal_1.name,
            'operator_name': self.operator_1.name,
            'sender_id': self.card_2.owner.id,
            'receiver_id': self.operator_1.business.id,
            'amount': '40.01',
            'description': 'My transaction'
        }

        response = self.client.post(
            self.url, data=json.dumps(data), content_type='application/json')
        self.assertEqual(response.status_code, HTTP_200_OK)
        data = json.loads(response.content)
        self.assertEqual(data['transaction_id'],
                         self.backend.transactions()[0].transfer_id)
        trans = self.backend.transactions()[0]
        self.assertEqual(trans.amount, Decimal('40.01'))
        self.assertEqual(trans.sender, self.card_2.owner)
        self.assertEqual(trans.recipient, self.operator_1.business)
        self.assertEqual(trans.description, 'My transaction')

    def test_card_payment_operator_name_business_unique_together(self):
        """
        Test a payment operation when there is more than one ``Operator``
        object with the same ``name`` defined.

        Enforces the checkup of the 'unique together' relationship of the two
        fields in the ``Operator`` model, which is used in the API view
        ``CardTransactionView`` to retrieve the operator.
        """
        OperatorFactory(name=self.operator_1.name)
        data = {
            'terminal_name': self.terminal_1.name,
            'operator_name': self.operator_1.name,
            'sender_id': self.card_2.owner.id,
            'receiver_id': self.operator_1.business.id,
            'amount': '50',
            'description': 'My transaction'
        }

        response = self.client.post(
            self.url, data=json.dumps(data), content_type='application/json')
        self.assertEqual(response.status_code, HTTP_200_OK)

    def test_card_receive(self):
        """ Test a payment from the business owner to the user/card-holder """
        data = {
            'terminal_name': self.terminal_1.name,
            'operator_name': self.operator_1.name,
            'receiver_id': self.card_2.owner.id,
            'sender_id': self.operator_1.business.id,
            'amount': '50',
            'description': 'My transaction'
        }
        response = self.client.post(
            self.url, data=json.dumps(data), content_type='application/json')
        self.assertEqual(response.status_code, HTTP_200_OK)
        data = json.loads(response.content)
        self.assertEqual(data['transaction_id'],
                         self.backend.transactions()[0].transfer_id)
        trans = self.backend.transactions()[0]
        self.assertEqual(trans.amount, 50)
        self.assertEqual(trans.recipient, self.card_2.owner)
        self.assertEqual(trans.sender, self.operator_1.business)
        self.assertEqual(trans.description, 'My transaction')

    def test_card_receive_credit_limit(self):
        """ Test a payment from the business owner to the user/card-holder,
        where the balance of the business owner can become negative
        (DummyCyclosBackend credit limit: 50) """
        data = {
            'terminal_name': self.terminal_1.name,
            'operator_name': self.operator_1.name,
            'receiver_id': self.card_2.owner.id,
            'sender_id': self.operator_1.business.id,
            'amount': '149',
            'description': 'My transaction'
        }
        response = self.client.post(
            self.url, data=json.dumps(data), content_type='application/json')
        self.assertEqual(response.status_code, HTTP_200_OK)
        data = json.loads(response.content)
        self.assertEqual(data['transaction_id'],
                         self.backend.transactions()[0].transfer_id)
        trans = self.backend.transactions()[0]
        self.assertEqual(trans.amount, 149)
        self.assertEqual(trans.recipient, self.card_2.owner)
        self.assertEqual(trans.sender, self.operator_1.business)
        self.assertEqual(trans.description, 'My transaction')

    def test_card_receive_credit_limit_invalid(self):
        """ Test a payment from the business owner to the user/card-holder,
        where the credit limit of the business owner is invalid.
        (DummyCyclosBackend credit limit: 50) """
        data = {
            'terminal_name': self.terminal_1.name,
            'operator_name': self.operator_1.name,
            'receiver_id': self.card_2.owner.id,
            'sender_id': self.operator_1.business.id,
            'amount': '151',
            'description': 'My transaction'
        }
        response = self.client.post(
            self.url, data=json.dumps(data), content_type='application/json')
        self.assertEqual(response.status_code, HTTP_400_BAD_REQUEST)

    def test_card_pay_invalid_terminal(self):
        """ Wrong terminal name """
        data = {
            'terminal_name': 'invalid',
            'operator_name': self.operator_1.name,
            'sender_id': self.card_2.owner.id,
            'receiver_id': self.operator_1.business.id,
            'amount': '50',
            'description': 'My transaction'
        }

        response = self.client.post(
            self.url, data=json.dumps(data), content_type='application/json')
        self.assertEqual(response.status_code, HTTP_400_BAD_REQUEST)

    def test_card_pay_invalid_operator(self):
        """ Wrong operator name """
        data = {
            'terminal_name': self.terminal_1.name,
            'operator_name': 'invalid',
            'sender_id': self.card_2.owner.id,
            'receiver_id': self.operator_1.business.id,
            'amount': '50',
            'description': 'My transaction'
        }

        response = self.client.post(
            self.url, data=json.dumps(data), content_type='application/json')
        self.assertEqual(response.status_code, HTTP_400_BAD_REQUEST)

    def test_card_pay_third_party_payment(self):
        """
        Unable to perform payments if we're not one of either party.
        Note that we authenticate with terminal_1/operator_1
        """
        data = {
            'terminal_name': self.terminal_4.name,
            'operator_name': self.operator_4.name,
            'sender_id': self.card_2.owner.id,
            'receiver_id': self.operator_4.business.id,
            'amount': '50',
            'description': 'My transaction'
        }

        response = self.client.post(
            self.url, data=json.dumps(data), content_type='application/json')
        self.assertEqual(response.status_code, HTTP_400_BAD_REQUEST)

    def test_card_pay_same_sender_receiver(self):
        """ Can't send payments if the user is both sender and receiver """
        data = {
            'terminal_name': self.terminal_1.name,
            'operator_name': self.operator_1.name,
            'sender_id': self.card_2.owner.id,
            'receiver_id': self.card_2.owner.id,
            'amount': '50',
            'description': 'My transaction'
        }

        response = self.client.post(
            self.url, data=json.dumps(data), content_type='application/json')
        self.assertEqual(response.status_code, HTTP_400_BAD_REQUEST)

    def test_card_pay_wrong_card(self):
        """ The payment must be made on the correct card resource """
        data = {
            'terminal_name': self.terminal_1.name,
            'operator_name': self.operator_1.name,
            'sender_id': self.card_3.owner.id,
            'receiver_id': self.operator_1.business.id,
            'amount': '50',
            'description': 'My transaction'
        }

        response = self.client.post(
            self.url, data=json.dumps(data), content_type='application/json')
        self.assertEqual(response.status_code, HTTP_400_BAD_REQUEST)

    def test_card_pay_from_blocked_card(self):
        """ The payment must be from a non-blocked card """
        data = {
            'terminal_name': self.terminal_1.name,
            'operator_name': self.operator_1.name,
            'sender_id': self.blocked_card.owner.id,
            'receiver_id': self.card_2.owner.id,
            'amount': '50',
            'description': 'My transaction'
        }
        url = reverse(
            'api_cards_card_payment', args=[self.blocked_card.number.uid_number])

        response = self.client.post(
            self.url, data=json.dumps(data), content_type='application/json')
        self.assertEqual(response.status_code, HTTP_400_BAD_REQUEST)

    @override_settings(INTER_COMMUNITIES_TRANSACTIONS=False)
    def test_card_pay_inter_community_not_possible(self):
        """ Testing INTER_COMMUNITIES_TRANSACTIONS=False blocks """
        data = {
            'terminal_name': self.terminal_1.name,
            'operator_name': self.operator_1.name,
            'sender_id': self.card_5.owner.id,
            'receiver_id': self.operator_1.business.id,
            'amount': '50',
            'description': 'My transaction'
        }
        response = self.client.post(
            self.url, data=json.dumps(data), content_type='application/json')
        self.assertEqual(response.status_code, HTTP_400_BAD_REQUEST)

    @override_settings(INTER_COMMUNITIES_TRANSACTIONS=True)
    def test_card_pay_inter_community_possible(self):
        """ Testing INTER_COMMUNITIES_TRANSACTIONS=True allows """
        data = {
            'terminal_name': self.terminal_1.name,
            'operator_name': self.operator_1.name,
            'sender_id': self.card_2.owner.id,
            'receiver_id': self.operator_1.business.id,
            'amount': '50',
            'description': 'My transaction'
        }
        response = self.client.post(
            self.url, data=json.dumps(data), content_type='application/json')
        self.assertEqual(response.status_code, HTTP_200_OK)