示例#1
0
def test_create_pad_update_when_cfs_down(session, client, jwt, app):
    """Assert that the payment records are created with 202."""
    token = jwt.create_jwt(get_claims(role=Role.SYSTEM.value), token_header)
    headers = {
        'Authorization': f'Bearer {token}',
        'content-type': 'application/json'
    }
    # Create account first
    rv = client.post('/api/v1/accounts',
                     data=json.dumps(get_unlinked_pad_account_payload()),
                     headers=headers)
    auth_account_id = rv.json.get('accountId')

    # Mock ServiceUnavailableException
    with patch('pay_api.services.oauth_service.OAuthService.post',
               side_effect=ServiceUnavailableException(
                   ConnectionError('mocked error'))):
        rv = client.put(
            f'/api/v1/accounts/{auth_account_id}',
            data=json.dumps(
                get_unlinked_pad_account_payload(bank_account='11111111')),
            headers=headers)

        assert rv.status_code == 503
示例#2
0
def test_transaction_post(session, client, jwt, app):
    """Assert that the endpoint returns 201."""
    token = jwt.create_jwt(get_claims(), token_header)
    headers = {
        'Authorization': f'Bearer {token}',
        'content-type': 'application/json'
    }

    # Create a payment first
    rv = client.post('/api/v1/payment-requests',
                     data=json.dumps(get_payment_request()),
                     headers=headers)
    payment_id = rv.json.get('id')
    data = {
        'clientSystemUrl':
        'http://localhost:8080/coops-web/transactions/transaction_id=abcd',
        'payReturnUrl': 'http://localhost:8080/pay-web'
    }
    rv = client.post(f'/api/v1/payment-requests/{payment_id}/transactions',
                     data=json.dumps(data),
                     headers={'content-type': 'application/json'})
    assert rv.status_code == 201
    assert rv.json.get('paymentId') == payment_id
    assert schema_utils.validate(rv.json, 'transaction')[0]
示例#3
0
def test_payment_invalid_corp_type(session, client, jwt, app):
    """Assert that the endpoint returns 400."""
    token = jwt.create_jwt(get_claims(), token_header)
    headers = {
        'Authorization': f'Bearer {token}',
        'content-type': 'application/json'
    }
    data = {
        'paymentInfo': {
            'methodOfPayment': 'CC'
        },
        'businessInfo': {
            'businessIdentifier': 'CP1234',
            'corpType': 'PC',
            'businessName': 'ABC Corp',
            'contactInfo': {
                'city': 'Victoria',
                'postalCode': 'V8P2P2',
                'province': 'BC',
                'addressLine1': '100 Douglas Street',
                'country': 'CA'
            }
        },
        'filingInfo': {
            'filingTypes': [{
                'filingTypeCode': 'OTADD',
                'filingDescription': 'TEST'
            }, {
                'filingTypeCode': 'OTANN'
            }]
        }
    }
    rv = client.post(f'/api/v1/payment-requests',
                     data=json.dumps(data),
                     headers=headers)
    assert rv.status_code == 400
示例#4
0
def test_transaction_put_with_no_receipt(session, client, jwt, app):
    """Assert that the endpoint returns 200."""
    token = jwt.create_jwt(get_claims(), token_header)
    headers = {
        'Authorization': f'Bearer {token}',
        'content-type': 'application/json'
    }

    # Create a payment first
    rv = client.post(f'/api/v1/payment-requests',
                     data=json.dumps(get_payment_request()),
                     headers=headers)
    payment_id = rv.json.get('id')
    redirect_uri = 'http%3A//localhost%3A8080/coops-web/transactions%3Ftransaction_id%3Dabcd'
    rv = client.post(
        f'/api/v1/payment-requests/{payment_id}/transactions?redirect_uri={redirect_uri}',
        data=None,
        headers=headers)
    txn_id = rv.json.get('id')
    rv = client.patch(
        f'/api/v1/payment-requests/{payment_id}/transactions/{txn_id}',
        data=None,
        headers=headers)
    assert rv.status_code == 200
示例#5
0
def test_get_daily_statements(session, client, jwt, app):
    """Assert that the default statement setting is daily."""
    # Create a payment account and statement details, then get all statements for the account

    token = jwt.create_jwt(get_claims(), token_header)
    headers = {
        'Authorization': f'Bearer {token}',
        'content-type': 'application/json'
    }

    rv = client.post('/api/v1/payment-requests',
                     data=json.dumps(
                         get_payment_request(business_identifier='CP0002000')),
                     headers=headers)

    invoice: Invoice = Invoice.find_by_id(rv.json.get('id'))
    pay_account: PaymentAccount = PaymentAccount.find_by_id(
        invoice.payment_account_id)

    settings_model = factory_statement_settings(
        payment_account_id=pay_account.id,
        frequency=StatementFrequency.DAILY.value)
    statement_model = factory_statement(
        payment_account_id=pay_account.id,
        frequency=StatementFrequency.DAILY.value,
        statement_settings_id=settings_model.id)
    factory_statement_invoices(statement_id=statement_model.id,
                               invoice_id=invoice.id)

    rv = client.get(
        f'/api/v1/accounts/{pay_account.auth_account_id}/statements',
        headers=headers)
    assert rv.status_code == 200
    assert rv.json.get('total') == 1
    assert rv.json.get('items')[0].get(
        'frequency') == StatementFrequency.DAILY.value
示例#6
0
def test_link_routing_slip_parent_is_a_child(client, jwt):
    """Assert linking to a child fails."""
    token = jwt.create_jwt(get_claims(roles=[Role.FAS_CREATE.value, Role.FAS_LINK.value, Role.FAS_SEARCH.value]),
                           token_header)
    headers = {'Authorization': f'Bearer {token}', 'content-type': 'application/json'}
    child = get_routing_slip_request('206380842')
    parent1 = get_routing_slip_request('206380867')
    parent2 = get_routing_slip_request('206380891')
    client.post('/api/v1/fas/routing-slips', data=json.dumps(child), headers=headers)
    client.post('/api/v1/fas/routing-slips', data=json.dumps(parent1), headers=headers)
    client.post('/api/v1/fas/routing-slips', data=json.dumps(parent2), headers=headers)

    # link parent 1 to parent 2

    data = {'childRoutingSlipNumber': f"{parent1.get('number')}", 'parentRoutingSlipNumber': f"{parent2.get('number')}"}
    rv = client.post('/api/v1/fas/routing-slips/links', data=json.dumps(data), headers=headers)
    assert rv.json.get('status') == 'LINKED'

    # now link child to parent

    data = {'childRoutingSlipNumber': f"{child.get('number')}", 'parentRoutingSlipNumber': f"{parent1.get('number')}"}
    rv = client.post('/api/v1/fas/routing-slips/links', data=json.dumps(data), headers=headers)
    assert rv.json.get('type') == 'RS_PARENT_ALREADY_LINKED'
    assert rv.status_code == 400
示例#7
0
def test_account_purchase_history_export_as_csv(session, client, jwt, app):
    """Assert that the endpoint returns 200."""
    token = jwt.create_jwt(get_claims(), token_header)
    headers = {
        'Authorization': f'Bearer {token}',
        'content-type': 'application/json'
    }

    rv = client.post('/api/v1/payment-requests', data=json.dumps(get_payment_request()),
                     headers=headers)

    invoice: Invoice = Invoice.find_by_id(rv.json.get('id'))
    pay_account: PaymentAccount = PaymentAccount.find_by_id(invoice.payment_account_id)

    headers = {
        'Authorization': f'Bearer {token}',
        'content-type': 'application/json',
        'Accept': 'text/csv'
    }

    rv = client.post(f'/api/v1/accounts/{pay_account.auth_account_id}/payments/reports', data=json.dumps({}),
                     headers=headers)

    assert rv.status_code == 201
示例#8
0
def test_account_payments(session, client, jwt, app):
    """Assert that the endpoint returns 200."""
    token = jwt.create_jwt(get_claims(), token_header)
    headers = {'Authorization': f'Bearer {token}', 'content-type': 'application/json'}

    inv_number = 'REG00001'
    payment_account = factory_payment_account().save()

    invoice_1 = factory_invoice(payment_account)
    invoice_1.save()
    factory_invoice_reference(invoice_1.id, invoice_number=inv_number).save()

    payment_1 = factory_payment(payment_status_code='CREATED',
                                payment_account_id=payment_account.id, invoice_number=inv_number)
    payment_1.save()

    auth_account_id = PaymentAccount.find_by_id(payment_account.id).auth_account_id

    rv = client.get(f'/api/v1/accounts/{auth_account_id}/payments', headers=headers)
    assert rv.status_code == 200
    assert rv.json.get('total') == 1
    rv = client.get(f'/api/v1/accounts/{auth_account_id}/payments?status=FAILED', headers=headers)
    assert rv.status_code == 200
    assert rv.json.get('total') == 0
示例#9
0
def test_fee_for_account_fee_settings(session, client, jwt, app):
    """Assert that the endpoint returns 200."""
    token = jwt.create_jwt(get_claims(role=Role.SYSTEM.value), token_header)
    headers = {
        'Authorization': f'Bearer {token}',
        'content-type': 'application/json'
    }
    rv = client.post('/api/v1/accounts',
                     data=json.dumps(get_gov_account_payload()),
                     headers=headers)

    account_id = rv.json.get('authAccountId')

    # Create account fee details.
    token = jwt.create_jwt(get_claims(role=Role.STAFF_ADMIN.value),
                           token_header)
    headers = {
        'Authorization': f'Bearer {token}',
        'content-type': 'application/json'
    }
    client.post(
        f'/api/v1/accounts/{account_id}/fees',
        data=json.dumps({
            'accountFees': [{
                'applyFilingFees': False,
                'serviceFeeCode': 'TRF02',  # 1.0
                'product': 'BUSINESS'
            }]
        }),
        headers=headers)

    # Get fee for this account.
    token = jwt.create_jwt(get_claims(role=Role.EDITOR.value), token_header)
    headers = {
        'Authorization': f'Bearer {token}',
        'content-type': 'application/json',
        'Account-Id': account_id
    }
    rv = client.get('/api/v1/fees/BEN/BCANN', headers=headers)
    assert rv.status_code == 200
    assert schema_utils.validate(rv.json, 'fees')[0]
    # assert filing fee is not applied and service fee is applied
    assert rv.json.get('filingFees') == 0
    assert rv.json.get('serviceFees') == 1.0

    # Now change the settings to apply filing fees and assert
    token = jwt.create_jwt(get_claims(role=Role.STAFF_ADMIN.value),
                           token_header)
    headers = {
        'Authorization': f'Bearer {token}',
        'content-type': 'application/json'
    }
    client.put(
        f'/api/v1/accounts/{account_id}/fees/BUSINESS',
        data=json.dumps({
            'applyFilingFees': True,
            'serviceFeeCode': 'TRF01',  # 1.5
            'product': 'BUSINESS'
        }),
        headers=headers)

    # Get fee for this account.
    token = jwt.create_jwt(get_claims(role=Role.EDITOR.value), token_header)
    headers = {
        'Authorization': f'Bearer {token}',
        'content-type': 'application/json',
        'Account-Id': account_id
    }
    rv = client.get('/api/v1/fees/BEN/BCANN', headers=headers)
    assert rv.status_code == 200
    assert schema_utils.validate(rv.json, 'fees')[0]
    # assert filing fee is applied and service fee is applied
    assert rv.json.get('filingFees') > 0
    assert rv.json.get('serviceFees') == 1.5
示例#10
0
def test_post_accounts_query_error(client, jwt, app, ldap_mock, query_profile_mock_error):
    """Assert that the endpoint returns 200."""
    token = jwt.create_jwt(get_claims(), get_token_header())
    headers = {'content-type': 'application/json', 'Authorization': f'Bearer {token}'}
    rv = client.post('/api/v1/profiles', data=json.dumps({'userId': 'TEST', 'password': '******'}), headers=headers)
    assert rv.status_code == 400
示例#11
0
def test_payment_request_online_banking_with_credit(session, client, jwt, app):
    """Assert that the endpoint returns 201."""
    token = jwt.create_jwt(get_claims(role=Role.SYSTEM.value), token_header)
    headers = {
        'Authorization': f'Bearer {token}',
        'content-type': 'application/json'
    }

    rv = client.post(
        '/api/v1/accounts',
        data=json.dumps(
            get_basic_account_payload(
                payment_method=PaymentMethod.ONLINE_BANKING.value)),
        headers=headers)
    auth_account_id = rv.json.get('authAccountId')

    # Update the payment account as ACTIVE
    payment_account: PaymentAccountModel = PaymentAccountModel.find_by_auth_account_id(
        auth_account_id)
    payment_account.credit = 51
    payment_account.save()

    token = jwt.create_jwt(get_claims(), token_header)
    headers = {
        'Authorization': f'Bearer {token}',
        'content-type': 'application/json'
    }
    rv = client.post('/api/v1/payment-requests',
                     data=json.dumps(
                         get_payment_request_with_payment_method(
                             business_identifier='CP0002000',
                             payment_method='ONLINE_BANKING')),
                     headers=headers)
    invoice_id = rv.json.get('id')

    rv = client.patch(
        f'/api/v1/payment-requests/{invoice_id}?applyCredit=true',
        data=json.dumps({}),
        headers=headers)

    payment_account: PaymentAccountModel = PaymentAccountModel.find_by_auth_account_id(
        auth_account_id)
    assert payment_account.credit == 1

    # Now set the credit less than the total of invoice.
    payment_account.credit = 49
    headers = {
        'Authorization': f'Bearer {token}',
        'content-type': 'application/json'
    }
    rv = client.post('/api/v1/payment-requests',
                     data=json.dumps(
                         get_payment_request_with_payment_method(
                             business_identifier='CP0002000',
                             payment_method='ONLINE_BANKING')),
                     headers=headers)
    invoice_id = rv.json.get('id')

    rv = client.patch(
        f'/api/v1/payment-requests/{invoice_id}?applyCredit=true',
        data=json.dumps({}),
        headers=headers)
    # Credit won't be applied as the invoice total is 50 and the credit should remain as 0.
    payment_account: PaymentAccountModel = PaymentAccountModel.find_by_auth_account_id(
        auth_account_id)
    assert payment_account.credit == 0
示例#12
0
def test_create_pad_refund(session, client, jwt, app, stan_server):
    """Assert that the endpoint returns 202 and creates a credit on the account."""
    # 1. Create a PAD payment_account and cfs_account.
    # 2. Create a PAD invoice and mark as PAID.
    # 3. Issue a refund and assert credit is reflected on payment_account.
    # 4. Create an invoice again and assert that credit is updated.
    auth_account_id = 1234

    token = jwt.create_jwt(get_claims(role=Role.SYSTEM.value), token_header)
    headers = {
        'Authorization': f'Bearer {token}',
        'content-type': 'application/json'
    }
    client.post(
        '/api/v1/accounts',
        data=json.dumps(
            get_unlinked_pad_account_payload(account_id=auth_account_id)),
        headers=headers)
    pay_account: PaymentAccountModel = PaymentAccountModel.find_by_auth_account_id(
        auth_account_id)
    cfs_account: CfsAccountModel = CfsAccountModel.find_by_account_id(
        pay_account.id)[0]
    cfs_account.cfs_party = '1111'
    cfs_account.cfs_account = '1111'
    cfs_account.cfs_site = '1111'
    cfs_account.status = CfsAccountStatus.ACTIVE.value
    cfs_account.save()

    pay_account.pad_activation_date = datetime.now()
    pay_account.save()

    token = jwt.create_jwt(get_claims(), token_header)
    headers = {
        'Authorization': f'Bearer {token}',
        'content-type': 'application/json',
        'Account-Id': auth_account_id
    }

    rv = client.post('/api/v1/payment-requests',
                     data=json.dumps(
                         get_payment_request_with_payment_method(
                             payment_method=PaymentMethod.PAD.value)),
                     headers=headers)

    inv_id = rv.json.get('id')
    inv_total = rv.json.get('total')

    inv: InvoiceModel = InvoiceModel.find_by_id(inv_id)
    inv.invoice_status_code = InvoiceStatus.PAID.value
    inv.save()

    token = jwt.create_jwt(get_claims(app_request=app, role=Role.SYSTEM.value),
                           token_header)
    headers = {
        'Authorization': f'Bearer {token}',
        'content-type': 'application/json'
    }
    rv = client.post(f'/api/v1/payment-requests/{inv_id}/refunds',
                     data=json.dumps({'reason': 'Test'}),
                     headers=headers)
    assert rv.status_code == 202
    assert rv.json.get('message') == REFUND_SUCCESS_MESSAGES['PAD.PAID']

    # Assert credit is updated.
    pay_account: PaymentAccountModel = PaymentAccountModel.find_by_auth_account_id(
        auth_account_id)
    credit = pay_account.credit
    assert pay_account.credit == inv_total

    # Create an invoice again and assert that credit is updated.
    token = jwt.create_jwt(get_claims(), token_header)
    headers = {
        'Authorization': f'Bearer {token}',
        'content-type': 'application/json',
        'Account-Id': auth_account_id
    }

    rv = client.post('/api/v1/payment-requests',
                     data=json.dumps(
                         get_payment_request_with_service_fees(
                             corp_type='CP', filing_type='OTADD')),
                     headers=headers)
    inv_total = rv.json.get('total')

    pay_account: PaymentAccountModel = PaymentAccountModel.find_by_auth_account_id(
        auth_account_id)
    credit -= inv_total
    assert pay_account.credit == credit

    # Create an invoice again and assert that credit is updated.
    token = jwt.create_jwt(get_claims(), token_header)
    headers = {
        'Authorization': f'Bearer {token}',
        'content-type': 'application/json',
        'Account-Id': auth_account_id
    }

    rv = client.post('/api/v1/payment-requests',
                     data=json.dumps(
                         get_payment_request_with_payment_method(
                             payment_method=PaymentMethod.PAD.value)),
                     headers=headers)
    inv_total = rv.json.get('total')
    # Credit must be zero now as the new invoice amount exceeds remaining credit.
    assert pay_account.credit == 0
示例#13
0
def test_get_fees_schedules(client, jwt):
    """Assert that the endpoint returns 200."""
    token = jwt.create_jwt(get_claims(role='staff'), token_header)
    headers = {'Authorization': f'Bearer {token}', 'content-type': 'application/json'}
    rv = client.get('/api/v1/fees/schedules', headers=headers)
    assert rv.status_code == 200
示例#14
0
def test_create_routing_slips_search(client, jwt, app):
    """Assert that the search works."""
    claims = get_claims(roles=[Role.FAS_CREATE.value, Role.FAS_SEARCH.value])
    token = jwt.create_jwt(claims, token_header)
    headers = {'Authorization': f'Bearer {token}', 'content-type': 'application/json'}
    payload = get_routing_slip_request(number='206380800')
    initiator = claims.get('name')
    rv = client.post('/api/v1/fas/routing-slips', data=json.dumps(payload), headers=headers)
    assert rv.status_code == 201
    rs_number = rv.json.get('number')
    # do the searches

    # search with routing slip number works
    rv = client.post('/api/v1/fas/routing-slips/queries', data=json.dumps({'routingSlipNumber': rs_number}),
                     headers=headers)

    items = rv.json.get('items')
    assert len(items) == 1
    assert items[0].get('number') == rs_number

    # search with partial routing slip number works

    rv = client.post('/api/v1/fas/routing-slips/queries', data=json.dumps({'routingSlipNumber': rs_number[1:-1]}),
                     headers=headers)

    items = rv.json.get('items')
    assert len(items) == 1
    assert items[0].get('number') == rs_number

    # search with initiator

    rv = client.post('/api/v1/fas/routing-slips/queries',
                     data=json.dumps({'routingSlipNumber': rs_number, 'initiator': initiator}),
                     headers=headers)

    items = rv.json.get('items')
    assert len(items) == 1
    assert items[0].get('number') == rs_number

    # search with dates

    valid_date_filter = {'startDate': (date.today() - timedelta(1)).strftime(DT_SHORT_FORMAT),
                         'endDate': (date.today() + timedelta(1)).strftime(DT_SHORT_FORMAT)}
    rv = client.post('/api/v1/fas/routing-slips/queries',
                     data=json.dumps({'routingSlipNumber': rs_number, 'dateFilter': valid_date_filter}),
                     headers=headers)

    items = rv.json.get('items')
    assert len(items) == 1
    assert items[0].get('number') == rs_number

    invalid_date_filter = {'startDate': (date.today() + timedelta(100)).strftime(DT_SHORT_FORMAT),
                           'endDate': (date.today() + timedelta(1)).strftime(DT_SHORT_FORMAT)}
    rv = client.post('/api/v1/fas/routing-slips/queries',
                     data=json.dumps({'routingSlipNumber': rs_number, 'dateFilter': invalid_date_filter}),
                     headers=headers)

    items = rv.json.get('items')
    assert len(items) == 0

    # search using status
    rv = client.post('/api/v1/fas/routing-slips/queries',
                     data=json.dumps({'status': 'ACTIVE'}),
                     headers=headers)

    items = rv.json.get('items')
    assert len(items) == 1
    assert items[0].get('number') == rs_number

    # search using invalid status
    rv = client.post('/api/v1/fas/routing-slips/queries',
                     data=json.dumps({'status': 'COMPLETED'}),
                     headers=headers)

    items = rv.json.get('items')
    assert len(items) == 0
示例#15
0
def test_create_routing_slips_search_with_folio_number(client, jwt, app):
    """Assert that the search works."""
    token = jwt.create_jwt(get_claims(roles=[Role.FAS_CREATE.value, Role.FAS_SEARCH.value]), token_header)
    headers = {'Authorization': f'Bearer {token}', 'content-type': 'application/json'}
    payload = get_routing_slip_request(number='206380792')
    rv = client.post('/api/v1/fas/routing-slips', data=json.dumps(payload), headers=headers)
    assert rv.status_code == 201
    payment_account_id = rv.json.get('paymentAccount').get('id')
    payment_account = PaymentAccount(id=payment_account_id)
    folio_number = 'test_folio'
    invoice = factory_invoice(payment_account, folio_number=folio_number, routing_slip=rv.json.get('number'),
                              payment_method_code=PaymentMethod.INTERNAL.value)
    invoice.save()

    # search with routing slip number works

    rv = client.post('/api/v1/fas/routing-slips/queries',
                     data=json.dumps({'routingSlipNumber': rv.json.get('number'), 'folioNumber': folio_number}),
                     headers=headers)

    items = rv.json.get('items')
    assert len(items) == 1, 'folio and routing slip combo works.'

    rv = client.post('/api/v1/fas/routing-slips/queries',
                     data=json.dumps({'folioNumber': folio_number}),
                     headers=headers)

    items = rv.json.get('items')
    assert len(items) == 1, 'folio alone works.'

    # create another routing slip with folo

    payload = get_routing_slip_request(number='206380867')
    rv = client.post('/api/v1/fas/routing-slips', data=json.dumps(payload), headers=headers)
    assert rv.status_code == 201
    payment_account_id = rv.json.get('paymentAccount').get('id')
    payment_account = PaymentAccount(id=payment_account_id)
    routing_slip_numbr = rv.json.get('number')
    invoice = factory_invoice(payment_account, folio_number=folio_number, routing_slip=routing_slip_numbr,
                              payment_method_code=PaymentMethod.INTERNAL.value)
    invoice.save()

    invoice = factory_invoice(payment_account, folio_number=folio_number, routing_slip=rv.json.get('number'),
                              payment_method_code=PaymentMethod.INTERNAL.value)
    invoice.save()

    rv = client.post('/api/v1/fas/routing-slips/queries',
                     data=json.dumps({'folioNumber': folio_number}),
                     headers=headers)

    items = rv.json.get('items')
    assert len(items) == 2, 'folio alone works.'

    rv = client.post('/api/v1/fas/routing-slips/queries',
                     data=json.dumps({'routingSlipNumber': routing_slip_numbr, 'folioNumber': folio_number}),
                     headers=headers)

    items = rv.json.get('items')
    assert len(items) == 1, 'folio and rs fetches only 1.'
    assert len(items[0].get('invoices')) == 2, 'fetches all the folios. UI wil filter it out'

    rv = client.post('/api/v1/fas/routing-slips/queries',
                     data=json.dumps({'routingSlipNumber': routing_slip_numbr}),
                     headers=headers)

    items = rv.json.get('items')
    assert len(items) == 1, 'folio and rs fetches only 1.'
    assert len(items[0].get('invoices')) == 2, 'folio alone works.'
示例#16
0
def test_link_routing_slip(client, jwt, app):
    """Assert that the linking of routing slip works as expected."""
    token = jwt.create_jwt(get_claims(roles=[Role.FAS_CREATE.value, Role.FAS_LINK.value,
                                             Role.FAS_SEARCH.value, Role.FAS_EDIT.value]),
                           token_header)
    headers = {'Authorization': f'Bearer {token}', 'content-type': 'application/json'}
    child = get_routing_slip_request('206380834')
    parent = get_routing_slip_request('206380867')
    paid_amount_child = child.get('payments')[0].get('paidAmount')
    paid_amount_parent = parent.get('payments')[0].get('paidAmount')
    client.post('/api/v1/fas/routing-slips', data=json.dumps(child), headers=headers)
    client.post('/api/v1/fas/routing-slips', data=json.dumps(parent), headers=headers)

    rv = client.get(f"/api/v1/fas/routing-slips/{child.get('number')}/links", headers=headers)
    assert rv.json.get('parent') is None

    # attempt to link NSF, should fail
    nsf = get_routing_slip_request('933458069')
    client.post('/api/v1/fas/routing-slips', data=json.dumps(nsf), headers=headers)
    rv = client.patch(f'/api/v1/fas/routing-slips/{nsf.get("number")}?action={PatchActions.UPDATE_STATUS.value}',
                      data=json.dumps({'status': RoutingSlipStatus.NSF.value}), headers=headers)

    data = {'childRoutingSlipNumber': f"{nsf.get('number')}", 'parentRoutingSlipNumber': f"{parent.get('number')}"}
    rv = client.post('/api/v1/fas/routing-slips/links', data=json.dumps(data), headers=headers)
    assert rv.json.get('type') == 'RS_CANT_LINK_NSF'
    assert rv.status_code == 400

    # link them together ,success cases
    data = {'childRoutingSlipNumber': f"{child.get('number')}", 'parentRoutingSlipNumber': f"{parent.get('number')}"}
    rv = client.post('/api/v1/fas/routing-slips/links', data=json.dumps(data), headers=headers)
    assert rv.json.get('status') == 'LINKED'
    assert rv.json.get('remainingAmount') == 0
    assert rv.json.get('total') == paid_amount_child

    rv = client.get(f"/api/v1/fas/routing-slips/{child.get('number')}/links", headers=headers)
    assert rv.json.get('parent') is not None
    assert rv.json.get('parent').get('number') == parent.get('number')
    assert rv.json.get('parent').get('remainingAmount') == paid_amount_child + \
        paid_amount_parent
    assert rv.json.get('parent').get('total') == paid_amount_parent

    rv = client.get(f"/api/v1/fas/routing-slips/{parent.get('number')}/links", headers=headers)
    assert len(rv.json.get('children')) == 1
    assert rv.json.get('children')[0].get('number') == child.get('number')

    # assert errors
    data = {'childRoutingSlipNumber': f"{child.get('number')}", 'parentRoutingSlipNumber': f"{parent.get('number')}"}
    rv = client.post('/api/v1/fas/routing-slips/links', data=json.dumps(data), headers=headers)
    assert rv.json.get('type') == 'RS_ALREADY_LINKED'
    assert rv.status_code == 400

    # assert errors
    data = {'childRoutingSlipNumber': f"{parent.get('number')}", 'parentRoutingSlipNumber': f"{child.get('number')}"}
    rv = client.post('/api/v1/fas/routing-slips/links', data=json.dumps(data), headers=headers)
    assert rv.json.get('type') == 'RS_ALREADY_A_PARENT'
    assert rv.status_code == 400

    # assert transactions
    child = get_routing_slip_request(number='206380859')
    parent = get_routing_slip_request(number='206380891')
    rv1 = client.post('/api/v1/fas/routing-slips', data=json.dumps(child), headers=headers)
    rv2 = client.post('/api/v1/fas/routing-slips', data=json.dumps(parent), headers=headers)
    payment_account_id = rv1.json.get('paymentAccount').get('id')
    payment_account = PaymentAccount(id=payment_account_id)
    folio_number = 'test_folio'
    invoice = factory_invoice(payment_account, folio_number=folio_number, routing_slip=rv1.json.get('number'),
                              payment_method_code=PaymentMethod.INTERNAL.value)
    invoice.save()
    # assert errors
    data = {'childRoutingSlipNumber': f"{child.get('number')}", 'parentRoutingSlipNumber': f"{parent.get('number')}"}
    rv = client.post('/api/v1/fas/routing-slips/links', data=json.dumps(data), headers=headers)
    assert rv.json.get('type') == 'RS_CHILD_HAS_TRANSACTIONS'
    assert rv.status_code == 400

    payment_account_id = rv2.json.get('paymentAccount').get('id')
    payment_account = PaymentAccount(id=payment_account_id)
    invoice2 = factory_invoice(payment_account, folio_number=folio_number, routing_slip=rv2.json.get('number'),
                               payment_method_code=PaymentMethod.INTERNAL.value)
    invoice2.save()
    data = {'childRoutingSlipNumber': f"{child.get('number')}", 'parentRoutingSlipNumber': f"{parent.get('number')}"}
    rv = client.post('/api/v1/fas/routing-slips/links', data=json.dumps(data), headers=headers)
    assert rv.json.get('type') == 'RS_CHILD_HAS_TRANSACTIONS'
    assert rv.status_code == 400

    child1 = get_routing_slip_request(number='206380842')
    client.post('/api/v1/fas/routing-slips', data=json.dumps(child1), headers=headers)

    data = {'childRoutingSlipNumber': f"{child1.get('number')}", 'parentRoutingSlipNumber': f"{child1.get('number')}"}
    rv = client.post('/api/v1/fas/routing-slips/links', data=json.dumps(data), headers=headers)
    assert rv.json.get('type') == 'RS_CANT_LINK_TO_SAME'
    assert rv.status_code == 400

    # parent record can have transactions
    payment_account_id = rv2.json.get('paymentAccount').get('id')
    payment_account = PaymentAccount(id=payment_account_id)
    invoice2 = factory_invoice(payment_account, folio_number=folio_number, routing_slip=rv2.json.get('number'),
                               payment_method_code=PaymentMethod.INTERNAL.value)
    invoice2.save()
    data = {'childRoutingSlipNumber': f"{child1.get('number')}", 'parentRoutingSlipNumber': f"{parent.get('number')}"}
    rv = client.post('/api/v1/fas/routing-slips/links', data=json.dumps(data), headers=headers)
    assert rv.status_code == 200, 'parent can have transactions'