Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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.*
38 changes: 38 additions & 0 deletions tests/utils/extend_model_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
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