def turnos(page=1):
    """
        READ
        Listar Todos los turnos reservados de los proximos tres dias.
        ID 1 CENTRO_INDEX permisos
    """
    usuarios_por_pag = Config.query.first().n_elements
    id_usuario = current_user.get_id()

    if User.tiene_permiso(id_usuario, 1):
        fecha_hoy = datetime.datetime.today().strftime('%Y-%m-%d')
        fecha_man = (datetime.datetime.today() +
                     datetime.timedelta(days=1)).strftime('%Y-%m-%d')
        fecha_pas = (datetime.datetime.today() +
                     datetime.timedelta(days=2)).strftime('%Y-%m-%d')

        turnos_hoy = Appointment.query.filter_by(appointment_date=fecha_hoy)
        turnos_man = Appointment.query.filter_by(appointment_date=fecha_man)
        turnos_pas = Appointment.query.filter_by(appointment_date=fecha_pas)
        turnos = turnos_hoy.union(turnos_man, turnos_pas)

        turnos = turnos.paginate(page, per_page=usuarios_por_pag)
        return render_template('admin/turnos.html', turnos=turnos)
    else:
        flash('No tienes permisos para realizar esa acción.', 'danger')
        return redirect(url_for('admin.index'))
def configuracion():
    """
      Vista de configuracion de sistema en administracion.
    """
    id_usuario = current_user.get_id()
    if User.tiene_permiso(id_usuario, 10):
        # Trae la informacion ya cargada para mostrarla en el formulario cuando method=GET
        config = Config.query.first()
        if not config:
            form = ConfigForm()
            # Guarda la informacion cargada desde el template cuando method=POST
            if form.validate_on_submit():
                config = Config(title=form.title.data,
                                description=form.description.data,
                                email=form.email.data,
                                n_elements=form.n_elements.data,
                                site_enabled=form.site_enabled.data)
                db.session.add(config)
                flash('Los cambios se guardaron correctamente.', 'success')
        else:
            form = ConfigForm(obj=config)
            # Guarda la informacion cargada desde el template cuando method=POST
            if form.validate_on_submit():
                form.populate_obj(config)
                flash('Los cambios se guardaron correctamente.', 'success')
        db.session.commit()
        return render_template('admin/configuracion.html',
                               form=form,
                               title='Centros de Ayuda GBA - Configuración')
    else:
        flash('No tienes permisos para realizar esa acción.', 'danger')
        return redirect(url_for('admin.index'))
def registrar_usuario():
    """
        CREATE
        Registar un nuevo usuario desde usuario admin
        ID 7 USER_NEW permisos
    """
    id_usuario = current_user.get_id()
    if User.tiene_permiso(id_usuario, 7):
        form = RegistrationForm()

        # POST.
        if form.validate_on_submit():
            user = User(email=form.email.data,
                        username=form.username.data,
                        first_name=form.first_name.data,
                        last_name=form.last_name.data,
                        active=form.active.data,
                        password=form.password.data)
            if form.admin.data:
                user.roles.append(Role.query.get(1))
            if form.operator.data:
                user.roles.append(Role.query.get(2))
            # agrega nuevo user a la db.
            db.session.add(user)
            db.session.commit()

            # redirecciona a pagina login.
            return redirect(url_for('admin.listar_usuarios'))
        return render_template('admin/register.html',
                               form=form,
                               title='Centros de Ayuda GBA - Registro')
    else:
        flash('No tienes permisos para realizar esa acción.', 'danger')
        return redirect(url_for('admin.index'))
def rechazar_centro(id):
    id_admin = current_user.get_id()
    if User.tiene_permiso(id_admin, 4):
        centro = HelpCenter.query.filter_by(id=id).first().status_id = 3
        db.session.commit()
        flash('Centro Rechazado', 'success')
        return redirect(url_for('admin.centros_ayuda'))
    else:
        flash('No tienes permisos para realizar esa acción.', 'danger')
        return redirect(url_for('admin.index'))
def actualizar_centro(id):

    id_admin = current_user.get_id()
    if User.tiene_permiso(id_admin, 4):

        results = []
        response = requests.get(
            'https://api-referencias.proyecto2020.linti.unlp.edu.ar/municipios'
        ).json()

        per_page = response['per_page']
        total = response['total']

        for page in range(1, math.ceil(total / per_page) + 1):
            response = requests.get(
                'https://api-referencias.proyecto2020.linti.unlp.edu.ar/municipios',
                params={
                    'page': page
                }).json()
            data = response['data']
            municipios = data['Town']
            for v in municipios.values():
                results.append((v['name']))

        municipios_list = sorted(results)

        current_center = HelpCenter.query.filter_by(id=id).first()
        current_protocol = current_center.visit_protocol
        current_protocol_name = str(current_protocol).split('/')[-1:][0]
        form = HelpCenterForm(obj=current_center)
        form.town.choices = municipios_list
        form.center_type_id.choices = CenterType.query.with_entities(
            CenterType.id, CenterType.name_center_type).all()
        if form.validate_on_submit():
            if form.visit_protocol.data != current_protocol:
                protocol_file = form.visit_protocol.data
                filename_vp = secure_filename(protocol_file.filename)
                protocol_path = path.join(current_app.root_path,
                                          'static/uploads', filename_vp)
                protocol_file.save(protocol_path)
                form.visit_protocol.data = protocol_path
            form.populate_obj(current_center)
            db.session.commit()
            flash('Los cambios se guardaron correctamente.', 'success')
            return redirect(url_for('admin.centros_ayuda'))
        return render_template('admin/centro_edit.html',
                               form=form,
                               current_protocol=current_protocol_name,
                               edit_mode=True)
    else:
        flash('No tienes permisos para realizar esa acción.', 'danger')
        return redirect(url_for('admin.index'))
def turnos_centro(id=0, page=1):
    id_usuario = current_user.get_id()
    usuarios_por_pag = Config.query.first().n_elements
    centro = HelpCenter.query.filter_by(id=id).first()
    if User.tiene_permiso(id_usuario, 1):
        turnos = Appointment.query.filter_by(center_id=centro.id).paginate(
            page, per_page=usuarios_por_pag)
        return render_template('admin/turnos.html',
                               turnos=turnos,
                               centro=centro)
    else:
        flash('No tienes permisos para realizar esa acción.', 'danger')
        return redirect(url_for('admin.index'))
def listar_usuarios(page=1):
    """
        READ
        Vista de modulo CRUD usuarios en administracion.
        ID 6 USER_INDEX permisos
    """
    usuarios_por_pag = Config.query.first().n_elements
    id_usuario = current_user.get_id()
    if User.tiene_permiso(id_usuario, 6):
        users = User.query.paginate(page, per_page=usuarios_por_pag)
        return render_template('admin/usuarios.html', users=users)
    else:
        flash('No tienes permisos para realizar esa acción.', 'danger')
        return redirect(url_for('admin.index'))
def actualizar_turno(id):
    """
        UPDATE
        Actualiza un turno
        ID 14 TURNO_UPDATE permisos
    """
    id_admin = current_user.get_id()
    if User.tiene_permiso(id_admin, 14):
        turno_edit = Appointment.query.get(id)
        if not turno_edit:
            flash('El turno solicitado no existe.', 'danger')
            return redirect(url_for('admin.index'))
        centro = HelpCenter.query.get(turno_edit.center_id)
        centro_nombre = centro.name_center
        form = AppointmentForm(obj=turno_edit, id=id)

        # POST.
        if form.validate_on_submit():
            form.populate_obj(turno_edit)
            delta = datetime.timedelta(minutes=30)
            start = form.start_time.data
            turno_edit.end_time = (
                datetime.datetime.combine(datetime.date(1, 1, 1), start) +
                delta).time()
            # Me trae el turno del centro recibido, con esa fecha y esa hora de inicio
            turnos_del_dia = Appointment.query.filter_by(
                center_id=turno_edit.center_id,
                appointment_date=turno_edit.appointment_date,
                start_time=turno_edit.start_time)
            if turnos_del_dia.count() == 1:
                db.session.commit()
                # redirecciona al listado de usuarios
                flash('Los cambios se guardaron correctamente.', 'success')
                return redirect(url_for('admin.turnos_centro', id=centro.id))
            else:
                flash('Turno no disponible', 'danger')
                return render_template(
                    'admin/turno_edit.html',
                    form=form,
                    center_name=centro_nombre,
                    title='Centros de Ayuda GBA - Actualizar turno')
        return render_template('admin/turno_edit.html',
                               form=form,
                               center_name=centro_nombre,
                               center_id=centro.id,
                               title='Centros de Ayuda GBA - Actualizar turno')
    else:
        flash('No tienes permisos para realizar esa acción.', 'danger')
        return redirect(url_for('admin.index'))
def usuarios_bloqueados(page=1):
    """
        READ
        Devuelve una lista de los usuarios bloqueados
        ID 6 USER_INDEX permisos
    """
    usuarios_por_pag = Config.query.first().n_elements
    id_usuario = current_user.get_id()
    if User.tiene_permiso(id_usuario, 6):
        users = User.query.filter_by(active=False).paginate(
            page, per_page=usuarios_por_pag)
        return render_template('admin/usuarios.html', users=users)
    else:
        flash('No tienes permisos para realizar esa acción.', 'danger')
        return redirect(url_for('admin.index'))
def actualizar_usuario(id_user):
    """
        Vista de actualizacion de un usuario enviado como parámetro con un usuario admin
        Requiere permiso con ID 9 (USER_UPDATE)
    """

    id_admin = current_user.get_id()
    if User.tiene_permiso(id_admin, 9):

        user_edit = User.query.filter_by(id=id_user).first()
        if not user_edit:
            flash('El usuario solicitado no existe.', 'danger')
            return redirect(url_for('admin.index'))

        roles = user_edit.roles.all()
        es_admin = Role.query.filter_by(name='admin').first() in roles
        es_operador = Role.query.filter_by(name='operador').first() in roles
        form = EditForm(obj=user_edit,
                        id=id_user,
                        admin=es_admin,
                        operator=es_operador)

        # POST.
        if form.validate_on_submit():
            form.populate_obj(user_edit)
            if form.admin.data:
                if not es_admin:
                    user_edit.roles.append(Role.query.get(1))
            elif es_admin:
                user_edit.roles.remove(Role.query.get(1))
            if form.operator.data:
                if not es_operador:
                    user_edit.roles.append(Role.query.get(2))
            elif es_operador:
                user_edit.roles.remove(Role.query.get(2))

            db.session.commit()
            # redirecciona al listado de usuarios
            flash('Los cambios se guardaron correctamente.', 'success')
            return redirect(url_for('admin.listar_usuarios'))

        return render_template('admin/update_user.html',
                               form=form,
                               title='Centros de Ayuda GBA - Configuración')
    else:
        flash('No tienes permisos para realizar esa acción.', 'danger')
        return redirect(url_for('admin.index'))
def turnos_buscar(page=1):
    search_name = request.form.get('buscar-nombre')
    search_date = request.form.get('buscar-fecha')
    if search_name or search_date:
        return redirect(
            url_for('admin.turnos_buscar',
                    buscar=search_name,
                    fecha=search_date))
    else:
        search_name = request.args.get('buscar')
        search_date = request.args.get('fecha')

    id_usuario = current_user.get_id()
    usuarios_por_pag = Config.query.first().n_elements
    if User.tiene_permiso(id_usuario, 1):
        if search_name:
            results = HelpCenter.query.filter(
                HelpCenter.name_center.contains(search_name)).with_entities(
                    HelpCenter.id)
            help_centers_ids = [value for value, in results]
            turnos = Appointment.query.filter(
                Appointment.center_id.in_(help_centers_ids)).union(
                    Appointment.query.filter(
                        Appointment.email.contains(search_name)))

            if search_date:
                turnos = turnos.filter_by(appointment_date=search_date)
        else:
            if search_date:
                turnos = Appointment.query.filter_by(
                    appointment_date=search_date)
            else:
                turnos = Appointment.query

        turnos = turnos.paginate(page, per_page=usuarios_por_pag)
        return render_template('admin/turnos.html',
                               turnos=turnos,
                               search_name=search_name,
                               search_date=search_date)
    else:
        flash('No tienes permisos para realizar esa acción.', 'danger')
        return redirect(url_for('admin.index'))
def buscar_por_nombre(page=1):
    """
        READ
        Devuelve una lista de usuarios con nombre enviado como parametro
        ID 6 USER_INDEX permisos
    """
    usuarios_por_pag = Config.query.first().n_elements

    search = request.form.get('buscar-nombre')
    id_usuario = current_user.get_id()
    if User.tiene_permiso(id_usuario, 6):
        users = User.query.filter(
            or_(User.first_name.contains(search),
                User.last_name.contains(search))).paginate(
                    page, per_page=usuarios_por_pag)
        return render_template('admin/usuarios.html',
                               users=users,
                               search=search)
    else:
        flash('No tienes permisos para realizar esa acción.', 'danger')
        return redirect(url_for('admin.index'))
def turnos_centro_buscar(id=0, page=1):
    search_date = request.form.get('buscar-fecha')
    search_name = request.form.get('buscar-nombre')
    id_usuario = current_user.get_id()
    usuarios_por_pag = Config.query.first().n_elements
    centro = HelpCenter.query.filter_by(id=id).first()
    if User.tiene_permiso(id_usuario, 1):
        turnos = Appointment.query.filter_by(center_id=centro.id)
        if search_name:
            turnos = turnos.filter(Appointment.email.contains(search_name))
        if search_date:
            turnos = turnos.filter_by(appointment_date=search_date)
        turnos = turnos.paginate(page, per_page=usuarios_por_pag)
        return render_template('admin/turnos.html',
                               turnos=turnos,
                               search_date=search_date,
                               search_name=search_name,
                               centro=centro)
    else:
        flash('No tienes permisos para realizar esa acción.', 'danger')
        return redirect(url_for('admin.index'))
def eliminar_centro(id):

    id_admin = current_user.get_id()
    if User.tiene_permiso(id_admin, 3):

        center_delete = HelpCenter.query.filter_by(id=id).first()
        if not center_delete:
            flash('El centro de ayuda solicitado no existe.', 'danger')
            return redirect(url_for('admin.centros_ayuda'))

        Appointment.query.filter_by(center_id=id).delete()
        db.session.delete(center_delete)
        db.session.commit()

        flash('El centro de ayuda se eliminó correctamente', 'success')
        return redirect(url_for('admin.centros_ayuda'))
    else:
        flash('No tienes permisos para realizar esa acción.', 'danger')
        return redirect(url_for('admin.index'))

    return 'Borrado de Centro de ayuda'
def eliminar_turno(id):
    """
        DELETE
        Eliminar un turno
        ID 13 TURNO_DESTROY permisos
    """
    id_usuario = current_user.get_id()
    if User.tiene_permiso(id_usuario, 13):

        turno = Appointment.query.get(id)
        if not turno:
            flash('El turno no existe.', 'danger')
            return redirect(url_for('admin_index'))

        db.session.delete(turno)
        db.session.commit()

        flash('El turno se eliminó correctamente.', 'success')
        return redirect(url_for('admin.turnos'))
    else:
        flash('No tienes permisos para realizar esa acción.', 'danger')
        return redirect(url_for('admin.index'))
def eliminar_usuario(id):
    """
        Vista de eliminacion de un usuario, enviado como parámetro con sus relaciones, con un usuario admin
        Requiere permiso con ID8 (USER_DESTROY)
    """

    id_admin = current_user.get_id()
    if User.tiene_permiso(id_admin, 8):

        user_delete = User.query.filter_by(id=id).first()
        if not user_delete:
            flash('El usuario solicitado no existe.', 'danger')
            return redirect(url_for('admin.index'))

        db.session.delete(user_delete)
        db.session.commit()

        flash('El usuario se eliminó correctamente', 'success')
        return redirect(url_for('admin.listar_usuarios'))
    else:
        flash('No tienes permisos para realizar esa acción.', 'danger')
        return redirect(url_for('admin.index'))
def activar_bloquear(id):
    """
        READ
        Bloquea un usuario activo
        /
        Activa un usuario bloqueado
        ID 9 USER_UPDATE permisos
    """
    id_usuario = current_user.get_id()
    if User.tiene_permiso(id_usuario, 9):

        user_edit = User.query.filter_by(id=id).first()
        if not user_edit:
            flash('El usuario solicitado no existe.', 'danger')
            return redirect(url_for('admin.index'))

        user = User.query.get(id)
        user.active = not user.active
        db.session.commit()
        flash('Los cambios se guardaron correctamente.', 'success')
        return redirect(url_for('admin.listar_usuarios'))
    else:
        flash('No tienes permisos para realizar esa acción.', 'danger')
        return redirect(url_for('admin.index'))
def crear_turno(id=0):
    """
        CREATE
        Registar un nuevo turno
        ID 12 TURNO_NEW permisos
    """
    id_usuario = current_user.get_id()
    if User.tiene_permiso(id_usuario, 12):

        # Si recibe Id por paremetro no es necesario seleccionar el Centro. Sino, mostrar Selector de centros.
        if id > 0:
            centro = HelpCenter.query.get(id)
            centro_nombre = centro.name_center
            form = AppointmentForm()
        else:
            form = AppointmentWithCenterForm()
            centros_ayuda_aceptados = HelpCenter.query.filter_by(
                status_id=1).with_entities(HelpCenter.id,
                                           HelpCenter.name_center).all()
            form.center_id.choices = centros_ayuda_aceptados
            centro_nombre = ''
        # POST
        if form.validate_on_submit():

            if id > 0:
                appointment = Appointment(
                    email=form.email.data,
                    first_name=form.first_name.data,
                    last_name=form.last_name.data,
                    phone=form.phone.data,
                    start_time=form.start_time.data,
                    appointment_date=form.appointment_date.data,
                    center_id=id)
            else:
                appointment = Appointment(
                    email=form.email.data,
                    first_name=form.first_name.data,
                    last_name=form.last_name.data,
                    phone=form.phone.data,
                    start_time=form.start_time.data,
                    appointment_date=form.appointment_date.data,
                    center_id=form.center_id.data)
                centro = HelpCenter.query.get(form.center_id.data)

            delta = datetime.timedelta(minutes=30)
            start = appointment.start_time
            appointment.end_time = (
                datetime.datetime.combine(datetime.date(1, 1, 1), start) +
                delta).time()
            # Me trae el turno del centro recibido, con esa fecha y esa hora de inicio
            turnos_del_dia = Appointment.query.filter_by(
                center_id=id,
                appointment_date=appointment.appointment_date,
                start_time=appointment.start_time).first()
            if not turnos_del_dia:
                centro.appointments.append(appointment)
                db.session.commit()
                # redirecciona a pagina turnos del dia del centro
                # return redirect(url_for('admin.turnos_centro({})'.format(id)))
                flash('Turno creado exitosamente', 'success')
                return redirect(url_for('admin.turnos_centro', id=centro.id))
            else:
                flash('Turno no disponible', 'danger')
                return render_template(
                    'admin/turno_edit.html',
                    form=form,
                    center_name=centro_nombre,
                    center_id=id,
                    title='Centros de Ayuda GBA - Sacar turno')

        return render_template('admin/turno_edit.html',
                               form=form,
                               center_name=centro_nombre,
                               center_id=id,
                               title='Centros de Ayuda GBA - Sacar turno')
    else:
        flash('No tienes permisos para realizar esa acción', 'danger')
        return redirect(url_for('admin.index'))
def crear_centro():

    id_admin = current_user.get_id()
    if User.tiene_permiso(id_admin, 2):

        results = []
        response = requests.get(
            'https://api-referencias.proyecto2020.linti.unlp.edu.ar/municipios'
        ).json()

        per_page = response['per_page']
        total = response['total']

        for page in range(1, math.ceil(total / per_page) + 1):
            response = requests.get(
                'https://api-referencias.proyecto2020.linti.unlp.edu.ar/municipios',
                params={
                    'page': page
                }).json()
            data = response['data']
            municipios = data['Town']
            for v in municipios.values():
                results.append((v['name']))

        municipios_list = sorted(results)

        form = HelpCenterForm()
        form.town.choices = municipios_list
        form.center_type_id.choices = CenterType.query.with_entities(
            CenterType.id, CenterType.name_center_type).all()
        if form.validate_on_submit():
            protocol_path = ""
            if form.visit_protocol.data:
                protocol_file = form.visit_protocol.data
                filename_vp = secure_filename(protocol_file.filename)
                protocol_path = path.join(current_app.root_path,
                                          'static/uploads', filename_vp)
                protocol_file.save(protocol_path)
            help_center = HelpCenter(name_center=form.name_center.data,
                                     address=form.address.data,
                                     phone=form.phone.data,
                                     opening_time=form.opening_time.data,
                                     close_time=form.close_time.data,
                                     town=form.town.data,
                                     web=form.web.data,
                                     email=form.email.data,
                                     visit_protocol=protocol_path,
                                     status_id=1,
                                     center_type_id=form.center_type_id.data,
                                     latitude=form.latitude.data,
                                     longitude=form.longitude.data)
            # agrega nuevo centro a la db.
            db.session.add(help_center)
            db.session.commit()

            # redirecciona a pagina login.
            return redirect(url_for('admin.centros_ayuda'))

        return render_template('admin/centro_edit.html', form=form)
    else:
        flash('No tienes permisos para realizar esa acción.', 'danger')
        return redirect(url_for('admin.index'))