Skip to content

Commit 30ace37

Browse files
ararcosJobzi
authored andcommitted
feat: TT-417 created CRUD project
1 parent d6c4c4d commit 30ace37

24 files changed

+479
-0
lines changed

V2/serverless.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,53 @@ functions:
9797
route: time-entries/{id}
9898
authLevel: anonymous
9999

100+
<<<<<<< HEAD
100101
create_customer:
101102
handler: time_tracker/customers/interface.create_customer
103+
=======
104+
get_projects:
105+
handler: time_tracker/projects/interface.get_projects
106+
>>>>>>> 58ac1f8 (feat: TT-417 created CRUD project)
102107
events:
103108
- http: true
104109
x-azure-settings:
105110
methods:
111+
<<<<<<< HEAD
106112
- POST
107113
route: customers/
108114
authLevel: anonymous
115+
=======
116+
- GET
117+
route: projects/{id:?}
118+
authLevel: anonymous
119+
120+
delete_project:
121+
handler: time_tracker/projects/interface.delete_project
122+
events:
123+
- http: true
124+
x-azure-settings:
125+
methods:
126+
- DELETE
127+
route: projects/{id}
128+
authLevel: anonymous
129+
130+
update_project:
131+
handler: time_tracker/projects/interface.update_project
132+
events:
133+
- http: true
134+
x-azure-settings:
135+
methods:
136+
- PUT
137+
route: projects/{id}
138+
authLevel: anonymous
139+
140+
create_project:
141+
handler: time_tracker/projects/interface.create_project
142+
events:
143+
- http: true
144+
x-azure-settings:
145+
methods:
146+
- POST
147+
route: projects/
148+
authLevel: anonymous
149+
>>>>>>> 58ac1f8 (feat: TT-417 created CRUD project)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# flake8: noqa
2+
from ._projects import create_project
3+
from ._projects import delete_project
4+
from ._projects import get_projects
5+
from ._projects import update_project
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# flake8: noqa
2+
from ._create_project import create_project
3+
from ._delete_project import delete_project
4+
from ._get_projects import get_projects
5+
from ._update_project import update_project
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import dataclasses
2+
import json
3+
import typing
4+
5+
import azure.functions as func
6+
7+
from ... import _domain
8+
from ... import _infrastructure
9+
from time_tracker._infrastructure import DB
10+
11+
12+
def create_project(req: func.HttpRequest) -> func.HttpResponse:
13+
database = DB()
14+
project_dao = _infrastructure.ProjectsSQLDao(database)
15+
project_service = _domain.ProjectService(project_dao)
16+
use_case = _domain._use_cases.CreateProjectUseCase(project_service)
17+
18+
project_data = req.get_json()
19+
20+
validation_errors = _validate_project(project_data)
21+
if validation_errors:
22+
return func.HttpResponse(
23+
body=json.dumps(validation_errors), status_code=400, mimetype="application/json"
24+
)
25+
26+
project_to_create = _domain.Project(
27+
id=None,
28+
name=project_data["name"],
29+
description=project_data["description"],
30+
project_type_id=1,
31+
customer_id=project_data["customer_id"],
32+
status=1,
33+
deleted=False
34+
)
35+
36+
created_project = use_case.create_project(project_to_create)
37+
38+
if not created_project:
39+
return func.HttpResponse(
40+
body=json.dumps({'error': 'project could not be created'}),
41+
status_code=500,
42+
mimetype="application/json"
43+
)
44+
45+
return func.HttpResponse(
46+
body=json.dumps(created_project.__dict__),
47+
status_code=201,
48+
mimetype="application/json"
49+
)
50+
51+
52+
def _validate_project(project_data: dict) -> typing.List[str]:
53+
project_fields = [field.name for field in dataclasses.fields(_domain.Project)]
54+
project_fields.pop(6)
55+
project_fields.pop(5)
56+
project_fields.pop(3)
57+
project_fields.pop(0)
58+
missing_keys = [field for field in project_fields if field not in project_data]
59+
return [
60+
f'The {missing_key} key is missing in the input data'
61+
for missing_key in missing_keys
62+
]
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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 delete_project(req: func.HttpRequest) -> func.HttpResponse:
11+
project_dao = _infrastructure.ProjectsSQLDao(DB())
12+
project_service = _domain.ProjectService(project_dao)
13+
use_case = _domain._use_cases.DeleteProjectUseCase(project_service)
14+
15+
try:
16+
project_id = int(req.route_params.get("id"))
17+
deleted_project = use_case.delete_project(project_id)
18+
if not deleted_project:
19+
return func.HttpResponse(
20+
body="Not found",
21+
status_code=404,
22+
mimetype="application/json"
23+
)
24+
25+
return func.HttpResponse(
26+
body=json.dumps(deleted_project.__dict__, default=str),
27+
status_code=200,
28+
mimetype="application/json",
29+
)
30+
31+
except ValueError:
32+
return func.HttpResponse(
33+
body=b"Invalid Format ID",
34+
status_code=400,
35+
mimetype="application/json"
36+
)
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import dataclasses
2+
import json
3+
import typing
4+
5+
import azure.functions as func
6+
7+
from ... import _domain
8+
from ... import _infrastructure
9+
from time_tracker._infrastructure import DB
10+
11+
12+
def get_projects(req: func.HttpRequest) -> func.HttpResponse:
13+
database = DB()
14+
project_dao = _infrastructure.ProjectsSQLDao(database)
15+
project_service = _domain.ProjectService(project_dao)
16+
17+
project_id = req.route_params.get("id")
18+
19+
try:
20+
if project_id:
21+
response = _get_by_id(int(project_id), project_service)
22+
if not response:
23+
return func.HttpResponse(
24+
body="Not found",
25+
status_code=404,
26+
mimetype="application/json"
27+
)
28+
else:
29+
response = _get_all(project_service)
30+
31+
return func.HttpResponse(
32+
body=json.dumps(response, default=str),
33+
status_code=200,
34+
mimetype="application/json",
35+
)
36+
37+
except ValueError:
38+
return func.HttpResponse(
39+
body=b"Invalid format id",
40+
status_code=400,
41+
mimetype="application/json"
42+
)
43+
44+
45+
def _get_by_id(project_id: int, project_service: _domain.ProjectService) -> str:
46+
use_case = _domain._use_cases.GetProjectUseCase(project_service)
47+
project = use_case.get_project_by_id(project_id)
48+
49+
return project.__dict__ if project else None
50+
51+
52+
def _get_all(project_service: _domain.ProjectService) -> typing.List:
53+
use_case = _domain._use_cases.GetProjectsUseCase(project_service)
54+
return [
55+
project.__dict__
56+
for project in use_case.get_projects()
57+
]
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import dataclasses
2+
import json
3+
import typing
4+
5+
import azure.functions as func
6+
7+
from ... import _domain
8+
from ... import _infrastructure
9+
from time_tracker._infrastructure import DB
10+
11+
12+
def update_project(req: func.HttpRequest) -> func.HttpResponse:
13+
database = DB()
14+
project_dao = _infrastructure.ProjectsSQLDao(database)
15+
project_service = _domain.ProjectService(project_dao)
16+
use_case = _domain._use_cases.UpdateProjectUseCase(project_service)
17+
18+
try:
19+
project_id = int(req.route_params.get("id"))
20+
project_data = req.get_json()
21+
status_code = 200
22+
23+
if not _validate_project(project_data):
24+
status_code = 400
25+
response = "Incorrect project body"
26+
27+
response = use_case.update_project(
28+
project_id,
29+
project_data.get("name"),
30+
project_data.get("description"),
31+
project_data.get("customer_id"),
32+
project_data.get("status")
33+
).__dict__
34+
35+
if not update_project:
36+
status_code = 404
37+
response = "Not found"
38+
39+
return func.HttpResponse(
40+
body=json.dumps(response, default=str),
41+
status_code=status_code,
42+
mimetype="application/json",
43+
)
44+
45+
except ValueError:
46+
return func.HttpResponse(
47+
body=b"Invalid Format ID",
48+
status_code=400,
49+
mimetype="application/json"
50+
)
51+
52+
53+
def _validate_project(project_data: dict) -> bool:
54+
project_keys = [field.name for field in dataclasses.fields(_domain.Project)]
55+
return all(key in project_keys for key in project_data.keys())
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# flake8: noqa
2+
from ._entities import Project
3+
from ._persistence_contracts import ProjectsDao
4+
from ._services import ProjectService
5+
from ._use_cases import (
6+
CreateProjectUseCase,
7+
DeleteProjectUseCase,
8+
GetProjectsUseCase,
9+
GetProjectUseCase,
10+
UpdateProjectUseCase
11+
)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# flake8: noqa
2+
from ._project import Project
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from dataclasses import dataclass
2+
from typing import List
3+
4+
5+
@dataclass(frozen=True)
6+
class Project:
7+
id: str
8+
name: str
9+
description: str
10+
project_type_id: int
11+
customer_id: int
12+
status: int
13+
deleted: bool

0 commit comments

Comments
 (0)