Skip to content

Commit

Permalink
2372, 23508 - redirect to direct pay, API and UI updates (#282)
Browse files Browse the repository at this point in the history
* 23732 - Updating API endpoint for Document Access Request.

* 23508 - Adding redirect to direct_pay for users with no pad (cc)

* PR updates.

* flake8
  • Loading branch information
hfekete authored Oct 30, 2024
1 parent ee9bfe1 commit edf7ce8
Show file tree
Hide file tree
Showing 14 changed files with 197 additions and 63 deletions.
3 changes: 2 additions & 1 deletion search-api/src/search_api/models/document_access_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ def json(self):
'submissionDate': self.submission_date.isoformat(),
'expiryDate': self.expiry_date.isoformat() if self.expiry_date else None,
'outputFileKey': self._output_file_key,
'submitter': self.submitter.display_name if self.submitter else None
'submitter': self.submitter.display_name if self.submitter else None,
'paymentToken': self.payment_token # invoice id from the pay db
}

documents = []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,18 +70,22 @@ def create_invoice(document_access_request: DocumentAccessRequest, user_jwt: Jwt
header, business_json)

if payment_response.status_code in (HTTPStatus.OK, HTTPStatus.CREATED):
payment_completion_date = datetime.utcnow()
is_pad = payment_response.json().get('paymentMethod') == 'PAD'
pid = payment_response.json().get('id')
today_utc = datetime.now()

document_access_request.payment_token = pid
if is_pad:
document_access_request.status = DocumentAccessRequest.Status.PAID
document_access_request.payment_completion_date = today_utc
else:
document_access_request.status = DocumentAccessRequest.Status.CREATED
document_access_request.payment_status_code = payment_response.json().get('statusCode', '')
document_access_request.payment_completion_date = payment_completion_date
validity_in_days = current_app.config.get('DOCUMENT_REQUEST_VALIDITY_DURATION', 14)
document_access_request.expiry_date = payment_completion_date + relativedelta(days=validity_in_days)
document_access_request.status = DocumentAccessRequest.Status.PAID
document_access_request.expiry_date = today_utc + relativedelta(days=validity_in_days)
document_access_request.save()
return {'isPaymentActionRequired': payment_response.json().get('isPaymentActionRequired',
False)}, HTTPStatus.CREATED

if payment_response.status_code == HTTPStatus.BAD_REQUEST:
# Set payment error type used to retrieve error messages from pay-api
error_type = payment_response.json().get('type')
Expand Down
4 changes: 0 additions & 4 deletions search-api/src/search_api/services/validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,6 @@ def validate_document_access_request(document_access_request_json: dict, account
if not account_org:
validation_errors.append({'error': 'Invalid Account'})

if account_org.get('orgType') != 'PREMIUM':
validation_errors.append({
'error': 'Document Access Request can be created only by a premium account user'})

documents = document_access_request_json.get('documentAccessRequest', {}).get('documents', [])
if not documents:
validation_errors.append({'error': 'Document list must contain atleast one document type'})
Expand Down
11 changes: 5 additions & 6 deletions search-api/tests/unit/api/businesses/test_document_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,10 @@
from search_api.models import Document, DocumentAccessRequest, User
from search_api.services import queue
from search_api.services.authz import STAFF_ROLE
from search_api.services.validator import RequestValidator
from search_api.services.flags import Flags

from tests.unit import MockResponse
from tests.unit.services.utils import create_header, helper_create_jwt
from tests.unit.services.utils import create_header


DOCUMENT_ACCESS_REQUEST_TEMPLATE = {
Expand Down Expand Up @@ -233,7 +232,7 @@ def create_user():
def _create_user(**kwargs):
if not kwargs:
return User()

return User(**kwargs)
return _create_user

Expand All @@ -256,7 +255,7 @@ def test_post_business_document_submit_ce_to_queue(ld, session, client, jwt, moc
idp_userid = '123'
iss = 'iss'
login_source = 'API_GW'

mocker.patch('search_api.services.validator.RequestValidator.validate_document_access_request',
return_value=[])
mocker.patch('search_api.resources.v1.businesses.documents.document_request.get_role',
Expand Down Expand Up @@ -287,7 +286,7 @@ def test_post_business_document_submit_ce_to_queue(ld, session, client, jwt, moc
HTTPStatus.OK)
mocker.patch('search_api.resources.v1.businesses.documents.document_request.get_business',
return_value=business_mock_response)

mock_pub = mocker.patch.object(queue, 'publish', return_value=[])

# set the test data for the flag
Expand All @@ -298,7 +297,7 @@ def test_post_business_document_submit_ce_to_queue(ld, session, client, jwt, moc
.variations(False, True)
.variation_for_user(flag_user['key'], flag_value)
.fallthrough_variation(False))

# Test
api_response = client.post(f'/api/v1/businesses/{business_identifier}/documents/requests',
data=json.dumps(DOCUMENT_ACCESS_REQUEST_TEMPLATE),
Expand Down
57 changes: 57 additions & 0 deletions search-api/tests/unit/mocks/create-invoice-cc-response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"_links": {
"collection": "/api/v1/payment-requests?invoice_id=41861",
"self": "/api/v1/payment-requests/41861"
},
"businessIdentifier": "FM1000026",
"corpTypeCode": "BUS",
"createdBy": "BCSC/ZGCBNHM6U7FPRXI7AJT6KFF7GSKY43TA",
"createdName": "BCREG2 Ayisha FIFTY",
"createdOn": "2024-10-25T21:19:17+00:00",
"details": [
{
"label": "Registration Number: ",
"value": "FM1000026"
}
],
"id": 41861,
"isPaymentActionRequired": true,
"lineItems": [
{
"description": "Business Summary",
"filingFees": 7.0,
"futureEffectiveFees": 0.0,
"gst": 0.0,
"id": 44464,
"priorityFees": 0.0,
"pst": 0.0,
"quantity": 1,
"serviceFees": 1.5,
"statusCode": "ACTIVE",
"total": 8.5,
"waivedBy": null,
"waivedFees": 0.0
}
],
"overdueDate": "2024-12-15T08:00:00+00:00",
"paid": 0.0,
"paymentAccount": {
"accountId": "3137",
"accountName": "Kial Dev 3 (BTR test account) - Public search access",
"billable": true,
"branchName": "Public search access"
},
"paymentMethod": "DIRECT_PAY",
"references": [
{
"createdOn": "2024-10-25T21:19:17+00:00",
"id": 34456,
"invoiceNumber": "REGUT00041861",
"statusCode": "ACTIVE"
}
],
"refund": 0.0,
"serviceFees": 1.5,
"statusCode": "CREATED",
"total": 8.5
}
49 changes: 49 additions & 0 deletions search-api/tests/unit/mocks/create-invoice-pad-response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"_links": {
"collection": "/api/v1/payment-requests?invoice_id=41863",
"self": "/api/v1/payment-requests/41863"
},
"businessIdentifier": "FM1000026",
"corpTypeCode": "BUS",
"createdBy": "BCSC/ZGCBNHM6U7FPRXI7AJT6KFF7GSKY43TA",
"createdName": "BCREG2 Ayisha FIFTY",
"createdOn": "2024-10-25T21:22:37+00:00",
"details": [
{
"label": "Registration Number: ",
"value": "FM1000026"
}
],
"id": 41863,
"isPaymentActionRequired": false,
"lineItems": [
{
"description": "Business Summary",
"filingFees": 7.0,
"futureEffectiveFees": 0.0,
"gst": 0.0,
"id": 44466,
"priorityFees": 0.0,
"pst": 0.0,
"quantity": 1,
"serviceFees": 1.5,
"statusCode": "ACTIVE",
"total": 7.0,
"waivedBy": null,
"waivedFees": 0.0
}
],
"overdueDate": "2024-12-15T08:00:00+00:00",
"paid": 0.0,
"paymentAccount": {
"accountId": "3101",
"accountName": "Kial Dev 2 (BTR test account)-Director search access",
"billable": true,
"branchName": "Director search access"
},
"paymentMethod": "PAD",
"refund": 0.0,
"serviceFees": 1.5,
"statusCode": "APPROVED",
"total": 8.5
}
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ def test_document_access_request_json(session):
'id': document_access_request.id,
'outputFileKey': None,
'paymentStatus': 'COMPLETED',
'paymentToken': document_access_request.payment_token,
'status': 'PAID',
'submissionDate': document_access_request.submission_date.isoformat(),
'submitter': 'firstname lastname'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@
from datetime import datetime
from http import HTTPStatus

import pytest
from flask import current_app, g

from search_api.models import DocumentAccessRequest, User
from search_api.request_handlers.document_access_request_handler import create_invoice, save_request


DOCUMENT_ACCESS_REQUEST_TEMPLATE = {
"documentAccessRequest":{
"documentAccessRequest": {
"documents": [
{
"type": "BUSINESS_SUMMARY_FILING_HISTORY"
Expand All @@ -33,9 +33,10 @@
}
}


def test_save_request(client, session, jwt, mocker):
"""Assert that request can be saved."""
g.jwt_oidc_token_info={}
g.jwt_oidc_token_info = {}
user = User(username='username', firstname='firstname', lastname='lastname', sub='sub', iss='iss', idp_userid='123')
user.save()
mocker.patch('search_api.models.User.get_or_create_user_by_jwt', return_value=user)
Expand All @@ -45,12 +46,15 @@ def test_save_request(client, session, jwt, mocker):
assert document_access_request.submitter.firstname == user.firstname


def test_create_invoice(client, session, jwt, mocker):
@pytest.mark.parametrize('test_name,mock_response,is_payment_completion_date_expected', [
('test_pad_invoice', {'id': 123, 'paymentMethod': 'PAD'}, True),
('test_pad_invoice', {'id': 123, 'paymentMethod': 'DIRECT_PAY'}, False)])
def test_create_invoice(client, session, jwt, mocker, test_name, mock_response, is_payment_completion_date_expected):
"""Assert that access request is updated with payment details."""
document_access_request = DocumentAccessRequest(
business_identifier='CP1234567',
account_id=123,
submission_date=datetime.utcnow()
submission_date=datetime.now()
)

document_access_request.save()
Expand All @@ -64,18 +68,22 @@ def test_create_invoice(client, session, jwt, mocker):
}
}

mock_response = MockResponse({'id': 123},HTTPStatus.CREATED)
mock_payment_response = MockResponse(mock_response, HTTPStatus.CREATED)
mocker.patch('search_api.request_handlers.document_access_request_handler.create_payment',
return_value=mock_response)
return_value=mock_payment_response)
mocker.patch('search_api.request_handlers.document_access_request_handler.get_role',
return_value='basic')

business_json = {'identifier': 'BC1234567', 'legalType': 'BC', 'legalName': 'Test - 1234567'}
create_invoice(document_access_request, jwt, request_json, business_json)

document_access_request = DocumentAccessRequest.find_by_id(document_access_request.id)

assert document_access_request.payment_token
assert document_access_request.payment_completion_date
if is_payment_completion_date_expected:
assert document_access_request.payment_completion_date
else:
assert not document_access_request.payment_completion_date
assert document_access_request.expiry_date


Expand All @@ -95,7 +103,7 @@ def test_create_invoice_failure(client, session, jwt, mocker):
'documentAccessRequest': document_access_request
}

mock_response = MockResponse({'type': 'BAD_REQUEST'},HTTPStatus.BAD_REQUEST)
mock_response = MockResponse({'type': 'BAD_REQUEST'}, HTTPStatus.BAD_REQUEST)
mocker.patch('search_api.request_handlers.document_access_request_handler.create_payment',
return_value=mock_response)
mocker.patch('search_api.request_handlers.document_access_request_handler.get_role',
Expand Down
17 changes: 0 additions & 17 deletions search-api/tests/unit/services/test_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,23 +71,6 @@ def test_document_access_request_valid(client, session, jwt, requests_mock):
assert err is None


def test_document_access_request_invalid_basic_account(client, session, jwt, requests_mock):
"""Assert that a auth-api user orgs request works as expected with the mock service endpoint."""
# setup
current_app.config.update(AUTH_SVC_URL=MOCK_URL_NO_KEY)
token = helper_create_jwt(jwt, [authz.PPR_ROLE])
USERS_ORG_COPY = copy.deepcopy(USERS_ORG)
USERS_ORG_COPY['orgs'][0]['orgType'] = 'BASIC'
org = USERS_ORG_COPY['orgs'][0]
requests_mock.get(f"{current_app.config.get('AUTH_SVC_URL')}users/orgs", json=USERS_ORG_COPY)
requests_mock.get(f"{current_app.config.get('AUTH_SVC_URL')}orgs/{org['id']}", json=org)

err =RequestValidator.validate_document_access_request(DOCUMENT_ACCESS_REQUEST_TEMPLATE, org['id'], token, 'basic')
# check

assert err[0]['error'] == 'Document Access Request can be created only by a premium account user'


@pytest.mark.parametrize('test_name, error_message', [
('no_documents', 'Document list must contain atleast one document type'),
('invalid_document_type', 'Invalid Document Type')
Expand Down
30 changes: 20 additions & 10 deletions search-ui/src/composables/document-access-request-factory.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { reactive } from 'vue'

import { DocumentType } from '@/enums'
import { StaffPaymentIF } from '@/interfaces'
import { AccessRequestsHistoryI, DocumentAccessRequestsI, CreateDocumentResponseI, DocumentI } from '@/interfaces'
import {
AccessRequestsHistoryI,
CreateDocumentResponseI,
DocumentAccessRequestsI,
DocumentI,
StaffPaymentIF
} from '@/interfaces'
import { EntityI } from '@/interfaces/entity'
import { getActiveAccessRequests, createDocumentAccessRequest, getDocument, fetchFilingDocument } from '@/requests'
import { Document } from '@/types'
import { createDocumentAccessRequest, fetchFilingDocument, getActiveAccessRequests, getDocument } from '@/requests'
import { Document } from '@/types'
import { DocumentAccessRequestPaymentStatus } from '@/enums/document-access-request-payment-status'


const documentAccessRequest = reactive({
Expand All @@ -14,7 +20,8 @@ const documentAccessRequest = reactive({
_error: null,
_loading: false,
_saving: false,
_downloading: false
_downloading: false,
_needsPayment: false
}) as DocumentAccessRequestsI

export const useDocumentAccessRequest = () => {
Expand Down Expand Up @@ -47,24 +54,27 @@ export const useDocumentAccessRequest = () => {
documentAccessRequest._error = response.error
} else {
documentAccessRequest.currentRequest = response.createDocumentResponse
}
if(documentAccessRequest.currentRequest.paymentStatus === DocumentAccessRequestPaymentStatus.CREATED) {
documentAccessRequest._needsPayment = true
}
}
documentAccessRequest._saving = false
}

const downloadDocument = async (businessIdentifier: string, document: DocumentI) => {
documentAccessRequest._downloading = true
documentAccessRequest._error = null
const response = await getDocument(businessIdentifier, document)
const response = await getDocument(businessIdentifier, document)
if (response?.error){
documentAccessRequest._error = response.error
}
}
documentAccessRequest._downloading = false
}

const downloadFilingDocument = async (businessIdentifier: string, filingId: number, document: Document) => {
const downloadFilingDocument = async (businessIdentifier: string, filingId: number, document: Document) => {
documentAccessRequest._downloading = true
documentAccessRequest._error = null
const response = await fetchFilingDocument(businessIdentifier, filingId, document)
const response = await fetchFilingDocument(businessIdentifier, filingId, document)
if (response?.error){
documentAccessRequest._error = response.error
}
Expand Down
4 changes: 4 additions & 0 deletions search-ui/src/enums/document-access-request-payment-status.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export enum DocumentAccessRequestPaymentStatus {
CREATED = 'CREATED',
PAID = 'PAID'
}
Loading

0 comments on commit edf7ce8

Please sign in to comment.