Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
feat: TT-365 Method POST activity and create function serverless
  • Loading branch information
scastillo-jp committed Oct 28, 2021
commit 003376dcf979ebe02f3de329a60070e22323098d
12 changes: 11 additions & 1 deletion V2/serverless.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,16 @@ functions:
- http: true
x-azure-settings:
methods:
- PUT
- PUT
route: activities/{id}
authLevel: anonymous

create_activity:
handler: time_entries/interface.create_activity
events:
- http: true
x-azure-settings:
methods:
- POST
route: activities/
authLevel: anonymous
20 changes: 20 additions & 0 deletions V2/tests/api/azure/activity_azure_endpoints_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,23 @@ def test__update_activity_azure_endpoint__returns_an_activity__when_found_an_act

assert response.status_code == 200
assert activitiy_json_data == json.dumps(new_activity)

def test__activity_azure_endpoint__creates_an_activity__when_activity_has_all_attributes(
create_temp_activities,
):
activities_json, tmp_directory = create_temp_activities
activities._create_activity.JSON_PATH = tmp_directory

activity_body = {'id': Faker().uuid4(), 'name': Faker().user_name(), 'description': Faker().sentence(),'deleted': Faker().uuid4() ,'status': 'active', 'tenant_id': Faker().uuid4()}
body = json.dumps(activity_body).encode("utf-8")
req = func.HttpRequest(
method='POST',
body= body,
url='/api/activities/',
)

response = activities._create_activity.create_activity(req)
activitiy_json_data = response.get_body()

assert response.status_code == 200
assert activitiy_json_data == body
15 changes: 15 additions & 0 deletions V2/tests/integration/daos/activities_json_dao_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,18 @@ def test_update__returns_none__when_doesnt_found_one_activity_to_update(
result = activities_json_dao.update('', activity_data)

assert result == None

def test_create_activity__returns_an_activity_dto__when_create_an_activity_that_matches_attributes(create_fake_activities):
create_fake_activities([])

activities_json_dao = ActivitiesJsonDao(Faker().file_path())
activity_data = {
"name": "test_name",
"description": "test_description",
"tenant_id": "test_tenant_id",
"id": "test_id",
"deleted": "test_deleted",
"status": "test_status",
}
result = activities_json_dao.create_activity(activity_data)
assert result == Activity(**activity_data)
12 changes: 12 additions & 0 deletions V2/tests/unit/services/activity_service_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,15 @@ def test__update_activity__uses_the_activity_dao__to_update_one_activity(

assert activity_dao.update.called
assert expected_activity == updated_activity

def test__create_activity__uses_the_activity_dao__to_create_an_activity(mocker):
expected_activity = mocker.Mock()
activity_dao = mocker.Mock(
create_activity=mocker.Mock(return_value=expected_activity)
)
activity_service = ActivityService(activity_dao)

actual_activity = activity_service.create_activity(Faker().pydict())

assert activity_dao.create_activity.called
assert expected_activity == actual_activity
15 changes: 14 additions & 1 deletion V2/tests/unit/use_cases/activities_use_case_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,20 @@ def test__get_activity_by_id_function__uses_the_activity_service__to_retrieve_ac
assert expected_activity == actual_activity


def test__create_activity_function__uses_the_activities_service__to_create_activity(
mocker: MockFixture,
):
expected_activity = mocker.Mock()
activity_service = mocker.Mock(
create_activity=mocker.Mock(return_value=expected_activity)
)

activity_use_case = _use_cases.CreateActivityUseCase(activity_service)
actual_activity = activity_use_case.create_activity(fake.pydict())

assert activity_service.create_activity.called
assert expected_activity == actual_activity

def test__delete_activity_function__uses_the_activity_service__to_change_activity_status(
mocker: MockFixture,
):
Expand All @@ -50,7 +64,6 @@ def test__delete_activity_function__uses_the_activity_service__to_change_activit
assert activity_service.delete.called
assert expected_activity == deleted_activity


def test__update_activity_function__uses_the_activities_service__to_update_an_activity(
mocker: MockFixture,
):
Expand Down
1 change: 1 addition & 0 deletions V2/time_entries/_application/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from ._activities import get_activities
from ._activities import delete_activity
from ._activities import update_activity
from ._activities import create_activity
1 change: 1 addition & 0 deletions V2/time_entries/_application/_activities/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from ._get_activities import get_activities
from ._delete_activity import delete_activity
from ._update_activity import update_activity
from ._create_activity import create_activity
48 changes: 48 additions & 0 deletions V2/time_entries/_application/_activities/_create_activity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from time_entries._infrastructure import ActivitiesJsonDao
from time_entries._domain import ActivityService, _use_cases, Activity

import azure.functions as func
import json
import logging
import dataclasses


JSON_PATH = (
'time_entries/_infrastructure/_data_persistence/activities_data.json'
)



def create_activity(req: func.HttpRequest) -> func.HttpResponse:
logging.info(
'Python HTTP trigger function processed a request to create an activity.'
)
activity_data = req.get_json()
status_code = 200
if _validate_activity(activity_data):
response = _create_activity(activity_data)
else:
status_code = 404
response = b'Not possible to create activity, attributes are not correct '

return func.HttpResponse(
body=response, status_code=status_code, mimetype="application/json"
)

def _create_activity(activity_data: dict) -> str:
activity_use_case = _use_cases.CreateActivityUseCase(
_create_activity_service(JSON_PATH)
)
activity = activity_use_case.create_activity(activity_data)
return json.dumps(activity.__dict__) if activity else b'Not Found'

def _validate_activity(activity_data: dict) -> bool:
activity_keys = [field.name for field in dataclasses.fields(Activity)]
new_activity_keys = list(activity_data.keys())
return all(map(lambda key: key in activity_keys, new_activity_keys)) and len(activity_keys) == len(new_activity_keys)

def _create_activity_service(path: str):
activity_json = ActivitiesJsonDao(path)
return ActivityService(activity_json)


Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,11 @@ def delete(self, id: str) -> Activity:
@abc.abstractmethod
def update(self, id: str, new_activity: dict) -> Activity:
pass

@abc.abstractmethod
def create_activity(self, activity_data: dict) -> Activity:
pass

@abc.abstractmethod
def delete(self, id: str) -> Activity:
pass
3 changes: 3 additions & 0 deletions V2/time_entries/_domain/_services/_activity.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,6 @@ def delete(self, activity_id: str) -> Activity:

def update(self, activity_id: str, new_activity: dict) -> Activity:
return self.activities_dao.update(activity_id, new_activity)

def create_activity(self, activity_data: dict) -> Activity:
return self.activities_dao.create_activity(activity_data)
1 change: 1 addition & 0 deletions V2/time_entries/_domain/_use_cases/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
from ._get_activity_by_id_use_case import GetActivityUseCase
from ._delete_activity_use_case import DeleteActivityUseCase
from ._update_activity_use_case import UpdateActivityUseCase
from ._create_activity_use_case import CreateActivityUseCase
11 changes: 11 additions & 0 deletions V2/time_entries/_domain/_use_cases/_create_activity_use_case.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from time_entries._domain import ActivityService, Activity
import typing


class CreateActivityUseCase:
def __init__(self, activity_service: ActivityService):
self.activity_service = activity_service

def create_activity(self, activity_data: dict ) -> Activity:
return self.activity_service.create_activity(activity_data)

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import json
import typing


class ActivitiesJsonDao(ActivitiesDao):
def __init__(self, json_data_file_path: str):
self.json_data_file_path = json_data_file_path
Expand Down Expand Up @@ -77,6 +76,19 @@ def update(self, activity_id: str, new_activity: dict) -> Activity:
except FileNotFoundError:
return None

def create_activity(self, activity_data: dict) -> Activity:
activities = self.__get_activities_from_file()
activities.append(activity_data)

try:
with open(self.json_data_file_path, 'w') as outfile:
json.dump(activities, outfile)

return self.__create_activity_dto(activity_data)
except FileNotFoundError:
print("Can not create activity")


def __get_activities_from_file(self) -> typing.List[dict]:
try:
file = open(self.json_data_file_path)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,3 @@
"_ts": 1632331515
}
]

1 change: 1 addition & 0 deletions V2/time_entries/interface.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from ._application import get_activities
from ._application import delete_activity
from ._application import update_activity
from ._application import create_activity
1 change: 1 addition & 0 deletions requirements/time_tracker_api/dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
# For development

# Tests
Faker==4.0.2
pytest==5.2.0
Flask_sqlalchemy

Expand Down
3 changes: 2 additions & 1 deletion requirements/time_tracker_api/prod.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
# Dependencies
-r ../commons.txt
-r ../azure_cosmos.txt
-r ../sql_db.txt
# -r ../sql_db.txt

# For production releases

#Required by Flask
Faker==4.0.2
Flask==1.1.1
Flask-WTF==0.15.1
flake8==3.7.9
Expand Down