Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
6 changes: 1 addition & 5 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,4 @@ migration_status.csv
.DS_Store

# windows env variables
.env.bat
# mac / linux env variables
.env
#PowerShell env variables
.env.ps1
env.*
32 changes: 32 additions & 0 deletions tests/utils/extend_model_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from unittest.mock import patch
from utils.extend_model import add_custom_attribute


@patch('time_tracker_api.project_types.project_types_model.create_dao')
@patch('time_tracker_api.customers.customers_model.create_dao')
def test_add_custom_attribute(customers_create_dao, projects_create_dao):
@add_custom_attribute('project_type', projects_create_dao)
@add_custom_attribute('customer', customers_create_dao)
@patch('time_tracker_api.projects.projects_model.ProjectCosmosDBModel')
def fn(project):
project.return_value.name = "Franklin, Mcdonald and Morrison"
project.return_value.description = "Include speech feeling court almost country smile economy. True quality mention key. Similar provide yard."
project.return_value.customer_id = (
"9afbfa3a-9de4-4b90-a1b7-a53d2c17a178"
)
project.return_value.project_type_id = (
"208aadb7-1ec1-4a67-a0b0-e0308d27045b"
)
project.return_value.technologies = "['python', 'restplus', 'openapi']"
project.return_value.status = "active"
project.return_value.customer_name = "Tucker Inc"
project.return_value.id = "768c924e-4501-457f-99c5-7198440d3c60"
project.return_value.tenant_id = "e2953984-03e7-4730-be29-1753d24df3b0"
project.return_value.deleted = None

return project.return_value

project = fn().__dict__

assert 'customer' in project
assert 'project_type' in project
20 changes: 19 additions & 1 deletion time_tracker_api/projects/projects_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,16 @@
from time_tracker_api.customers.customers_model import (
create_dao as customers_create_dao,
)
from time_tracker_api.project_types.project_types_model import (
create_dao as project_types_create_dao,
)
from time_tracker_api.customers.customers_model import CustomerCosmosDBModel
from utils.query_builder import CosmosDBQueryBuilder
from utils.extend_model import add_customer_name_to_projects
from utils.extend_model import (
add_customer_name_to_projects,
add_custom_attribute_in_list,
add_custom_attribute,
)


class ProjectDao(CRUDDao):
Expand Down Expand Up @@ -101,6 +108,17 @@ class ProjectCosmosDBDao(APICosmosDBDao, ProjectDao):
def __init__(self, repository):
CosmosDBDao.__init__(self, repository)

@add_custom_attribute('customer', customers_create_dao)
@add_custom_attribute('project_type', project_types_create_dao)
def get(self, id) -> ProjectCosmosDBModel:
"""
Get one project an active client
:param (str) id: project's id
"""
return super().get(id)

@add_custom_attribute_in_list('customer', customers_create_dao)
@add_custom_attribute_in_list('project_type', project_types_create_dao)
def get_all(
self, conditions: dict = None, project_ids: List = None, **kwargs
) -> list:
Expand Down
37 changes: 37 additions & 0 deletions time_tracker_api/projects/projects_namespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,51 @@
},
)

project_type_nested_field = ns.model('ProjectType', {
'name': fields.String(
title='Name',
required=True,
max_length=50,
description='Name of the project type',
example=faker.random_element(["Customer", "Training", "Internal"]),
),
'description': NullableString(
title='Description',
required=False,
max_length=250,
description='Comments about the project type',
example=faker.paragraph(),
)
})

customer_nested_field = ns.model('Customer', {
'name': fields.String(
title='Name',
required=True,
max_length=50,
description='Name of the customer',
example=faker.company(),
),
'description': NullableString(
title='Description',
required=False,
max_length=250,
description='Description about the customer',
example=faker.paragraph(),
)
})

project_response_fields = {
# TODO: Remove this DEAD CODE
'customer_name': fields.String(
required=True,
title='Customer Name',
max_length=50,
description='Name of the customer of the project',
example=faker.company(),
),
'customer': fields.Nested(customer_nested_field),
'project_type': fields.Nested(project_type_nested_field),
}
project_response_fields.update(common_fields)

Expand Down
58 changes: 58 additions & 0 deletions utils/extend_model.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,64 @@
from functools import wraps
import re


def add_custom_attribute(attr, dao):
"""
Decorator to add an custom attribute in model, based on entity's id
:param (attr) attribute: name of the new attribute
:param (dao) dao: related entity to the model
"""

def decorator_for_single_item(func):
@wraps(func)
def wrapper(*args, **kwargs):
current_dao = dao()
entity_model = func(*args, **kwargs)
attribute_id = f"{attr}_id"

if entity_model and attribute_id in entity_model.__dict__:
value_id = entity_model.__dict__[attribute_id]
if value_id:
related_entity = current_dao.get(value_id)
setattr(entity_model, attr, related_entity)

return entity_model

return wrapper

return decorator_for_single_item


def add_custom_attribute_in_list(attr, dao):
"""
Decorator to add an custom attribute in model_list, based on entity's id
:param (attr) attribute: name of the new attribute
:param (dao) dao: related entity to the model
"""

def decorator_for_list_item(func):
@wraps(func)
def wrapper(*args, **kwargs):
current_dao = dao()
entity_model_list = func(*args, **kwargs)
attribute_id = f"{attr}_id"

related_entity_list = current_dao.get_all()
related_entities_ids_dict = {x.id: x for x in related_entity_list}

for entity_model in entity_model_list:
value_id = entity_model.__dict__[attribute_id]
setattr(
entity_model, attr, related_entities_ids_dict.get(value_id)
)

return entity_model_list

return wrapper

return decorator_for_list_item


def add_customer_name_to_projects(projects, customers):
"""
Add attribute customer_name in project model, based on customer_id of the
Expand Down