Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

loans: date range search #783

Merged
merged 2 commits into from
Apr 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ __pycache__/

# Idea software family
.idea/
.vscode/

# C extensions
*.so
Expand Down
3 changes: 0 additions & 3 deletions .vscode/settings.json

This file was deleted.

25 changes: 13 additions & 12 deletions invenio_app_ils/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@
from .documents.api import DOCUMENT_PID_FETCHER, DOCUMENT_PID_MINTER, \
DOCUMENT_PID_TYPE, Document
from .documents.search import DocumentSearch
from .facets import default_value_when_missing_filter, keyed_range_filter, \
not_empty_object_or_list_filter, overdue_agg, overdue_loans_filter
from .facets import date_range_filter, default_value_when_missing_filter, \
keyed_range_filter, not_empty_object_or_list_filter, overdue_agg, \
overdue_loans_filter
from .records.views import UserInfoResource

from invenio_circulation.config import _LOANID_CONVERTER # isort:skip
Expand Down Expand Up @@ -1140,10 +1141,10 @@ def _(x):
),
),
filters=dict(
circulation=default_value_when_missing_filter("circulation.state",
"NOT_ON_LOAN"),
),
post_filters=dict(
circulation=default_value_when_missing_filter(
"circulation.state", "NOT_ON_LOAN"),
status=terms_filter("status"),
medium=terms_filter("medium"),
restrictions=terms_filter("circulation_restriction"),
Expand Down Expand Up @@ -1186,17 +1187,17 @@ def _(x):
)
),
),
filters={
"returns.end_date": overdue_loans_filter("end_date"),
},
post_filters=dict(
state=terms_filter("state"),
delivery=terms_filter("delivery.method"),
availability=keyed_range_filter(
post_filters={
"state": terms_filter("state"),
"delivery": terms_filter("delivery.method"),
"availability": keyed_range_filter(
"document.circulation.has_items_for_loan",
{"Available for loan": {"gt": 0}},
),
),
"returns.end_date": overdue_loans_filter("end_date"),
"loans_from_date": date_range_filter("start_date", "gte"),
"loans_to_date": date_range_filter("start_date", "lte"),
},
),
acq_orders=dict( # OrderSearch.Meta.index
aggs=dict(
Expand Down
16 changes: 15 additions & 1 deletion invenio_app_ils/facets.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
# it under the terms of the MIT License; see LICENSE file for more details.

"""Facets and factories for result filtering and aggregation."""
from datetime import timedelta

import arrow
from elasticsearch_dsl.query import Bool, Q, Range
Expand Down Expand Up @@ -113,3 +112,18 @@ def overdue_agg():
)
)
)


def date_range_filter(field, comparator):
"""Create a range filter.

:param field: Field name.
:param comparator: Comparison we want with the supplied date.
"""
def inner(values):
try:
input_date = str(arrow.get(values[0]).date())
except arrow.parser.ParserError as e:
raise ValueError("Input should be a date")
return Range(**{field: {comparator: input_date}})
return inner
22 changes: 19 additions & 3 deletions tests/api/test_facets.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@
from datetime import timedelta

import arrow
import pytest
from elasticsearch_dsl.query import Bool, Q, Range, Terms
from flask import current_app

from invenio_app_ils.facets import default_value_when_missing_filter, \
keyed_range_filter, overdue_loans_filter
from invenio_app_ils.facets import date_range_filter, \
default_value_when_missing_filter, keyed_range_filter, \
overdue_loans_filter


def test_keyed_range_filter():
Expand All @@ -34,7 +36,6 @@ def test_keyed_range_filter():

def test_current_ranged_loans_filter(app):
"""Test ranged current loans filter."""

with app.app_context():
rfilter = overdue_loans_filter("field")

Expand All @@ -57,3 +58,18 @@ def test_default_value_when_missing_filter(app):
assert rfilter("test") == Terms(field="test")
assert rfilter("missing val") == Bool(
**{'must_not': {'exists': {'field': "field"}}})


@pytest.mark.parametrize("input_date", ["", "a string", "2020-02-02"])
def test_date_range_filter(app, input_date):
"""Test date range filter date validation and query."""
from_filter = date_range_filter("field", "gte")
to_filter = date_range_filter("field", "lte")

try:
assert from_filter([input_date]) == Range(field={"gte": input_date})
assert to_filter([input_date]) == Range(field={"lte": input_date})
except:
with pytest.raises(ValueError) as err:
from_filter([input_date])
to_filter([input_date])
20 changes: 7 additions & 13 deletions ui/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"format": "prettier --config ./.prettierrc --ignore-path ./.prettierignore --write \"**/*.js\""
},
"dependencies": {
"axios": "^0.19.0",
"axios": "^0.19.2",
"extract-text-webpack-plugin": "^3.0.2",
"formik": "^2.0.6",
"less": "^3.10.3",
Expand All @@ -30,7 +30,7 @@
"react-router-dom": "^5.1.2",
"react-scripts": "^3.4.0",
"react-scroll": "^1.7.16",
"react-searchkit": "^0.16.0",
"react-searchkit": "^0.18.0",
"react-show-more": "^2.0.0",
"react-tagcloud": "^2.0.0",
"redux": "^4.0.4",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ beforeEach(() => {
});

const searchApi = new InvenioSearchApi({
url: documentApi.searchBaseURL,
withCredentials: true,
axios: {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did it change because of axios or react-searchkit? (sorry if this was mentioned somewhere before)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kprzerwa searchkit :)

url: documentApi.searchBaseURL,
withCredentials: true,
},
});

describe('SearchControls tests', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,16 +101,23 @@ exports[`SearchControls tests should mount SearchControls component 1`] = `
}
>
<ReactSearchKit
appName="RSK"
defaultSortByOnEmptyQuery={null}
history={null}
eventListenerEnabled={false}
searchApi={
InvenioSearchApi {
"axiosConfig": Object {
"url": "https://localhost:5000/api/documents/",
"withCredentials": true,
},
"http": [Function],
"requestInterceptor": undefined,
"requestSerializer": InvenioRequestSerializer {
"_addFilter": [Function],
"_addFilters": [Function],
"serialize": [Function],
},
"responseInterceptor": undefined,
"responseSerializer": InvenioResponseSerializer {
"serialize": [Function],
},
Expand Down Expand Up @@ -139,15 +146,17 @@ exports[`SearchControls tests should mount SearchControls component 1`] = `
}
>
<Connect(Bootstrap)
historyListen={null}
appName="RSK"
eventListenerEnabled={false}
searchOnInit={true}
>
<Bootstrap
historyListen={null}
appName="RSK"
eventListenerEnabled={false}
onAppInitialized={[Function]}
onBrowserHistoryExternallyChanged={[Function]}
searchOnInit={true}
searchOnUrlQueryStringChanged={[Function]}
updateQueryState={[Function]}
>
<SearchControls
layoutToggle={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,13 @@ class OrderResponseSerializer {

export class OrderSearch extends Component {
searchApi = new InvenioSearchApi({
axios: {
url: orderApi.searchBaseURL,
withCredentials: true,
},
invenio: {
responseSerializer: OrderResponseSerializer,
},
url: orderApi.searchBaseURL,
withCredentials: true,
});

renderSearchBar = (_, queryString, onInputChange, executeSearch) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ import history from '@history';

export class VendorSearch extends Component {
searchApi = new InvenioSearchApi({
url: vendorApi.searchBaseURL,
withCredentials: true,
axios: {
url: vendorApi.searchBaseURL,
withCredentials: true,
},
});
searchConfig = getSearchConfig('vendors');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ import history from '@history';

export class DocumentSearch extends Component {
searchApi = new InvenioSearchApi({
url: documentApi.searchBaseURL,
withCredentials: true,
axios: {
url: documentApi.searchBaseURL,
withCredentials: true,
},
});
searchConfig = getSearchConfig('documents');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ import { responseRejectInterceptor } from '@api/base';

export class DocumentRequestSearch extends Component {
searchApi = new InvenioSearchApi({
url: documentRequestApi.searchBaseURL,
withCredentials: true,
axios: {
url: documentRequestApi.searchBaseURL,
withCredentials: true,
},
interceptors: {
response: { reject: responseRejectInterceptor },
},
Expand Down
6 changes: 4 additions & 2 deletions ui/src/pages/backoffice/EItem/EItemSearch/EItemSearch.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ import history from '@history';

export class EItemSearch extends Component {
searchApi = new InvenioSearchApi({
url: eitemApi.searchBaseURL,
withCredentials: true,
axios: {
url: eitemApi.searchBaseURL,
withCredentials: true,
},
interceptors: {
response: { reject: responseRejectInterceptor },
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ import { BorrowingRequestListEntry } from './components';

export class BorrowingRequestSearch extends Component {
searchApi = new InvenioSearchApi({
url: borrowingRequestApi.searchBaseURL,
withCredentials: true,
axios: {
url: borrowingRequestApi.searchBaseURL,
withCredentials: true,
},
});

renderSearchBar = (_, queryString, onInputChange, executeSearch) => {
Expand Down
6 changes: 4 additions & 2 deletions ui/src/pages/backoffice/ILL/LibrarySearch/LibrarySearch.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ import { LibraryListEntry } from './components/LibraryListEntry';

export class LibrarySearch extends Component {
searchApi = new InvenioSearchApi({
url: libraryApi.searchBaseURL,
withCredentials: true,
axios: {
url: libraryApi.searchBaseURL,
withCredentials: true,
},
});
searchConfig = getSearchConfig('libraries');

Expand Down
6 changes: 4 additions & 2 deletions ui/src/pages/backoffice/Item/ItemSearch/ItemSearch.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ import {

export class ItemSearch extends Component {
searchApi = new InvenioSearchApi({
url: itemApi.searchBaseURL,
withCredentials: true,
axios: {
url: itemApi.searchBaseURL,
withCredentials: true,
},
interceptors: {
response: { reject: responseRejectInterceptor },
},
Expand Down
6 changes: 4 additions & 2 deletions ui/src/pages/backoffice/Loan/LoanSearch/LoanSearch.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@ import {
SearchAggregationsCards,
} from '@components/SearchControls';

import { SearchDateRange } from './SearchDateRange';

export class LoanSearch extends Component {
searchApi = new InvenioSearchApi({
url: loanApi.searchBaseURL,
withCredentials: true,
axios: { url: loanApi.searchBaseURL, withCredentials: true },
interceptors: {
response: { reject: responseRejectInterceptor },
},
Expand Down Expand Up @@ -87,6 +88,7 @@ export class LoanSearch extends Component {
<Grid.Column width={3} className={'search-aggregations'}>
<Header content={'Filter by'} />
<SearchAggregationsCards modelName={'loans'} />
<SearchDateRange />
</Grid.Column>
<Grid.Column width={13}>
<SearchEmptyResults extras={this.renderEmptyResultsExtra} />
Expand Down
Loading