Skip to content

Commit 4538307

Browse files
fix: TT-274 fix error on archive a customer removes the project (#307)
1 parent 5f95b5b commit 4538307

File tree

5 files changed

+130
-50
lines changed

5 files changed

+130
-50
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,6 @@ migration_status.csv
4141
env.*
4242

4343
# SSL certificate for cosmos emulator
44-
emulatorcert.crt
44+
emulatorcert.crt
45+
46+
seed_database.json

tests/time_tracker_api/projects/projects_model_test.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,18 @@
55
CustomerCosmosDBModel,
66
CustomerCosmosDBDao,
77
)
8+
from time_tracker_api.project_types.project_types_model import (
9+
ProjectTypeCosmosDBModel,
10+
ProjectTypeCosmosDBDao,
11+
)
812
from time_tracker_api.projects.projects_model import (
913
ProjectCosmosDBRepository,
1014
ProjectCosmosDBModel,
1115
create_dao,
1216
)
17+
from faker import Faker
18+
19+
fake = Faker()
1320

1421

1522
@patch(
@@ -77,3 +84,57 @@ def test_get_project_with_their_customer(
7784

7885
assert isinstance(project, ProjectCosmosDBModel)
7986
assert project.__dict__['customer_name'] == customer_data['name']
87+
88+
89+
def test_get_all_projects_with_customers(
90+
mocker,
91+
):
92+
customer_id = fake.uuid4()
93+
project_type_id = fake.uuid4()
94+
95+
customer_data = {
96+
'id': customer_id,
97+
'name': fake.company(),
98+
'description': fake.paragraph(),
99+
'tenant_id': fake.uuid4(),
100+
}
101+
102+
project_data = {
103+
'customer_id': customer_id,
104+
'id': fake.uuid4(),
105+
'name': fake.company(),
106+
'description': fake.paragraph(),
107+
'project_type_id': project_type_id,
108+
'tenant_id': fake.uuid4(),
109+
}
110+
111+
project_type_dao = {
112+
'id': project_type_id,
113+
'name': fake.name(),
114+
'description': fake.paragraph(),
115+
'tenant_id': fake.uuid4(),
116+
}
117+
118+
expected_customer = CustomerCosmosDBModel(customer_data)
119+
expected_project = ProjectCosmosDBModel(project_data)
120+
expected_project_type = ProjectTypeCosmosDBModel(project_type_dao)
121+
122+
customer_dao_get_all_mock = mocker.patch.object(
123+
CustomerCosmosDBDao, 'get_all'
124+
)
125+
customer_dao_get_all_mock.return_value = [expected_customer]
126+
127+
projects_repository_find_all_mock = mocker.patch.object(
128+
ProjectCosmosDBRepository, 'find_all'
129+
)
130+
projects_repository_find_all_mock.return_value = [expected_project]
131+
132+
project_type_dao_get_all_mock = mocker.patch.object(
133+
ProjectTypeCosmosDBDao, 'get_all'
134+
)
135+
project_type_dao_get_all_mock.return_value = [expected_project_type]
136+
projects = create_dao().get_all()
137+
138+
assert isinstance(projects[0], ProjectCosmosDBModel)
139+
assert projects[0].__dict__['customer_name'] == customer_data['name']
140+
assert len(projects) == 1

time_tracker_api/project_types/project_types_model.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22

33
from azure.cosmos import PartitionKey
44

5-
from commons.data_access_layer.cosmos_db import CosmosDBModel, CosmosDBDao, CosmosDBRepository
5+
from commons.data_access_layer.cosmos_db import (
6+
CosmosDBModel,
7+
CosmosDBDao,
8+
CosmosDBRepository,
9+
)
610
from time_tracker_api.database import CRUDDao, APICosmosDBDao
711

812

@@ -17,7 +21,7 @@ class ProjectTypeDao(CRUDDao):
1721
'uniqueKeys': [
1822
{'paths': ['/name', '/customer_id', '/deleted']},
1923
]
20-
}
24+
},
2125
}
2226

2327

@@ -32,7 +36,9 @@ class ProjectTypeCosmosDBModel(CosmosDBModel):
3236
tenant_id: str
3337

3438
def __init__(self, data):
35-
super(ProjectTypeCosmosDBModel, self).__init__(data) # pragma: no cover
39+
super(ProjectTypeCosmosDBModel, self).__init__(
40+
data
41+
) # pragma: no cover
3642

3743
def __repr__(self):
3844
return '<ProjectType %r>' % self.name # pragma: no cover
@@ -41,12 +47,13 @@ def __str___(self):
4147
return "the project type \"%s\"" % self.name # pragma: no cover
4248

4349

44-
def create_dao() -> ProjectTypeDao:
45-
repository = CosmosDBRepository.from_definition(container_definition,
46-
mapper=ProjectTypeCosmosDBModel)
50+
class ProjectTypeCosmosDBDao(APICosmosDBDao, ProjectTypeDao):
51+
def __init__(self, repository):
52+
CosmosDBDao.__init__(self, repository)
4753

48-
class ProjectTypeCosmosDBDao(APICosmosDBDao, ProjectTypeDao):
49-
def __init__(self):
50-
CosmosDBDao.__init__(self, repository)
5154

52-
return ProjectTypeCosmosDBDao()
55+
def create_dao() -> ProjectTypeDao:
56+
repository = CosmosDBRepository.from_definition(
57+
container_definition, mapper=ProjectTypeCosmosDBModel
58+
)
59+
return ProjectTypeCosmosDBDao(repository)

time_tracker_api/projects/projects_model.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -134,15 +134,17 @@ def get_all(
134134
"""
135135
event_ctx = self.create_event_context("read-many")
136136
customer_dao = customers_create_dao()
137+
customer_status = kwargs.get('customer_status', None)
138+
customer_conditions = (
139+
{'status': customer_status} if customer_status else None
140+
)
141+
137142
customers = customer_dao.get_all(
138-
max_count=kwargs.get('max_count', None)
143+
conditions=customer_conditions,
144+
max_count=kwargs.get('max_count', None),
139145
)
140146

141-
customers_id = [
142-
customer.id
143-
for customer in customers
144-
if customer.status == 'active'
145-
]
147+
customers_id = [customer.id for customer in customers]
146148

147149
conditions = conditions if conditions else {}
148150

time_tracker_api/projects/projects_namespace.py

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -70,39 +70,45 @@
7070
},
7171
)
7272

73-
project_type_nested_field = ns.model('ProjectType', {
74-
'name': fields.String(
75-
title='Name',
76-
required=True,
77-
max_length=50,
78-
description='Name of the project type',
79-
example=faker.random_element(["Customer", "Training", "Internal"]),
80-
),
81-
'description': NullableString(
82-
title='Description',
83-
required=False,
84-
max_length=250,
85-
description='Comments about the project type',
86-
example=faker.paragraph(),
87-
)
88-
})
73+
project_type_nested_field = ns.model(
74+
'ProjectType',
75+
{
76+
'name': fields.String(
77+
title='Name',
78+
required=True,
79+
max_length=50,
80+
description='Name of the project type',
81+
example=faker.random_element(["Customer", "Training", "Internal"]),
82+
),
83+
'description': NullableString(
84+
title='Description',
85+
required=False,
86+
max_length=250,
87+
description='Comments about the project type',
88+
example=faker.paragraph(),
89+
),
90+
},
91+
)
8992

90-
customer_nested_field = ns.model('Customer', {
91-
'name': fields.String(
92-
title='Name',
93-
required=True,
94-
max_length=50,
95-
description='Name of the customer',
96-
example=faker.company(),
97-
),
98-
'description': NullableString(
99-
title='Description',
100-
required=False,
101-
max_length=250,
102-
description='Description about the customer',
103-
example=faker.paragraph(),
104-
)
105-
})
93+
customer_nested_field = ns.model(
94+
'Customer',
95+
{
96+
'name': fields.String(
97+
title='Name',
98+
required=True,
99+
max_length=50,
100+
description='Name of the customer',
101+
example=faker.company(),
102+
),
103+
'description': NullableString(
104+
title='Description',
105+
required=False,
106+
max_length=250,
107+
description='Description about the customer',
108+
example=faker.paragraph(),
109+
),
110+
},
111+
)
106112

107113
project_response_fields = {
108114
# TODO: Remove this DEAD CODE
@@ -135,7 +141,9 @@ class Projects(Resource):
135141
def get(self):
136142
"""List all projects"""
137143
conditions = attributes_filter.parse_args()
138-
return project_dao.get_all(conditions=conditions)
144+
return project_dao.get_all(
145+
conditions=conditions, customer_status='active'
146+
)
139147

140148
@ns.doc('create_project')
141149
@ns.response(HTTPStatus.CONFLICT, 'This project already exists')

0 commit comments

Comments
 (0)