From b3fdb7b6f87fb063d19441dffccf7374a04c1c75 Mon Sep 17 00:00:00 2001 From: kenlt-uk Date: Wed, 7 Nov 2018 23:13:44 +0000 Subject: [PATCH 1/8] Make get events require auth --- app/routes/events/rest.py | 1 + tests/app/routes/events/test_rest.py | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/routes/events/rest.py b/app/routes/events/rest.py index 1c24457c..bd18d2f7 100644 --- a/app/routes/events/rest.py +++ b/app/routes/events/rest.py @@ -27,6 +27,7 @@ @events_blueprint.route('/events') +@jwt_required def get_events(): events = [e.serialize() if e else None for e in dao_get_events()] diff --git a/tests/app/routes/events/test_rest.py b/tests/app/routes/events/test_rest.py index 1989c416..94206ce8 100644 --- a/tests/app/routes/events/test_rest.py +++ b/tests/app/routes/events/test_rest.py @@ -84,7 +84,8 @@ class WhenGettingEvents(object): def it_returns_all_events(self, client, sample_event, db_session): response = client.get( - url_for('events.get_events') + url_for('events.get_events'), + headers=[('Content-Type', 'application/json'), create_authorization_header()] ) data = json.loads(response.get_data(as_text=True)) @@ -100,7 +101,8 @@ def it_returns_all_events_with_event_dates(self, client, sample_speaker, sample_ create_event(event_type_id=sample_event_type.id, event_dates=[event_date_earliest]) response = client.get( - url_for('events.get_events') + url_for('events.get_events'), + headers=[('Content-Type', 'application/json'), create_authorization_header()] ) data = json.loads(response.get_data(as_text=True)) From f9ca10c81577f28aaa30feba91fabeff0f749305 Mon Sep 17 00:00:00 2001 From: kenlt-uk Date: Thu, 8 Nov 2018 01:08:19 +0000 Subject: [PATCH 2/8] Update db.py to tidy code --- tests/db.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/db.py b/tests/db.py index f74b2140..2ba20198 100644 --- a/tests/db.py +++ b/tests/db.py @@ -36,11 +36,10 @@ def create_event( } event = Event(**data) - dao_create_event(event) - if event_dates: event.event_dates.extend(event_dates) - db.session.commit() + + dao_create_event(event) return event From 69cdbae997c37d0615c82581f6f1f40f1d3ce325 Mon Sep 17 00:00:00 2001 From: kenlt-uk Date: Thu, 8 Nov 2018 01:09:48 +0000 Subject: [PATCH 3/8] Update events _dao with get_future_events --- app/dao/events_dao.py | 10 +++++++++- tests/app/dao/test_events_dao.py | 19 ++++++++++++++++++- tests/conftest.py | 12 ++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/app/dao/events_dao.py b/app/dao/events_dao.py index b0d261fb..704f0f48 100644 --- a/app/dao/events_dao.py +++ b/app/dao/events_dao.py @@ -1,6 +1,8 @@ +from datetime import datetime + from app import db from app.dao.decorators import transactional -from app.models import Event +from app.models import Event, EventDate @transactional @@ -17,3 +19,9 @@ def dao_update_event(event_id, **kwargs): def dao_get_events(): return Event.query.order_by(Event.id).all() + + +def dao_get_future_events(): + return Event.query.join(EventDate).filter( + EventDate.event_datetime > datetime.utcnow() + ).order_by(Event.id).all() diff --git a/tests/app/dao/test_events_dao.py b/tests/app/dao/test_events_dao.py index 5a99c02d..6e4d77cc 100644 --- a/tests/app/dao/test_events_dao.py +++ b/tests/app/dao/test_events_dao.py @@ -1,4 +1,8 @@ -from app.dao.events_dao import dao_create_event, dao_update_event, dao_get_events +from freezegun import freeze_time + +from app.dao.events_dao import ( + dao_create_event, dao_update_event, dao_get_events, dao_get_future_events +) from app.models import Event from tests.db import create_event, create_event_date @@ -35,3 +39,16 @@ def it_gets_all_events(self, db, db_session, sample_event, sample_event_type): assert Event.query.count() == 2 assert set(events) == set(events_from_db) + + @freeze_time("2018-01-10T19:00:00") + def it_gets_all_future_events(self, db, db_session, sample_event_with_dates, sample_event_type): + event = create_event( + title='future event', + event_type_id=sample_event_type.id, + event_dates=[create_event_date(event_datetime='2018-01-20T19:00:00')] + ) + events_from_db = dao_get_future_events() + + assert Event.query.count() == 2 + assert len(events_from_db) == 1 + assert events_from_db[0] == event diff --git a/tests/conftest.py b/tests/conftest.py index 549be615..764334f4 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -77,6 +77,13 @@ def sample_event(db): return create_event(title='test_title', description='test description') +@pytest.fixture(scope='function') +def sample_event_with_dates(db, sample_event_date_without_event): + return create_event( + title='test_title', description='test description', event_dates=[sample_event_date_without_event] + ) + + @pytest.fixture(scope='function') def sample_event_type(db): return create_event_type(event_type='short course') @@ -87,6 +94,11 @@ def sample_event_date(db, sample_event): return create_event_date(event_id=sample_event.id) +@pytest.fixture(scope='function') +def sample_event_date_without_event(db): + return create_event_date() + + @pytest.fixture(scope='function') def sample_fee(db, sample_event_type): return create_fee(fee=5, conc_fee=3, event_type_id=sample_event_type.id) From 3e03b1a317601f4ee382da7b3d4bc454c6529ae6 Mon Sep 17 00:00:00 2001 From: kenlt-uk Date: Thu, 8 Nov 2018 01:10:23 +0000 Subject: [PATCH 4/8] Update events endpoint with future events --- app/routes/events/rest.py | 16 ++++++++++++- tests/app/routes/events/test_rest.py | 34 +++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/app/routes/events/rest.py b/app/routes/events/rest.py index bd18d2f7..1d0fe835 100644 --- a/app/routes/events/rest.py +++ b/app/routes/events/rest.py @@ -9,7 +9,9 @@ from flask_jwt_extended import jwt_required -from app.dao.events_dao import dao_create_event, dao_get_events, dao_update_event +from app.dao.events_dao import ( + dao_create_event, dao_get_events, dao_get_future_events, dao_update_event +) from app.dao.event_dates_dao import dao_create_event_date from app.dao.event_types_dao import dao_get_event_type_by_old_id from app.dao.speakers_dao import dao_get_speaker_by_name @@ -41,6 +43,18 @@ def extract_startdate(json): return jsonify(events) +@events_blueprint.route('/events/future') +@jwt_required +def get_future_events(): + events = [e.serialize() if e else None for e in dao_get_future_events()] + + def extract_startdate(json): + return json['event_dates'][0]['event_datetime'] + + events.sort(key=extract_startdate) + return jsonify(events) + + @events_blueprint.route('/events/extract-speakers', methods=['POST']) def extract_speakers(): data = request.get_json(force=True) diff --git a/tests/app/routes/events/test_rest.py b/tests/app/routes/events/test_rest.py index 94206ce8..6f7dd1c7 100644 --- a/tests/app/routes/events/test_rest.py +++ b/tests/app/routes/events/test_rest.py @@ -2,9 +2,11 @@ import pytest from flask import json, url_for +from freezegun import freeze_time + from app.dao.events_dao import dao_update_event from app.dao.event_dates_dao import dao_update_event_date -from app.models import EventDate +from app.models import EventDate, Event from tests.conftest import create_authorization_header from tests.db import create_event, create_event_date, create_event_type, create_speaker @@ -91,6 +93,36 @@ def it_returns_all_events(self, client, sample_event, db_session): data = json.loads(response.get_data(as_text=True)) assert len(data) == 1 + @freeze_time("2018-01-10T19:00:00") + def it_returns_all_future_events(self, client, sample_event_with_dates, sample_event_type, db_session): + event_1 = create_event( + title='future event', + event_type_id=sample_event_type.id, + event_dates=[create_event_date(event_datetime='2018-01-20T19:00:00')] + ) + event_2 = create_event( + title='future event', + event_type_id=sample_event_type.id, + event_dates=[create_event_date(event_datetime='2018-01-25T19:00:00')] + ) + + # don't expect to do a join on empty events + create_event( + title='future event', + event_type_id=sample_event_type.id + ) + + response = client.get( + url_for('events.get_future_events'), + headers=[('Content-Type', 'application/json'), create_authorization_header()] + ) + + data = json.loads(response.get_data(as_text=True)) + assert Event.query.count() == 4 + assert len(data) == 2 + assert data[0]['id'] == str(event_1.id) + assert data[1]['id'] == str(event_2.id) + def it_returns_all_events_with_event_dates(self, client, sample_speaker, sample_event_type, db_session): event_date_1 = create_event_date(event_datetime="2018-01-03") event_date_earliest = create_event_date(event_datetime="2018-01-01") From ba1f8455e6e4643e1d499a68e48e705bc755737f Mon Sep 17 00:00:00 2001 From: kenlt-uk Date: Thu, 8 Nov 2018 01:11:29 +0000 Subject: [PATCH 5/8] Add GetEvents and GetFutureEvents - also reorder functions --- integration_test.sh | 60 +++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/integration_test.sh b/integration_test.sh index 68cd7d38..c1a74c6e 100755 --- a/integration_test.sh +++ b/integration_test.sh @@ -31,6 +31,22 @@ function GetFees { -H "Authorization: Bearer $TKN" | jq . } +function GetEvents { + echo "*** Get events ***" + + curl -X GET $api_server'/events' \ + -H "Accept: application/json" \ + -H "Authorization: Bearer $TKN" +} + +function GetFutureEvents { + echo "*** Get future events ***" + + curl -X GET $api_server'/events/future' \ + -H "Accept: application/json" \ + -H "Authorization: Bearer $TKN" +} + function GetEventTypes { echo "*** Get event_types ***" @@ -229,18 +245,6 @@ function Logout { -H "Authorization: Bearer $TKN" | jq . } -# API calls -# GetFees -# GetEventTypes -# PostSpeakers -# GetSpeakers -# ImportVenues -# GetVenues -# ExtractSpeakers -# ImportEvents -# Logout -# GetFees - # setup setupURLS "$2" setupAccessToken @@ -254,40 +258,48 @@ fi case "$arg" in -a) echo "Run all" - GetFees - GetEventTypes + ExtractSpeakers ImportEventTypes ImportSpeakers - GetSpeakers ImportVenues + GetFees + GetEventTypes + GetSpeakers GetVenues - ExtractSpeakers Logout GetFees ;; + -es) + ExtractSpeakers + ;; + -et) GetEventTypes ;; - -iet) - ImportEventTypes + -e) + GetEvents ;; - -iv) - ImportVenues + -fe) + GetFutureEvents ;; -s) GetSpeakers ;; - -is) - ImportSpeakers + -iet) + ImportEventTypes ;; - -es) - ExtractSpeakers + -iv) + ImportVenues + ;; + + -is) + ImportSpeakers ;; -ie) From 29d216a0b29b9daca2b6adcf4107098615f367ee Mon Sep 17 00:00:00 2001 From: kenlt-uk Date: Thu, 8 Nov 2018 01:32:56 +0000 Subject: [PATCH 6/8] Update events_dao for past_year_events --- app/dao/events_dao.py | 11 +++++++++-- tests/app/dao/test_events_dao.py | 20 +++++++++++++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/app/dao/events_dao.py b/app/dao/events_dao.py index 704f0f48..0df82089 100644 --- a/app/dao/events_dao.py +++ b/app/dao/events_dao.py @@ -1,4 +1,4 @@ -from datetime import datetime +from datetime import datetime, timedelta from app import db from app.dao.decorators import transactional @@ -23,5 +23,12 @@ def dao_get_events(): def dao_get_future_events(): return Event.query.join(EventDate).filter( - EventDate.event_datetime > datetime.utcnow() + EventDate.event_datetime >= datetime.today() + ).order_by(Event.id).all() + + +def dao_get_past_year_events(): + return Event.query.join(EventDate).filter( + EventDate.event_datetime < datetime.today(), + EventDate.event_datetime > datetime.today() - timedelta(days=365) ).order_by(Event.id).all() diff --git a/tests/app/dao/test_events_dao.py b/tests/app/dao/test_events_dao.py index 6e4d77cc..44b1e012 100644 --- a/tests/app/dao/test_events_dao.py +++ b/tests/app/dao/test_events_dao.py @@ -1,7 +1,7 @@ from freezegun import freeze_time from app.dao.events_dao import ( - dao_create_event, dao_update_event, dao_get_events, dao_get_future_events + dao_create_event, dao_update_event, dao_get_events, dao_get_future_events, dao_get_past_year_events ) from app.models import Event @@ -52,3 +52,21 @@ def it_gets_all_future_events(self, db, db_session, sample_event_with_dates, sam assert Event.query.count() == 2 assert len(events_from_db) == 1 assert events_from_db[0] == event + + @freeze_time("2018-01-10T19:00:00") + def it_gets_past_year_events(self, db, db_session, sample_event_with_dates, sample_event_type): + create_event( + title='way past last year event', + event_type_id=sample_event_type.id, + event_dates=[create_event_date(event_datetime='2016-01-01T19:00:00')] + ) + create_event( + title='future event', + event_type_id=sample_event_type.id, + event_dates=[create_event_date(event_datetime='2018-01-20T19:00:00')] + ) + events_from_db = dao_get_past_year_events() + + assert Event.query.count() == 3 + assert len(events_from_db) == 1 + assert events_from_db[0] == sample_event_with_dates From f71ea6e5fbac4827b03de29277ee492b9afd5028 Mon Sep 17 00:00:00 2001 From: kenlt-uk Date: Thu, 8 Nov 2018 01:33:28 +0000 Subject: [PATCH 7/8] Update events endpoint with past_year_events --- app/routes/events/rest.py | 25 ++++++++++++++-------- tests/app/routes/events/test_rest.py | 31 +++++++++++++++++++++------- 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/app/routes/events/rest.py b/app/routes/events/rest.py index 1d0fe835..511e7e15 100644 --- a/app/routes/events/rest.py +++ b/app/routes/events/rest.py @@ -10,7 +10,7 @@ from flask_jwt_extended import jwt_required from app.dao.events_dao import ( - dao_create_event, dao_get_events, dao_get_future_events, dao_update_event + dao_create_event, dao_get_events, dao_get_future_events, dao_get_past_year_events, dao_update_event ) from app.dao.event_dates_dao import dao_create_event_date from app.dao.event_types_dao import dao_get_event_type_by_old_id @@ -28,17 +28,18 @@ register_errors(events_blueprint) +def extract_startdate(json): + if json['event_dates']: + return json['event_dates'][0]['event_datetime'] + else: + return 0 + + @events_blueprint.route('/events') @jwt_required def get_events(): events = [e.serialize() if e else None for e in dao_get_events()] - def extract_startdate(json): - if json['event_dates']: - return json['event_dates'][0]['event_datetime'] - else: - return 0 - events.sort(key=extract_startdate) return jsonify(events) @@ -48,8 +49,14 @@ def extract_startdate(json): def get_future_events(): events = [e.serialize() if e else None for e in dao_get_future_events()] - def extract_startdate(json): - return json['event_dates'][0]['event_datetime'] + events.sort(key=extract_startdate) + return jsonify(events) + + +@events_blueprint.route('/events/past_year') +@jwt_required +def get_past_year_events(): + events = [e.serialize() if e else None for e in dao_get_past_year_events()] events.sort(key=extract_startdate) return jsonify(events) diff --git a/tests/app/routes/events/test_rest.py b/tests/app/routes/events/test_rest.py index 6f7dd1c7..74c18073 100644 --- a/tests/app/routes/events/test_rest.py +++ b/tests/app/routes/events/test_rest.py @@ -106,23 +106,40 @@ def it_returns_all_future_events(self, client, sample_event_with_dates, sample_e event_dates=[create_event_date(event_datetime='2018-01-25T19:00:00')] ) - # don't expect to do a join on empty events - create_event( - title='future event', - event_type_id=sample_event_type.id - ) - response = client.get( url_for('events.get_future_events'), headers=[('Content-Type', 'application/json'), create_authorization_header()] ) data = json.loads(response.get_data(as_text=True)) - assert Event.query.count() == 4 + assert Event.query.count() == 3 assert len(data) == 2 assert data[0]['id'] == str(event_1.id) assert data[1]['id'] == str(event_2.id) + @freeze_time("2018-01-10T19:00:00") + def it_returns_past_year_events(self, client, sample_event_with_dates, sample_event_type, db_session): + create_event( + title='future event', + event_type_id=sample_event_type.id, + event_dates=[create_event_date(event_datetime='2018-01-20T19:00:00')] + ) + create_event( + title='way past year event', + event_type_id=sample_event_type.id, + event_dates=[create_event_date(event_datetime='2016-01-25T19:00:00')] + ) + + response = client.get( + url_for('events.get_past_year_events'), + headers=[('Content-Type', 'application/json'), create_authorization_header()] + ) + + data = json.loads(response.get_data(as_text=True)) + assert Event.query.count() == 3 + assert len(data) == 1 + assert data[0]['id'] == str(sample_event_with_dates.id) + def it_returns_all_events_with_event_dates(self, client, sample_speaker, sample_event_type, db_session): event_date_1 = create_event_date(event_datetime="2018-01-03") event_date_earliest = create_event_date(event_datetime="2018-01-01") From 696e60a1ab1d8b6aa0c9d1b8938cddf1b01493f1 Mon Sep 17 00:00:00 2001 From: kenlt-uk Date: Fri, 9 Nov 2018 00:30:08 +0000 Subject: [PATCH 8/8] Sort event_dates in event --- app/models.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/models.py b/app/models.py index 5c78cea1..c0dcc0cb 100644 --- a/app/models.py +++ b/app/models.py @@ -115,6 +115,11 @@ class Event(db.Model): venue = db.relationship("Venue", backref=db.backref("event", uselist=False)) def serialize(self): + def sorted_event_dates(): + dates = [e.serialize() for e in self.event_dates] + dates.sort(key=lambda k: k['event_datetime']) + return dates + return { 'id': self.id, 'old_id': self.old_id, @@ -128,7 +133,7 @@ def serialize(self): 'multi_day_fee': self.multi_day_fee, 'multi_day_conc_fee': self.multi_day_conc_fee, 'venue': self.venue.serialize() if self.venue else None, - 'event_dates': [e.serialize() for e in self.event_dates] + 'event_dates': sorted_event_dates() } def __repr__(self):