예제 #1
0
    def post(self):
        my_print("==> In AppointmentPost, POST /appointments/")
        json_data = request.get_json()
        if not json_data:
            return {
                "message": "No input data received for creating an appointment"
            }, 400

        # Should delete draft appointment, and free up slot, before booking.
        # Clear up a draft if one was previously created by user reserving this time.
        if json_data.get('appointment_draft_id'):
            draft_id_to_delete = int(json_data['appointment_draft_id'])
            Appointment.delete_draft([draft_id_to_delete])
            if not application.config['DISABLE_AUTO_REFRESH']:
                socketio.emit('appointment_delete', draft_id_to_delete)

        is_blackout_appt = json_data.get('blackout_flag', 'N') == 'Y'
        csr = None
        user = None
        office = None

        #  Create a citizen for later use.
        citizen = self.citizen_schema.load({}).data

        # Check if the appointment is created by public user. Can't depend on the IDP as BCeID is used by other users as well
        is_public_user_appointment = is_public_user()
        if is_public_user_appointment:
            office_id = json_data.get('office_id')
            service_id = json_data.get('service_id')
            user = PublicUser.find_by_username(g.oidc_token_info['username'])
            # Add values for contact info and notes
            json_data['contact_information'] = user.email
            telephone = f'. Phone: {user.telephone}' if user.telephone else ''
            json_data['comments'] = json_data.get('comments', '') + telephone

            citizen.user_id = user.user_id
            citizen.citizen_name = user.display_name

            office = Office.find_by_id(office_id)
            service = Service.query.get(int(service_id))

            # Validate if the same user has other appointments for same day at same office
            appointments = Appointment.find_by_username_and_office_id(
                office_id=office_id,
                user_name=g.oidc_token_info['username'],
                start_time=json_data.get('start_time'),
                timezone=office.timezone.timezone_name)
            if appointments and len(
                    appointments) >= office.max_person_appointment_per_day:
                return {
                    "code": "MAX_NO_OF_APPOINTMENTS_REACHED",
                    "message": "Maximum number of appointments reached"
                }, 400

            # Check for race condition
            start_time = parse(json_data.get('start_time'))
            end_time = parse(json_data.get('end_time'))
            if not AvailabilityService.has_available_slots(
                    office=office,
                    start_time=start_time,
                    end_time=end_time,
                    service=service):
                return {
                    "code":
                    "CONFLICT_APPOINTMENT",
                    "message":
                    "Cannot create appointment due to scheduling conflict.  Please pick another time."
                }, 400

        else:
            csr = CSR.find_by_username(g.oidc_token_info['username'])
            office_id = csr.office_id
            office = Office.find_by_id(office_id)

        citizen.office_id = office_id
        citizen.qt_xn_citizen_ind = 0
        citizen_state = CitizenState.query.filter_by(
            cs_state_name="Appointment booked").first()
        citizen.cs_id = citizen_state.cs_id
        citizen.start_time = datetime.now()
        citizen.service_count = 1

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

        appointment, warning = self.appointment_schema.load(json_data)
        if is_public_user_appointment:
            appointment.citizen_name = user.display_name
            appointment.online_flag = True

        if warning:
            logging.warning("WARNING: %s", warning)
            return {"message": warning}, 422

        if appointment.office_id == office_id:
            appointment.citizen_id = citizen.citizen_id
            db.session.add(appointment)
            db.session.commit()

            # Generate CHES token
            try:
                ches_token = generate_ches_token()
            except Exception as exc:
                pprint(f'Error on token generation - {exc}')

            # If staff user is creating a blackout event then send email to all of the citizens with appointments for that period
            if is_blackout_appt:
                appointment_ids_to_delete = []
                appointments_for_the_day = Appointment.get_appointment_conflicts(
                    office_id, json_data.get('start_time'),
                    json_data.get('end_time'))
                for (cancelled_appointment, office, timezone,
                     user) in appointments_for_the_day:
                    if cancelled_appointment.appointment_id != appointment.appointment_id and not cancelled_appointment.checked_in_time:
                        appointment_ids_to_delete.append(
                            cancelled_appointment.appointment_id)

                        # Send blackout email
                        try:
                            pprint(
                                'Sending email for appointment cancellation due to blackout'
                            )
                            send_email(
                                ches_token,
                                *get_blackout_email_contents(
                                    appointment, cancelled_appointment, office,
                                    timezone, user))
                        except Exception as exc:
                            pprint(f'Error on email sending - {exc}')

                # Delete appointments
                if len(appointment_ids_to_delete) > 0:
                    Appointment.delete_appointments(appointment_ids_to_delete)

            else:
                # Send confirmation email
                try:
                    pprint('Sending email for appointment confirmation')
                    send_email(
                        ches_token,
                        *get_confirmation_email_contents(
                            appointment, office, office.timezone, user))
                except Exception as exc:
                    pprint(f'Error on email sending - {exc}')

            SnowPlow.snowplow_appointment(citizen, csr, appointment,
                                          'appointment_create')

            result = self.appointment_schema.dump(appointment)

            if not application.config['DISABLE_AUTO_REFRESH']:
                socketio.emit('appointment_create', result.data)

            return {"appointment": result.data, "errors": result.errors}, 201

        else:
            return {
                "The Appointment Office ID and CSR Office ID do not match!"
            }, 403
예제 #2
0
    def post(self):
        json_data = request.get_json()
        if not json_data:
            return {"message": "No input data received for creating an appointment"}, 400

        is_blackout_appt = json_data.get('blackout_flag', 'N') == 'Y'
        csr = None
        user = None
        office = None

        #  Create a citizen for later use.
        citizen = self.citizen_schema.load({}).data

        # Check if the appointment is created by public user. Can't depend on the IDP as BCeID is used by other users as well
        is_public_user_appointment = is_public_user()
        if is_public_user_appointment:
            office_id = json_data.get('office_id')
            user = PublicUser.find_by_username(g.oidc_token_info['username'])
            # Add values for contact info and notes
            json_data['contact_information'] = user.email
            telephone = f'. Phone: {user.telephone}' if user.telephone else ''
            json_data['comments'] = json_data.get('comments', '') + telephone

            citizen.user_id = user.user_id
            citizen.citizen_name = user.display_name

            office = Office.find_by_id(office_id)
            # Validate if the same user has other appointments for same day at same office
            appointments = Appointment.find_by_username_and_office_id(office_id=office_id,
                                                                      user_name=g.oidc_token_info['username'],
                                                                      start_time=json_data.get('start_time'),
                                                                      timezone=office.timezone.timezone_name)
            if appointments and len(appointments) >= office.max_person_appointment_per_day:
                return {"code": "MAX_NO_OF_APPOINTMENTS_REACHED", "message": "Maximum number of appointments reached"}, 400

            # Check for race condition
            start_time = parse(json_data.get('start_time'))
            end_time = parse(json_data.get('end_time'))
            if not AvailabilityService.has_available_slots(office=office, start_time=start_time, end_time=end_time):
                return {"code": "CONFLICT_APPOINTMENT",
                        "message": "Cannot create appointment due to conflict in time"}, 400

        else:
            csr = CSR.find_by_username(g.oidc_token_info['username'])
            office_id = csr.office_id
            office = Office.find_by_id(office_id)

        citizen.office_id = office_id
        citizen.qt_xn_citizen_ind = 0
        citizen_state = CitizenState.query.filter_by(cs_state_name="Appointment booked").first()
        citizen.cs_id = citizen_state.cs_id
        citizen.start_time = datetime.now()
        citizen.service_count = 1

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

        appointment, warning = self.appointment_schema.load(json_data)
        if is_public_user_appointment:
            appointment.citizen_name = user.display_name
            appointment.online_flag = True

        if warning:
            logging.warning("WARNING: %s", warning)
            return {"message": warning}, 422

        if appointment.office_id == office_id:
            appointment.citizen_id = citizen.citizen_id
            db.session.add(appointment)
            db.session.commit()

            # If staff user is creating a blackout event then send email to all of the citizens with appointments for that period
            if is_blackout_appt:
                appointment_ids_to_delete = []
                appointments_for_the_day = Appointment.get_appointment_conflicts(office_id, json_data.get('start_time'),
                                                                                 json_data.get('end_time'))
                for (cancelled_appointment, office, timezone, user) in appointments_for_the_day:
                    if cancelled_appointment.appointment_id != appointment.appointment_id and not cancelled_appointment.checked_in_time:
                        appointment_ids_to_delete.append(cancelled_appointment.appointment_id)

                        # Send blackout email
                        @copy_current_request_context
                        def async_email(subject, email, sender, body):
                            return send_email(subject, email, sender, body)

                        thread = Thread(target=async_email, args=get_blackout_email_contents(appointment, cancelled_appointment, office, timezone, user))
                        thread.daemon = True
                        thread.start()

                # Delete appointments
                if len(appointment_ids_to_delete) > 0:
                    Appointment.delete_appointments(appointment_ids_to_delete)

            else:
                # Send confirmation email
                @copy_current_request_context
                def async_email(subject, email, sender, body):
                    send_email(subject, email, sender, body)

                thread = Thread(target=async_email, args=get_confirmation_email_contents(appointment, office, office.timezone, user))
                thread.daemon = True
                thread.start()

            SnowPlow.snowplow_appointment(citizen, csr, appointment, 'appointment_create')

            result = self.appointment_schema.dump(appointment)

            return {"appointment": result.data,
                    "errors": result.errors}, 201

        else:
            return {"The Appointment Office ID and CSR Office ID do not match!"}, 403