Skip to content

Commit 5e71d90

Browse files
mandres2015Jobzi
authored andcommitted
feat: TT-417 created CRUD project
test: TT-417 add test of projects test: TT-417 add test with customer id refactor: TT-417 created enums and use test: TT-417 add missing tests test: TT-417 add missing tests and resolve comments refactor: TT-417 add HTTPStatus from http reactor: TT-407 rebase with master - DELETE
1 parent f9e1403 commit 5e71d90

File tree

11 files changed

+125
-0
lines changed

11 files changed

+125
-0
lines changed

V2/serverless.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,15 @@ functions:
107107
route: time-entries/{id}
108108
authLevel: anonymous
109109

110+
get_latest_time_entry:
111+
handler: time_tracker/time_entries/interface.get_latest_entries
112+
- http: true
113+
x-azure-settings:
114+
methods:
115+
- GET
116+
route: time-entries/latest
117+
authLevel: anonymous
118+
110119
update_time_entry:
111120
handler: time_tracker/time_entries/interface.update_time_entry
112121
events:
@@ -177,3 +186,4 @@ functions:
177186
route: projects/
178187

179188
authLevel: anonymous
189+

V2/tests/api/azure/time_entry_azure_endpoints_test.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,45 @@ def test__get_time_entries_azure_endpoint__returns_a_status_code_400__when_time_
139139
assert response.get_body() == b'Invalid Format ID'
140140

141141

142+
def test__get_latest_entries_azure_endpoint__returns_a_list_of_latest_time_entries__when_an_owner_id_match(
143+
test_db, time_entry_factory, insert_time_entry, insert_activity, activity_factory,
144+
):
145+
inserted_activity = insert_activity(activity_factory(), test_db).__dict__
146+
time_entry_body = time_entry_factory(activity_id=inserted_activity["id"], technologies="[jira,sql]")
147+
inserted_time_entry = insert_time_entry(time_entry_body, test_db).__dict__
148+
149+
req = func.HttpRequest(
150+
method='GET',
151+
body=None,
152+
url=TIME_ENTRY_URL+"latest/",
153+
params={"owner_id": inserted_time_entry["owner_id"]},
154+
)
155+
156+
response = azure_time_entries._get_latest_entries.get_latest_entries(req)
157+
time_entry_json_data = json.loads(response.get_body().decode("utf-8"))
158+
159+
assert response.status_code == 200
160+
assert time_entry_json_data == [inserted_time_entry]
161+
162+
163+
def test__get_latest_entries_azure_endpoint__returns_no_time_entries_found__when_recieve_an_invalid_owner_id(
164+
test_db, insert_activity, activity_factory,
165+
):
166+
insert_activity(activity_factory(), test_db)
167+
168+
req = func.HttpRequest(
169+
method='GET',
170+
body=None,
171+
url=TIME_ENTRY_URL+"latest/",
172+
params={"owner_id": Faker().pyint()},
173+
)
174+
175+
response = azure_time_entries._get_latest_entries.get_latest_entries(req)
176+
177+
assert response.status_code == 404
178+
assert response.get_body() == b'No time entries found'
179+
180+
142181
def test__update_time_entry_azure_endpoint__returns_an_time_entry__when_found_an_time_entry_to_update(
143182
test_db, time_entry_factory, insert_time_entry, activity_factory, insert_activity
144183
):

V2/tests/integration/daos/time_entries_dao_test.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,32 @@ def test_delete__returns_none__when_no_time_entry_matching_its_id_is_found(
7373
assert result is None
7474

7575

76+
def test_get_latest_entries__returns_a_list_of_latest_time_entries__when_an_owner_id_match(
77+
create_fake_dao, time_entry_factory, insert_activity, activity_factory, test_db
78+
):
79+
dao = create_fake_dao(test_db)
80+
inserted_activity = insert_activity(activity_factory(), dao.db)
81+
time_entry_to_insert = time_entry_factory(
82+
activity_id=inserted_activity.id,
83+
technologies="[jira,sql]")
84+
inserted_time_entry = dao.create(time_entry_to_insert)
85+
86+
result = dao.get_latest_entries(int(inserted_time_entry.owner_id))
87+
88+
assert result == [inserted_time_entry.__dict__]
89+
90+
91+
def test_get_latest_entries__returns_none__when_an_owner_id_is_not_found(
92+
create_fake_dao, test_db, insert_activity, activity_factory
93+
):
94+
dao = create_fake_dao(test_db)
95+
insert_activity(activity_factory(), dao.db)
96+
97+
result = dao.get_latest_entries(Faker().pyint())
98+
99+
assert result is None
100+
101+
76102
def test_update__returns_an_time_entry_dto__when_found_one_time_entry_to_update(
77103
test_db, create_fake_dao, time_entry_factory, insert_activity, activity_factory
78104
):

V2/tests/unit/services/time_entry_service_test.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,21 @@ def test__delete_time_entry__uses_the_time_entry_dao__to_delete_time_entry_selec
3131
assert expected_time_entry == deleted_time_entry
3232

3333

34+
def test__get_latest_entries__uses_the_time_entry_dao__to_get_last_entries(
35+
mocker,
36+
):
37+
expected_latest_time_entries = mocker.Mock()
38+
time_entry_dao = mocker.Mock(
39+
get_latest_entries=mocker.Mock(return_value=expected_latest_time_entries)
40+
)
41+
42+
time_entry_service = TimeEntryService(time_entry_dao)
43+
latest_time_entries = time_entry_service.get_latest_entries(Faker().pyint(), Faker().pyint())
44+
45+
assert expected_latest_time_entries == latest_time_entries
46+
assert time_entry_dao.get_latest_entries.called
47+
48+
3449
def test__update_time_entry__uses_the_time_entry_dao__to_update_one_time_entry(
3550
mocker,
3651
):

V2/tests/unit/use_cases/time_entries_use_case_test.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,19 @@ def test__delete_time_entry_function__uses_the_time_entry_service__to_delete_tim
3434
assert expected_time_entry == deleted_time_entry
3535

3636

37+
def test__get_latest_entries_function__uses_the_time_entry_service__to_get_last_entries(
38+
mocker: MockFixture,
39+
):
40+
expected_latest_time_entries = mocker.Mock()
41+
time_entry_service = mocker.Mock(get_latest_entries=mocker.Mock(return_value=expected_latest_time_entries))
42+
43+
time_entry_use_case = _use_cases.GetLastestTimeEntryUseCase(time_entry_service)
44+
latest_time_entries = time_entry_use_case.get_latest_entries(Faker().pyint(), Faker().pyint())
45+
46+
assert time_entry_service.get_latest_entries.called
47+
assert expected_latest_time_entries == latest_time_entries
48+
49+
3750
def test__update_time_entries_function__uses_the_time_entry_service__to_update_an_time_entry(
3851
mocker: MockFixture,
3952
):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# flake8: noqa
22
from ._create_time_entry import create_time_entry
33
from ._delete_time_entry import delete_time_entry
4+
from ._get_latest_entries import get_latest_entries
45
from ._update_time_entry import update_time_entry
56
from ._get_time_entries import get_time_entries
67
from ._get_latest_entries import get_latest_entries

V2/time_tracker/time_entries/_domain/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from ._use_cases import (
66
CreateTimeEntryUseCase,
77
DeleteTimeEntryUseCase,
8+
GetLastestTimeEntryUseCase,
89
UpdateTimeEntryUseCase,
910
GetTimeEntriesUseCase,
1011
GetTimeEntryUseCase,

V2/time_tracker/time_entries/_domain/_services/_time_entry.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import typing
22

33
from time_tracker.time_entries._domain import TimeEntry, TimeEntriesDao
4+
import typing
45

56

67
class TimeEntryService:
@@ -13,6 +14,9 @@ def create(self, time_entry_data: TimeEntry) -> TimeEntry:
1314
def delete(self, id: int) -> TimeEntry:
1415
return self.time_entry_dao.delete(id)
1516

17+
def get_latest_entries(self, owner_id: int, limit: int) -> typing.List[TimeEntry]:
18+
return self.time_entry_dao.get_latest_entries(owner_id, limit)
19+
1620
def update(self, time_entry_id: int, new_time_entry: dict) -> TimeEntry:
1721
return self.time_entry_dao.update(time_entry_id, new_time_entry)
1822

V2/time_tracker/time_entries/_domain/_use_cases/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# flake8: noqa
22
from ._create_time_entry_use_case import CreateTimeEntryUseCase
33
from ._delete_time_entry_use_case import DeleteTimeEntryUseCase
4+
from ._get_latest_entries_use_case import GetLastestTimeEntryUseCase
45
from ._update_time_entry_use_case import UpdateTimeEntryUseCase
56
from ._get_time_entry_use_case import GetTimeEntriesUseCase
67
from ._get_time_entry_by_id_use_case import GetTimeEntryUseCase

V2/time_tracker/time_entries/_infrastructure/_data_persistence/_time_entries_sql_dao.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,20 @@ def delete(self, time_entry_id: int) -> domain.TimeEntry:
8484
time_entry = self.db.get_session().execute(query_deleted_time_entry).one_or_none()
8585
return self.__create_time_entry_dto(dict(time_entry)) if time_entry else None
8686

87+
def get_latest_entries(self, owner_id: int, limit: int = 20) -> typing.List[domain.TimeEntry]:
88+
query = (
89+
self.time_entry.select()
90+
.where(sqlalchemy.and_(
91+
self.time_entry.c.owner_id == owner_id,
92+
self.time_entry.c.deleted.is_(False)
93+
))
94+
.order_by(self.time_entry.c.start_date.desc())
95+
.limit(limit)
96+
)
97+
time_entries_data = self.db.get_session().execute(query)
98+
list_time_entries = [dict(entry) for entry in time_entries_data]
99+
return list_time_entries if len(list_time_entries) > 0 else None
100+
87101
def __create_time_entry_dto(self, time_entry: dict) -> domain.TimeEntry:
88102
time_entry.update({
89103
"start_date": str(time_entry.get("start_date")),

0 commit comments

Comments
 (0)