Skip to content

Commit 44d5392

Browse files
committed
reactor: TT-407 rebase with master - DELETE
1 parent fd0bc98 commit 44d5392

File tree

15 files changed

+206
-15
lines changed

15 files changed

+206
-15
lines changed

V2/serverless.yml

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
service: azure-time-tracker
22

3-
frameworkVersion: "2"
3+
frameworkVersion: '2'
44

55
provider:
66
name: azure
@@ -23,18 +23,18 @@ plugins:
2323

2424
package:
2525
patterns:
26-
- "!env/**"
27-
- "!.env/**"
28-
- "!local.settings.json"
29-
- "!.vscode/**"
30-
- "!__pycache__/**"
31-
- "!node_modules/**"
32-
- "!.python_packages/**"
33-
- "!.funcignore"
34-
- "!package.json"
35-
- "!package-lock.json"
36-
- "!.gitignore"
37-
- "!.git/**"
26+
- '!env/**'
27+
- '!.env/**'
28+
- '!local.settings.json'
29+
- '!.vscode/**'
30+
- '!__pycache__/**'
31+
- '!node_modules/**'
32+
- '!.python_packages/**'
33+
- '!.funcignore'
34+
- '!package.json'
35+
- '!package-lock.json'
36+
- '!.gitignore'
37+
- '!.git/**'
3838

3939
functions:
4040
get_activities:
@@ -117,6 +117,16 @@ functions:
117117
route: time-entries/{id}
118118
authLevel: anonymous
119119

120+
get_latest_time_entry:
121+
handler: time_tracker/time_entries/interface.get_latest_entries
122+
events:
123+
- http: true
124+
x-azure-settings:
125+
methods:
126+
- GET
127+
route: time-entries/latest
128+
authLevel: anonymous
129+
120130
create_customer:
121131
handler: time_tracker/customers/interface.create_customer
122132
events:
@@ -165,4 +175,5 @@ functions:
165175
methods:
166176
- POST
167177
route: projects/
178+
168179
authLevel: anonymous

V2/tests/api/azure/time_entry_azure_endpoints_test.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,3 +208,42 @@ def test__update_time_entries_azure_endpoint__returns_a_status_code_400__when_ti
208208

209209
assert response.status_code == 400
210210
assert response.get_body() == b'Incorrect time entry body'
211+
212+
213+
def test__get_latest_entries_azure_endpoint__returns_a_list_of_latest_time_entries__when_an_owner_id_match(
214+
test_db, time_entry_factory, insert_time_entry, insert_activity, activity_factory,
215+
):
216+
inserted_activity = insert_activity(activity_factory(), test_db).__dict__
217+
time_entry_body = time_entry_factory(activity_id=inserted_activity["id"], technologies="[jira,sql]")
218+
inserted_time_entry = insert_time_entry(time_entry_body, test_db)
219+
220+
req = func.HttpRequest(
221+
method='GET',
222+
body=None,
223+
url=TIME_ENTRY_URL+"latest/",
224+
params={"owner_id": inserted_time_entry["owner_id"]},
225+
)
226+
227+
response = azure_time_entries._get_latest_entries.get_latest_entries(req)
228+
time_entry_json_data = json.loads(response.get_body().decode("utf-8"))
229+
230+
assert response.status_code == 200
231+
assert time_entry_json_data == [inserted_time_entry]
232+
233+
234+
def test__get_latest_entries_azure_endpoint__returns_No_time_entries_found__when_recieve_an_invalid_owner_id(
235+
test_db, insert_activity, activity_factory,
236+
):
237+
insert_activity(activity_factory(), test_db)
238+
239+
req = func.HttpRequest(
240+
method='GET',
241+
body=None,
242+
url=TIME_ENTRY_URL+"latest/",
243+
params={"owner_id": Faker().pyint()},
244+
)
245+
246+
response = azure_time_entries._get_latest_entries.get_latest_entries(req)
247+
248+
assert response.status_code == 404
249+
assert response.get_body() == b'No time entries found'

V2/tests/integration/daos/time_entries_dao_test.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ def test_update__returns_an_time_entry_dto__when_found_one_time_entry_to_update(
9090

9191

9292
def test_update__returns_none__when_doesnt_found_one_time_entry_to_update(
93-
test_db, create_fake_dao, time_entry_factory, insert_activity, activity_factory
93+
test_db, create_fake_dao, time_entry_factory, insert_activity, activity_factory
9494
):
9595
dao = create_fake_dao(test_db)
9696
inserted_activity = insert_activity(activity_factory(), dao.db)
@@ -153,3 +153,29 @@ def test__get_by_id__returns_none__when_no_time_entry_matches_by_id(
153153
time_entry = dao.get_by_id(Faker().pyint())
154154

155155
assert time_entry is None
156+
157+
158+
def test_get_latest_entries__returns_a_list_of_latest_time_entries__when_an_owner_id_match(
159+
create_fake_dao, time_entry_factory, insert_activity, activity_factory, test_db
160+
):
161+
dao = create_fake_dao(test_db)
162+
inserted_activity = insert_activity(activity_factory(), dao.db)
163+
time_entry_to_insert = time_entry_factory(
164+
activity_id=inserted_activity.id,
165+
technologies="[jira,sql]")
166+
inserted_time_entry = dao.create(time_entry_to_insert)
167+
168+
result = dao.get_latest_entries(int(inserted_time_entry.owner_id))
169+
170+
assert result == [inserted_time_entry.__dict__]
171+
172+
173+
def test_get_latest_entries__returns_None__when_an_owner_id_is_not_found(
174+
create_fake_dao, test_db, insert_activity, activity_factory
175+
):
176+
dao = create_fake_dao(test_db)
177+
insert_activity(activity_factory(), dao.db)
178+
179+
result = dao.get_latest_entries(Faker().pyint())
180+
181+
assert result is None

V2/tests/unit/services/time_entry_service_test.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from faker import Faker
22

33
from time_tracker.time_entries._domain import TimeEntryService
4+
from faker import Faker
45

56

67
def test__create_time_entries__uses_the_time_entry_dao__to_create_an_time_entry(mocker, time_entry_factory):
@@ -72,3 +73,18 @@ def test__get_by_id__uses_the_time_entry_dao__to_retrieve_one_time_entry(mocker)
7273

7374
assert time_entry_dao.get_by_id.called
7475
assert expected_time_entry == actual_time_entry
76+
77+
78+
def test__get_latest_entries__uses_the_time_entry_dao__to_get_last_entries(
79+
mocker,
80+
):
81+
expected_latest_time_entries = mocker.Mock()
82+
time_entry_dao = mocker.Mock(
83+
get_latest_entries=mocker.Mock(return_value=expected_latest_time_entries)
84+
)
85+
86+
time_entry_service = TimeEntryService(time_entry_dao)
87+
latest_time_entries = time_entry_service.get_latest_entries(Faker().pyint(), Faker().pyint())
88+
89+
assert expected_latest_time_entries == latest_time_entries
90+
assert time_entry_dao.get_latest_entries.called

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
@@ -75,3 +75,16 @@ def test__get_time_entry_by_id_function__uses_the_time_entry_service__to_retriev
7575

7676
assert time_entry_service.get_by_id.called
7777
assert expected_time_entries == actual_time_entry
78+
79+
80+
def test__get_latest_entries_function__uses_the_time_entry_service__to_get_last_entries(
81+
mocker: MockFixture,
82+
):
83+
expected_latest_time_entries = mocker.Mock()
84+
time_entry_service = mocker.Mock(get_latest_entries=mocker.Mock(return_value=expected_latest_time_entries))
85+
86+
time_entry_use_case = _use_cases.GetLastestTimeEntryUseCase(time_entry_service)
87+
latest_time_entries = time_entry_use_case.get_latest_entries(Faker().pyint(), Faker().pyint())
88+
89+
assert time_entry_service.get_latest_entries.called
90+
assert expected_latest_time_entries == latest_time_entries

V2/time_tracker/time_entries/_application/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
from ._time_entries import delete_time_entry
44
from ._time_entries import update_time_entry
55
from ._time_entries import get_time_entries
6+
from ._time_entries import get_latest_entries

V2/time_tracker/time_entries/_application/_time_entries/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
from ._delete_time_entry import delete_time_entry
44
from ._update_time_entry import update_time_entry
55
from ._get_time_entries import get_time_entries
6+
from ._get_latest_entries import get_latest_entries
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import json
2+
3+
import azure.functions as func
4+
5+
from ... import _domain
6+
from ... import _infrastructure
7+
from time_tracker._infrastructure import DB
8+
9+
10+
def get_latest_entries(req: func.HttpRequest) -> func.HttpResponse:
11+
database = DB()
12+
time_entry_dao = _infrastructure.TimeEntriesSQLDao(database)
13+
time_entry_service = _domain.TimeEntryService(time_entry_dao)
14+
use_case = _domain._use_cases.GetLastestTimeEntryUseCase(time_entry_service)
15+
16+
try:
17+
owner_id = req.params.get("owner_id")
18+
limit = req.params.get("limit")
19+
20+
if not owner_id:
21+
return func.HttpResponse(
22+
body="No owner id found",
23+
status_code=404,
24+
mimetype="application/json"
25+
)
26+
27+
time_entries = use_case.get_latest_entries(int(owner_id), int(limit) if limit and int(limit) > 0 else None)
28+
29+
if not time_entries or len(time_entries) == 0:
30+
return func.HttpResponse(
31+
body="No time entries found",
32+
status_code=404,
33+
mimetype="application/json"
34+
)
35+
36+
return func.HttpResponse(
37+
body=json.dumps(time_entries, default=str),
38+
status_code=200,
39+
mimetype="application/json",
40+
)
41+
42+
except ValueError:
43+
return func.HttpResponse(
44+
body=b"Invalid Format ID",
45+
status_code=400,
46+
mimetype="application/json"
47+
)

V2/time_tracker/time_entries/_domain/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@
77
DeleteTimeEntryUseCase,
88
UpdateTimeEntryUseCase,
99
GetTimeEntriesUseCase,
10-
GetTimeEntryUseCase
10+
GetTimeEntryUseCase,
11+
GetLastestTimeEntryUseCase,
1112
)

V2/time_tracker/time_entries/_domain/_persistence_contracts/_time_entries_dao.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,14 @@ def delete(self, id: int) -> TimeEntry:
1717
def update(self, id: int, new_time_entry: dict) -> TimeEntry:
1818
pass
1919

20+
@abc.abstractmethod
2021
def get_by_id(self, id: int) -> TimeEntry:
2122
pass
2223

2324
@abc.abstractmethod
2425
def get_all(self) -> typing.List[TimeEntry]:
2526
pass
27+
28+
@abc.abstractmethod
29+
def get_latest_entries(self, owner_id: int, limit: int) -> typing.List[TimeEntry]:
30+
pass

0 commit comments

Comments
 (0)