From 85c68908c9379eb05bc28d805eac36ae639f72b2 Mon Sep 17 00:00:00 2001 From: Vanessa Date: Fri, 23 Apr 2021 12:37:55 -0500 Subject: [PATCH 1/2] fix: TT-225 Add build query with not in and add id_running_entry in params --- .../time_entries/time_entries_model_test.py | 4 +++- .../time_entries/time_entries_dao.py | 2 +- .../time_entries/time_entries_repository.py | 16 +++++++-------- utils/query_builder.py | 20 +++++++++++++++++++ 4 files changed, 31 insertions(+), 11 deletions(-) diff --git a/tests/time_tracker_api/time_entries/time_entries_model_test.py b/tests/time_tracker_api/time_entries/time_entries_model_test.py index ce5f026b..3c0e4fd6 100644 --- a/tests/time_tracker_api/time_entries/time_entries_model_test.py +++ b/tests/time_tracker_api/time_entries/time_entries_model_test.py @@ -334,7 +334,7 @@ def test_get_last_entry( time_entry_repository.container = Mock() time_entry_repository.container.query_items = query_items_mock - time_entry = time_entry_repository.get_last_entry('id1', event_context) + time_entry = time_entry_repository.get_last_entry('id1', ['id1'], event_context) find_partition_key_value_mock.assert_called_once() assert isinstance(time_entry, TimeEntryCosmosDBModel) @@ -356,6 +356,7 @@ def test_get_last_entry( running_item = { 'id': 'id', 'owner_id': '1', + 'id_running_entry': '1', 'update_last_entry_if_overlap': True, 'start_date': '2021-03-22T10:30:00.000Z', 'end_date': '2021-03-22T11:30:00.000Z', @@ -400,6 +401,7 @@ def test_update_last_entry( time_entry_repository.update_last_entry( running_item.get('owner_id'), running_item.get('start_date'), + running_item.get('id_running_entry'), event_context, ) diff --git a/time_tracker_api/time_entries/time_entries_dao.py b/time_tracker_api/time_entries/time_entries_dao.py index 5be65759..32c7112a 100644 --- a/time_tracker_api/time_entries/time_entries_dao.py +++ b/time_tracker_api/time_entries/time_entries_dao.py @@ -230,7 +230,7 @@ def update(self, id, data: dict, description=None): if data.get('update_last_entry_if_overlap', None): self.repository.update_last_entry( - data.get('owner_id'), data.get('start_date'), event_ctx + data.get('owner_id'), data.get('start_date'), data.get('id'), event_ctx ) return self.repository.partial_update( diff --git a/time_tracker_api/time_entries/time_entries_repository.py b/time_tracker_api/time_entries/time_entries_repository.py index 9609c5d7..39dabd79 100644 --- a/time_tracker_api/time_entries/time_entries_repository.py +++ b/time_tracker_api/time_entries/time_entries_repository.py @@ -238,6 +238,7 @@ def find_all_v2( def get_last_entry( self, owner_id: str, + id_running_entry: str, event_context: EventContext, visible_only=True, mapper: Callable = None, @@ -246,29 +247,26 @@ def get_last_entry( CosmosDBQueryBuilder() .add_sql_where_equal_condition({'owner_id': owner_id}) .add_sql_order_by_condition('end_date', Order.DESC) - .add_sql_limit_condition(1) - .add_sql_offset_condition(1) - .build() + .add_sql_not_in_condition('id', [id_running_entry]) + .build_with_order_by() ) - query_str = query_builder.get_query() params = query_builder.get_parameters() - partition_key_value = self.find_partition_key_value(event_context) result = self.container.query_items( query=query_str, parameters=params, partition_key=partition_key_value, ) - function_mapper = self.get_mapper_or_dict(mapper) return function_mapper(next(result)) + def update_last_entry( - self, owner_id: str, start_date: str, event_context: EventContext + self, owner_id: str, start_date: str, id_running_entry: str, event_context: EventContext ): - last_entry = self.get_last_entry(owner_id, event_context) - + last_entry = self.get_last_entry( + owner_id, id_running_entry, event_context) end_date = str_to_datetime(last_entry.end_date) _start_date = str_to_datetime(start_date) diff --git a/utils/query_builder.py b/utils/query_builder.py index 9aea4df9..66d87f66 100644 --- a/utils/query_builder.py +++ b/utils/query_builder.py @@ -20,6 +20,7 @@ def __init__(self): self.limit = None self.offset = None self.order_by = None + self.not_in = [] def add_select_conditions(self, columns: List[str] = None): columns = columns if columns else ["*"] @@ -61,6 +62,13 @@ def add_sql_order_by_condition(self, attribute: str, order: Order): self.order_by = (attribute, order.name) return self + + def add_sql_not_in_condition(self, attribute: str = None, ids_list: List[str] = None): + if ids_list and attribute and len(ids_list) > 0: + ids_values = convert_list_to_tuple_string(ids_list) + self.where_conditions.append(f"c.{attribute} NOT IN {ids_values}") + return self + def __build_select(self): if len(self.select_conditions) < 1: self.select_conditions.append("*") @@ -109,6 +117,18 @@ def build(self): ) return self + def build_with_order_by(self): + self.query = """ + SELECT {select_conditions} FROM c + {where_conditions} + {order_by_condition} + """.format( + select_conditions=self.__build_select(), + where_conditions=self.__build_where(), + order_by_condition=self.__build_order_by(), + ) + return self + def get_query(self): return self.query From 5bdfcbf03b0efd5130a4844d571894a63968d6f1 Mon Sep 17 00:00:00 2001 From: Vanessa Date: Sat, 24 Apr 2021 15:43:29 -0500 Subject: [PATCH 2/2] fix: TT-225 Add test_add_sql_not_in_condition test and remove build_with_order_by method --- tests/utils/query_builder_test.py | 27 +++++++++++++++++++ .../time_entries/time_entries_repository.py | 2 +- utils/query_builder.py | 13 --------- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/tests/utils/query_builder_test.py b/tests/utils/query_builder_test.py index 84abc9b9..ab1b7204 100644 --- a/tests/utils/query_builder_test.py +++ b/tests/utils/query_builder_test.py @@ -302,3 +302,30 @@ def test__build_order_by( orderBy_condition = query_builder._CosmosDBQueryBuilder__build_order_by() assert orderBy_condition == expected_order_by_condition + +@pytest.mark.parametrize( + "attribute,ids_list,expected_not_in_list", + [ + ("id", [], []), + (None, None, []), + ("id", None, []), + (None, ["id"], []), + ("id", ["id"], ["c.id NOT IN ('id')"]), + ("id", ["id1", "id2"], ["c.id NOT IN ('id1', 'id2')"]), + ("owner_id", ["id1", "id2"], ["c.owner_id NOT IN ('id1', 'id2')"]), + ("customer_id", ["id1", "id2"], [ + "c.customer_id NOT IN ('id1', 'id2')"]), + ], +) +def test_add_sql_not_in_condition( + attribute, + ids_list, + expected_not_in_list, +): + query_builder = CosmosDBQueryBuilder().add_sql_not_in_condition( + attribute, ids_list + ) + assert len(query_builder.where_conditions) == len( + expected_not_in_list + ) + assert query_builder.where_conditions == expected_not_in_list \ No newline at end of file diff --git a/time_tracker_api/time_entries/time_entries_repository.py b/time_tracker_api/time_entries/time_entries_repository.py index 39dabd79..7d0837e3 100644 --- a/time_tracker_api/time_entries/time_entries_repository.py +++ b/time_tracker_api/time_entries/time_entries_repository.py @@ -248,7 +248,7 @@ def get_last_entry( .add_sql_where_equal_condition({'owner_id': owner_id}) .add_sql_order_by_condition('end_date', Order.DESC) .add_sql_not_in_condition('id', [id_running_entry]) - .build_with_order_by() + .build() ) query_str = query_builder.get_query() params = query_builder.get_parameters() diff --git a/utils/query_builder.py b/utils/query_builder.py index 66d87f66..1fd0e5c9 100644 --- a/utils/query_builder.py +++ b/utils/query_builder.py @@ -20,7 +20,6 @@ def __init__(self): self.limit = None self.offset = None self.order_by = None - self.not_in = [] def add_select_conditions(self, columns: List[str] = None): columns = columns if columns else ["*"] @@ -117,18 +116,6 @@ def build(self): ) return self - def build_with_order_by(self): - self.query = """ - SELECT {select_conditions} FROM c - {where_conditions} - {order_by_condition} - """.format( - select_conditions=self.__build_select(), - where_conditions=self.__build_where(), - order_by_condition=self.__build_order_by(), - ) - return self - def get_query(self): return self.query