def post(self, id):
        csr = CSR.find_by_username(g.jwt_oidc_token_info['username'])

        service_request = ServiceReq.query.filter_by(sr_id=id) \
            .join(ServiceReq.citizen, aliased=True) \
            .filter_by(office_id=csr.office_id).first_or_404()

        active_service_state = SRState.get_state_by_name("Active")
        complete_service_state = SRState.get_state_by_name("Complete")

        # Find the currently active service_request and close it
        current_sr_number = 0
        for req in service_request.citizen.service_reqs:
            if req.sr_state_id == active_service_state.sr_state_id:
                req.sr_state_id = complete_service_state.sr_state_id
                req.finish_service(csr, clear_comments=False)
                current_sr_number = req.sr_number
                db.session.add(req)

        # Then set the requested service to active
        service_request.sr_state_id = active_service_state.sr_state_id

        period_state_being_served = PeriodState.get_state_by_name(
            "Being Served")

        new_period = Period(sr_id=service_request.sr_id,
                            csr_id=csr.csr_id,
                            reception_csr_ind=csr.receptionist_ind,
                            ps_id=period_state_being_served.ps_id,
                            time_start=datetime.utcnow())

        db.session.add(new_period)
        db.session.add(service_request)

        db.session.commit()

        #  To make service active, stop current service, restart previous service.
        SnowPlow.snowplow_event(service_request.citizen.citizen_id,
                                csr,
                                "stopservice",
                                current_sr_number=current_sr_number)
        SnowPlow.snowplow_event(service_request.citizen.citizen_id,
                                csr,
                                "restartservice",
                                current_sr_number=service_request.sr_number)

        citizen_result = self.citizen_schema.dump(service_request.citizen)
        socketio.emit('update_active_citizen',
                      citizen_result,
                      room=csr.office_id)
        result = self.service_request_schema.dump(service_request)

        return {
            'service_request': result,
            'errors': self.service_request_schema.validate(service_request)
        }, 200
    def post(self, id):
        csr = CSR.find_by_username(g.jwt_oidc_token_info['username'])

        citizen = Citizen.query\
        .options(joinedload(Citizen.service_reqs).joinedload(ServiceReq.periods).options(raiseload(Period.sr),joinedload(Period.csr).raiseload('*')),joinedload(Citizen.office),raiseload(Citizen.user)) \
        .filter_by(citizen_id=id, office_id=csr.office_id)
        
        citizen = citizen.first()

        my_print("==> POST /citizens/" + str(citizen.citizen_id) + '/place_on_hold/, Ticket: ' + citizen.ticket_number)
        active_service_request = citizen.get_active_service_request()

        if active_service_request is None:
            return {"message": "Citizen has no active service requests"}

        active_service_request.place_on_hold(csr)
        pending_service_state = SRState.get_state_by_name("Active")
        active_service_request.sr_state_id = pending_service_state.sr_state_id

        db.session.add(citizen)
        db.session.commit()

        socketio.emit('update_customer_list', {}, room=csr.office.office_name)
        result = self.citizen_schema.dump(citizen)
        socketio.emit('update_active_citizen', result, room=csr.office.office_name)

        return {'citizen': result,
                'errors': self.citizen_schema.validate(citizen)}, 200
    def post(self, id):
        lock = FileLock("lock/invite_citizen.lock")

        with lock:
            csr = CSR.find_by_username(g.oidc_token_info['username'])
            citizen = db.session.query(Citizen).with_lockmode('update').filter_by(citizen_id=id).first()
            active_service_state = SRState.get_state_by_name("Active")

            active_service_request = citizen.get_active_service_request()

            if active_service_request is None:
                return {"message": "Citizen has no active service requests"}, 400

            try:
                active_service_request.invite(csr, invite_type="specific", sr_count = len(citizen.service_reqs))
            except TypeError:
                return {"message": "Citizen  has already been invited"}, 400

            active_service_request.sr_state_id = active_service_state.sr_state_id

            db.session.add(citizen)
            db.session.commit()

            socketio.emit('update_customer_list', {}, room=csr.office_id)
            socketio.emit('citizen_invited', {}, room='sb-%s' % csr.office.office_number)
            result = self.citizen_schema.dump(citizen)
            socketio.emit('update_active_citizen', result.data, room=csr.office_id)

        return {'citizen': result.data,
                'errors': result.errors}, 200
    def post(self, id):
        csr = CSR.find_by_username(g.jwt_oidc_token_info['username'])
        citizen = Citizen.query.filter_by(citizen_id=id).first()
        my_print("==> POST /citizens/" + str(citizen.citizen_id) +
                 '/finish_service/, Ticket: ' + citizen.ticket_number)
        active_service_request = citizen.get_active_service_request()
        inaccurate = request.args.get('inaccurate')

        if active_service_request is None:
            return {"message": "Citizen has no active service requests"}

        #  If citizen here overnight, or inaccurate time flag set, update accurate time flag.
        if citizen.start_time.date() != datetime.now().date(
        ) or inaccurate == 'true':
            citizen.accurate_time_ind = 0

        SnowPlow.snowplow_event(
            citizen.citizen_id,
            csr,
            "finish",
            quantity=active_service_request.quantity,
            current_sr_number=active_service_request.sr_number)

        active_sr_id = active_service_request.sr_id
        active_service_request.finish_service(csr, self.clear_comments_flag)
        citizen_state = CitizenState.query.filter_by(
            cs_state_name="Received Services").first()
        citizen.cs_id = citizen_state.cs_id

        pending_service_state = SRState.get_state_by_name("Complete")
        active_service_request.sr_state_id = pending_service_state.sr_state_id

        # remove walkin unique id when service is finished
        citizen.walkin_unique_id = None

        db.session.add(citizen)
        db.session.commit()

        #  Loop to stop all services in the service stopped state (which are all except the active service)
        if len(citizen.service_reqs) != 1:
            for sr in citizen.service_reqs:
                if sr.sr_id != active_sr_id:
                    SnowPlow.snowplow_event(citizen.citizen_id,
                                            csr,
                                            "finishstopped",
                                            quantity=sr.quantity,
                                            current_sr_number=sr.sr_number)

        socketio.emit('citizen_invited', {},
                      room='sb-%s' % csr.office.office_number)
        result = self.citizen_schema.dump(citizen)
        socketio.emit('update_active_citizen', result, room=csr.office_id)

        return {
            'citizen': result,
            'errors': self.citizen_schema.validate(citizen)
        }, 200
    def post(self, id):
        csr = CSR.find_by_username(g.jwt_oidc_token_info['username'])
        lock = FileLock("lock/begin_citizen_{}.lock".format(csr.office_id))

        with lock:
            citizen = Citizen.query\
            .options(joinedload(Citizen.service_reqs).options(joinedload(ServiceReq.periods).options(joinedload(Period.ps).options(raiseload('*')),joinedload(Period.csr).options(raiseload('*')),raiseload('*')), joinedload(ServiceReq.service).options(joinedload(Service.parent).options(raiseload(Service.parent).options(raiseload('*'))),raiseload('*'))), joinedload(Citizen.office).options(joinedload(Office.sb),raiseload('*')), raiseload(Citizen.user)) \
            .filter_by(citizen_id=id)
            citizen = citizen.first()
            pending_service_state = SRState.get_state_by_name("Active")

            if citizen is None:
                print(
                    "==> POST /citizen/<id>/begin_service/ error. No citizen with id "
                    + str(id))
                return {"message": "No citizen found with id " + str(id)}
            else:
                my_print("==> POST /citizens/" + str(citizen.citizen_id) +
                         '/begin_service/, Ticket: ' + citizen.ticket_number)

            active_service_request = citizen.get_active_service_request()

            if active_service_request is None:
                return {"message": "Citizen has no active service requests"}

            try:
                #  Get Snowplow call.
                active_period = active_service_request.get_active_period()
                snowplow_event = "beginservice"
                if active_period.ps.ps_name == "On hold":
                    snowplow_event = "invitefromhold"
                if active_period.ps.ps_name == "Ticket Creation":
                    snowplow_event = "servecitizen"

                active_service_request.begin_service(csr, snowplow_event)
            except TypeError:
                return {"message": "Citizen  has already been invited"}, 400

            active_service_request.sr_state_id = pending_service_state.sr_state_id

            db.session.add(citizen)
            db.session.commit()

            if snowplow_event != "beginservice":
                socketio.emit('update_customer_list', {},
                              room=csr.office.office_name)

            result = self.citizen_schema.dump(citizen)
            socketio.emit('update_active_citizen',
                          result,
                          room=csr.office.office_name)

        return {
            'citizen': result,
            'errors': self.citizen_schema.validate(citizen)
        }, 200
Пример #6
0
    def post(self, id):

        csr = CSR.find_by_username(g.oidc_token_info['username'])
        citizen = Citizen.query.filter_by(citizen_id=id, office_id=csr.office_id).first()
        sr_state = SRState.get_state_by_name("Complete")

        #  Create parameters for and make snowplow call.  Default is no service request, CSR pressed cancel.
        quantity = 0
        sr_number = 1
        active_sr = 0
        status = "service-creation"
        if len(citizen.service_reqs) != 0:
            active_service_request = citizen.get_active_service_request()
            quantity = active_service_request.quantity
            sr_number = active_service_request.sr_number
            active_sr = active_service_request.sr_id
            active_period = active_service_request.get_active_period()
            if active_period.ps.ps_name == "Invited":
                status = "at-prep"
            else:
                status = "being-served"

        SnowPlow.snowplow_event(citizen.citizen_id, csr, ("left/" + status),
                                quantity = quantity, current_sr_number= sr_number)

        for service_request in citizen.service_reqs:

            service_request.sr_state_id = sr_state.sr_state_id

            for p in service_request.periods:
                if p.time_end is None:
                    p.time_end = datetime.now()

            #  Make snowplow calls to finish any stopped services
            if service_request.sr_id != active_sr:
                SnowPlow.snowplow_event(citizen.citizen_id, csr, "finishstopped",
                                        quantity = service_request.quantity,
                                        current_sr_number= service_request.sr_number)

        citizen.cs = CitizenState.query.filter_by(cs_state_name='Left before receiving services').first()
        if self.clear_comments_flag:
            citizen.citizen_comments = None

        if citizen.start_time.date() != datetime.now().date():
            citizen.accurate_time_ind = 0

        db.session.add(citizen)
        db.session.commit()

        socketio.emit('citizen_invited', {}, room='sb-%s' % csr.office.office_number)
        result = self.citizen_schema.dump(citizen)
        socketio.emit('update_active_citizen', result.data, room=csr.office_id)

        return {'citizen': result.data,
                'errors': result.errors}, 200
    def post(self, id):
        csr = CSR.find_by_username(g.oidc_token_info['username'])
        citizen = Citizen.query.filter_by(citizen_id=id,
                                          office_id=csr.office_id).first()
        active_service_request = citizen.get_active_service_request()
        inaccurate = request.args.get('inaccurate')

        if active_service_request is None:
            return {"message": "Citizen has no active service requests"}

        SnowPlow.snowplow_event(
            citizen.citizen_id,
            csr,
            "finish",
            quantity=active_service_request.quantity,
            current_sr_number=active_service_request.sr_number)

        active_sr_id = active_service_request.sr_id
        active_service_request.finish_service(csr, self.clear_comments_flag)
        citizen_state = CitizenState.query.filter_by(
            cs_state_name="Received Services").first()
        citizen.cs_id = citizen_state.cs_id

        pending_service_state = SRState.get_state_by_name("Complete")
        active_service_request.sr_state_id = pending_service_state.sr_state_id

        if citizen.start_time.date() != datetime.now().date(
        ) or inaccurate == 'true':
            citizen.accurate_time_ind = 0

        db.session.add(citizen)
        db.session.commit()

        #  Loop to stop all services in the service stopped state (which are all except the active service)
        if len(citizen.service_reqs) != 1:
            for sr in citizen.service_reqs:
                if sr.sr_id != active_sr_id:
                    SnowPlow.snowplow_event(citizen.citizen_id,
                                            csr,
                                            "finishstopped",
                                            quantity=sr.quantity,
                                            current_sr_number=sr.sr_number)

        socketio.emit('citizen_invited', {},
                      room='sb-%s' % csr.office.office_number)
        result = self.citizen_schema.dump(citizen)
        socketio.emit('update_active_citizen', result.data, room=csr.office_id)

        return {'citizen': result.data, 'errors': result.errors}, 200
Пример #8
0
    def get(self):
        try:
            csr = CSR.find_by_username(g.oidc_token_info['username'])

            if not csr:
                return {'Message': 'User Not Found'}, 404

            db.session.add(csr)
            active_sr_state = SRState.get_state_by_name("Active")
            today = datetime.now()

            active_citizens = Citizen.query \
                .join(Citizen.service_reqs) \
                .filter_by(sr_state_id=active_sr_state.sr_state_id) \
                .join(ServiceReq.periods) \
                .filter_by(csr_id=csr.csr_id) \
                .filter(Period.time_end.is_(None))

            individual_exams = Exam.query \
                .filter_by(office_id=csr.office_id) \
                .filter(Exam.exam_returned_date.is_(None),
                        Exam.expiry_date <= today,
                        Exam.deleted_date.is_(None)) \
                .join(ExamType, Exam.exam_type_id == ExamType.exam_type_id) \
                .filter(ExamType.group_exam_ind == 0).count()

            group_exams = Exam.query \
                .filter_by(office_id=csr.office_id) \
                .filter(Exam.deleted_date.is_(None)) \
                .join(ExamType, Exam.exam_type_id == ExamType.exam_type_id) \
                .filter(ExamType.group_exam_ind == 1) \
                .join(Booking, Exam.booking_id == Booking.booking_id) \
                .filter(Booking.invigilator_id.is_(None))\
                .filter(Booking.sbc_staff_invigilated == 0).count()

            result = self.csr_schema.dump(csr)
            active_citizens = self.citizen_schema.dump(active_citizens)

            return {
                'csr': result.data,
                'individual_exams': individual_exams,
                'group_exams': group_exams,
                'active_citizens': active_citizens.data,
                'errors': result.errors
            }

        except exc.SQLAlchemyError as e:
            print(e)
            return {'message': 'API is down'}, 500
Пример #9
0
    def post(self, id):
        csr = CSR.find_by_username(g.jwt_oidc_token_info['username'])
        lock = FileLock("lock/invite_citizen_{}.lock".format(csr.office_id))

        with lock:
            citizen = db.session.query(Citizen).filter_by(
                citizen_id=id).first()
            my_print("==> POST /citizens/" + str(citizen.citizen_id) +
                     '/invite/, Ticket: ' + citizen.ticket_number)
            active_service_state = SRState.get_state_by_name("Active")

            active_service_request = citizen.get_active_service_request()

            if active_service_request is None:
                return {
                    "message": "Citizen has no active service requests"
                }, 400

            try:
                active_service_request.invite(csr,
                                              invite_type="specific",
                                              sr_count=len(
                                                  citizen.service_reqs))
            except TypeError:
                return {"message": "Citizen  has already been invited"}, 400

            active_service_request.sr_state_id = active_service_state.sr_state_id

            db.session.add(citizen)
            db.session.commit()

            socketio.emit('update_customer_list', {},
                          room=csr.office.office_name)
            socketio.emit('citizen_invited', {},
                          room='sb-%s' % csr.office.office_number)
            result = self.citizen_schema.dump(citizen)
            socketio.emit('update_active_citizen',
                          result,
                          room=csr.office.office_name)

        return {
            'citizen': result,
            'errors': self.citizen_schema.validate(citizen)
        }, 200
    def post(self, id):
        csr = CSR.find_by_username(g.oidc_token_info['username'])
        lock = FileLock("lock/begin_citizen_{}.lock".format(csr.office_id))

        with lock:
            citizen = Citizen.query.filter_by(citizen_id=id,
                                              office_id=csr.office_id).first()
            pending_service_state = SRState.get_state_by_name("Active")

            my_print("==> POST /citizens/" + str(citizen.citizen_id) +
                     '/begin_service, Ticket: ' + citizen.ticket_number)

            active_service_request = citizen.get_active_service_request()

            if active_service_request is None:
                return {"message": "Citizen has no active service requests"}

            try:
                #  Get Snowplow call.
                active_period = active_service_request.get_active_period()
                snowplow_event = "beginservice"
                if active_period.ps.ps_name == "On hold":
                    snowplow_event = "invitefromhold"
                if active_period.ps.ps_name == "Ticket Creation":
                    snowplow_event = "servecitizen"

                active_service_request.begin_service(csr, snowplow_event)
            except TypeError:
                return {"message": "Citizen  has already been invited"}, 400

            active_service_request.sr_state_id = pending_service_state.sr_state_id

            db.session.add(citizen)
            db.session.commit()

            if snowplow_event != "beginservice":
                socketio.emit('update_customer_list', {}, room=csr.office_id)

            result = self.citizen_schema.dump(citizen)
            socketio.emit('update_active_citizen',
                          result.data,
                          room=csr.office_id)

        return {'citizen': result.data, 'errors': result.errors}, 200
Пример #11
0
    def post(self, id):
        csr = CSR.find_by_username(g.jwt_oidc_token_info['username'])
        citizen = Citizen.query.filter_by(citizen_id=id).first()
        active_service_request = citizen.get_active_service_request()

        my_print("==> POST /citizens/" + str(citizen.citizen_id) +
                 '/add_to_queue, Ticket: ' + citizen.ticket_number)

        if active_service_request is None:
            return {"message": "Citizen has no active service requests"}

        #  Figure out what Snowplow call to make.  Default is addtoqueue
        snowplow_call = "addtoqueue"
        if len(citizen.service_reqs) != 1 or len(
                active_service_request.periods) != 1:
            active_period = active_service_request.get_active_period()
            if active_period.ps.ps_name == "Invited":
                snowplow_call = "queuefromprep"
            elif active_period.ps.ps_name == "Being Served":
                snowplow_call = "returntoqueue"
            else:
                #  TODO:  Put in a Feedback Slack/Service now call here.
                return {"message": "Invalid citizen/period state. "}

        active_service_request.add_to_queue(csr, snowplow_call)

        pending_service_state = SRState.get_state_by_name("Pending")
        active_service_request.sr_state_id = pending_service_state.sr_state_id

        db.session.add(citizen)
        db.session.commit()

        socketio.emit('update_customer_list', {}, room=csr.office_id)
        socketio.emit('citizen_invited', {},
                      room='sb-%s' % csr.office.office_number)
        result = self.citizen_schema.dump(citizen)
        socketio.emit('update_active_citizen', result, room=csr.office_id)

        return {
            'citizen': result,
            'errors': self.citizen_schema.validate(citizen)
        }, 200
Пример #12
0
    def post(self, id):
        csr = CSR.find_by_username(g.oidc_token_info['username'])

        citizen = Citizen.query.filter_by(citizen_id=id,
                                          office_id=csr.office_id).first()
        active_service_request = citizen.get_active_service_request()

        if active_service_request is None:
            return {"message": "Citizen has no active service requests"}

        active_service_request.place_on_hold(csr)
        pending_service_state = SRState.get_state_by_name("Active")
        active_service_request.sr_state_id = pending_service_state.sr_state_id

        db.session.add(citizen)
        db.session.commit()

        socketio.emit('update_customer_list', {}, room=csr.office_id)
        result = self.citizen_schema.dump(citizen)
        socketio.emit('update_active_citizen', result.data, room=csr.office_id)

        return {'citizen': result.data, 'errors': result.errors}, 200
    def post(self):
        json_data = request.get_json()

        if not json_data:
            return {"message": "No input data received for creating service request"}, 400

        csr = CSR.find_by_username(g.oidc_token_info['username'])

        try:
            service_request = self.service_request_schema.load(json_data['service_request']).data

        except ValidationError as err:
            return {"message": err.messages}, 422
        except KeyError as err:
            print (err)
            return {"message": str(err)}

        active_sr_state = SRState.get_state_by_name("Active")
        complete_sr_state = SRState.get_state_by_name("Complete")
        citizen_state = CitizenState.query.filter_by(cs_state_name="Active").first()
        citizen = Citizen.query.get(service_request.citizen_id)
        service = Service.query.get(service_request.service_id)

        if citizen is None:
            return {"message": "No matching citizen found for citizen_id"}, 400

        if service is None:
            return {"message": "No matching service found for service_id"}, 400

        # Find the currently active service_request and close it (if it exists)
        current_sr_number = 0
        for req in citizen.service_reqs:
            if req.sr_state_id == active_sr_state.sr_state_id:
                req.sr_state_id = complete_sr_state.sr_state_id
                req.finish_service(csr, clear_comments=False)
                current_sr_number = req.sr_number
                db.session.add(req)

        service_request.sr_state_id = active_sr_state.sr_state_id

        # Only add ticket creation period and ticket number if it's their first service_request
        if len(citizen.service_reqs) == 0:
            period_state_ticket_creation = PeriodState.get_state_by_name("Ticket Creation")

            ticket_create_period = Period(
                csr_id=csr.csr_id,
                reception_csr_ind=csr.receptionist_ind,
                ps_id=period_state_ticket_creation.ps_id,
                time_start=citizen.get_service_start_time(),
                time_end=datetime.now()
            )
            service_request.periods.append(ticket_create_period)

            # Move start_time back 6 hours to account for DST and UTC offsets
            # It's only important that the number carries over _around_ midnight
            offset_start_time = citizen.start_time - timedelta(hours=6)

            service_count = ServiceReq.query \
                    .join(ServiceReq.citizen, aliased=True) \
                    .filter(Citizen.start_time >= offset_start_time.strftime("%Y-%m-%d")) \
                    .filter_by(office_id=csr.office_id) \
                    .join(ServiceReq.service, aliased=True) \
                    .filter_by(prefix=service.prefix) \
                    .count()

            citizen.ticket_number = service.prefix + str(service_count)
        else:
            period_state_being_served = PeriodState.get_state_by_name("Being Served")

            ticket_create_period = Period(
                csr_id=csr.csr_id,
                reception_csr_ind=csr.receptionist_ind,
                ps_id=period_state_being_served.ps_id,
                time_start=datetime.now()
            )
            service_request.periods.append(ticket_create_period)

        citizen.cs_id = citizen_state.cs_id

        #  If first service, just choose it.  If additional service, more work needed.
        if len(citizen.service_reqs) == 0:
            snowplow_event = "chooseservice"
        else:
            snowplow_event = "additionalservice"

        service_request.sr_number = len(citizen.service_reqs) + 1

        db.session.add(service_request)
        db.session.add(citizen)
        db.session.commit()

        #  If first service, just need a choose service call.
        if snowplow_event == "chooseservice":
            SnowPlow.choose_service(service_request, csr, "chooseservice")

        #  If not first service, need stop service, choose service, and additional service calls.
        else:
            SnowPlow.snowplow_event(citizen.citizen_id, csr, "stopservice", current_sr_number=current_sr_number)
            SnowPlow.choose_service(service_request, csr, "chooseservice")
            SnowPlow.snowplow_event(citizen.citizen_id, csr, "additionalservice", current_sr_number=service_request.sr_number)

        citizen_result = self.citizen_schema.dump(citizen)
        socketio.emit('update_active_citizen', citizen_result.data, room=csr.office_id)
        result = self.service_request_schema.dump(service_request)

        return {'service_request': result.data,
                'errors': result.errors}, 201
Пример #14
0
    def post(self):

        csr = CSR.find_by_username(g.oidc_token_info['username'])
        lock = FileLock("lock/invite_citizen_{}.lock".format(csr.office_id))

        with lock:

            active_citizen_state = CitizenState.query.filter_by(
                cs_state_name='Active').first()
            waiting_period_state = PeriodState.get_state_by_name("Waiting")
            citizen = None
            json_data = request.get_json()

            if json_data and 'counter_id' in json_data:
                counter_id = int(json_data.get('counter_id'))
            else:
                counter_id = int(csr.counter_id)

            citizen = Citizen.query \
                .filter_by(counter_id=counter_id, cs_id=active_citizen_state.cs_id, office_id=csr.office_id) \
                .join(Citizen.service_reqs) \
                .join(ServiceReq.periods) \
                .filter_by(ps_id=waiting_period_state.ps_id) \
                .filter(Period.time_end.is_(None)) \
                .order_by(Citizen.priority, Citizen.citizen_id) \
                .first()

            # If no matching citizen with the same counter type, get next one
            if citizen is None:
                citizen = Citizen.query \
                    .filter_by(cs_id=active_citizen_state.cs_id, office_id=csr.office_id) \
                    .join(Citizen.service_reqs) \
                    .join(ServiceReq.periods) \
                    .filter_by(ps_id=waiting_period_state.ps_id) \
                    .filter(Period.time_end.is_(None)) \
                    .order_by(Citizen.priority, Citizen.citizen_id) \
                    .first()

            if citizen is None:
                return {"message": "There is no citizen to invite"}, 400

            my_print("==> POST /citizens/invite/ Citizen: " +
                     str(citizen.citizen_id) + ', Ticket: ' +
                     citizen.ticket_number)

            db.session.refresh(citizen)
            active_service_request = citizen.get_active_service_request()

            try:
                active_service_request.invite(csr,
                                              invite_type="generic",
                                              sr_count=len(
                                                  citizen.service_reqs))
            except TypeError:
                return {
                    "message": "Error inviting citizen. Please try again."
                }, 400

            active_service_state = SRState.get_state_by_name("Active")
            active_service_request.sr_state_id = active_service_state.sr_state_id

            db.session.add(citizen)
            db.session.commit()

            socketio.emit('update_customer_list', {}, room=csr.office_id)
            socketio.emit('citizen_invited', {},
                          room='sb-%s' % csr.office.office_number)
            result = self.citizen_schema.dump(citizen)
            socketio.emit('update_active_citizen',
                          result.data,
                          room=csr.office_id)

        return {'citizen': result.data, 'errors': result.errors}, 200
Пример #15
0
    def get(self):
        try:
            csr = CSR.find_by_username(g.oidc_token_info['username'])

            if not csr:
                return {'Message': 'User Not Found'}, 404

            db.session.add(csr)
            active_sr_state = SRState.get_state_by_name("Active")
            today = datetime.now()
            start_date = self.timezone.localize(today)

            active_citizens = Citizen.query \
                .join(Citizen.service_reqs) \
                .filter_by(sr_state_id=active_sr_state.sr_state_id) \
                .join(ServiceReq.periods) \
                .filter_by(csr_id=csr.csr_id) \
                .filter(Period.time_end.is_(None))

            individual_exams = Exam.query \
                .filter_by(office_id=csr.office_id) \
                .filter(Exam.exam_returned_date.is_(None),
                        Exam.expiry_date <= today,
                        Exam.deleted_date.is_(None)) \
                .join(ExamType, Exam.exam_type_id == ExamType.exam_type_id) \
                .filter(ExamType.group_exam_ind == 0).count()

            individual_exams_past_schedule = Exam.query \
                .join(Booking, Exam.booking_id == Booking.booking_id)\
                .filter(Booking.start_time < start_date)\
                .filter_by(office_id=csr.office_id) \
                .join(ExamType, Exam.exam_type_id == ExamType.exam_type_id) \
                .filter(ExamType.group_exam_ind == 0).count()

            group_exams = Exam.query \
                .filter_by(office_id=csr.office_id) \
                .filter(Exam.deleted_date.is_(None)) \
                .join(ExamType, Exam.exam_type_id == ExamType.exam_type_id) \
                .filter(ExamType.group_exam_ind == 1) \
                .join(Booking, Exam.booking_id == Booking.booking_id) \
                .filter(Booking.sbc_staff_invigilated == 0).count()
                #.filter(Booking.invigilator_id.is_(None))\ TODO: Update this plz

            group_attention = Exam.query \
                .filter_by(office_id=csr.office_id)\
                .filter(Exam.deleted_date.is_(None))\
                .filter(Exam.exam_returned_date.is_(None))\
                .join(ExamType, Exam.exam_type_id == ExamType.exam_type_id)\
                .filter(ExamType.group_exam_ind == 1)\
                .join(Booking, Exam.booking_id == Booking.booking_id)\
                .filter(Booking.start_time < start_date).count()

            if group_attention > 0 and individual_exams > 0:
                group_attention += individual_exams

            result = self.csr_schema.dump(csr)
            active_citizens = self.citizen_schema.dump(active_citizens)

            return {'csr': result.data,
                    'individual_exams': individual_exams,
                    'individual_exams_past_schedule': individual_exams_past_schedule,
                    'group_exams': group_exams,
                    'group_individual_attention': group_attention,
                    'active_citizens': active_citizens.data,
                    'back_office_display': self.back_office_display,
                    'recurring_feature_flag': self.recurring_feature_flag,
                    'errors': result.errors}

        except exc.SQLAlchemyError as e:
            print(e)
            return {'message': 'API is down'}, 500
Пример #16
0
    def get(self):
        try:
            # print('====> ATTENTION NEEDED')
            csr = CSR.find_by_username(g.jwt_oidc_token_info['username'])

            if not csr:
                return {'Message': 'User Not Found'}, 404

            db.session.add(csr)
            active_sr_state = SRState.get_state_by_name("Active")
            today = datetime.now()
            start_date = self.timezone.localize(today).date()
            # print('====> ATTENTION NEEDED==>start_Date',start_date)

            active_citizens = Citizen.query \
                .join(Citizen.service_reqs) \
                .filter_by(sr_state_id=active_sr_state.sr_state_id) \
                .join(ServiceReq.periods) \
                .filter_by(csr_id=csr.csr_id) \
                .filter(Period.time_end.is_(None))

            #   Get a list of all current exams for the office.
            office_exams = Exam.query \
                .filter(Exam.office_id == csr.office_id, \
                        Exam.exam_returned_date.is_(None), \
                        Exam.deleted_date.is_(None)) \
                .join(ExamType, Exam.exam_type_id == ExamType.exam_type_id) \
                .outerjoin(Booking, Exam.booking_id == Booking.booking_id) \
                .outerjoin(Booking.booking_invigilators, Booking.booking_id == Booking.booking_invigilators.c.invigilator_id) \
                .all()

            #   Default condition ... attention is not needed for any exam.
            attention_needed = False

            #   Check for attention needed, individual exam.
            individual = []
            for exam in office_exams:

                if exam.exam_type.group_exam_ind == 0:
                    # print('====> INDIVIDUAL EXAM CHECKS',exam.exam_name)
                    if exam.booking is not None:
                        # print('====> EXAM BOOKING IS NOT NONE')
                        # print('====> EXAM.BOOKING==>start_Date', start_date)
                        # print('====> EXAM.BOOKING==>exam.booking.start_time', exam.booking.start_time)
                        attention_needed = attention_needed or exam.booking.start_time.date(
                        ) < start_date
                        # print('====> ATTENTION NEEDED',attention_needed)
                    if exam.expiry_date is not None:
                        # print('====> EXPIRY IS NOT NONE')
                        # print('====> EXAM.BOOKING==>start_Date', start_date)
                        # print('====> EXAM.BOOKING==>exam.expiry_date', exam.expiry_date)
                        attention_needed = attention_needed or exam.expiry_date.date(
                        ) < start_date
                        # print('====> ATTENTION NEEDED', attention_needed)
                    if exam.is_pesticide and exam.exam_received_date is None:
                        # print('====> PESTICIDE AND NOT RECEIVED')
                        attention_needed = True
                        # print('====> ATTENTION NEEDED', attention_needed)
                    if exam.exam_returned_date is not None:
                        # print('====> exam.exam_returned_date')
                        attention_needed = False
                        # print('====> ATTENTION NEEDED', attention_needed)
                    if attention_needed:
                        individual.append(exam)

            #   Only do further checks if attention not already needed.
            group = []
            if not attention_needed:
                for exam in office_exams:
                    if exam.exam_type.group_exam_ind == 1:
                        # print('====> GROUP EXAM CHECKS',exam.exam_name)
                        if exam.booking is not None:
                            # print('====> ATTENTION NEEDED==>start_Date', start_date)
                            # print('====> EXAM.BOOKING==>exam.booking.start_time', exam.booking.start_time)
                            attention_needed = attention_needed or exam.booking.start_time.date(
                            ) < start_date
                            # print('====> ATTENTION NEEDED', attention_needed)
                        if exam.expiry_date is not None:
                            # print('====> EXPIRY IS NOT NONE')
                            # print('====> EXAM.BOOKING==>start_Date', start_date)
                            # print('====> EXAM.BOOKING==>exam.expiry_date', exam.expiry_date)
                            attention_needed = attention_needed or exam.expiry_date.date(
                            ) < start_date
                            # print('====> ATTENTION NEEDED', attention_needed)
                        if exam.booking is not None and exam.number_of_students is not None:
                            # print('====> exam.number_of_students IS NOT NONE')
                            # print('====> EXAM.BOOKING==>exam.number_of_students', exam.number_of_students)
                            # print('====> EXAM.BOOKING==>len(exam.booking.invigilators', len(exam.booking.invigilators))
                            attention_needed = attention_needed or (
                                len(exam.booking.invigilators) < 1
                                and exam.number_of_students < 25)
                            attention_needed = attention_needed or (
                                len(exam.booking.invigilators) < 2
                                and exam.number_of_students > 24)
                            # print('====> ATTENTION NEEDED', attention_needed)
                        if exam.is_pesticide and exam.exam_received_date is None:
                            # print('====> PESTICIDE AND NOT RECEIVED')
                            attention_needed = True
                            # print('====> ATTENTION NEEDED', attention_needed)
                        if exam.exam_returned_date is not None:
                            attention_needed = False
                            # print('====> ATTENTION NEEDED', attention_needed)
                        if attention_needed:
                            group.append(exam)

            result = self.csr_schema.dump(csr)
            active_citizens = self.citizen_schema.dump(active_citizens)

            return {
                'csr': result,
                'attention_needed': attention_needed,
                'active_citizens': active_citizens,
                'back_office_display': self.back_office_display,
                'recurring_feature_flag': self.recurring_feature_flag,
                'errors': self.csr_schema.validate(csr)
            }

        except exc.SQLAlchemyError as e:
            print(e)
            return {'message': 'API is down'}, 500
Пример #17
0
    def post(self, id):
        csr = CSR.find_by_username(g.jwt_oidc_token_info['username'])
        citizen = Citizen.query.filter_by(citizen_id=id).first()
        active_service_request = citizen.get_active_service_request()

        my_print("==> POST /citizens/" + str(citizen.citizen_id) +
                 '/add_to_queue, Ticket: ' + citizen.ticket_number)

        if active_service_request is None:
            return {"message": "Citizen has no active service requests"}

        #  Figure out what Snowplow call to make.  Default is addtoqueue
        snowplow_call = "addtoqueue"
        if len(citizen.service_reqs) != 1 or len(
                active_service_request.periods) != 1:
            active_period = active_service_request.get_active_period()
            if active_period.ps.ps_name == "Invited":
                snowplow_call = "queuefromprep"
            elif active_period.ps.ps_name == "Being Served":
                snowplow_call = "returntoqueue"
            else:
                #  TODO:  Put in a Feedback Slack/Service now call here.
                return {"message": "Invalid citizen/period state. "}

        active_service_request.add_to_queue(csr, snowplow_call)

        pending_service_state = SRState.get_state_by_name("Pending")
        active_service_request.sr_state_id = pending_service_state.sr_state_id
        # send walkin spot confirmation
        try:
            if (citizen.notification_phone or citizen.notification_email
                ) and not (citizen.reminder_flag) and not (
                    citizen.notification_sent_time):
                update_table = False
                try:
                    appointment_portal_url = application.config.get(
                        'APPOINTMENT_PORTAL_URL', '')
                    # Dynamic URL creations
                    url = ''
                    if appointment_portal_url and citizen.walkin_unique_id:
                        if appointment_portal_url.endswith('/'):
                            appointment_portal_url = appointment_portal_url[:
                                                                            -1]
                        url = "{}/{}/{}".format(appointment_portal_url,
                                                'walk-in-Q',
                                                citizen.walkin_unique_id)
                    # email
                    email_sent = False
                    if citizen.notification_email:
                        officeObj = Office.find_by_id(citizen.office_id)
                        print(
                            'Sending email for walk in spot confirmations to')
                        email_sent = get_walkin_spot_confirmation_email_contents(
                            citizen, url, officeObj)
                    # SMS
                    sms_sent = False
                    if citizen.notification_phone:
                        sms_sent = send_walkin_spot_confirmation_sms(
                            citizen, url,
                            request.headers['Authorization'].replace(
                                'Bearer ', ''))
                    if email_sent:
                        status = send_email(
                            request.headers['Authorization'].replace(
                                'Bearer ', ''), *email_sent)
                        update_table = True
                    if sms_sent:
                        update_table = True
                except Exception as exc:
                    pprint(f'Error on token generation - {exc}')
                    update_table = False
                if update_table:
                    citizen.reminder_flag = 0
                    citizen.notification_sent_time = datetime.utcnow()
        except Exception as err:
            logging.error('{}'.format(str(err)))
            pprint(err)

        db.session.add(citizen)
        db.session.commit()

        socketio.emit('update_customer_list', {}, room=csr.office.office_name)
        socketio.emit('citizen_invited', {},
                      room='sb-%s' % csr.office.office_number)
        result = self.citizen_schema.dump(citizen)
        socketio.emit('update_active_citizen',
                      result,
                      room=csr.office.office_name)

        return {
            'citizen': result,
            'errors': self.citizen_schema.validate(citizen)
        }, 200
Пример #18
0
    def post(self, id):

        my_print("++> POST API call time before csr = statement: " + str(datetime.now()))
        csr = CSR.find_by_username(g.oidc_token_info['username'])
        my_print("    ++> Time before citizen = statement: " + str(datetime.now()))
        citizen = Citizen.query.filter_by(citizen_id=id).first()

        my_print("    ++> Time before citizen ID statement: " + str(datetime.now()))
        citizen_id_string = self.get_citizen_string(citizen)
        citizen_ticket = self.get_ticket_string(citizen)

        my_print("    ++> Time before citizen ticket statement: " + str(datetime.now()))
        my_print("    ++> POST /citizens/" + citizen_id_string + '/citizen_left/, Ticket: ' + citizen_ticket)
        my_print("    ++> Time before sr_state statement: " + str(datetime.now()))
        sr_state = SRState.get_state_by_name("Complete")

        #  Create parameters for and make snowplow call.  Default is no service request, CSR pressed cancel.
        quantity = 0
        sr_number = 1
        active_sr = 0
        status = "service-creation"
        if len(citizen.service_reqs) != 0:
            active_service_request = citizen.get_active_service_request()
            quantity = active_service_request.quantity
            sr_number = active_service_request.sr_number
            active_sr = active_service_request.sr_id
            active_period = active_service_request.get_active_period()
            if active_period.ps.ps_name == "Invited":
                status = "at-prep"
            else:
                status = "being-served"

        my_print("    ++> Time before Snowplow call: " + str(datetime.now()))
        SnowPlow.snowplow_event(citizen.citizen_id, csr, ("left/" + status),
                                quantity = quantity, current_sr_number= sr_number)

        my_print("    ++> Time before closing non-active service requests: " + str(datetime.now()))
        for service_request in citizen.service_reqs:

            service_request.sr_state_id = sr_state.sr_state_id

            for p in service_request.periods:
                if p.time_end is None:
                    p.time_end = datetime.now()

            #  Make snowplow calls to finish any stopped services
            if service_request.sr_id != active_sr:
                SnowPlow.snowplow_event(citizen.citizen_id, csr, "finishstopped",
                                        quantity = service_request.quantity,
                                        current_sr_number= service_request.sr_number)

        my_print("    ++> Time before updating citizen state: " + str(datetime.now()))
        citizen.cs = CitizenState.query.filter_by(cs_state_name='Left before receiving services').first()
        if self.clear_comments_flag:
            citizen.citizen_comments = None

        if citizen.start_time.date() != datetime.now().date():
            citizen.accurate_time_ind = 0

        my_print("    ++> Time before updating citizen database: " + str(datetime.now()))
        db.session.add(citizen)
        my_print("    ++> Time before database commit: " + str(datetime.now()))
        db.session.commit()

        my_print("    ++> Time before socket io invited call: " + str(datetime.now()))
        socketio.emit('citizen_invited', {}, room='sb-%s' % csr.office.office_number)
        my_print("    ++> Time before creating the result: " + str(datetime.now()))
        result = self.citizen_schema.dump(citizen)
        my_print("    ++> Time before socket io update call: " + str(datetime.now()))
        socketio.emit('update_active_citizen', result.data, room=csr.office_id)

        my_print("    ++> Time before return result call: " + str(datetime.now()))
        return {'citizen': result.data,
                'errors': result.errors}, 200
Пример #19
0
    def post(self):

        lock = FileLock("lock/invite_citizen.lock")

        with lock:
            csr = CSR.find_by_username(g.oidc_token_info['username'])

            active_citizen_state = CitizenState.query.filter_by(cs_state_name='Active').first()
            waiting_period_state = PeriodState.get_state_by_name("Waiting")
            citizen = None

            try:
                qt_xn_csr_ind = request.get_json().get('qt_xn_csr_ind')
            except AttributeError:
                qt_xn_csr_ind = csr.qt_xn_csr_ind

            if qt_xn_csr_ind:
                citizen = Citizen.query \
                    .filter_by(qt_xn_citizen_ind=1, cs_id=active_citizen_state.cs_id, office_id=csr.office_id) \
                    .join(Citizen.service_reqs) \
                    .join(ServiceReq.periods) \
                    .filter_by(ps_id=waiting_period_state.ps_id) \
                    .filter(Period.time_end.is_(None)) \
                    .order_by(Citizen.priority, Citizen.citizen_id) \
                    .first()
            else:
                citizen = Citizen.query \
                    .filter_by(qt_xn_citizen_ind=0, cs_id=active_citizen_state.cs_id, office_id=csr.office_id) \
                    .join(Citizen.service_reqs) \
                    .join(ServiceReq.periods) \
                    .filter_by(ps_id=waiting_period_state.ps_id) \
                    .filter(Period.time_end.is_(None)) \
                    .order_by(Citizen.priority, Citizen.citizen_id) \
                    .first()

            # Either no quick txn citizens for the quick txn csr, or vice versa
            if citizen is None:
                citizen = Citizen.query \
                    .filter_by(cs_id=active_citizen_state.cs_id, office_id=csr.office_id) \
                    .join(Citizen.service_reqs) \
                    .join(ServiceReq.periods) \
                    .filter_by(ps_id=waiting_period_state.ps_id) \
                    .filter(Period.time_end.is_(None)) \
                    .order_by(Citizen.priority, Citizen.citizen_id) \
                    .first()

            if citizen is None:
                return {"message": "There is no citizen to invite"}, 400

            db.session.refresh(citizen)
            active_service_request = citizen.get_active_service_request()

            try:
                active_service_request.invite(csr, invite_type="generic", sr_count = len(citizen.service_reqs))
            except TypeError:
                return {"message": "Error inviting citizen. Please try again."}, 400

            active_service_state = SRState.get_state_by_name("Active")
            active_service_request.sr_state_id = active_service_state.sr_state_id

            db.session.add(citizen)
            db.session.commit()

            socketio.emit('update_customer_list', {}, room=csr.office_id)
            socketio.emit('citizen_invited', {}, room='sb-%s' % csr.office.office_number)
            result = self.citizen_schema.dump(citizen)
            socketio.emit('update_active_citizen', result.data, room=csr.office_id)

        return {'citizen': result.data,
                'errors': result.errors}, 200
    def post(self):
        try:
            json_data = request.get_json()
        except Exception as error:
            return {"message": str(error)}, 401

        csr = CSR.find_by_username(g.jwt_oidc_token_info['username'])
        service_request, message, code = get_service_request(
            self, json_data, csr)
        if (service_request is None):
            return {"message": message}, code

        active_sr_state = SRState.get_state_by_name("Active")
        complete_sr_state = SRState.get_state_by_name("Complete")
        citizen = None
        try:

            citizen = Citizen.query \
                .options(joinedload(Citizen.service_reqs).joinedload(ServiceReq.periods).options(raiseload(Period.sr),joinedload(Period.csr).raiseload('*')),joinedload(Citizen.office),raiseload(Citizen.user)) \
                .filter_by(citizen_id=service_request.citizen_id)

            citizen = citizen.first()

        except:
            print("==> An exception getting citizen info")
            print("    --> CSR:       " + csr.username)
            print("    --> json_data: " +
                  json.dumps(json_data['service_request']))

        if citizen is None:
            return {"message": "No matching citizen found for citizen_id"}, 400

        service, message, code = get_service(service_request, json_data, csr)
        if (service is None):
            return {"message": message}, code

        # Find the currently active service_request and close it (if it exists)
        current_sr_number = 0
        for req in citizen.service_reqs:
            if req.sr_state_id == active_sr_state.sr_state_id:
                req.sr_state_id = complete_sr_state.sr_state_id
                req.finish_service(csr, clear_comments=False)
                current_sr_number = req.sr_number
                db.session.add(req)

        service_request.sr_state_id = active_sr_state.sr_state_id

        # Only add ticket creation period and ticket number if it's their first service_request
        if len(citizen.service_reqs) == 0:
            period_state_ticket_creation = PeriodState.get_state_by_name(
                "Ticket Creation")

            ticket_create_period = Period(
                csr_id=csr.csr_id,
                reception_csr_ind=csr.receptionist_ind,
                ps_id=period_state_ticket_creation.ps_id,
                time_start=citizen.get_service_start_time(),
                time_end=datetime.now())
            service_request.periods.append(ticket_create_period)

            # Move start_time back 11 hours to account for DST and UTC offsets
            # tickets up till 10pm will not affect ticket numbering on next day
            offset_start_time = citizen.start_time - timedelta(hours=11)

            service_count = ServiceReq.query \
                    .join(ServiceReq.citizen, aliased=True) \
                    .filter(Citizen.start_time >= offset_start_time.strftime("%Y-%m-%d")) \
                    .filter_by(office_id=csr.office_id) \
                    .join(ServiceReq.service, aliased=True) \
                    .filter_by(prefix=service.prefix) \
                    .count()

            citizen.ticket_number = service.prefix + str(service_count)
        else:
            period_state_being_served = PeriodState.get_state_by_name(
                "Being Served")

            ticket_create_period = Period(
                csr_id=csr.csr_id,
                reception_csr_ind=csr.receptionist_ind,
                ps_id=period_state_being_served.ps_id,
                time_start=datetime.now())
            service_request.periods.append(ticket_create_period)

        citizen.cs_id = active_id

        #  If first service, just choose it.  If additional service, more work needed.
        if len(citizen.service_reqs) == 0:
            snowplow_event = "chooseservice"
        else:
            snowplow_event = "additionalservice"

        service_request.sr_number = len(citizen.service_reqs) + 1

        db.session.add(service_request)
        db.session.add(citizen)
        db.session.commit()

        #  If first service, just need a choose service call.
        if snowplow_event == "chooseservice":
            SnowPlow.choose_service(service_request, csr, "chooseservice")

        #  If not first service, need stop service, choose service, and additional service calls.
        else:
            SnowPlow.snowplow_event(citizen.citizen_id,
                                    csr,
                                    "stopservice",
                                    current_sr_number=current_sr_number)
            SnowPlow.choose_service(service_request, csr, "chooseservice")
            SnowPlow.snowplow_event(
                citizen.citizen_id,
                csr,
                "additionalservice",
                current_sr_number=service_request.sr_number)

        citizen_result = self.citizen_schema.dump(citizen)
        socketio.emit('update_active_citizen',
                      citizen_result,
                      room=csr.office.office_name)
        result = self.service_request_schema.dump(service_request)

        return {
            'service_request': result,
            'errors': self.service_request_schema.validate(service_request)
        }, 201
Пример #21
0
def find_active_ss():
    active_service_state = SRState.get_state_by_name("Active")
    return active_service_state
Пример #22
0
    def get(self):
        try:
            csr = CSR.find_by_username(g.oidc_token_info['username'])

            if not csr:
                return {'Message': 'User Not Found'}, 404

            db.session.add(csr)
            active_sr_state = SRState.get_state_by_name("Active")
            today = datetime.now()
            start_date = self.timezone.localize(today)

            active_citizens = Citizen.query \
                .join(Citizen.service_reqs) \
                .filter_by(sr_state_id=active_sr_state.sr_state_id) \
                .join(ServiceReq.periods) \
                .filter_by(csr_id=csr.csr_id) \
                .filter(Period.time_end.is_(None))

            #   Get a list of all current exams for the office.
            office_exams = Exam.query \
                .filter(Exam.office_id == csr.office_id, \
                        Exam.exam_returned_date.is_(None), \
                        Exam.deleted_date.is_(None)) \
                .join(ExamType, Exam.exam_type_id == ExamType.exam_type_id) \
                .outerjoin(Booking, Exam.booking_id == Booking.booking_id) \
                .outerjoin(Booking.booking_invigilators, Booking.booking_id == Booking.booking_invigilators.c.invigilator_id) \
                .all()

            #   Default condition ... attention is not needed for any exam.
            attention_needed = False

            #   Check for attention needed, individual exam.
            individual = []
            for exam in office_exams:

                if exam.exam_type.group_exam_ind == 0:
                    if exam.booking is not None:
                        attention_needed = attention_needed or exam.booking.start_time < start_date
                    if exam.expiry_date is not None:
                        attention_needed = attention_needed or exam.expiry_date < start_date
                    if exam.exam_returned_date is not None:
                        attention_needed = False
                    if attention_needed:
                        individual.append(exam)


            #   Only do further checks if attention not already needed.
            group = []
            if not attention_needed:
                for exam in office_exams:
                    if exam.exam_type.group_exam_ind == 1:
                        attention_needed = attention_needed or exam.booking.start_time < start_date
                        if exam.expiry_date is not None:
                            attention_needed = attention_needed or exam.expiry_date < start_date
                        if exam.booking is not None and exam.number_of_students is not None:
                            attention_needed = attention_needed or exam.booking.start_time < start_date
                            attention_needed = attention_needed or (len(exam.booking.invigilators) < 1
                                                                    and exam.number_of_students < 25)
                            attention_needed = attention_needed or (len(exam.booking.invigilators) < 2
                                                                    and exam.number_of_students > 24)
                        if exam.exam_returned_date is not None:
                            attention_needed = False
                        if attention_needed:
                            group.append(exam)

            result = self.csr_schema.dump(csr)
            active_citizens = self.citizen_schema.dump(active_citizens)

            return {'csr': result.data,
                    'attention_needed': attention_needed,
                    'active_citizens': active_citizens.data,
                    'back_office_display': self.back_office_display,
                    'recurring_feature_flag': self.recurring_feature_flag,
                    'errors': result.errors}

        except exc.SQLAlchemyError as e:
            print(e)
            return {'message': 'API is down'}, 500