Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
1 change: 1 addition & 0 deletions requirements/dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pytest==5.2.0

# Mocking
pytest-mock==2.0.0
Faker==4.0.2

# Coverage
coverage==4.5.1
6 changes: 6 additions & 0 deletions time_tracker_api/activities/activities_namespace.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from flask_restplus import fields, Resource, Namespace
from time_tracker_api.api import audit_fields
from faker import Faker

faker = Faker()

ns = Namespace('activities', description='API for activities')

Expand All @@ -10,10 +13,12 @@
title='Name',
max_length=50,
description='Canonical name of the activity',
example=faker.word(['Development', 'Training'])
),
'description': fields.String(
title='Description',
description='Comments about the activity',
example=faker.paragraph()
),
})

Expand All @@ -23,6 +28,7 @@
required=True,
title='Identifier',
description='The unique identifier',
example=faker.uuid4()
)
}
activity_response_fields.update(audit_fields)
Expand Down
8 changes: 7 additions & 1 deletion time_tracker_api/api.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
from flask_restplus import Api, fields
from faker import Faker

faker = Faker()

api = Api(version='1.0.1', title="TimeTracker API",
description="API for the TimeTracker project")
Expand All @@ -8,19 +11,22 @@
'created_at': fields.Date(
readOnly=True,
title='Created',
description='Date of creation'
description='Date of creation',
example=faker.iso8601(end_datetime=None)
),
'tenant_id': fields.String(
readOnly=True,
title='Tenant',
max_length=64,
description='The tenant this belongs to',
example=faker.uuid4()
),
'created_by': fields.String(
readOnly=True,
title='Creator',
max_length=64,
description='User that created it',
example=faker.uuid4()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add trailing comas

),
}

Expand Down
20 changes: 10 additions & 10 deletions time_tracker_api/projects/projects_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,29 @@ def __init__(self):
def get_all(self):
return self.projects

def get(self, uid):
def get(self, id):
for project in self.projects:
if project.get('uid') == uid:
if project.get('id') == id:
return project
raise MissingResource("Project '%s' not found" % uid)
raise MissingResource("Project '%s' not found" % id)

def create(self, project):
self.counter += 1
project['uid'] = str(self.counter)
project['id'] = str(self.counter)
self.projects.append(project)
return project

def update(self, uid, data):
project = self.get(uid)
def update(self, id, data):
project = self.get(id)
if project:
project.update(data)
return project
else:
raise MissingResource("Project '%s' not found" % uid)
raise MissingResource("Project '%s' not found" % id)

def delete(self, uid):
if uid:
project = self.get(uid)
def delete(self, id):
if id:
project = self.get(id)
self.projects.remove(project)

def flush(self):
Expand Down
31 changes: 19 additions & 12 deletions time_tracker_api/projects/projects_namespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
from .projects_model import project_dao
from time_tracker_api.errors import MissingResource
from time_tracker_api.api import audit_fields
from faker import Faker

faker = Faker()

ns = Namespace('projects', description='API for projects (clients)')

Expand All @@ -11,17 +14,20 @@
required=True,
title='Name',
max_length=50,
description='Name of the project'
description='Name of the project',
example=faker.word(['YoSpace', 'Yira'])
),
'description': fields.String(
title='Description',
description='Description about the project'
description='Description about the project',
example=faker.paragraph()
),
'type': fields.String(
required=True,
title='Type',
max_length=30,
description='If it is `Costumer`, `Training` or other type',
example=faker.word(['Customer', 'Training'])
),
})

Expand All @@ -31,6 +37,7 @@
required=True,
title='Identifier',
description='The unique identifier',
example=faker.uuid4()
)
}
project_response_fields.update(audit_fields)
Expand Down Expand Up @@ -66,24 +73,24 @@ def post(self):
help='Is the project active?')


@ns.route('/<string:uid>')
@ns.route('/<string:id>')
@ns.response(404, 'Project not found')
@ns.param('uid', 'The project identifier')
@ns.param('id', 'The project identifier')
class Project(Resource):
@ns.doc('get_project')
@ns.marshal_with(project)
def get(self, uid):
def get(self, id):
"""Retrieve a project"""
return project_dao.get(uid)
return project_dao.get(id)

@ns.doc('update_project_status')
@ns.expect(project)
@ns.response(204, 'State of the project successfully updated')
def post(self, uid):
def post(self, id):
"""Updates a project using form data"""
try:
update_data = project_update_parser.parse_args()
return project_dao.update(uid, update_data), 200
return project_dao.update(id, update_data), 200
except ValueError:
abort(code=400)
except MissingResource as e:
Expand All @@ -92,13 +99,13 @@ def post(self, uid):
@ns.doc('put_project')
@ns.expect(project_input)
@ns.marshal_with(project)
def put(self, uid):
def put(self, id):
"""Create or replace a project"""
return project_dao.update(uid, ns.payload)
return project_dao.update(id, ns.payload)

@ns.doc('delete_project')
@ns.response(204, 'Project deleted successfully')
def delete(self, uid):
def delete(self, id):
"""Deletes a project"""
project_dao.delete(uid)
project_dao.delete(id)
return None, 204
17 changes: 11 additions & 6 deletions time_tracker_api/technologies/technologies_namespace.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from flask_restplus import Namespace, Resource, fields
from time_tracker_api.api import audit_fields
from faker import Faker

faker = Faker()

ns = Namespace('technologies', description='API for technologies used')

Expand All @@ -9,7 +12,8 @@
required=True,
title='Name',
max_length=50,
description='Name of the technology'
description='Name of the technology',
example=faker.word(['Java', 'Python', 'Elixir'])
),
})

Expand All @@ -19,6 +23,7 @@
required=True,
title='Identifier',
description='The unique identifier',
example=faker.uuid4()
),
}
technology_response_fields.update(audit_fields)
Expand Down Expand Up @@ -46,25 +51,25 @@ def post(self):
return ns.payload, 201


@ns.route('/<string:uid>')
@ns.route('/<string:id>')
@ns.response(404, 'Technology not found')
@ns.param('uid', 'The technology identifier')
@ns.param('id', 'The technology identifier')
class Technology(Resource):
@ns.doc('get_technology')
@ns.marshal_with(technology)
def get(self, uid):
def get(self, id):
"""Retrieve a technology"""
return {}

@ns.doc('put_technology')
@ns.expect(technology_input)
@ns.marshal_with(technology)
def put(self, uid):
def put(self, id):
"""Updates a technology"""
return ns.payload()

@ns.doc('delete_technology')
@ns.response(204, 'Technology deleted successfully')
def delete(self, uid):
def delete(self, id):
"""Deletes a technology"""
return None, 204
15 changes: 13 additions & 2 deletions time_tracker_api/time_entries/time_entries_namespace.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from flask_restplus import fields, Resource, Namespace
from time_tracker_api.api import audit_fields
from time_tracker_api import database
from faker import Faker

faker = Faker()

ns = Namespace('time-entries', description='API for time entries')

Expand All @@ -11,12 +14,14 @@
title='Project',
max_length=64,
description='The id of the selected project',
example=faker.uuid4()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, the ids that are stored in the database are going to be integers because that is how SQL databases do it. So let's keep the ids as random integers of 4 digits maximum, at least for now. Later when we start doing migrations to uuid we do the change, but the representation has to be truth to real.

),
'activity_id': fields.String(
required=False,
title='Activity',
max_length=64,
description='The id of the selected activity',
example=faker.uuid4()
),
'technologies': fields.String(
required=True,
Expand All @@ -26,17 +31,20 @@
),
'description': fields.String(
title='Comments',
description='Comments about the time entry'
description='Comments about the time entry',
example=faker.paragraph()
),
'start_date': fields.DateTime(
required=True,
title='Start date',
description='When the user started doing this activity',
example=faker.iso8601(end_datetime=None)
),
'end_date': fields.DateTime(
required=True,
title='End date',
description='When the user ended doing this activity',
example=faker.iso8601(end_datetime=None)
),
})

Expand All @@ -46,11 +54,13 @@
required=True,
title='Identifier',
description='The unique identifier',
example=faker.uuid4()
),
'running': fields.Boolean(
readOnly=True,
title='Is it running?',
description='Whether this time entry is currently running or not'
description='Whether this time entry is currently running or not',
example=faker.boolean()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, running has to be true if the end_date has no value. I think that end_date has to have a value or not.

),
}
time_entry_response_fields.update(audit_fields)
Expand All @@ -64,6 +74,7 @@

model = database.create('time-entries')


@ns.route('')
class TimeEntries(Resource):
@ns.doc('list_time_entries')
Expand Down