API: add an activity w/o gpx file

This commit is contained in:
Sam 2018-05-08 15:46:54 +02:00
parent 4d36a047d9
commit 9b1335233d
3 changed files with 179 additions and 12 deletions

View File

@ -1,6 +1,6 @@
import json import json
import os import os
from datetime import timedelta from datetime import datetime, timedelta
from flask import Blueprint, current_app, jsonify, request from flask import Blueprint, current_app, jsonify, request
from mpwo_api import appLog, db from mpwo_api import appLog, db
@ -185,3 +185,52 @@ def post_activity(auth_user_id):
'message': 'Error during activity save.' 'message': 'Error during activity save.'
} }
return jsonify(response_object), 500 return jsonify(response_object), 500
@activities_blueprint.route('/activities/no_gpx', methods=['POST'])
@authenticate
def post_activity_no_gpx(auth_user_id):
"""Post an activity without gpx file"""
activity_data = request.get_json()
if not activity_data or activity_data.get('sport_id') is None \
or activity_data.get('duration') is None \
or activity_data.get('distance') is None \
or activity_data.get('activity_date') is None:
response_object = {
'status': 'error',
'message': 'Invalid payload.'
}
return jsonify(response_object), 400
try:
new_activity = Activity(
user_id=auth_user_id,
sport_id=activity_data.get('sport_id'),
activity_date=datetime.strptime(
activity_data.get('activity_date'), '%d/%m/%Y'),
duration=timedelta(seconds=activity_data.get('duration'))
)
new_activity.moving = new_activity.duration
new_activity.distance = activity_data.get('distance')
new_activity.ave_speed = new_activity.distance / (
new_activity.duration.seconds / 3600)
new_activity.max_speed = new_activity.ave_speed
db.session.add(new_activity)
db.session.commit()
response_object = {
'status': 'created',
'data': {
'activities': [new_activity.serialize()]
}
}
return jsonify(response_object), 201
except (exc.IntegrityError, ValueError) as e:
db.session.rollback()
appLog.error(e)
response_object = {
'status': 'fail',
'message': 'Error during activity save.'
}
return jsonify(response_object), 500

View File

@ -41,13 +41,13 @@ class Activity(db.Model):
duration = db.Column(db.Interval, nullable=False) duration = db.Column(db.Interval, nullable=False)
pauses = db.Column(db.Interval, nullable=True) pauses = db.Column(db.Interval, nullable=True)
moving = db.Column(db.Interval, nullable=True) moving = db.Column(db.Interval, nullable=True)
distance = db.Column(db.Numeric(5, 2), nullable=True) distance = db.Column(db.Numeric(5, 2), nullable=True) # kilometers
min_alt = db.Column(db.Numeric(5, 2), nullable=True) min_alt = db.Column(db.Numeric(5, 2), nullable=True) # meters
max_alt = db.Column(db.Numeric(5, 2), nullable=True) max_alt = db.Column(db.Numeric(5, 2), nullable=True) # meters
descent = db.Column(db.Numeric(5, 2), nullable=True) descent = db.Column(db.Numeric(5, 2), nullable=True) # meters
ascent = db.Column(db.Numeric(5, 2), nullable=True) ascent = db.Column(db.Numeric(5, 2), nullable=True) # meters
max_speed = db.Column(db.Numeric(5, 2), nullable=True) max_speed = db.Column(db.Numeric(5, 2), nullable=True) # km/h
ave_speed = db.Column(db.Numeric(5, 2), nullable=True) ave_speed = db.Column(db.Numeric(5, 2), nullable=True) # km/h
def __str__(self): def __str__(self):
return str(self.sports.label) + \ return str(self.sports.label) + \

View File

@ -103,7 +103,7 @@ def test_get_activities_for_authenticated_user_no_activity(app):
assert len(data['data']['activities']) == 0 assert len(data['data']['activities']) == 0
def test_add_an_activity(app): def test_add_an_activity_gpx(app):
add_user('test', 'test@test.com', '12345678') add_user('test', 'test@test.com', '12345678')
add_sport('cycling') add_sport('cycling')
@ -135,7 +135,7 @@ def test_add_an_activity(app):
assert 'created' in data['status'] assert 'created' in data['status']
def test_add_an_activity_invalid_file(app): def test_add_an_activity_gpx_invalid_file(app):
add_user('test', 'test@test.com', '12345678') add_user('test', 'test@test.com', '12345678')
add_sport('cycling') add_sport('cycling')
@ -168,7 +168,7 @@ def test_add_an_activity_invalid_file(app):
assert data['message'] == 'File extension not allowed.' assert data['message'] == 'File extension not allowed.'
def test_add_an_activity_no_sport_id(app): def test_add_an_activity_gpx_no_sport_id(app):
add_user('test', 'test@test.com', '12345678') add_user('test', 'test@test.com', '12345678')
add_sport('cycling') add_sport('cycling')
@ -201,7 +201,7 @@ def test_add_an_activity_no_sport_id(app):
assert data['message'] == 'Invalid payload.' assert data['message'] == 'Invalid payload.'
def test_add_an_activity_no_file(app): def test_add_an_activity_gpx_no_file(app):
add_user('test', 'test@test.com', '12345678') add_user('test', 'test@test.com', '12345678')
add_sport('cycling') add_sport('cycling')
@ -233,6 +233,124 @@ def test_add_an_activity_no_file(app):
assert data['message'] == 'No file part.' assert data['message'] == 'No file part.'
def test_add_an_activity_no_gpx(app):
add_user('test', 'test@test.com', '12345678')
add_sport('cycling')
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
data=json.dumps(dict(
email='test@test.com',
password='12345678'
)),
content_type='application/json'
)
response = client.post(
'/api/activities/no_gpx',
content_type='application/json',
data=json.dumps(dict(
sport_id=1,
duration=3600,
activity_date='15/05/2018',
distance=10
)),
headers=dict(
Authorization='Bearer ' + json.loads(
resp_login.data.decode()
)['auth_token']
)
)
data = json.loads(response.data.decode())
assert response.status_code == 201
assert 'created' in data['status']
assert len(data['data']['activities']) == 1
assert 'creation_date' in data['data']['activities'][0]
assert data['data']['activities'][0]['activity_date'] == 'Tue, 15 May 2018 00:00:00 GMT' # noqa
assert data['data']['activities'][0]['user_id'] == 1
assert data['data']['activities'][0]['sport_id'] == 1
assert data['data']['activities'][0]['duration'] == '1:00:00'
assert data['data']['activities'][0]['ascent'] is None
assert data['data']['activities'][0]['ave_speed'] == 10.0
assert data['data']['activities'][0]['descent'] is None
assert data['data']['activities'][0]['distance'] == 10.0
assert data['data']['activities'][0]['max_alt'] is None
assert data['data']['activities'][0]['max_speed'] == 10.0
assert data['data']['activities'][0]['min_alt'] is None
assert data['data']['activities'][0]['moving'] == '1:00:00'
assert data['data']['activities'][0]['pauses'] is None
def test_add_an_activity_no_gpx_invalid_payload(app):
add_user('test', 'test@test.com', '12345678')
add_sport('cycling')
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
data=json.dumps(dict(
email='test@test.com',
password='12345678'
)),
content_type='application/json'
)
response = client.post(
'/api/activities/no_gpx',
content_type='application/json',
data=json.dumps(dict(
sport_id=1,
duration=3600,
distance=10
)),
headers=dict(
Authorization='Bearer ' + json.loads(
resp_login.data.decode()
)['auth_token']
)
)
data = json.loads(response.data.decode())
assert response.status_code == 400
assert 'error' in data['status']
assert 'Invalid payload.' in data['message']
def test_add_an_activity_no_gpx_error(app):
add_user('test', 'test@test.com', '12345678')
add_sport('cycling')
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
data=json.dumps(dict(
email='test@test.com',
password='12345678'
)),
content_type='application/json'
)
response = client.post(
'/api/activities/no_gpx',
content_type='application/json',
data=json.dumps(dict(
sport_id=1,
duration=3600,
activity_date='15/2018',
distance=10
)),
headers=dict(
Authorization='Bearer ' + json.loads(
resp_login.data.decode()
)['auth_token']
)
)
data = json.loads(response.data.decode())
assert response.status_code == 500
assert 'fail' in data['status']
assert 'Error during activity save.' in data['message']
def test_get_an_activity_without_gpx(app): def test_get_an_activity_without_gpx(app):
add_user('test', 'test@test.com', '12345678') add_user('test', 'test@test.com', '12345678')
add_sport('cycling') add_sport('cycling')