Skip to content

Commit a4b6cb8

Browse files
author
EliuX
committed
feat: Close #93 Add filter to projects, project-types and time-entries
2 parents afad986 + beb8c84 commit a4b6cb8

File tree

11 files changed

+58
-11
lines changed

11 files changed

+58
-11
lines changed

commons/data_access_layer/cosmos_db.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,8 @@ class CosmosDBDao(CRUDDao):
219219
def __init__(self, repository: CosmosDBRepository):
220220
self.repository = repository
221221

222-
def get_all(self) -> list:
223-
return self.repository.find_all(partition_key_value=self.partition_key_value)
222+
def get_all(self, conditions: []) -> list:
223+
return self.repository.find_all(partition_key_value=self.partition_key_value, conditions= conditions)
224224

225225
def get(self, id):
226226
return self.repository.find(id, partition_key_value=self.partition_key_value)

tests/time_tracker_api/activities/activities_namespace_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,4 +258,4 @@ def test_delete_activity_should_return_422_for_invalid_id_format(client: FlaskCl
258258

259259
assert HTTPStatus.UNPROCESSABLE_ENTITY == response.status_code
260260
repository_remove_mock.assert_called_once_with(str(invalid_id),
261-
partition_key_value=tenant_id)
261+
partition_key_value=tenant_id)

tests/time_tracker_api/customers/customers_namespace_test.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from flask.testing import FlaskClient
44
from flask_restplus._http import HTTPStatus
55
from pytest_mock import MockFixture
6+
from werkzeug.datastructures import ImmutableMultiDict
67

78
fake = Faker()
89

@@ -68,6 +69,20 @@ def test_list_all_customers(client: FlaskClient,
6869
assert [] == json_data
6970
repository_find_all_mock.assert_called_once()
7071

72+
def test_list_all_customers_with_conditions(client: FlaskClient, mocker: MockFixture):
73+
from time_tracker_api.customers.customers_namespace import customer_dao
74+
repository_find_all_mock = mocker.patch.object(customer_dao.repository,
75+
'find_all',
76+
return_value=[])
77+
78+
response = client.get("/customers?a=b", follow_redirects=True)
79+
80+
assert HTTPStatus.OK == response.status_code
81+
json_data = json.loads(response.data)
82+
assert [] == json_data
83+
repository_find_all_mock.assert_called_once_with(conditions=ImmutableMultiDict({'a': 'b'}),
84+
partition_key_value='ioet')
85+
7186

7287
def test_get_customer_should_succeed_with_valid_id(client: FlaskClient,
7388
mocker: MockFixture,

tests/time_tracker_api/project_types/project_types_namespace_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,4 +269,4 @@ def test_delete_project_should_return_unprocessable_entity_for_invalid_id_format
269269

270270
assert HTTPStatus.UNPROCESSABLE_ENTITY == response.status_code
271271
repository_remove_mock.assert_called_once_with(str(invalid_id),
272-
partition_key_value=tenant_id)
272+
partition_key_value=tenant_id)

tests/time_tracker_api/projects/projects_namespace_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,4 +269,4 @@ def test_delete_project_should_return_unprocessable_entity_for_invalid_id_format
269269

270270
assert HTTPStatus.UNPROCESSABLE_ENTITY == response.status_code
271271
repository_remove_mock.assert_called_once_with(str(invalid_id),
272-
partition_key_value=tenant_id)
272+
partition_key_value=tenant_id)

time_tracker_api/activities/activities_namespace.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from faker import Faker
22
from flask_restplus import fields, Resource, Namespace
33
from flask_restplus._http import HTTPStatus
4+
from flask import request
45

56
from time_tracker_api.activities.activities_model import create_dao
67
from time_tracker_api.api import common_fields
@@ -44,7 +45,7 @@ class Activities(Resource):
4445
@ns.marshal_list_with(activity)
4546
def get(self):
4647
"""List all activities"""
47-
return activity_dao.get_all()
48+
return activity_dao.get_all(conditions=request.args)
4849

4950
@ns.doc('create_activity')
5051
@ns.response(HTTPStatus.CONFLICT, 'This activity already exists')

time_tracker_api/api.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from azure.cosmos.exceptions import CosmosResourceExistsError, CosmosResourceNotFoundError, CosmosHttpResponseError
22
from faker import Faker
33
from flask import current_app as app
4-
from flask_restplus import Api, fields
4+
from flask_restplus import Api, fields, reqparse
55
from flask_restplus._http import HTTPStatus
66

77
from commons.data_access_layer.cosmos_db import CustomError
@@ -18,6 +18,14 @@
1818
security="TimeTracker JWT",
1919
)
2020

21+
# Filters
22+
def create_attributes_filter(attributes_filter):
23+
filter_attributes_parser = reqparse.RequestParser()
24+
for attribute in attributes_filter:
25+
filter_attributes_parser.add_argument(f'filters[{attribute}]', location='args')
26+
27+
return filter_attributes_parser
28+
2129
# For matching UUIDs
2230
UUID_REGEX = '[0-9a-f]{8}\-[0-9a-f]{4}\-4[0-9a-f]{3}\-[89ab][0-9a-f]{3}\-[0-9a-f]{12}'
2331

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import re
2+
3+
def remove_none_values(dictionary):
4+
dictionary_with_values = {}
5+
for key, value in dictionary.items():
6+
if value is not None:
7+
dictionary_with_values.update({key: value})
8+
return dictionary_with_values
9+
10+
11+
def remove_filters_wrapper_from_keys(dictionary):
12+
dictionary_with_unwrapped_keys = {}
13+
for key, value in dictionary.items():
14+
unwrapped_key = re.search('\\[(.+?)\\]', key).groups()[0]
15+
dictionary_with_unwrapped_keys.update({unwrapped_key: value})
16+
return dictionary_with_unwrapped_keys

time_tracker_api/customers/customers_namespace.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from faker import Faker
22
from flask_restplus import Namespace, Resource, fields
33
from flask_restplus._http import HTTPStatus
4+
from flask import request
45

56
from time_tracker_api.api import common_fields
67
from time_tracker_api.customers.customers_model import create_dao
@@ -45,7 +46,7 @@ class Customers(Resource):
4546
@ns.marshal_list_with(customer)
4647
def get(self):
4748
"""List all customers"""
48-
return customer_dao.get_all()
49+
return customer_dao.get_all(conditions=request.args)
4950

5051
@ns.doc('create_customer')
5152
@ns.response(HTTPStatus.CONFLICT, 'This customer already exists')

time_tracker_api/project_types/project_types_namespace.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from faker import Faker
22
from flask_restplus import Namespace, Resource, fields
33
from flask_restplus._http import HTTPStatus
4+
from flask import request
45

56
from time_tracker_api.api import common_fields, UUID_REGEX
67
from time_tracker_api.project_types.project_types_model import create_dao
@@ -60,7 +61,7 @@ class ProjectTypes(Resource):
6061
@ns.marshal_list_with(project_type)
6162
def get(self):
6263
"""List all project types"""
63-
return project_type_dao.get_all()
64+
return project_type_dao.get_all(conditions=request.args)
6465

6566
@ns.doc('create_project_type')
6667
@ns.response(HTTPStatus.CONFLICT, 'This project type already exists')

0 commit comments

Comments
 (0)