Skip to content

Commit

Permalink
22011 - Reviews endpoint: apply sorting and filtering (bcgov#2949)
Browse files Browse the repository at this point in the history
* 22011 - apply sorting and filtering

* 22011 - move dataclass, add unit test
  • Loading branch information
ketaki-deodhar authored Aug 28, 2024
1 parent 37e0b4e commit d45d405
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 17 deletions.
72 changes: 58 additions & 14 deletions legal-api/src/legal_api/models/review.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@
"""This module holds the data about review."""
from __future__ import annotations

from dataclasses import dataclass, field
from datetime import timezone
from enum import auto
from typing import List

from legal_api.utils.base import BaseEnum
from legal_api.utils.datetime import datetime
from legal_api.utils.legislation_datetime import LegislationDatetime

from .db import db
from .filing import Filing
Expand Down Expand Up @@ -79,15 +82,48 @@ def get_review(cls, filing_id) -> Review:
return review

@classmethod
def get_paginated_reviews(cls, page, limit):
"""Return paginated reviews."""
def get_paginated_reviews(cls, review_filter, mapped_sort_by_column):
"""Return filtered, sorted and paginated reviews."""
query = db.session.query(Review, Filing.effective_date). \
join(Filing, Filing.id == Review.filing_id). \
order_by(Review.creation_date.asc())

pagination = query.paginate(per_page=limit, page=page)
join(Filing, Filing.id == Review.filing_id)

if review_filter.start_date:
start_date_utc = LegislationDatetime.as_utc_timezone_from_legislation_date_str(review_filter.start_date)
query = query.filter(Review.submission_date >= start_date_utc)
if review_filter.end_date:
end_date_utc = LegislationDatetime.as_utc_timezone_from_legislation_date_str(review_filter.end_date)
query = query.filter(Review.submission_date <= end_date_utc)
if review_filter.nr_number:
query = query.filter(Review.nr_number.ilike(f'%{review_filter.nr_number}%'))
if review_filter.identifier:
query = query.filter(Review.identifier.ilike(f'%{review_filter.identifier}%'))
if review_filter.completing_party:
query = query.filter(Review.identifier.ilike(f'%{review_filter.completing_party}%'))
if review_filter.status:
query = query.filter(Review.status.in_(review_filter.status))
if review_filter.submitted_sort_by:
column = Review.__table__.columns[mapped_sort_by_column]
desc_sort_order = review_filter.submitted_sort_order
query = query.order_by(column.desc() if desc_sort_order == 'true' else column.asc())
else:
query = query.order_by(Review.creation_date.asc())

pagination = query.paginate(per_page=review_filter.limit, page=review_filter.page)
results = pagination.items
total_count = pagination.total
result = Review.build_reviews(results)

reviews = {
'reviews': result,
'page': review_filter.page,
'limit': review_filter.limit,
'total': total_count
}
return reviews

@classmethod
def build_reviews(cls, results):
"""Return reviews with appended future effective date."""
result = []

for review, effective_date in results:
Expand All @@ -99,14 +135,7 @@ def get_paginated_reviews(cls, page, limit):
**review.json,
'futureEffectiveDate': future_effective_date
})

reviews = {
'reviews': result,
'page': page,
'limit': limit,
'total': total_count
}
return reviews
return result

@property
def json(self) -> dict:
Expand All @@ -122,3 +151,18 @@ def json(self) -> dict:
'filingId': self.filing_id,
'results': [result.json for result in self.review_results]
}

@dataclass
class ReviewFilter:
"""Used for filtering and sorting reviews."""

status: List[str] = field()
start_date: str = ''
end_date: str = ''
nr_number: str = ''
identifier: str = ''
completing_party: str = ''
submitted_sort_by: str = ''
submitted_sort_order: bool = ''
page: int = 1
limit: int = 10
34 changes: 31 additions & 3 deletions legal-api/src/legal_api/resources/v2/admin/reviews.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,20 @@
@jwt.has_one_of_roles([UserRoles.staff])
def get_reviews():
"""Return a list of reviews."""
page = int(request.args.get('page', 1))
limit = int(request.args.get('limit', 10))
result = Review.get_paginated_reviews(page, limit)
review_filter = Review.ReviewFilter(
start_date=request.args.get('startDate', None),
end_date=request.args.get('endDate', None),
nr_number=request.args.get('nrNumber', None),
identifier=request.args.get('identifier', None),
completing_party=request.args.get('completingParty', None),
status=request.args.getlist('status', None),
submitted_sort_by=request.args.get('sortBy', None),
submitted_sort_order=request.args.get('sortDesc', None),
page=int(request.args.get('page', 1)),
limit=int(request.args.get('limit', 10))
)

result = Review.get_paginated_reviews(review_filter, get_mapped_column(review_filter.submitted_sort_by))
reviews = result['reviews']

nr_numbers = get_applicable_nr_numbers(reviews)
Expand Down Expand Up @@ -75,6 +86,23 @@ def update_reviews(reviews, nr_expiry_date):
review['nrExpiryDate'] = match['expiry_date']


def get_mapped_column(submitted_sort_by):
"""Get mapped column for each param."""
mapped_column = ''
if submitted_sort_by:
if submitted_sort_by == 'nrNumber':
mapped_column = 'nr_number'
if submitted_sort_by == 'completingParty':
mapped_column = 'completing_party'
if submitted_sort_by == 'submissionDate':
mapped_column = 'submission_date'
if submitted_sort_by == 'status':
mapped_column = 'status'
if submitted_sort_by == 'identifier':
mapped_column = 'identifier'
return mapped_column


@bp_admin.route('/reviews/<int:review_id>', methods=['POST'])
@cross_origin(origin='*')
@jwt.has_one_of_roles([UserRoles.staff])
Expand Down
19 changes: 19 additions & 0 deletions legal-api/tests/unit/resources/v2/test_admin/test_reviews.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,26 @@ def test_get_reviews_with_valid_user(app, session, client, jwt, mocker):
assert 1 == rv.json.get('page')
assert 10 == rv.json.get('limit')
assert no_of_reviews == rv.json.get('total')

def test_filterd_get_reviews(app, session, client, jwt, mocker):
"""Assert reviews are filtered and sorted by given params."""
no_of_reviews = 6
create_reviews(no_of_reviews)
nrs_response = create_nr_data(no_of_reviews)

mock_response_obj = mocker.Mock()
mock_response_obj.json.return_value = nrs_response

mocker.patch('legal_api.services.NameXService.query_nr_numbers', return_value=mock_response_obj)

rv = client.get(f'/api/v2/admin/reviews?sortBy=nrNumber&sortDesc=true&page=1&limit=5',
headers=create_header(jwt, [STAFF_ROLE], 'user'))

assert rv.status_code == HTTPStatus.OK
assert len(rv.json.get('reviews')) == 5
assert no_of_reviews == rv.json.get('total')
assert rv.json.get('reviews')[0]['nrNumber'] == 'NR 8798955'
assert rv.json.get('reviews')[4]['nrNumber'] == 'NR 8798951'

def test_get_specific_review_with_valid_user(app, session, client, jwt, mocker):
"""Assert specific review object returned for STAFF role."""
Expand Down

0 comments on commit d45d405

Please sign in to comment.