From bbbcc94e9ead367a44c01272525559ebf73e3a9c Mon Sep 17 00:00:00 2001 From: Javier Sarango Date: Fri, 4 Jun 2021 10:16:45 -0500 Subject: [PATCH 1/9] fix: TT-256 Avoid creating fake users from test --- tests/conftest.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index a536eee4..ef24c3ea 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,3 +1,4 @@ +import copy from datetime import datetime, timedelta import jwt @@ -216,14 +217,15 @@ def time_entries_dao(): return time_entries_dao -@pytest.yield_fixture(scope="module") +@pytest.fixture(scope="module") def running_time_entry( time_entry_repository: TimeEntryCosmosDBRepository, owner_id: str, tenant_id: str, event_context: EventContext, ): - created_time_entry = time_entry_repository.create( + current_time_entry_repository = copy.copy(time_entry_repository) + created_time_entry = current_time_entry_repository.create( { "project_id": fake.uuid4(), "owner_id": owner_id, @@ -234,7 +236,7 @@ def running_time_entry( yield created_time_entry - time_entry_repository.delete_permanently( + current_time_entry_repository.delete_permanently( id=created_time_entry.id, event_context=event_context ) From 533756b5751306d4a754c883f57454d004f799f8 Mon Sep 17 00:00:00 2001 From: semantic-release Date: Tue, 8 Jun 2021 14:18:44 +0000 Subject: [PATCH 2/9] 0.34.3 Automatically generated by python-semantic-release --- CHANGELOG.md | 4 ++++ time_tracker_api/version.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f36f659d..2f78e165 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ +## v0.34.3 (2021-06-08) +### Fix +* TT-256 Avoid creating fake users from test ([`bbbcc94`](https://github.com/ioet/time-tracker-backend/commit/bbbcc94e9ead367a44c01272525559ebf73e3a9c)) + ## v0.34.2 (2021-06-02) ### Fix * TT-257 Fixed customer name null on get a specific project ([#295](https://github.com/ioet/time-tracker-backend/issues/295)) ([`bf2b24d`](https://github.com/ioet/time-tracker-backend/commit/bf2b24d69614d69bd446799d3d0bdb7fa0bc2126)) diff --git a/time_tracker_api/version.py b/time_tracker_api/version.py index 3c92ca22..b0e56f63 100644 --- a/time_tracker_api/version.py +++ b/time_tracker_api/version.py @@ -1 +1 @@ -__version__ = '0.34.2' +__version__ = '0.34.3' From 24971dcb1d6787fbed5ff00f4495b4adcd347881 Mon Sep 17 00:00:00 2001 From: jcalarcon98 Date: Thu, 3 Jun 2021 21:30:35 -0500 Subject: [PATCH 3/9] feat: TT-243 Add functions and testing to base query builder --- tests/utils/query_builder_test.py | 109 ++++++++++++++++++++++++++++++ utils/query_builder.py | 29 ++++++++ 2 files changed, 138 insertions(+) diff --git a/tests/utils/query_builder_test.py b/tests/utils/query_builder_test.py index 742730db..22546527 100644 --- a/tests/utils/query_builder_test.py +++ b/tests/utils/query_builder_test.py @@ -90,6 +90,88 @@ def test_add_sql_where_equal_condition_with_None_should_not_update_lists(): assert query_builder.parameters == [] +@pytest.mark.parametrize( + "data,expected_where_list,expected_params", + [ + ([], [], []), + ( + [ + { + "field_name": "end_date", + "compare_field_name": "start_date", + "compare_field_value": "nomatter", + }, + { + "field_name": "start_date", + "compare_field_name": "end_date", + "compare_field_value": "nomatter", + }, + ], + [ + "c.end_date != @start_date", + "c.start_date != @end_date", + ], + [ + {'name': '@start_date', 'value': 'nomatter'}, + {'name': '@end_date', 'value': 'nomatter'}, + ], + ), + ], +) +def test_add_sql_where_not_equal_condition_should_update_where_conditions_list( + data, expected_where_list, expected_params +): + query_builder = CosmosDBQueryBuilder().add_sql_where_not_equal_condition( + data + ) + + assert len(query_builder.where_conditions) == len(expected_where_list) + assert len(query_builder.parameters) == len(expected_params) + assert query_builder.where_conditions == expected_where_list + assert query_builder.parameters == expected_params + + +def test_add_sql_where_not_equal_condition_with_none_data_should_not_update_lists(): + query_builder = CosmosDBQueryBuilder().add_sql_where_not_equal_condition( + None + ) + + assert len(query_builder.where_conditions) == 0 + assert len(query_builder.parameters) == 0 + assert query_builder.parameters == [] + assert query_builder.where_conditions == [] + + +@pytest.mark.parametrize( + "data,expected_params", + [ + ( + [ + { + "field_name": "end_date", + "compare_field_name": "start_date", + "compare_field_value": "nomatter", + } + ], + [ + {'name': '@start_date', 'value': 'nomatter'}, + ], + ) + ], +) +def test_add_sql_where_not_equal_conditions_should_not_update_parameters_if_already_exists( + data, expected_params +): + query_builder = CosmosDBQueryBuilder() + query_builder.parameters = [ + {'name': '@start_date', 'value': 'nomatter'}, + ] + + query_builder.add_sql_where_not_equal_condition(data) + + assert len(query_builder.parameters) == len(expected_params) + + @pytest.mark.parametrize( "visibility_bool,expected_where_list", [(True, ['NOT IS_DEFINED(c.deleted)']), (False, [])], @@ -331,3 +413,30 @@ def test_add_sql_not_in_condition( ) assert len(query_builder.where_conditions) == len(expected_not_in_list) assert query_builder.where_conditions == expected_not_in_list + + +def test_add_sql_non_existent_attribute_condition_should_update_where_conditions_list(): + query_builder = ( + CosmosDBQueryBuilder().add_sql_non_existent_attribute_condition('name') + ) + expected_condition = "(NOT IS_DEFINED(c.name) OR c.name = null)" + + assert len(query_builder.where_conditions) == 1 + assert query_builder.where_conditions[0].strip() == expected_condition + + +@pytest.mark.parametrize( + "expected_condition,expected_params", + [("c.id!=@ignore_id", {"name": "@ignore_id", "value": "nomatter"})], +) +def test_add_sql_ignore_id_condition_should_update_where_conditions_list( + expected_condition, expected_params +): + query_builder = CosmosDBQueryBuilder().add_sql_ignore_id_condition( + 'nomatter' + ) + + assert len(query_builder.where_conditions) == 1 + assert len(query_builder.parameters) == 1 + assert query_builder.where_conditions[0].strip() == expected_condition + assert query_builder.parameters[0] == expected_params diff --git a/utils/query_builder.py b/utils/query_builder.py index 2899aab4..3acaad5f 100644 --- a/utils/query_builder.py +++ b/utils/query_builder.py @@ -42,6 +42,22 @@ def add_sql_where_equal_condition(self, data: dict = None): self.parameters.append({'name': f'@{k}', 'value': v}) return self + def add_sql_where_not_equal_condition(self, conditions: list = None): + if conditions: + for condition_values in conditions: + field_name = condition_values['field_name'] + compare_field_name = condition_values['compare_field_name'] + compare_field_value = condition_values['compare_field_value'] + condition = f"c.{field_name} != @{compare_field_name}" + self.where_conditions.append(condition) + parameter = { + 'name': f'@{compare_field_name}', + 'value': compare_field_value, + } + if parameter not in self.parameters: + self.parameters.append(parameter) + return self + def add_sql_visibility_condition(self, visible_only: bool): if visible_only: self.where_conditions.append('NOT IS_DEFINED(c.deleted)') @@ -69,6 +85,19 @@ def add_sql_not_in_condition( self.where_conditions.append(f"c.{attribute} NOT IN {ids_values}") return self + def add_sql_non_existent_attribute_condition(self, attribute: str): + condition = f""" + (NOT IS_DEFINED(c.{attribute}) OR c.{attribute} = null) + """ + self.where_conditions.append(condition) + return self + + def add_sql_ignore_id_condition(self, id: str = None): + if id: + self.where_conditions.append("c.id!=@ignore_id") + self.parameters.append({'name': '@ignore_id', 'value': id}) + return self + def __build_select(self): if len(self.select_conditions) < 1: self.select_conditions.append("*") From 91d13b2e041d4d5876e79866ff8958aa9815ceac Mon Sep 17 00:00:00 2001 From: jcalarcon98 Date: Thu, 3 Jun 2021 21:35:01 -0500 Subject: [PATCH 4/9] feat: TT-243 Add function and testing to time entries query builder --- .../time_entries_query_builder_test.py | 44 +++++++++++++++++++ .../time_entries_query_builder.py | 18 ++++++++ 2 files changed, 62 insertions(+) diff --git a/tests/time_tracker_api/time_entries/time_entries_query_builder_test.py b/tests/time_tracker_api/time_entries/time_entries_query_builder_test.py index 3e7fdc91..4f87e3de 100644 --- a/tests/time_tracker_api/time_entries/time_entries_query_builder_test.py +++ b/tests/time_tracker_api/time_entries/time_entries_query_builder_test.py @@ -55,3 +55,47 @@ def test_build_with_add_sql_date_range_condition(): assert remove_white_spaces(query) == remove_white_spaces(expected_query) assert len(time_entry_query_builder.where_conditions) == 1 assert len(time_entry_query_builder.get_parameters()) == 2 + + +def test_add_sql_interception_with_date_range_condition(): + start_date = "2021-03-19T05:07:00.000Z" + end_date = "2021-03-25T10:00:00.000Z" + + time_entry_query_builder = ( + TimeEntryQueryBuilder().add_sql_interception_with_date_range_condition( + start_date, end_date + ) + ) + + expected_params = [ + {"name": "@start_date", "value": start_date}, + {"name": "@end_date", "value": end_date}, + ] + + assert len(time_entry_query_builder.where_conditions) == 1 + assert len(time_entry_query_builder.parameters) == len(expected_params) + assert time_entry_query_builder.parameters == expected_params + + +def test_build_with_add_sql_interception_with_date_range_condition(): + start_date = "2021-03-19T05:07:00.000Z" + end_date = "2021-03-25T10:00:00.000Z" + time_entry_query_builder = ( + TimeEntryQueryBuilder() + .add_sql_interception_with_date_range_condition(start_date, end_date) + .build() + ) + + expected_query = """ + SELECT * FROM c + WHERE (((c.start_date BETWEEN @start_date AND @end_date) + OR (c.end_date BETWEEN @start_date AND @end_date)) + OR ((@start_date BETWEEN c.start_date AND c.end_date) + OR (@end_date BETWEEN c.start_date AND c.end_date))) + """ + + builder_query = time_entry_query_builder.get_query() + + assert remove_white_spaces(builder_query) == remove_white_spaces( + expected_query + ) diff --git a/time_tracker_api/time_entries/time_entries_query_builder.py b/time_tracker_api/time_entries/time_entries_query_builder.py index 03bec701..8f48d372 100644 --- a/time_tracker_api/time_entries/time_entries_query_builder.py +++ b/time_tracker_api/time_entries/time_entries_query_builder.py @@ -21,3 +21,21 @@ def add_sql_date_range_condition(self, date_range: tuple = None): ] ) return self + + def add_sql_interception_with_date_range_condition( + self, start_date, end_date + ): + condition = """ + (((c.start_date BETWEEN @start_date AND @end_date) + OR (c.end_date BETWEEN @start_date AND @end_date)) + OR ((@start_date BETWEEN c.start_date AND c.end_date) + OR (@end_date BETWEEN c.start_date AND c.end_date))) + """ + self.where_conditions.append(condition) + self.parameters.extend( + [ + {'name': '@start_date', 'value': start_date}, + {'name': '@end_date', 'value': end_date}, + ] + ) + return self From fb3900d2f9f94c69e57f2bef7a8c368ae6a96f72 Mon Sep 17 00:00:00 2001 From: jcalarcon98 Date: Thu, 3 Jun 2021 21:36:51 -0500 Subject: [PATCH 5/9] feat: TT-243 Refactor find_running and find_interception_with_date_range functions --- .../time_entries/time_entries_repository.py | 95 +++++++++---------- 1 file changed, 47 insertions(+), 48 deletions(-) diff --git a/time_tracker_api/time_entries/time_entries_repository.py b/time_tracker_api/time_entries/time_entries_repository.py index c4bc7f02..e6a1d83c 100644 --- a/time_tracker_api/time_entries/time_entries_repository.py +++ b/time_tracker_api/time_entries/time_entries_repository.py @@ -42,13 +42,6 @@ def __init__(self): mapper=TimeEntryCosmosDBModel, ) - @staticmethod - def create_sql_ignore_id_condition(id: str): - if id is None: - return '' - else: - return "AND c.id!=@ignore_id" - def find_all_entries( self, event_context: EventContext, @@ -247,35 +240,38 @@ def find_interception_with_date_range( "owner_id": owner_id, "tenant_id": tenant_id, } - params = [ - {"name": "@start_date", "value": start_date}, - {"name": "@end_date", "value": end_date or current_datetime_str()}, - {"name": "@ignore_id", "value": ignore_id}, + + not_equal_conditions = [ + { + "field_name": "start_date", + "compare_field_name": "end_date", + "compare_field_value": end_date, + }, + { + "field_name": "end_date", + "compare_field_name": "start_date", + "compare_field_value": start_date, + }, ] - params.extend(self.generate_params(conditions)) + + query_builder = ( + TimeEntryQueryBuilder() + .add_sql_interception_with_date_range_condition( + start_date, end_date + ) + .add_sql_where_not_equal_condition(not_equal_conditions) + .add_sql_where_equal_condition(conditions) + .add_sql_ignore_id_condition(ignore_id) + .add_sql_visibility_condition(visible_only) + .add_sql_order_by_condition('start_date', Order.DESC) + .build() + ) + + query_str = query_builder.get_query() + params = query_builder.get_parameters() + result = self.container.query_items( - query=""" - SELECT * FROM c - WHERE (((c.start_date BETWEEN @start_date AND @end_date) - OR (c.end_date BETWEEN @start_date AND @end_date)) - OR ((@start_date BETWEEN c.start_date AND c.end_date) - OR (@end_date BETWEEN c.start_date AND c.end_date))) - AND c.start_date!= @end_date - AND c.end_date!= @start_date - {conditions_clause} - {ignore_id_condition} - {visibility_condition} - {order_clause} - """.format( - ignore_id_condition=self.create_sql_ignore_id_condition( - ignore_id - ), - visibility_condition=self.create_sql_condition_for_visibility( - visible_only - ), - conditions_clause=self.create_sql_where_conditions(conditions), - order_clause=self.create_sql_order_clause(), - ), + query=query_str, parameters=params, partition_key=tenant_id, ) @@ -290,20 +286,23 @@ def find_running( "owner_id": owner_id, "tenant_id": tenant_id, } + + query_builder = ( + TimeEntryQueryBuilder() + .add_sql_non_existent_attribute_condition('end_date') + .add_sql_where_equal_condition(conditions) + .add_sql_visibility_condition(True) + .add_sql_offset_condition(0) + .add_sql_limit_condition(1) + .build() + ) + + query_str = query_builder.get_query() + params = query_builder.get_parameters() + result = self.container.query_items( - query=""" - SELECT * from c - WHERE (NOT IS_DEFINED(c.end_date) OR c.end_date = null) - {conditions_clause} - {visibility_condition} - OFFSET 0 LIMIT 1 - """.format( - visibility_condition=self.create_sql_condition_for_visibility( - True - ), - conditions_clause=self.create_sql_where_conditions(conditions), - ), - parameters=self.generate_params(conditions), + query=query_str, + parameters=params, partition_key=tenant_id, max_item_count=1, ) @@ -311,7 +310,7 @@ def find_running( function_mapper = self.get_mapper_or_dict(mapper) try: return function_mapper(next(result)) - except StopIteration as no_result: + except StopIteration: raise CustomError(HTTPStatus.NO_CONTENT) def validate_data(self, data, event_context: EventContext): From 1febce8370f7d7cd76f540227a8cb3fb3236c731 Mon Sep 17 00:00:00 2001 From: jcalarcon98 Date: Thu, 3 Jun 2021 23:58:50 -0500 Subject: [PATCH 6/9] feat: TT-243 Add current datetime if end_date is None --- time_tracker_api/time_entries/time_entries_repository.py | 1 + 1 file changed, 1 insertion(+) diff --git a/time_tracker_api/time_entries/time_entries_repository.py b/time_tracker_api/time_entries/time_entries_repository.py index e6a1d83c..219ae897 100644 --- a/time_tracker_api/time_entries/time_entries_repository.py +++ b/time_tracker_api/time_entries/time_entries_repository.py @@ -240,6 +240,7 @@ def find_interception_with_date_range( "owner_id": owner_id, "tenant_id": tenant_id, } + end_date = end_date or current_datetime_str() not_equal_conditions = [ { From 0681d3b8fad61fa3aed7fc1dcf38180c4e79c5b9 Mon Sep 17 00:00:00 2001 From: jcalarcon98 Date: Fri, 4 Jun 2021 17:24:10 -0500 Subject: [PATCH 7/9] feat: TT-243 Fixing code smells --- .../time_entries/time_entries_query_builder_test.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/time_tracker_api/time_entries/time_entries_query_builder_test.py b/tests/time_tracker_api/time_entries/time_entries_query_builder_test.py index 4f87e3de..c56173e7 100644 --- a/tests/time_tracker_api/time_entries/time_entries_query_builder_test.py +++ b/tests/time_tracker_api/time_entries/time_entries_query_builder_test.py @@ -16,17 +16,19 @@ def test_TimeEntryQueryBuilder_is_subclass_CosmosDBQueryBuilder(): def test_add_sql_date_range_condition_should_update_where_list(): + start_date = "2021-03-19T05:07:00.000Z" + end_date = "2021-03-25T10:00:00.000Z" time_entry_query_builder = ( TimeEntryQueryBuilder().add_sql_date_range_condition( { - "start_date": "2021-03-19T05:07:00.000Z", - "end_date": "2021-03-25T10:00:00.000Z", + "start_date": start_date, + "end_date": end_date, } ) ) expected_params = [ - {"name": "@start_date", "value": "2021-03-19T05:07:00.000Z"}, - {"name": "@end_date", "value": "2021-03-25T10:00:00.000Z"}, + {"name": "@start_date", "value": start_date}, + {"name": "@end_date", "value": end_date}, ] assert len(time_entry_query_builder.where_conditions) == 1 assert len(time_entry_query_builder.parameters) == len(expected_params) From bad6ee2aa307173d00463f9c0f3eb30836abaf0e Mon Sep 17 00:00:00 2001 From: jcalarcon98 Date: Fri, 4 Jun 2021 17:33:17 -0500 Subject: [PATCH 8/9] feat: TT-243 Improve code quality by fixing code smells --- .../time_entries/time_entries_query_builder_test.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/time_tracker_api/time_entries/time_entries_query_builder_test.py b/tests/time_tracker_api/time_entries/time_entries_query_builder_test.py index c56173e7..05db1d58 100644 --- a/tests/time_tracker_api/time_entries/time_entries_query_builder_test.py +++ b/tests/time_tracker_api/time_entries/time_entries_query_builder_test.py @@ -40,8 +40,8 @@ def test_build_with_add_sql_date_range_condition(): TimeEntryQueryBuilder() .add_sql_date_range_condition( { - "start_date": "2021-03-19T05:00:00.000Z", - "end_date": "2021-03-20T10:00:00.000Z", + "start_date": "2021-04-19T05:00:00.000Z", + "end_date": "2021-04-20T10:00:00.000Z", } ) .build() @@ -60,8 +60,8 @@ def test_build_with_add_sql_date_range_condition(): def test_add_sql_interception_with_date_range_condition(): - start_date = "2021-03-19T05:07:00.000Z" - end_date = "2021-03-25T10:00:00.000Z" + start_date = "2021-01-19T05:07:00.000Z" + end_date = "2021-01-25T10:00:00.000Z" time_entry_query_builder = ( TimeEntryQueryBuilder().add_sql_interception_with_date_range_condition( @@ -80,8 +80,8 @@ def test_add_sql_interception_with_date_range_condition(): def test_build_with_add_sql_interception_with_date_range_condition(): - start_date = "2021-03-19T05:07:00.000Z" - end_date = "2021-03-25T10:00:00.000Z" + start_date = "2021-02-19T05:07:00.000Z" + end_date = "2021-02-25T10:00:00.000Z" time_entry_query_builder = ( TimeEntryQueryBuilder() .add_sql_interception_with_date_range_condition(start_date, end_date) From 498a64322d105102136aed6d712da8d327e1227e Mon Sep 17 00:00:00 2001 From: jcalarcon98 Date: Wed, 9 Jun 2021 23:48:03 -0500 Subject: [PATCH 9/9] feat: TT-243 Refactor code based on PR reviews --- .../time_entries_query_builder_test.py | 27 +++++ tests/utils/query_builder_test.py | 109 ------------------ .../time_entries_query_builder.py | 13 +++ .../time_entries/time_entries_repository.py | 16 +-- utils/query_builder.py | 29 ----- 5 files changed, 41 insertions(+), 153 deletions(-) diff --git a/tests/time_tracker_api/time_entries/time_entries_query_builder_test.py b/tests/time_tracker_api/time_entries/time_entries_query_builder_test.py index 05db1d58..fd23bd01 100644 --- a/tests/time_tracker_api/time_entries/time_entries_query_builder_test.py +++ b/tests/time_tracker_api/time_entries/time_entries_query_builder_test.py @@ -94,6 +94,8 @@ def test_build_with_add_sql_interception_with_date_range_condition(): OR (c.end_date BETWEEN @start_date AND @end_date)) OR ((@start_date BETWEEN c.start_date AND c.end_date) OR (@end_date BETWEEN c.start_date AND c.end_date))) + AND c.start_date!= @end_date + AND c.end_date!= @start_date """ builder_query = time_entry_query_builder.get_query() @@ -101,3 +103,28 @@ def test_build_with_add_sql_interception_with_date_range_condition(): assert remove_white_spaces(builder_query) == remove_white_spaces( expected_query ) + + +def test_add_sql_is_running_time_entry_condition_should_update_where_conditions_list(): + query_builder = ( + TimeEntryQueryBuilder().add_sql_is_running_time_entry_condition() + ) + + assert len(query_builder.where_conditions) == 1 + + +@pytest.mark.parametrize( + "expected_condition,expected_params", + [("c.id!=@ignore_id", {"name": "@ignore_id", "value": "nomatter"})], +) +def test_add_sql_ignore_id_condition_should_update_where_conditions_list( + expected_condition, expected_params +): + query_builder = TimeEntryQueryBuilder().add_sql_ignore_id_condition( + 'nomatter' + ) + + assert len(query_builder.where_conditions) == 1 + assert len(query_builder.parameters) == 1 + assert query_builder.where_conditions[0].strip() == expected_condition + assert query_builder.parameters[0] == expected_params diff --git a/tests/utils/query_builder_test.py b/tests/utils/query_builder_test.py index 22546527..742730db 100644 --- a/tests/utils/query_builder_test.py +++ b/tests/utils/query_builder_test.py @@ -90,88 +90,6 @@ def test_add_sql_where_equal_condition_with_None_should_not_update_lists(): assert query_builder.parameters == [] -@pytest.mark.parametrize( - "data,expected_where_list,expected_params", - [ - ([], [], []), - ( - [ - { - "field_name": "end_date", - "compare_field_name": "start_date", - "compare_field_value": "nomatter", - }, - { - "field_name": "start_date", - "compare_field_name": "end_date", - "compare_field_value": "nomatter", - }, - ], - [ - "c.end_date != @start_date", - "c.start_date != @end_date", - ], - [ - {'name': '@start_date', 'value': 'nomatter'}, - {'name': '@end_date', 'value': 'nomatter'}, - ], - ), - ], -) -def test_add_sql_where_not_equal_condition_should_update_where_conditions_list( - data, expected_where_list, expected_params -): - query_builder = CosmosDBQueryBuilder().add_sql_where_not_equal_condition( - data - ) - - assert len(query_builder.where_conditions) == len(expected_where_list) - assert len(query_builder.parameters) == len(expected_params) - assert query_builder.where_conditions == expected_where_list - assert query_builder.parameters == expected_params - - -def test_add_sql_where_not_equal_condition_with_none_data_should_not_update_lists(): - query_builder = CosmosDBQueryBuilder().add_sql_where_not_equal_condition( - None - ) - - assert len(query_builder.where_conditions) == 0 - assert len(query_builder.parameters) == 0 - assert query_builder.parameters == [] - assert query_builder.where_conditions == [] - - -@pytest.mark.parametrize( - "data,expected_params", - [ - ( - [ - { - "field_name": "end_date", - "compare_field_name": "start_date", - "compare_field_value": "nomatter", - } - ], - [ - {'name': '@start_date', 'value': 'nomatter'}, - ], - ) - ], -) -def test_add_sql_where_not_equal_conditions_should_not_update_parameters_if_already_exists( - data, expected_params -): - query_builder = CosmosDBQueryBuilder() - query_builder.parameters = [ - {'name': '@start_date', 'value': 'nomatter'}, - ] - - query_builder.add_sql_where_not_equal_condition(data) - - assert len(query_builder.parameters) == len(expected_params) - - @pytest.mark.parametrize( "visibility_bool,expected_where_list", [(True, ['NOT IS_DEFINED(c.deleted)']), (False, [])], @@ -413,30 +331,3 @@ def test_add_sql_not_in_condition( ) assert len(query_builder.where_conditions) == len(expected_not_in_list) assert query_builder.where_conditions == expected_not_in_list - - -def test_add_sql_non_existent_attribute_condition_should_update_where_conditions_list(): - query_builder = ( - CosmosDBQueryBuilder().add_sql_non_existent_attribute_condition('name') - ) - expected_condition = "(NOT IS_DEFINED(c.name) OR c.name = null)" - - assert len(query_builder.where_conditions) == 1 - assert query_builder.where_conditions[0].strip() == expected_condition - - -@pytest.mark.parametrize( - "expected_condition,expected_params", - [("c.id!=@ignore_id", {"name": "@ignore_id", "value": "nomatter"})], -) -def test_add_sql_ignore_id_condition_should_update_where_conditions_list( - expected_condition, expected_params -): - query_builder = CosmosDBQueryBuilder().add_sql_ignore_id_condition( - 'nomatter' - ) - - assert len(query_builder.where_conditions) == 1 - assert len(query_builder.parameters) == 1 - assert query_builder.where_conditions[0].strip() == expected_condition - assert query_builder.parameters[0] == expected_params diff --git a/time_tracker_api/time_entries/time_entries_query_builder.py b/time_tracker_api/time_entries/time_entries_query_builder.py index 8f48d372..3147d43f 100644 --- a/time_tracker_api/time_entries/time_entries_query_builder.py +++ b/time_tracker_api/time_entries/time_entries_query_builder.py @@ -30,6 +30,8 @@ def add_sql_interception_with_date_range_condition( OR (c.end_date BETWEEN @start_date AND @end_date)) OR ((@start_date BETWEEN c.start_date AND c.end_date) OR (@end_date BETWEEN c.start_date AND c.end_date))) + AND c.start_date!= @end_date + AND c.end_date!= @start_date """ self.where_conditions.append(condition) self.parameters.extend( @@ -39,3 +41,14 @@ def add_sql_interception_with_date_range_condition( ] ) return self + + def add_sql_is_running_time_entry_condition(self): + condition = "(NOT IS_DEFINED(c.end_date) OR c.end_date = null)" + self.where_conditions.append(condition) + return self + + def add_sql_ignore_id_condition(self, id: str = None): + if id: + self.where_conditions.append("c.id!=@ignore_id") + self.parameters.append({'name': '@ignore_id', 'value': id}) + return self diff --git a/time_tracker_api/time_entries/time_entries_repository.py b/time_tracker_api/time_entries/time_entries_repository.py index 219ae897..48d55672 100644 --- a/time_tracker_api/time_entries/time_entries_repository.py +++ b/time_tracker_api/time_entries/time_entries_repository.py @@ -242,25 +242,11 @@ def find_interception_with_date_range( } end_date = end_date or current_datetime_str() - not_equal_conditions = [ - { - "field_name": "start_date", - "compare_field_name": "end_date", - "compare_field_value": end_date, - }, - { - "field_name": "end_date", - "compare_field_name": "start_date", - "compare_field_value": start_date, - }, - ] - query_builder = ( TimeEntryQueryBuilder() .add_sql_interception_with_date_range_condition( start_date, end_date ) - .add_sql_where_not_equal_condition(not_equal_conditions) .add_sql_where_equal_condition(conditions) .add_sql_ignore_id_condition(ignore_id) .add_sql_visibility_condition(visible_only) @@ -290,7 +276,7 @@ def find_running( query_builder = ( TimeEntryQueryBuilder() - .add_sql_non_existent_attribute_condition('end_date') + .add_sql_is_running_time_entry_condition() .add_sql_where_equal_condition(conditions) .add_sql_visibility_condition(True) .add_sql_offset_condition(0) diff --git a/utils/query_builder.py b/utils/query_builder.py index 3acaad5f..2899aab4 100644 --- a/utils/query_builder.py +++ b/utils/query_builder.py @@ -42,22 +42,6 @@ def add_sql_where_equal_condition(self, data: dict = None): self.parameters.append({'name': f'@{k}', 'value': v}) return self - def add_sql_where_not_equal_condition(self, conditions: list = None): - if conditions: - for condition_values in conditions: - field_name = condition_values['field_name'] - compare_field_name = condition_values['compare_field_name'] - compare_field_value = condition_values['compare_field_value'] - condition = f"c.{field_name} != @{compare_field_name}" - self.where_conditions.append(condition) - parameter = { - 'name': f'@{compare_field_name}', - 'value': compare_field_value, - } - if parameter not in self.parameters: - self.parameters.append(parameter) - return self - def add_sql_visibility_condition(self, visible_only: bool): if visible_only: self.where_conditions.append('NOT IS_DEFINED(c.deleted)') @@ -85,19 +69,6 @@ def add_sql_not_in_condition( self.where_conditions.append(f"c.{attribute} NOT IN {ids_values}") return self - def add_sql_non_existent_attribute_condition(self, attribute: str): - condition = f""" - (NOT IS_DEFINED(c.{attribute}) OR c.{attribute} = null) - """ - self.where_conditions.append(condition) - return self - - def add_sql_ignore_id_condition(self, id: str = None): - if id: - self.where_conditions.append("c.id!=@ignore_id") - self.parameters.append({'name': '@ignore_id', 'value': id}) - return self - def __build_select(self): if len(self.select_conditions) < 1: self.select_conditions.append("*")