Exemple #1
0
    def pending_list(self,
                     disbursements=SAMPLE_DISBURSEMENTS,
                     preconfirmed=[]):
        responses.add(
            responses.GET,
            api_url('/disbursements/?resolution=pending&offset=0&limit=100'),
            match_querystring=True,
            json={
                'count': len(disbursements),
                'results': disbursements
            },
            status=200)

        responses.add(
            responses.GET,
            api_url(
                '/disbursements/?resolution=preconfirmed&offset=0&limit=100'),
            match_querystring=True,
            json={
                'count': len(preconfirmed),
                'results': preconfirmed
            },
            status=200)

        for disbursement in (disbursements + preconfirmed):
            self.add_nomis_responses_for_disbursement(disbursement)
Exemple #2
0
 def test_new_credits_display(self):
     with responses.RequestsMock() as rsps:
         rsps.add(
             rsps.GET,
             api_url('/credits/batches/'),
             json=wrap_response_data(),
             status=200,
         )
         # get new credits
         rsps.add(
             rsps.GET,
             api_url('/credits/?ordering=-received_at&offset=0&limit=100&status=credit_pending&resolution=pending'),
             json=wrap_response_data(CREDIT_1, CREDIT_2),
             status=200,
             match_querystring=True,
         )
         # get manual credits
         rsps.add(
             rsps.GET,
             api_url('/credits/?resolution=manual&status=credit_pending&offset=0&limit=100&ordering=-received_at'),
             json=wrap_response_data(),
             status=200,
             match_querystring=True,
         )
         self.login()
         response = self.client.get(self.url, follow=True)
         self.assertContains(response, '52.00')
         self.assertContains(response, '45.00')
Exemple #3
0
 def test_error_response(self):
     self.login()
     with responses.RequestsMock() as rsps:
         self.mock_prison_list(rsps)
         rsps.add(rsps.POST,
                  api_url('/requests/'),
                  json={'non_field_errors': 'ERROR MSG 1'},
                  status=400)
         rsps.add(
             rsps.GET,
             api_url(
                 '/requests/?username=my-username&role__name=prison-clerk'),
             json={'count': 0},
             status=200)
         response = self.client.post(reverse('move-prison'),
                                     data={
                                         'first_name': 'My First Name',
                                         'last_name': 'My Last Name',
                                         'email': '*****@*****.**',
                                         'username': '******',
                                         'role': 'prison-clerk',
                                         'prison': 'INP',
                                         'change-role': 'true',
                                     },
                                     follow=True)
     self.assertContains(response, 'ERROR MSG 1')
Exemple #4
0
    def test_update_prisoner(self):
        self.login(credentials={
            'username': '******',
            'password': '******'
        })

        # go to update page
        disbursement = SAMPLE_DISBURSEMENTS[3]
        self.pending_detail(disbursement=disbursement)
        responses.add(
            responses.GET,
            api_url('/prisoner_locations/{prisoner_number}/'.format(
                prisoner_number=disbursement['prisoner_number'])),
            json={
                'prisoner_number': disbursement['prisoner_number'],
                'prisoner_dob': '1970-01-01',
                'prisoner_name': 'JILLY HALL',
                'prison': 'BXI'
            },
            status=200,
        )

        response = self.client.get(
            reverse('disbursements:update_prisoner',
                    args=[disbursement['id']]))
        self.assertContains(response, disbursement['prisoner_number'])

        responses.reset()

        # post update
        new_prisoner_number = 'A1401AE'
        responses.add(
            responses.GET,
            api_url('/prisoner_locations/{prisoner_number}/'.format(
                prisoner_number=new_prisoner_number)),
            json={
                'prisoner_number': new_prisoner_number,
                'prisoner_dob': '1970-01-01',
                'prisoner_name': 'JILLY HALL',
                'prison': 'BXI'
            },
            status=200,
        )
        responses.add(
            responses.PATCH,
            api_url('/disbursements/{pk}/'.format(pk=disbursement['id'])),
            status=200)

        updated_disbursement = dict(**disbursement)
        updated_disbursement['prisoner_number'] = new_prisoner_number
        updated_disbursement['prisoner_name'] = 'JILLY HALL'
        self.pending_detail(disbursement=updated_disbursement)

        response = self.client.post(
            reverse('disbursements:update_prisoner',
                    args=[updated_disbursement['id']]),
            data={'prisoner_number': new_prisoner_number},
            follow=True)
        self.assertOnPage(response, 'disbursements:pending_detail')
        self.assertContains(response, new_prisoner_number)
    def mocker(mock_nomis_get_account_balances,
               mock_nomis_get_location,
               disbursements,
               preconfirmed=None):
        preconfirmed = preconfirmed or []

        responses.add(
            responses.GET,
            api_url('/disbursements/?resolution=pending&offset=0&limit=100'),
            match_querystring=True,
            json={
                'count': len(disbursements),
                'results': disbursements
            },
            status=200)

        responses.add(
            responses.GET,
            api_url(
                '/disbursements/?resolution=preconfirmed&offset=0&limit=100'),
            match_querystring=True,
            json={
                'count': len(preconfirmed),
                'results': preconfirmed
            },
            status=200)

        for disbursement in (disbursements + preconfirmed):
            mock_nomis_responses_for_disbursement(
                mock_nomis_get_account_balances,
                mock_nomis_get_location,
                disbursement,
            )
    def test_confirm_disbursement(self, calls_mocker,
                                  mock_nomis_create_transaction):
        self.login(credentials={
            'username': '******',
            'password': '******'
        })

        disbursement = SAMPLE_DISBURSEMENTS[4]
        calls_mocker(disbursement)
        responses.add(responses.POST,
                      api_url('/disbursements/actions/preconfirm/'),
                      status=200)
        responses.add(responses.POST,
                      api_url('/disbursements/actions/confirm/'),
                      status=200)

        response = self.client.post(self.url(disbursement['id']),
                                    data={'confirmation': 'yes'},
                                    follow=True)
        self.assertOnPage(response, 'disbursements:confirmed')
        self.assertContains(response, '12345-1')

        mock_nomis_create_transaction.assert_called_once_with(
            prison_id='BXI',
            prisoner_number='A1448AE',
            amount=3000,
            record_id='d660',
            description='Sent to Katy Hicks',
            transaction_type='RELA',
            retries=1,
        )
Exemple #7
0
    def test_confirm_disbursement_resets_on_failure(self):
        self.login(credentials={
            'username': '******',
            'password': '******'
        })

        disbursement = SAMPLE_DISBURSEMENTS[4]
        self.pending_detail(disbursement=disbursement)
        responses.add(responses.POST,
                      api_url('/disbursements/actions/preconfirm/'),
                      status=200)
        responses.add(
            responses.POST,
            nomis_url(
                '/prison/{nomis_id}/offenders/{prisoner_number}/transactions/'.
                format(nomis_id=disbursement['prison'],
                       prisoner_number=disbursement['prisoner_number'])),
            status=500)
        responses.add(responses.POST,
                      api_url('/disbursements/actions/reset/'),
                      status=200)

        with silence_logger():
            response = self.client.post(self.url(disbursement['id']),
                                        data={'confirmation': 'yes'},
                                        follow=True)
        self.assertOnPage(response, 'disbursements:pending_detail')
        self.assertContains(response,
                            'Payment not confirmed due to technical error')
 def test_new_credits_display(self):
     with responses.RequestsMock() as rsps:
         rsps.add(
             rsps.GET,
             api_url('/credits/batches/'),
             json=wrap_response_data(),
             status=200,
         )
         # get new credits
         rsps.add(
             rsps.GET,
             api_url('/credits/?ordering=-received_at&offset=0&limit=100&status=credit_pending&resolution=pending'),
             json=wrap_response_data(CREDIT_1, CREDIT_2),
             status=200,
             match_querystring=True,
         )
         # get manual credits
         rsps.add(
             rsps.GET,
             api_url('/credits/?resolution=manual&status=credit_pending&offset=0&limit=100&ordering=-received_at'),
             json=wrap_response_data(),
             status=200,
             match_querystring=True,
         )
         self.login()
         response = self.client.get(self.url, follow=True)
         self.assertContains(response, '52.00')
         self.assertContains(response, '45.00')
Exemple #9
0
 def test_no_disbursements_response(self):
     self.login()
     with responses.RequestsMock() as rsps:
         rsps.add(rsps.GET, api_url('/disbursements/?resolution=pending&limit=1',),
                  json={'count': 0, 'results': []}, match_querystring=True)
         rsps.add(rsps.GET, api_url('/disbursements/',),
                  json={'count': 0, 'results': []})
         response = self.client.get(self.url)
     self.assertContains(response, 'No disbursements found')
     form = response.context_data['form']
     self.assertTrue(form.is_valid())
     self.assertEqual(form.cleaned_data['page'], 1)
     self.assertEqual(form.cleaned_data['ordering'], '-created')
     self.assertEqual(form.cleaned_data['date_filter'], 'confirmed')
     content = response.content.decode()
     self.assertNotIn('This service is currently unavailable', content)
    def test_create_edited_valid_company_cheque_disbursement(self):
        responses.add(
            responses.POST,
            api_url('/disbursements/'),
            json={'id': 1},
            status=200,
        )

        self.login()
        self.choose_sending_method(method=SENDING_METHOD.CHEQUE)
        self.enter_prisoner_details()
        self.enter_amount(10)
        self.enter_recipient_details()
        self.enter_recipient_postcode()
        self.enter_recipient_address()
        self.enter_remittance_description(remittance='no')
        response = self.client.get(reverse('disbursements:details_check'))
        self.assertContains(response, 'John')
        self.assertContains(response, 'Smith')

        # edit recipient
        self.enter_recipient_details({
            'recipient_type': 'company',
            'recipient_company_name': 'Boots',
            'recipient_first_name': '',
            'recipient_last_name': '',
            'address_line1': '54 Fake Road',
            'address_line2': '',
            'city': 'London',
            'postcode': 'n17 9bj',
            'recipient_email': '*****@*****.**',
        })
        response = self.client.get(reverse('disbursements:details_check'))
        self.assertContains(response, 'Boots')
        self.assertNotContains(response, 'John')
        self.assertNotContains(response, 'Smith')

        # save
        response = self.client.post(reverse('disbursements:created'), follow=True)
        self.assertOnPage(response, 'disbursements:created')

        post_requests = [call.request for call in responses.calls if call.request.method == responses.POST]
        self.assertEqual(len(post_requests), 1)
        self.assertJSONEqual(post_requests[0].body.decode(), {
            'method': SENDING_METHOD.CHEQUE,
            'prisoner_number': self.prisoner_number,
            'prison': 'BXI',
            'prisoner_name': 'JILLY HALL',
            'amount': 1000,
            'recipient_is_company': True,
            'recipient_first_name': '',
            'recipient_last_name': 'Boots',
            'address_line1': '54 Fake Road',
            'address_line2': '',
            'city': 'London',
            'postcode': 'N17 9BJ',
            'recipient_email': '*****@*****.**',
            'remittance_description': 'Payment from JILLY HALL',
        })
Exemple #11
0
    def pending_detail(self, disbursement):
        responses.add(
            responses.GET,
            api_url('/disbursements/{pk}/'.format(pk=disbursement['id'])),
            json=disbursement,
            status=200)

        self.add_nomis_responses_for_disbursement(disbursement)
 def mocker(mock_nomis_get_account_balances, mock_nomis_get_location,
            disbursement):
     responses.add(
         responses.GET,
         api_url('/disbursements/{pk}/'.format(pk=disbursement['id'])),
         json=disbursement,
         status=200)
     mock_nomis_responses_for_disbursement(mock_nomis_get_account_balances,
                                           mock_nomis_get_location,
                                           disbursement)
    def test_processing_credits_redirects_to_new_for_expired_batch(self):
        with responses.RequestsMock() as rsps:
            # get active batches
            rsps.add(
                rsps.GET,
                api_url('/credits/batches/'),
                json=wrap_response_data(EXPIRED_PROCESSING_BATCH),
                status=200,
            )
            # get active batches
            rsps.add(
                rsps.GET,
                api_url('/credits/batches/'),
                json=wrap_response_data(EXPIRED_PROCESSING_BATCH),
                status=200,
            )
            # get incomplete credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=pending&pk=1&pk=2'),
                json=wrap_response_data(CREDIT_2),
                status=200,
                match_querystring=True,
            )
            # get complete credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=credited&pk=1&pk=2'),
                json=wrap_response_data(CREDIT_1),
                status=200,
                match_querystring=True,
            )
            rsps.add(
                rsps.DELETE,
                api_url('/credits/batches/%s/' % PROCESSING_BATCH['id']),
                status=200,
            )
            # get new credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?ordering=-received_at&offset=0&limit=100&status=credit_pending&resolution=pending'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )
            # get manual credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=manual&status=credit_pending&offset=0&limit=100&ordering=-received_at'),
                json=wrap_response_data(CREDIT_2),
                status=200,
                match_querystring=True,
            )

            self.login()
            response = self.client.get(self.url, follow=True)
            self.assertRedirects(response, reverse('new-credits'))
Exemple #14
0
    def test_processing_credits_redirects_to_new_for_expired_batch(self):
        with responses.RequestsMock() as rsps:
            # get active batches
            rsps.add(
                rsps.GET,
                api_url('/credits/batches/'),
                json=wrap_response_data(EXPIRED_PROCESSING_BATCH),
                status=200,
            )
            # get active batches
            rsps.add(
                rsps.GET,
                api_url('/credits/batches/'),
                json=wrap_response_data(EXPIRED_PROCESSING_BATCH),
                status=200,
            )
            # get incomplete credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=pending&pk=1&pk=2'),
                json=wrap_response_data(CREDIT_2),
                status=200,
                match_querystring=True,
            )
            # get complete credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=credited&pk=1&pk=2'),
                json=wrap_response_data(CREDIT_1),
                status=200,
                match_querystring=True,
            )
            rsps.add(
                rsps.DELETE,
                api_url('/credits/batches/%s/' % PROCESSING_BATCH['id']),
                status=200,
            )
            # get new credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?ordering=-received_at&offset=0&limit=100&status=credit_pending&resolution=pending'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )
            # get manual credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=manual&status=credit_pending&offset=0&limit=100&ordering=-received_at'),
                json=wrap_response_data(CREDIT_2),
                status=200,
                match_querystring=True,
            )

            self.login()
            response = self.client.get(self.url, follow=True)
            self.assertRedirects(response, reverse('new-credits'))
Exemple #15
0
    def test_reject_disbursement(self):
        self.login(credentials={
            'username': '******',
            'password': '******'
        })

        disbursement = SAMPLE_DISBURSEMENTS[4]
        responses.add(responses.POST,
                      api_url('/disbursements/comments/'),
                      status=201)
        responses.add(responses.POST,
                      api_url('/disbursements/actions/reject/'),
                      status=200)
        self.pending_list(disbursements=SAMPLE_DISBURSEMENTS[:3])

        response = self.client.post(self.url(disbursement['id']),
                                    data={'reason': 'bad one'},
                                    follow=True)
        self.assertOnPage(response, 'disbursements:pending_list')
        self.assertContains(response, 'Payment request cancelled.')
Exemple #16
0
    def test_processed_credits_detail_view(self):
        with responses.RequestsMock() as rsps:
            self.login()

            rsps.add(
                rsps.GET,
                api_url(
                    '/credits/?logged_at__gte=2017-06-03+00:00:00&limit=100'
                    '&logged_at__lt=2017-06-04+00:00:00&user=1'
                    '&log__action=credited&offset=0&ordering=-received_at'
                ),
                json={
                    'count': 2,
                    'results': [
                        {
                            'id': 142,
                            'prisoner_name': 'John Smith',
                            'prisoner_number': 'A1234BC',
                            'amount': 5200,
                            'formatted_amount': '£52.00',
                            'sender_name': 'Fred Smith',
                            'prison': 'BXI',
                            'owner': 1,
                            'owner_name': 'Clerk 1',
                            'received_at': '2017-06-02T12:00:00Z',
                            'resolution': 'credited',
                            'credited_at': '2017-06-03T12:00:00Z',
                            'refunded_at': None,
                        },
                        {
                            'id': 183,
                            'prisoner_name': 'John Smith',
                            'prisoner_number': 'A1234BC',
                            'amount': 2650,
                            'formatted_amount': '£26.50',
                            'sender_name': 'Mary Smith',
                            'prison': 'BXI',
                            'owner': 1,
                            'owner_name': 'Clerk 1',
                            'received_at': '2017-06-01T12:00:00Z',
                            'resolution': 'credited',
                            'credited_at': '2017-06-03T12:00:00Z',
                            'refunded_at': None,
                        },
                    ]
                },
                match_querystring=True,
                status=200,
            )

            response = self.client.get(self.url)
            self.assertEqual(response.status_code, 200)
            self.assertContains(response, text='John Smith', count=2)
Exemple #17
0
    def test_processing_credits_displays_continue_when_done(self):
        with responses.RequestsMock() as rsps:
            # get active batches
            rsps.add(
                rsps.GET,
                api_url('/credits/batches/'),
                json=wrap_response_data(PROCESSING_BATCH),
                status=200,
            )
            # get incomplete credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=pending&pk=1&pk=2'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )

            self.login()
            response = self.client.get(reverse('processing-credits'), follow=True)
            self.assertContains(response, 'Continue')
    def test_processed_credits_detail_view(self):
        with responses.RequestsMock() as rsps:
            self.login()

            rsps.add(
                rsps.GET,
                api_url(
                    '/credits/?logged_at__gte=2017-06-03+00:00:00&limit=100'
                    '&logged_at__lt=2017-06-04+00:00:00&user=1'
                    '&log__action=credited&offset=0&ordering=-received_at'
                ),
                json={
                    'count': 2,
                    'results': [
                        {
                            'id': 142,
                            'prisoner_name': 'John Smith',
                            'prisoner_number': 'A1234BC',
                            'amount': 5200,
                            'formatted_amount': '£52.00',
                            'sender_name': 'Fred Smith',
                            'prison': 'BXI',
                            'owner': 1,
                            'owner_name': 'Clerk 1',
                            'received_at': '2017-06-02T12:00:00Z',
                            'resolution': 'credited',
                            'credited_at': '2017-06-03T12:00:00Z',
                            'refunded_at': None,
                        },
                        {
                            'id': 183,
                            'prisoner_name': 'John Smith',
                            'prisoner_number': 'A1234BC',
                            'amount': 2650,
                            'formatted_amount': '£26.50',
                            'sender_name': 'Mary Smith',
                            'prison': 'BXI',
                            'owner': 1,
                            'owner_name': 'Clerk 1',
                            'received_at': '2017-06-01T12:00:00Z',
                            'resolution': 'credited',
                            'credited_at': '2017-06-03T12:00:00Z',
                            'refunded_at': None,
                        },
                    ]
                },
                match_querystring=True,
                status=200,
            )

            response = self.client.get(self.url)
            self.assertEqual(response.status_code, 200)
            self.assertContains(response, text='John Smith', count=2)
    def test_processing_credits_displays_continue_when_done(self):
        with responses.RequestsMock() as rsps:
            # get active batches
            rsps.add(
                rsps.GET,
                api_url('/credits/batches/'),
                json=wrap_response_data(PROCESSING_BATCH),
                status=200,
            )
            # get incomplete credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=pending&pk=1&pk=2'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )

            self.login()
            response = self.client.get(reverse('processing-credits'), follow=True)
            self.assertContains(response, 'Continue')
    def test_confirm_disbursement_resets_on_failure(self, calls_mocker, _):
        self.login(credentials={
            'username': '******',
            'password': '******'
        })

        disbursement = SAMPLE_DISBURSEMENTS[4]
        calls_mocker(disbursement)
        responses.add(responses.POST,
                      api_url('/disbursements/actions/preconfirm/'),
                      status=200)
        responses.add(responses.POST,
                      api_url('/disbursements/actions/reset/'),
                      status=200)

        with silence_logger():
            response = self.client.post(self.url(disbursement['id']),
                                        data={'confirmation': 'yes'},
                                        follow=True)
        self.assertOnPage(response, 'disbursements:pending_detail')
        self.assertContains(response,
                            'Payment not confirmed due to technical error')
Exemple #21
0
 def test_disbursements_listed(self):
     self.login()
     with responses.RequestsMock() as rsps:
         rsps.add(rsps.GET, api_url('/disbursements/?resolution=pending&limit=1',),
                  json={'count': 1, 'results': []}, match_querystring=True)
         rsps.add(rsps.GET, api_url('/disbursements/',),
                  json={'count': 1, 'results': [{
                      'id': 100, 'amount': 1250, 'invoice_number': 'PMD1000100',
                      'method': 'cheque', 'resolution': 'sent', 'nomis_transaction_id': '123-1',
                      'prisoner_name': 'JOHN HALLS', 'prisoner_number': 'A1409AE',
                      'recipient_is_company_name': False,
                      'recipient_first_name': 'FN', 'recipient_last_name': 'SN', 'recipient_email': '',
                      'address_line1': '102 Petty France', 'address_line2': '',
                      'city': 'London', 'postcode': 'SW1H 9AJ', 'country': 'UK',
                      'sort_code': '', 'account_number': '', 'roll_number': '',
                      'log_set': [{'action': 'created', 'created': '2018-01-10T08:00:00Z',
                                   'user': self.user},
                                  {'action': 'confirmed', 'created': '2018-01-10T09:00:00Z',
                                   'user': self.user},
                                  {'action': 'sent', 'created': '2018-01-10T10:00:00Z',
                                   'user': self.user}],
                  }]})
         response = self.client.get(self.url)
     content = response.content.decode()
     self.assertNotIn('This service is currently unavailable', content)
     self.assertIn('Cheque', content)
     self.assertNotIn('Bank transfer', content)
     self.assertIn('Confirmed 10/01/2018', content)
     self.assertIn('Sent to SSCL', content)
     self.assertIn('PMD1000100', content)
     self.assertIn('£12.50', content)
     self.assertIn('123-1', content)
     self.assertIn('JOHN HALLS', content)
     self.assertIn('A1409AE', content)
     self.assertIn('FN SN', content)
     self.assertIn('102 Petty France', content)
     self.assertIn('London', content)
     self.assertIn('SW1H 9AJ', content)
     self.assertIn('Page 1 of 1', content)
 def test_error_response(self):
     self.login()
     with responses.RequestsMock() as rsps:
         self.mock_prison_list(rsps)
         rsps.add(rsps.POST, api_url('/requests/'),
                  json={'non_field_errors': 'ERROR MSG 1'}, status=400)
         response = self.client.post(reverse('move-prison'), data={
             'first_name': 'My First Name', 'last_name': 'My Last Name',
             'email': '*****@*****.**', 'username': '******',
             'role': 'prison-clerk', 'prison': 'INP',
             'change-role': 'true',
         }, follow=True)
     self.assertContains(response, 'ERROR MSG 1')
Exemple #23
0
 def test_success_response(self):
     self.login()
     with responses.RequestsMock() as rsps:
         self.mock_prison_list(rsps)
         rsps.add(rsps.POST, api_url('/requests/'),
                  json={}, status=201)
         response = self.client.post(reverse('move-prison'), data={
             'first_name': 'My First Name', 'last_name': 'My Last Name',
             'email': '*****@*****.**', 'username': '******',
             'role': 'prison-clerk', 'prison': 'INP',
             'change-role': 'true',
         }, follow=True)
     self.assertContains(response, 'Your request for access has been sent')
Exemple #24
0
 def test_success_response_no_previous_request(self):
     with responses.RequestsMock() as rsps:
         self.mock_prison_list(rsps)
         rsps.add(rsps.POST, api_url('/requests/'), json={}, status=201)
         rsps.add(
             rsps.GET,
             api_url(
                 '/requests/?username=my-username&role__name=prison-clerk'),
             json={'count': 0},
             status=200)
         response = self.client.post(reverse('sign-up'),
                                     data={
                                         'first_name': 'My First Name',
                                         'last_name': 'My Last Name',
                                         'email': '*****@*****.**',
                                         'username': '******',
                                         'role': 'prison-clerk',
                                         'prison': 'INP',
                                         'reason': 'because'
                                     },
                                     follow=True)
     self.assertContains(response, 'Your request for access has been sent')
Exemple #25
0
 def prisoner_location_response(self, disbursement):
     responses.add(
         responses.GET,
         api_url('/prisoner_locations/{prisoner_number}/'.format(
             prisoner_number=disbursement['prisoner_number'])),
         json={
             'prisoner_number': disbursement['prisoner_number'],
             'prisoner_dob': '1970-01-01',
             'prisoner_name': 'TEST QUASH2',
             'prison': 'BXI'
         },
         status=200,
     )
Exemple #26
0
    def test_confirm_disbursement(self):
        self.login(credentials={
            'username': '******',
            'password': '******'
        })

        disbursement = SAMPLE_DISBURSEMENTS[4]
        self.pending_detail(disbursement=disbursement)
        responses.add(responses.POST,
                      api_url('/disbursements/actions/preconfirm/'),
                      status=200)
        responses.add(
            responses.POST,
            nomis_url(
                '/prison/{nomis_id}/offenders/{prisoner_number}/transactions/'.
                format(nomis_id=disbursement['prison'],
                       prisoner_number=disbursement['prisoner_number'])),
            json={'id': '12345-1'},
            status=200)
        responses.add(responses.POST,
                      api_url('/disbursements/actions/confirm/'),
                      status=200)

        response = self.client.post(self.url(disbursement['id']),
                                    data={'confirmation': 'yes'},
                                    follow=True)
        self.assertOnPage(response, 'disbursements:confirmed')
        self.assertContains(response, '12345-1')
        nomis_call = responses.calls[-3]
        nomis_request = json.loads(nomis_call.request.body.decode())
        self.assertDictEqual(
            nomis_request, {
                'type': 'RELA',
                'description': 'Sent to Katy Hicks',
                'amount': 3000,
                'client_transaction_id': 'd660',
                'client_unique_ref': 'd660',
            })
    def test_new_credits_redirects_to_processing_when_batch_active(self):
        with responses.RequestsMock() as rsps:
            # get active batches
            rsps.add(
                rsps.GET,
                api_url('/credits/batches/'),
                json=wrap_response_data(PROCESSING_BATCH),
                status=200,
            )
            # get incomplete credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=pending&pk=1&pk=2'),
                json=wrap_response_data(CREDIT_1, CREDIT_2),
                status=200,
                match_querystring=True,
            )
            # get active batches
            rsps.add(
                rsps.GET,
                api_url('/credits/batches/'),
                json=wrap_response_data(PROCESSING_BATCH),
                status=200,
            )
            # get incomplete credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=pending&pk=1&pk=2'),
                json=wrap_response_data(CREDIT_1, CREDIT_2),
                status=200,
                match_querystring=True,
            )

            self.login()
            response = self.client.get(reverse('new-credits'), follow=True)
            self.assertRedirects(response, self.url)
Exemple #28
0
    def test_new_credits_redirects_to_processing_when_batch_active(self):
        with responses.RequestsMock() as rsps:
            # get active batches
            rsps.add(
                rsps.GET,
                api_url('/credits/batches/'),
                json=wrap_response_data(PROCESSING_BATCH),
                status=200,
            )
            # get incomplete credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=pending&pk=1&pk=2'),
                json=wrap_response_data(CREDIT_1, CREDIT_2),
                status=200,
                match_querystring=True,
            )
            # get active batches
            rsps.add(
                rsps.GET,
                api_url('/credits/batches/'),
                json=wrap_response_data(PROCESSING_BATCH),
                status=200,
            )
            # get incomplete credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=pending&pk=1&pk=2'),
                json=wrap_response_data(CREDIT_1, CREDIT_2),
                status=200,
                match_querystring=True,
            )

            self.login()
            response = self.client.get(reverse('new-credits'), follow=True)
            self.assertRedirects(response, self.url)
Exemple #29
0
    def test_create_valid_bank_transfer_disbursement(self):
        responses.add(
            responses.POST,
            api_url('/disbursements/'),
            json={'id': 1},
            status=200,
        )

        self.login()
        self.choose_sending_method(method=SENDING_METHOD.BANK_TRANSFER)
        self.enter_prisoner_details()
        self.enter_amount(10)
        self.enter_recipient_details()
        self.enter_recipient_postcode()
        self.enter_recipient_address()
        self.enter_recipient_bank_account()
        self.enter_remittance_description(remittance='yes',
                                          remittance_description='')

        response = self.client.post(reverse('disbursements:created'),
                                    follow=True)
        self.assertOnPage(response, 'disbursements:created')

        post_requests = [
            call.request for call in responses.calls
            if call.request.method == responses.POST
        ]
        self.assertEqual(len(post_requests), 1)
        self.assertJSONEqual(
            post_requests[0].body.decode(), {
                'method': SENDING_METHOD.BANK_TRANSFER,
                'prisoner_number': self.prisoner_number,
                'prison': 'BXI',
                'prisoner_name': 'JILLY HALL',
                'amount': 1000,
                'sort_code': '605789',
                'account_number': '90908787',
                'roll_number': '',
                'recipient_is_company': False,
                'recipient_first_name': 'John',
                'recipient_last_name': 'Smith',
                'address_line1': '54 Fake Road',
                'address_line2': '',
                'city': 'London',
                'postcode': 'N17 9BJ',
                'recipient_email': '*****@*****.**',
                'remittance_description': '',
            })
Exemple #30
0
    def test_update_address(self):
        self.login(credentials={
            'username': '******',
            'password': '******'
        })

        # go to update page
        disbursement = SAMPLE_DISBURSEMENTS[3]
        self.pending_detail(disbursement=disbursement)
        self.prisoner_location_response(disbursement)

        response = self.client.get(
            reverse('disbursements:update_recipient_address',
                    args=[disbursement['id']]))
        self.assertOnPage(response, 'disbursements:update_recipient_address')
        # address picker shouldn't show on update
        self.assertNotContains(response, 'Choose address')
        self.assertNotContains(response, 'Or enter address manually')

        responses.reset()

        # post update
        responses.add(
            responses.PATCH,
            api_url('/disbursements/{pk}/'.format(pk=disbursement['id'])),
            status=200)

        new_address = {
            'address_line1': '54 Fake Road',
            'address_line2': '',
            'city': 'London',
            'postcode': 'n17 9xy'
        }
        updated_disbursement = dict(**disbursement)
        updated_disbursement.update(new_address)
        self.pending_detail(disbursement=updated_disbursement)
        self.prisoner_location_response(disbursement)

        response = self.client.post(reverse(
            'disbursements:update_recipient_address',
            args=[updated_disbursement['id']]),
                                    data=new_address,
                                    follow=True)
        self.assertOnPage(response, 'disbursements:pending_detail')
        self.assertContains(response, new_address['address_line1'])
        self.assertContains(response, new_address['address_line2'])
        self.assertContains(response, new_address['city'])
        self.assertContains(response, new_address['postcode'])
 def test_confirming_shows_landing_page(self):
     self.login(login_data=self.unconfirmed_login_data)
     with responses.RequestsMock() as rsps:
         rsps.add(
             rsps.PUT,
             api_url(
                 f"/users/{self.unconfirmed_login_data['user_data']['username']}/flags/{READ_ML_BRIEFING_FLAG}/"
             ),
             status=200,
         )
         response = self.client.post(
             reverse('ml-briefing-confirmation'),
             data={'read_briefing': 'yes'},
             follow=True,
         )
     self.assertOnPage(response, 'home')
Exemple #32
0
    def test_processed_credits_list_view(self):
        with responses.RequestsMock() as rsps:
            self.login()

            rsps.add(
                rsps.GET,
                api_url('/credits/processed/'),
                json={
                    'count':
                    3,
                    'results': [
                        {
                            'logged_at': '2017-06-04',
                            'owner': 1,
                            'owner_name': 'Clerk 1',
                            'count': 10,
                            'total': 10500,
                            'comment_count': 0
                        },
                        {
                            'logged_at': '2017-06-03',
                            'owner': 1,
                            'owner_name': 'Clerk 1',
                            'count': 4,
                            'total': 6000,
                            'comment_count': 4
                        },
                        {
                            'logged_at': '2017-06-03',
                            'owner': 2,
                            'owner_name': 'Clerk 2',
                            'count': 5,
                            'total': 3200,
                            'comment_count': 5
                        },
                    ]
                },
                status=200,
            )

            response = self.client.get(self.url)
            self.assertEqual(response.status_code, 200)
            self.assertSequenceEqual(response.context['page_range'], [1])
            self.assertEqual(response.context['current_page'], 1)
            self.assertContains(response, text='10 credits')
            self.assertContains(response, text='4 credits')
            self.assertContains(response, text='5 credits')
Exemple #33
0
    def test_invalid_prisoner_number(self):
        prisoner_number = 'A1404AE'
        responses.add(
            responses.GET,
            api_url('/prisoner_locations/{prisoner_number}/'.format(
                prisoner_number=prisoner_number)),
            status=404,
        )

        self.login()
        self.choose_sending_method(method=SENDING_METHOD.BANK_TRANSFER)
        response = self.client.post(self.url,
                                    data={'prisoner_number': prisoner_number},
                                    follow=True)

        self.assertOnPage(response, 'disbursements:prisoner')
        self.assertContains(response, PrisonerForm.error_messages['not_found'])
Exemple #34
0
    def test_processed_credits_list_view_no_results(self):
        with responses.RequestsMock() as rsps:
            self.login()

            rsps.add(
                rsps.GET,
                api_url('/credits/processed/'),
                json={
                    'count': 0,
                    'results': []
                },
                status=200,
            )

            response = self.client.get(self.url)
            self.assertEqual(response.status_code, 200)
            self.assertContains(response, text='No credits')
Exemple #35
0
    def enter_prisoner_details(self):
        responses.add(
            responses.GET,
            api_url('/prisoner_locations/{prisoner_number}/'.format(
                prisoner_number=self.prisoner_number)),
            json={
                'prisoner_number': self.prisoner_number,
                'prisoner_dob': '1970-01-01',
                'prisoner_name': 'JILLY HALL',
                'prison': self.nomis_id
            },
            status=200,
        )

        return self.client.post(reverse('disbursements:prisoner'),
                                data={'prisoner_number': self.prisoner_number},
                                follow=True)
Exemple #36
0
 def mock_prison_list(self, rsps):
     rsps.add(rsps.GET,
              api_url('/prisons/'),
              json={
                  'count':
                  2,
                  'results': [
                      {
                          'nomis_id': 'IXB',
                          'name': 'Prison 1'
                      },
                      {
                          'nomis_id': 'INP',
                          'name': 'Prison 2'
                      },
                  ]
              })
    def test_processed_credits_list_view(self):
        with responses.RequestsMock() as rsps:
            self.login()

            rsps.add(
                rsps.GET,
                api_url('/credits/processed/'),
                json={
                    'count': 3,
                    'results': [
                        {
                            'logged_at': '2017-06-04',
                            'owner': 1,
                            'owner_name': 'Clerk 1',
                            'count': 10,
                            'total': 10500,
                            'comment_count': 0
                        },
                        {
                            'logged_at': '2017-06-03',
                            'owner': 1,
                            'owner_name': 'Clerk 1',
                            'count': 4,
                            'total': 6000,
                            'comment_count': 4
                        },
                        {
                            'logged_at': '2017-06-03',
                            'owner': 2,
                            'owner_name': 'Clerk 2',
                            'count': 5,
                            'total': 3200,
                            'comment_count': 5
                        },
                    ]
                },
                status=200,
            )

            response = self.client.get(self.url)
            self.assertEqual(response.status_code, 200)
            self.assertSequenceEqual(response.context['page_range'], [1])
            self.assertEqual(response.context['current_page'], 1)
            self.assertContains(response, text='10 credits')
            self.assertContains(response, text='4 credits')
            self.assertContains(response, text='5 credits')
    def test_processed_credits_list_view_no_results(self):
        with responses.RequestsMock() as rsps:
            self.login()

            rsps.add(
                rsps.GET,
                api_url('/credits/processed/'),
                json={
                    'count': 0,
                    'results': []
                },
                status=200,
            )

            response = self.client.get(self.url)
            self.assertEqual(response.status_code, 200)
            self.assertContains(response, text='No credits')
    def test_create_valid_cheque_disbursement(self):
        responses.add(
            responses.POST,
            api_url('/disbursements/'),
            json={'id': 1},
            status=200,
        )

        self.login()
        self.choose_sending_method(method=SENDING_METHOD.CHEQUE)
        self.enter_prisoner_details()
        self.enter_amount()
        self.enter_recipient_details()
        self.enter_recipient_postcode()
        self.enter_recipient_address()
        self.enter_remittance_description(remittance='no')
        response = self.client.post(reverse('disbursements:created'), follow=True)

        self.assertOnPage(response, 'disbursements:created')
    def test_create_valid_bank_transfer_disbursement(self):
        responses.add(
            responses.POST,
            api_url('/disbursements/'),
            json={'id': 1},
            status=200,
        )

        self.login()
        self.choose_sending_method(method=SENDING_METHOD.BANK_TRANSFER)
        self.enter_prisoner_details()
        self.enter_amount(10)
        self.enter_recipient_details()
        self.enter_recipient_postcode()
        self.enter_recipient_address()
        self.enter_recipient_bank_account()
        self.enter_remittance_description(remittance='yes', remittance_description='')

        response = self.client.post(reverse('disbursements:created'), follow=True)
        self.assertOnPage(response, 'disbursements:created')

        post_requests = [call.request for call in responses.calls if call.request.method == responses.POST]
        self.assertEqual(len(post_requests), 1)
        self.assertJSONEqual(post_requests[0].body.decode(), {
            'method': SENDING_METHOD.BANK_TRANSFER,
            'prisoner_number': self.prisoner_number,
            'prison': 'BXI',
            'prisoner_name': 'JILLY HALL',
            'amount': 1000,
            'sort_code': '605789',
            'account_number': '90908787',
            'roll_number': '',
            'recipient_is_company': False,
            'recipient_first_name': 'John',
            'recipient_last_name': 'Smith',
            'address_line1': '54 Fake Road',
            'address_line2': '',
            'city': 'London',
            'postcode': 'N17 9BJ',
            'recipient_email': '*****@*****.**',
            'remittance_description': '',
        })
Exemple #41
0
    def test_create_valid_cheque_disbursement(self):
        responses.add(
            responses.POST,
            api_url('/disbursements/'),
            json={'id': 1},
            status=200,
        )

        self.login()
        self.choose_sending_method(method=SENDING_METHOD.CHEQUE)
        self.enter_prisoner_details()
        self.enter_amount()
        self.enter_recipient_details()
        self.enter_recipient_postcode()
        self.enter_recipient_address()
        self.enter_remittance_description(remittance='no')
        response = self.client.post(reverse('disbursements:created'),
                                    follow=True)

        self.assertOnPage(response, 'disbursements:created')
    def enter_prisoner_details(self):
        responses.add(
            responses.GET,
            api_url('/prisoner_locations/{prisoner_number}/'.format(
                prisoner_number=self.prisoner_number
            )),
            json={
                'prisoner_number': self.prisoner_number,
                'prisoner_dob': '1970-01-01',
                'prisoner_name': 'JILLY HALL',
                'prison': self.nomis_id
            },
            status=200,
        )

        return self.client.post(
            reverse('disbursements:prisoner'),
            data={'prisoner_number': self.prisoner_number},
            follow=True
        )
    def test_prisoner_in_different_prison(self):
        prisoner_number = 'A1404AE'
        responses.add(
            responses.GET,
            api_url('/prisoner_locations/{prisoner_number}/'.format(
                prisoner_number=prisoner_number
            )),
            status=403,
        )

        self.login()
        self.choose_sending_method(method=SENDING_METHOD.BANK_TRANSFER)
        response = self.client.post(
            self.url,
            data={'prisoner_number': prisoner_number},
            follow=True
        )

        self.assertOnPage(response, 'disbursements:prisoner')
        self.assertContains(response, PrisonerForm.error_messages['wrong_prison'])
    def test_processed_credits_detail_view_no_results(self):
        with responses.RequestsMock() as rsps:
            self.login()

            rsps.add(
                rsps.GET,
                api_url(
                    '/credits/?logged_at__gte=2017-06-03+00:00:00&limit=100'
                    '&logged_at__lt=2017-06-04+00:00:00&user=1'
                    '&log__action=credited&offset=0&ordering=-received_at'
                ),
                json={
                    'count': 0,
                    'results': []
                },
                match_querystring=True,
                status=200,
            )

            response = self.client.get(self.url)
            self.assertEqual(response.status_code, 200)
            self.assertContains(response, text='No credits')
 def test_disbursements_search(self):
     self.login()
     with responses.RequestsMock() as rsps:
         rsps.add(rsps.GET, api_url('/disbursements/?offset=10&limit=10&ordering=-created&resolution=confirmed',),
                  match_querystring=True,
                  json={'count': 11, 'results': [{
                      'id': 99, 'amount': 25010, 'invoice_number': '1000099',
                      'method': 'bank_transfer', 'resolution': 'confirmed', 'nomis_transaction_id': None,
                      'prisoner_name': 'JOHN HALLS', 'prisoner_number': 'A1409AE',
                      'recipient_is_company_name': False,
                      'recipient_first_name': 'FN', 'recipient_last_name': 'SN', 'recipient_email': 'email@local',
                      'address_line1': '13 Place Vendôme', 'address_line2': '',
                      'city': 'Paris', 'postcode': '75001', 'country': 'France',
                      'sort_code': '000000', 'account_number': '1234567890', 'roll_number': '',
                      'log_set': [{'action': 'created', 'created': '2018-01-10T08:00:00Z',
                                   'user': self.user},
                                  {'action': 'confirmed', 'created': '2018-01-10T09:00:00Z',
                                   'user': self.user}],
                  }]})
         response = self.client.get(self.url + '?page=2&resolution=confirmed')
     form = response.context_data['form']
     self.assertTrue(form.is_valid())
     self.assertEqual(form.cleaned_data['page'], 2)
     self.assertEqual(form.cleaned_data['resolution'], 'confirmed')
     content = response.content.decode()
     self.assertNotIn('This service is currently unavailable', content)
     self.assertNotIn('Cheque', content)
     self.assertIn('Account 1234567890', content)
     self.assertIn('Confirmed 10/01/2018', content)
     self.assertNotIn('Sent by SSCL', content)
     self.assertNotIn('1000099', content)
     self.assertIn('£250.10', content)
     self.assertIn('France', content)
     self.assertIn('00-00-00', content)
     self.assertIn('1234567890', content)
     self.assertIn('email@local', content)
     self.assertIn('Page 2 of 2', content)
 def mock_prison_list(self, rsps):
     rsps.add(rsps.GET, api_url('/prisons/'),
              json={'count': 2, 'results': [
                  {'nomis_id': 'IXB', 'name': 'Prison 1'},
                  {'nomis_id': 'INP', 'name': 'Prison 2'},
              ]})
    def test_new_credits_submit(self):
        with responses.RequestsMock() as rsps:
            # get new credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?ordering=-received_at&offset=0&limit=100&status=credit_pending&resolution=pending'),
                json=wrap_response_data(CREDIT_1, CREDIT_2),
                status=200,
                match_querystring=True,
            )
            # get manual credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=manual&status=credit_pending&offset=0&limit=100&ordering=-received_at'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )
            # create batch
            rsps.add(
                rsps.POST,
                api_url('/credits/batches/'),
                status=201,
            )
            # credit credits to NOMIS and API
            rsps.add(
                rsps.POST,
                nomis_url('/prison/BXI/offenders/A1234BC/transactions/'),
                json={'id': '6244779-1'},
                status=200,
            )
            rsps.add(
                rsps.POST,
                api_url('/credits/actions/credit/'),
                status=204,
            )
            rsps.add(
                rsps.POST,
                nomis_url('/prison/BXI/offenders/A1234GG/transactions/'),
                json={'id': '6244780-1'},
                status=200,
            )
            rsps.add(
                rsps.POST,
                api_url('/credits/actions/credit/'),
                status=204,
            )
            # REDIRECT after success
            # get active batches
            rsps.add(
                rsps.GET,
                api_url('/credits/batches/'),
                json=wrap_response_data(PROCESSING_BATCH),
                status=200,
            )
            # get incomplete credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=pending&pk=1&pk=2'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )
            # get complete credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=credited&pk=1&pk=2'),
                json=wrap_response_data(CREDIT_1, CREDIT_2),
                status=200,
                match_querystring=True,
            )
            # delete completed batch
            rsps.add(
                rsps.DELETE,
                api_url('/credits/batches/%s/' % PROCESSING_BATCH['id']),
                status=200,
            )
            # get new credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?ordering=-received_at&offset=0&limit=100&status=credit_pending&resolution=pending'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )
            # get manual credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=manual&status=credit_pending&offset=0&limit=100&ordering=-received_at'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )

            self.login()
            response = self.client.post(
                self.url,
                data={'credits': [1, 2], 'submit_new': None},
                follow=True
            )
            self.assertEqual(response.status_code, 200)
            expected_calls = [
                [{'id': 1, 'credited': True, 'nomis_transaction_id': '6244779-1'}],
                [{'id': 2, 'credited': True, 'nomis_transaction_id': '6244780-1'}]
            ]
            self.assertTrue(
                json.loads(rsps.calls[4].request.body.decode('utf-8')) in expected_calls and
                json.loads(rsps.calls[6].request.body.decode('utf-8')) in expected_calls
            )
            self.assertContains(response, '2 credits sent to NOMIS')
            self.assertEqual(len(mail.outbox), 2)
            self.assertTrue(
                '£52.00' in mail.outbox[0].body and '£45.00' in mail.outbox[1].body or
                '£52.00' in mail.outbox[1].body and '£45.00' in mail.outbox[0].body
            )
    def test_search_view(self):
        with responses.RequestsMock() as rsps:
            self.login()
            login_data = self._default_login_data

            # uncredited
            rsps.add(
                rsps.GET,
                api_url('/credits/'),
                json={
                    'count': 1,
                    'results': [
                        {
                            'id': 200,
                            'prisoner_name': 'HUGH MARSH',
                            'prisoner_number': 'A1235BC',
                            'amount': 1500,
                            'formatted_amount': '£15.00',
                            'sender_name': 'Fred Smith',
                            'prison': 'BXI',
                            'owner': None,
                            'owner_name': None,
                            'received_at': '2017-01-26T12:00:00Z',
                            'resolution': 'pending',
                            'credited_at': None,
                            'refunded_at': None,
                        },
                    ]
                },
                status=200,
            )

            # credited
            rsps.add(
                rsps.GET,
                api_url('/credits/'),
                json={
                    'count': 2,
                    'results': [
                        {
                            'id': 142,
                            'prisoner_name': 'John Smith',
                            'prisoner_number': 'A1234BC',
                            'amount': 5200,
                            'formatted_amount': '£52.00',
                            'sender_name': 'Fred Smith',
                            'prison': 'BXI',
                            'owner': login_data['user_pk'],
                            'owner_name': '%s %s' % (
                                login_data['user_data']['first_name'],
                                login_data['user_data']['last_name'],
                            ),
                            'received_at': '2017-01-25T12:00:00Z',
                            'resolution': 'credited',
                            'credited_at': '2017-01-26T12:00:00Z',
                            'refunded_at': None,
                        },
                        {
                            'id': 183,
                            'prisoner_name': 'John Smith',
                            'prisoner_number': 'A1234BC',
                            'amount': 2650,
                            'formatted_amount': '£26.50',
                            'sender_name': 'Mary Smith',
                            'prison': 'BXI',
                            'owner': login_data['user_pk'],
                            'owner_name': '%s %s' % (
                                login_data['user_data']['first_name'],
                                login_data['user_data']['last_name'],
                            ),
                            'received_at': '2017-01-25T12:00:00Z',
                            'resolution': 'credited',
                            'credited_at': '2017-01-26T12:00:00Z',
                            'refunded_at': None,
                        },
                    ]
                },
                status=200,
            )

            response = self.client.get(self.url, data={
                'search': 'Smith',
            })

        self.assertEqual(response.status_code, 200)
        self.assertSequenceEqual(response.context['page_range'], [1])
        self.assertEqual(response.context['current_page'], 1)
        self.assertEqual(response.context['credit_owner_name'], '%s %s' % (
            login_data['user_data']['first_name'],
            login_data['user_data']['last_name'],
        ))
        self.assertIn('<strong>3</strong> credits', response.content.decode(response.charset))
        self.assertContains(response, text='John Smith', count=2)
    def test_manual_credits_submit(self):
        with responses.RequestsMock() as rsps:
            # get new credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?ordering=-received_at&offset=0&limit=100&status=credit_pending&resolution=pending'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )
            # get manual credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=manual&status=credit_pending&offset=0&limit=100&ordering=-received_at'),
                json=wrap_response_data(CREDIT_1, CREDIT_2),
                status=200,
                match_querystring=True,
            )
            # credit credit to API
            rsps.add(
                rsps.POST,
                api_url('/credits/actions/credit/'),
                status=204,
            )
            # REDIRECT after success
            # get active batches
            rsps.add(
                rsps.GET,
                api_url('/credits/batches/'),
                json=wrap_response_data(),
                status=200,
            )
            # get new credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?ordering=-received_at&offset=0&limit=100&status=credit_pending&resolution=pending'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )
            # get manual credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=manual&status=credit_pending&offset=0&limit=100&ordering=-received_at'),
                json=wrap_response_data(CREDIT_2),
                status=200,
                match_querystring=True,
            )

            self.login()
            response = self.client.post(
                self.url,
                data={'submit_manual_1': None},
                follow=True
            )
            self.assertEqual(
                json.loads(rsps.calls[2].request.body.decode('utf-8')),
                [{'id': 1, 'credited': True}]
            )
            self.assertEqual(response.status_code, 200)
            self.assertContains(response, '1 credit manually input by you into NOMIS')
    def test_new_credits_submit_with_uncreditable(self):
        with responses.RequestsMock() as rsps:
            # get new credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?ordering=-received_at&offset=0&limit=100&status=credit_pending&resolution=pending'),
                json=wrap_response_data(CREDIT_1, CREDIT_2),
                status=200,
                match_querystring=True,
            )
            # get manual credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=manual&status=credit_pending&offset=0&limit=100&ordering=-received_at'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )
            # create batch
            rsps.add(
                rsps.POST,
                api_url('/credits/batches/'),
                status=201,
            )
            # credit credits to NOMIS and API
            rsps.add(
                rsps.POST,
                nomis_url('/prison/BXI/offenders/A1234BC/transactions/'),
                status=400,
            )
            rsps.add(
                rsps.POST,
                api_url('/credits/actions/setmanual/'),
                status=204,
            )
            rsps.add(
                rsps.POST,
                nomis_url('/prison/BXI/offenders/A1234GG/transactions/'),
                json={'id': '6244780-1'},
                status=200,
            )
            rsps.add(
                rsps.POST,
                api_url('/credits/actions/credit/'),
                status=204,
            )
            # REDIRECT after success
            # get active batches
            rsps.add(
                rsps.GET,
                api_url('/credits/batches/'),
                json=wrap_response_data(PROCESSING_BATCH),
                status=200,
            )
            # get incomplete credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=pending&pk=1&pk=2'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )
            # get complete credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=credited&pk=1&pk=2'),
                json=wrap_response_data(CREDIT_2),
                status=200,
                match_querystring=True,
            )
            # delete completed batch
            rsps.add(
                rsps.DELETE,
                api_url('/credits/batches/%s/' % PROCESSING_BATCH['id']),
                status=200,
            )
            # get new credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?ordering=-received_at&offset=0&limit=100&status=credit_pending&resolution=pending'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )
            # get manual credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=manual&status=credit_pending&offset=0&limit=100&ordering=-received_at'),
                json=wrap_response_data(CREDIT_1),
                status=200,
                match_querystring=True,
            )
            rsps.add(
                rsps.GET,
                nomis_url('/offenders/A1234BC/location/'),
                json={
                    'establishment': {
                        'code': 'LEI',
                        'desc': 'LEEDS (HMP)'
                    }
                },
                status=200,
            )

            self.login()
            with silence_logger(name='mtp', level=logging.CRITICAL):
                response = self.client.post(
                    self.url,
                    data={'credits': [1, 2], 'submit_new': None},
                    follow=True
                )
            self.assertEqual(response.status_code, 200)
            self.assertContains(response, '1 credit sent to NOMIS')
            self.assertContains(response, '1 credit needs your manual input in NOMIS')
            self.assertEqual(len(mail.outbox), 1)