Skip to content

Commit

Permalink
Sprint 11 2 (#265)
Browse files Browse the repository at this point in the history
* Sprint 11 4 (#261)

* Fixed Edit Group Exam Modal to Disable Past Date Selection

Exam dates can no longer be edited to a date that is in the past.  Also fixed eratic form validation that prevented the submit button from being pressed when certain dates were selected.

* Fixed Issue with Appointment Booking Modal Notes

Notes were being captured but not displayed in the modal.  Fixed.  Also adjusted calendar start time to 8:30am.

* Fixed Errors in Branch Agenda

Previously this component was more complex and it relied on an invisible full-calendar instance to consume and parse the event data however this approach was causing issues.  Since the Agenda has recently been simplified and no longer supports multiple views etc., there is no need for full-calendar.  Have re-implemented using only moment.js and eliminated the errors related to full-calendar

* Deleted Date for Invigilators and Rooms

Client was flooded with requests for how to delete invigilators and rooms upon launch. To accomodate for this request but maintain data integrity, a deleted date was added to both the invigilator and room models, such that if these fields were set to a date in the admin panels for these objects, they will no longer show up in the application drop downs or calendars.

* Allow Office Mgr to Edit Group/Session Exam Details

Logic controlling access to the full version of the Edit Exam Modal did not consider the ita_designate key.  Office Manager previously saw only the fields-limited CSR version.   Changed so that office mgr has same access as GA role.  Also fixed:
-liaison_designate were unable to edit office of pesticide exams.
-the exam_type field of the EditExamModal was listing exam_types which did not make sense. Disabled the ability to switch exam_type on a pesticide exam or challenger exam at all and restricted changing 'other' 'individual ita' and 'group ita' to exam type options of their catagory only.
-adjusted the other field-display and field-disable logic to ensure access to necessary features for office managers
-set the time of the editExamSuccess banner to 3 seconds instead of 6

* Admin Panel - Room -> Office Name Sort

Clients required rooms to be sorted by office name after testing in production.

* Typo (#262)

Missing command from sprint-11-4 PR.

* Sprint 11 6 (#263)

* Admin Panel - Room Searching

Client required rooms to be searchable through admin panels.

* Backend Changes for Tracking Number Length

Bookings application required backend changes to reflect tracking number length of 255 chars. Alembic would not generate a migration file for the length change, so the last migration file in the alembic chain was modified to see this change happen.

* Return Exam fix: Action Taken Length & Deleted Invigilator Changes
-Action Taken field now displays an error at the maximum input length and prevents further input
-Adjusted the exam_inventory table to display the life-ring error symbol on any exam assigned to a deleted invigilator and adjusted the filters to show such exams as not ready.
-Changed a call to previous method name which was revised in EditGrouoBooking modal

* AddExamForm Modal exam_name length validation

Modified existing validation logic to check if exam_name field exceeds 50 characters in length and displays error / prevents advancing until corrected.

* Added exam_name length validation to EditExamModal

Added validation and an error message as per the Return Exam modal at the 50 character limit.

* Fixed Error in Appointments with double clicking

Fixed error where double clicking the appointments page would cause two modals to open.

Also removed stray console.log from return_exam_modal

* Delete Room Admin Warning

Clients required there to be a warning given to admin users if a room is about to have a deleted date applied to it, but it currently being used for bookings in the future. The flask admin on_model_change method was used to detect changes in the deleted date field before submission, and looking at the booking model for instances of such a room being used with start times greater than today (doesn't care about historical instances). If the room isn't in use, the room can be deleted. If the room is in use, and error message propagates telling the user that they were unable to apply the deleted date. Any other changes that the user might make on top of applying a deleted date to a room in use will be saved.

* Changed displayed hours of Appointments Calendar to 8.30 am - 5 pm (#264)
  • Loading branch information
gil0109 authored May 18, 2019
1 parent 223066f commit 073ef9f
Show file tree
Hide file tree
Showing 22 changed files with 429 additions and 279 deletions.
27 changes: 13 additions & 14 deletions api/app/admin/invigilator.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

class InvigilatorConfig(Base):
roles_allowed = ['SUPPORT', 'GA']
delete_allowed = ['SUPPORT']

def is_accessible(self):
return current_user.is_authenticated and current_user.role.role_code in self.roles_allowed
Expand All @@ -31,15 +30,9 @@ def get_query(self):
elif current_user.role.role_code == 'GA':
return self.session.query(self.model).filter_by(office_id=current_user.office_id)

# Check to see whether or not the user can delete records based on their role
def _handle_view(self, name, **kwargs):
if current_user.role.role_code in self.delete_allowed:
self.can_delete = True
else:
self.can_delete = False

create_modal = False
edit_modal = False
can_delete = False

column_list = [
'office.office_name',
Expand All @@ -48,16 +41,19 @@ def _handle_view(self, name, **kwargs):
'contact_email',
'contract_number',
'contract_expiry_date',
'invigilator_notes'
'invigilator_notes',
'deleted'
]

form_excluded_columns = [
'bookings'
]

column_labels = {'office.office_name': 'Office Name'}
column_labels = {'office.office_name': 'Office Name',
'deleted': 'Deleted'}

column_searchable_list = {'invigilator_name'}
column_searchable_list = {'invigilator_name',
'deleted'}

form_create_rules = (
'office',
Expand All @@ -66,7 +62,8 @@ def _handle_view(self, name, **kwargs):
'contact_email',
'contract_number',
'contract_expiry_date',
'invigilator_notes'
'invigilator_notes',
'deleted'
)

form_edit_rules = (
Expand All @@ -76,14 +73,16 @@ def _handle_view(self, name, **kwargs):
'contact_email',
'contract_number',
'contract_expiry_date',
'invigilator_notes'
'invigilator_notes',
'deleted'
)

column_sortable_list = [
'invigilator_name',
'contact_email',
'contract_number',
'contract_expiry_date'
'contract_expiry_date',
'deleted'
]

column_default_sort = 'invigilator_name'
Expand Down
48 changes: 41 additions & 7 deletions api/app/admin/room.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,15 @@
See the License for the specific language governing permissions and
limitations under the License.'''

from app.models.bookings import Room
from app.models.bookings import Booking, Room
from .base import Base
from flask import flash, request
from flask_admin.babel import gettext
from flask_admin.model.helpers import get_mdict_item_or_list
from flask_login import current_user
from qsystem import db
from datetime import datetime
import pytz


class RoomConfig(Base):
Expand All @@ -30,6 +35,25 @@ def get_query(self):
elif current_user.role.role_code == 'GA':
return self.session.query(self.model).filter_by(office_id=current_user.office_id)

def on_model_change(self, form, model, is_created):

room_id = get_mdict_item_or_list(request.args, 'id')
today = datetime.now()
today_aware = pytz.utc.localize(today)

booking_room = Booking.query.filter_by(room_id=room_id)\
.filter(Booking.start_time > today_aware).count()

specific_room = Room.query.filter_by(room_id=room_id).first()
room_name = specific_room.room_name

if model.deleted is not None and booking_room > 0:
message = "'" + room_name + "' is currently being used for bookings. " \
"Reschedule bookings that use this room before setting the deleted date."
flash(gettext(message), 'warning')
model.deleted = None
form.deleted.data = None

create_modal = False
edit_modal = False
can_delete = False
Expand All @@ -38,35 +62,45 @@ def get_query(self):
'office.office_name',
'room_name',
'capacity',
'color'
'color',
'deleted'
]

form_excluded_columns = [
'sb',
'booking'
]

column_labels = {'office.office_name': 'Office Name'}
column_labels = {'office.office_name': 'Office Name',
'deleted': 'Deleted'}

form_create_rules = (
'office',
'room_name',
'capacity',
'color'
'color',
'deleted'
)

form_edit_rules = (
'office',
'room_name',
'capacity',
'color'
'color',
'deleted'
)

column_sortable_list = [
'room_name',
'capacity',
'color'
'color',
'deleted',
'office.office_name'
]

column_searchable_list = {
'office.office_name'
}


RoomModelView = RoomConfig(Room, db.session)
RoomModelView = RoomConfig(Room, db.session)
2 changes: 1 addition & 1 deletion api/app/models/bookings/exam.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class Exam(Base):
exam_method = db.Column(db.String(15), nullable=False)
deleted_date = db.Column(db.String(50), nullable=True)
exam_returned_date = db.Column(db.DateTime, nullable=True)
exam_returned_tracking_number = db.Column(db.String(50), nullable=True)
exam_returned_tracking_number = db.Column(db.String(255), nullable=True)
exam_written_ind = db.Column(db.Integer, nullable=False, default=0)
offsite_location = db.Column(db.String(50), nullable=True)

Expand Down
1 change: 1 addition & 0 deletions api/app/models/bookings/invigilator.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class Invigilator(Base):
contact_email = db.Column(db.String(50), nullable=True)
contract_number = db.Column(db.String(50), nullable=False)
contract_expiry_date = db.Column(db.String(50), nullable=False)
deleted = db.Column(db.DateTime, nullable=True)

bookings = db.relationship("Booking")
office = db.relationship("Office", lazy="joined")
Expand Down
1 change: 1 addition & 0 deletions api/app/models/bookings/room.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class Room(Base):
room_name = db.Column(db.String(50), nullable=False)
capacity = db.Column(db.Integer, nullable=False)
color = db.Column(db.String(25), nullable=False)
deleted = db.Column(db.DateTime, nullable=True)

booking = db.relationship("Booking")
office = db.relationship("Office", lazy='joined')
Expand Down
4 changes: 3 additions & 1 deletion api/app/resources/bookings/invigilator/invigilator_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ def get(self):
csr = CSR.find_by_username(g.oidc_token_info['username'])

try:
invigilators = Invigilator.query.filter_by(office_id=csr.office_id)
invigilators = Invigilator.query.filter_by(office_id=csr.office_id)\
.filter(Invigilator.deleted.is_(None))

result = self.invigilator_schema.dump(invigilators)
return {'invigilators': result.data,
'errors': result.errors}, 200
Expand Down
3 changes: 2 additions & 1 deletion api/app/resources/bookings/room/room_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ def get(self):
csr = CSR.find_by_username(g.oidc_token_info['username'])

try:
rooms = Room.query.filter_by(office_id=csr.office_id)
rooms = Room.query.filter_by(office_id=csr.office_id)\
.filter(Room.deleted.is_(None))
result = self.rooms_schema.dump(rooms)
return {'rooms': result.data,
'errors': result.errors}, 200
Expand Down
1 change: 1 addition & 0 deletions api/app/schemas/bookings/invigilator_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,6 @@ class Meta:
invigilator_id = fields.Int(dump_only=True)
invigilator_name = fields.Str()
invigilator_notes = fields.Str()
deleted = fields.Str()

office = fields.Nested(OfficeSchema())
1 change: 1 addition & 0 deletions api/app/schemas/bookings/room_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,6 @@ class Meta:
color = fields.Str()
room_id = fields.Int(dump_only=True)
room_name = fields.Str()
deleted = fields.Str()

office = fields.Nested(OfficeSchema())
32 changes: 32 additions & 0 deletions api/migrations/versions/2c9c7262d221_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""empty message
Revision ID: 2c9c7262d221
Revises: 3a98e5395000
Create Date: 2019-05-15 10:16:23.063868
"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = '2c9c7262d221'
down_revision = '3a98e5395000'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('invigilator', sa.Column('deleted', sa.DateTime(), nullable=True))
op.add_column('room', sa.Column('deleted', sa.DateTime(), nullable=True))
op.alter_column('exam', 'exam_returned_tracking_number', existing_type=sa.VARCHAR(length=50), type_=sa.String(length=255))
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('room', 'deleted')
op.drop_column('invigilator', 'deleted')
op.alter_column('exam', 'exam_returned_tracking_number', existing_type=sa.VARCHAR(length=255), type_=sa.String(length=50))
# ### end Alembic commands ###
Loading

0 comments on commit 073ef9f

Please sign in to comment.