<repo_name>fdzr/test<file_sep>/sala_reuniones/widgets.py
from django import forms
from django.conf import settings


class DatePicker(forms.DateInput):
    class Media:
        css = {
            'all': ('%scss/datepicker.min.css' % settings.STATIC_URL,)
        }
        js = ('%sjs/bootstrap-datepicker.min.js' % settings.STATIC_URL,
              '%sjs/bootstrap-datepicker.es.js' % settings.STATIC_URL
              )


class TimePicker(forms.TimeInput):
    class Media:
        css = {
            'all': ('%scss/jquery-clockpicker.min.css' % settings.STATIC_URL,)
        }
        js = ('%sjs/jquery-clockpicker.min.js' % settings.STATIC_URL,)
<file_sep>/sala_reuniones/migrations/0001_initial.py
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2019-01-19 18:55
from __future__ import unicode_literals

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

    initial = True

    dependencies = [
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]

    operations = [
        migrations.CreateModel(
            name='HorarioDisponibilidad',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('hora_inicio', models.TimeField(verbose_name='Hora de inicio')),
                ('hora_fin', models.TimeField(verbose_name='Hora de terminar')),
            ],
            options={
                'ordering': ['hora_inicio'],
                'verbose_name_plural': 'Horario disponibilidades',
            },
        ),
        migrations.CreateModel(
            name='Insumo',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('nombre', models.CharField(max_length=30)),
            ],
            options={
                'ordering': ['nombre'],
            },
        ),
        migrations.CreateModel(
            name='Reserva',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('fecha', models.DateField()),
                ('hora_inicio', models.TimeField(verbose_name='Hora inicial')),
                ('hora_final', models.TimeField(verbose_name='Hora final')),
                ('capacidad', models.IntegerField(verbose_name='Capacidad de personas')),
                ('confirmada', models.BooleanField(default=False)),
            ],
            options={
                'ordering': ['fecha'],
            },
        ),
        migrations.CreateModel(
            name='SalaReuniones',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('nombre', models.CharField(max_length=50)),
                ('ubicacion', models.CharField(max_length=100, verbose_name='Ubicaci\xf3n')),
                ('capacidad', models.IntegerField()),
                ('estado', models.CharField(choices=[('nd', 'No disponible'), ('d', 'Disponible'), ('r', 'Reservada'), ('c', 'Confirmada')], default='d', max_length=20)),
                ('horario_disponibilidad', models.ManyToManyField(to='sala_reuniones.HorarioDisponibilidad')),
                ('insumos', models.ManyToManyField(blank=True, default=['Proyector', 'Pizarr\xf3n'], to='sala_reuniones.Insumo')),
            ],
            options={
                'ordering': ['nombre'],
                'verbose_name_plural': 'Sala de reuniones',
            },
        ),
        migrations.AddField(
            model_name='reserva',
            name='sala_reuniones',
            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sala_reuniones.SalaReuniones'),
        ),
        migrations.AddField(
            model_name='reserva',
            name='user',
            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
        ),
    ]
<file_sep>/sala_reuniones/templates/sala_reuniones/reserva_confirm_delete.html
{% extends "sala_reuniones/base.html" %}

{% block content %}
	<div class="row">
		<div class="panel panel-default">
			<div class="panel-heading">Eliminar</div>
			<div class="panel-body">
				<form action="" method="POST">{% csrf_token %}
					<p>Seguro q desea eliminar la reserva del sal&oacute;n 
						<span class="label label-warning">
							<em>{{ object.sala_reuniones.nombre}}</em>
						</span> 
						para el 
						<span class="label label-default">{{object.fecha}}</span>
						de <span class="label label-default">{{object.hora_inicio}} - {{object.hora_final}}</span>?
					</p>
					<br>
					<br>
					<br>
					<div class="form-group">
						<button class="btn btn-block btn-danger" type="submit">Eliminar</button>
					</div>
				</form>
				
			</div>
		</div>

	</div>
{% endblock content %}<file_sep>/sala_reuniones/tests/tests_views.py
# -*- encoding:utf-8 -*-
# -*- coding:utf-8 -*-


from datetime import datetime, date

from django.test import TestCase, Client
from django.core.urlresolvers import reverse
from django.urls import resolve
from django.contrib.auth.models import User

from sala_reuniones.views import HomeView, ListarReservasViews
from sala_reuniones.models import Insumo, HorarioDisponibilidad, SalaReuniones, Reserva
from sala_reuniones.forms import ReservaForm


class HomeViewTest(TestCase):

    def test_home_view(self):
        response = self.client.get(reverse('home'))
        return self.assertEqual(200, response.status_code)

    def test_home_view_with_class(self):
        view = resolve('/')
        return self.assertEqual(view.func.view_class, HomeView)


class RedirectViewTest(TestCase):
    def setUp(self):
        self.form_data = {'username': 'Frank', 'email': '<EMAIL>', 'password1': '<PASSWORD>', 'password2': '<PASSWORD>'}

    def test_no_users_yet(self):
        self.assertQuerysetEqual([], User.objects.all())

    def test_register_redirection_successful(self):
        response = self.client.post(reverse('registrarse'), self.form_data)
        self.assertEqual(302, response.status_code)

    def test_register_new_user(self):
        response = self.client.post(reverse('registrarse'), self.form_data)
        self.assertTrue(User.objects.all())

    def test_register_new_user_with_name(self):
        response = self.client.post(reverse('registrarse'), self.form_data)
        self.assertEqual('Frank', User.objects.filter(username='Frank').first().username)


class LoginViewTest(TestCase):
    def setUp(self):
        self.user = User.objects.create(username='test', is_superuser=True)
        self.user.set_password('<PASSWORD>')
        self.user.save()

        self.form_data = {'username': 'test', 'password': '<PASSWORD>'}

    def test_login_user_redirect_home(self):
        response = self.client.post(reverse('entrar'), self.form_data)
        self.assertRedirects(response, reverse('home'))


class LogoutViewTest(TestCase):

    def setUp(self):
        self.user = User.objects.create(username='test', is_superuser=True)
        self.user.set_password('<PASSWORD>')
        self.user.save()

        self.client = Client()
        self.client.login(username='test', password='<PASSWORD>')

    def test_logout_with_status_code(self):
        response = self.client.get(reverse('salir'))
        self.assertEqual(302, response.status_code)

    def test_logout_redirection_home(self):
        response = self.client.get(reverse('salir'))
        self.assertEqual(response.url, reverse('home'))


class AdicionarReservaViewTest(TestCase):

    def setUp(self):
        self.user = User.objects.create(username='test', is_superuser=True)
        self.user.set_password('<PASSWORD>')
        self.user.save()

        self.insumo = Insumo.objects.create(nombre=u'Pizarrón')
        self.insumo2 = Insumo.objects.create(nombre='Proyector')

        self.horario_disponibilidad1 = HorarioDisponibilidad.objects.create(hora_inicio='10:00', hora_fin='12:00')
        self.horario_disponibilidad2 = HorarioDisponibilidad.objects.create(hora_inicio='13:00', hora_fin='15:00')

        self.sala_reunion = SalaReuniones.objects.create(nombre='Sala 1', ubicacion='Norte', capacidad=10)
        self.sala_reunion.horario_disponibilidad.add(self.horario_disponibilidad1)
        self.sala_reunion.insumos.add(self.insumo)
        self.sala_reunion.save()

        self.client = Client()
        self.client.login(username='test', password='<PASSWORD>')

    def test_add_reservation(self):
        form_data = {'fecha': '2019-01-29',
                     'hora_inicio': '10:00',
                     'hora_final': '12:00',
                     'capacidad': 10,
                     'sala_reuniones': self.sala_reunion.pk,
                     'user': self.user.pk
                     }

        form = ReservaForm(form_data, pk=self.sala_reunion.pk)
        self.assertTrue(form.is_valid())

    def test_add_reservation_check_reservation(self):
        form_data = {'fecha': '2019-01-29',
                     'hora_inicio': '10:00',
                     'hora_final': '12:00',
                     'capacidad': 10,
                     'sala_reuniones': self.sala_reunion.pk,
                     'user': self.user.pk
                     }

        form = ReservaForm(form_data, pk=self.sala_reunion.pk)
        form.save()
        self.assertTrue(Reserva.objects.all())

    def test_check_errors_add_reservation_date_past(self):
        form_data = {'fecha': '2019-01-20',
                     'hora_inicio': '10:00',
                     'hora_final': '12:00',
                     'capacidad': 10,
                     'sala_reuniones': self.sala_reunion.pk,
                     'user': self.user.pk
                     }

        form = ReservaForm(form_data, pk=self.sala_reunion.pk)
        self.assertEqual(form.errors['fecha'][0], u'Este campo no admite fechas en el pasado.')

    def test_list_reservations(self):
        response = self.client.get(reverse('sala_reuniones:listar_reservas'))
        self.assertEqual(200, response.status_code)

    def test_list_reservations_check_view(self):
        view = resolve('/sala_reuniones/listar/reservas/')
        self.assertEqual(view.func.view_class, ListarReservasViews)


class EditarReservaViewTest(TestCase):

    def setUp(self):
        self.user = User.objects.create(username='test', is_superuser=True)
        self.user.set_password('<PASSWORD>')
        self.user.save()

        self.insumo = Insumo.objects.create(nombre=u'Pizarrón')
        self.insumo2 = Insumo.objects.create(nombre='Proyector')

        self.horario_disponibilidad1 = HorarioDisponibilidad.objects.create(hora_inicio='10:00', hora_fin='12:00')
        self.horario_disponibilidad2 = HorarioDisponibilidad.objects.create(hora_inicio='13:00', hora_fin='15:00')

        self.sala_reunion = SalaReuniones.objects.create(nombre='Sala 1', ubicacion='Norte', capacidad=10)
        self.sala_reunion.horario_disponibilidad.add(self.horario_disponibilidad1)
        self.sala_reunion.insumos.add(self.insumo)
        self.sala_reunion.save()

        self.reserva = Reserva.objects.create(fecha='2019-01-20', hora_inicio='10:00',
                                              hora_final='12:00', capacidad=10, sala_reuniones=self.sala_reunion,
                                              user=self.user)

        self.form_data = {'fecha': '2019-01-28',
                          'hora_inicio': '10:00',
                          'hora_final': '12:00',
                          'capacidad': 50,
                          'sala_reuniones': self.sala_reunion.pk,
                          'user': self.user.pk
                          }

        self.client = Client()
        self.client.login(username='test', password='<PASSWORD>')

    def test_edit_with_url(self):
        response = self.client.post(reverse('sala_reuniones:editar_reserva',
                                            kwargs={'pk': self.reserva.pk}), self.form_data)

        self.assertEqual(302, response.status_code)

    def test_edit_field_capacidad(self):
        response = self.client.post(reverse('sala_reuniones:editar_reserva',
                                            kwargs={'pk': self.reserva.pk}), self.form_data)
        reserva = Reserva.objects.get(pk=self.reserva.pk).capacidad
        self.assertEqual(50, reserva)


class EliminarReservasViewTest(TestCase):

    def setUp(self):
        self.user = User.objects.create(username='test', is_superuser=True)
        self.user.set_password('<PASSWORD>')
        self.user.save()

        self.insumo = Insumo.objects.create(nombre=u'Pizarrón')
        self.insumo2 = Insumo.objects.create(nombre='Proyector')

        self.horario_disponibilidad1 = HorarioDisponibilidad.objects.create(hora_inicio='10:00', hora_fin='12:00')
        self.horario_disponibilidad2 = HorarioDisponibilidad.objects.create(hora_inicio='13:00', hora_fin='15:00')

        self.sala_reunion = SalaReuniones.objects.create(nombre='Sala 1', ubicacion='Norte', capacidad=10)
        self.sala_reunion.horario_disponibilidad.add(self.horario_disponibilidad1)
        self.sala_reunion.insumos.add(self.insumo)
        self.sala_reunion.save()

        self.reserva = Reserva.objects.create(fecha='2019-01-20', hora_inicio='10:00',
                                              hora_final='12:00', capacidad=10, sala_reuniones=self.sala_reunion,
                                              user=self.user)

        self.client = Client()
        self.client.login(username='test', password='<PASSWORD>')

    def test_delete_status_code(self):
        response = self.client.post(reverse('sala_reuniones:eliminar_reserva', kwargs={'pk': self.reserva.pk}))
        self.assertEqual(response.status_code, 302)

    def test_delete_redirection(self):
        response = self.client.post(reverse('sala_reuniones:eliminar_reserva', kwargs={'pk': self.reserva.pk}))
        self.assertRedirects(response, reverse('sala_reuniones:listar_reservas'))

    def test_delete_reserva_query(self):
        response = self.client.post(reverse('sala_reuniones:eliminar_reserva', kwargs={'pk': self.reserva.pk}))
        self.assertQuerysetEqual([], Reserva.objects.all())
<file_sep>/sala_reuniones/urls.py
from django.conf.urls import url

from .views import (AdicionarReservaView,
                    ListarReservasViews,
                    ReservasFullcalendario,
                    EditarReservaView,
                    EliminarReservasView)


urlpatterns = [

    url(r'^adicionar/reserva/(?P<pk>\d+)/$', AdicionarReservaView.as_view(), name='adicionar_reserva'),
    url(r'^listar/reservas/$', ListarReservasViews.as_view(), name='listar_reservas'),
    url(r'^listar/reservas/calendario/$', ReservasFullcalendario.as_view(), name='calendario_reservas'),
    url(r'^editar/reserva/(?P<pk>\d+)/$', EditarReservaView.as_view(), name='editar_reserva'),
    url(r'^eliminar/reserva/(?P<pk>\d+)/$', EliminarReservasView.as_view(), name='eliminar_reserva')

]
<file_sep>/sala_reuniones/models.py
# -*- encoding:utf-8 -*-
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models
from django.conf import settings


# Create your models here.


class Insumo(models.Model):
    nombre = models.CharField(max_length=30)

    class Meta:
        ordering = ['nombre']

    def __unicode__(self):
        return unicode(self.nombre)

    def __str__(self):
        return self.nombre


class HorarioDisponibilidad(models.Model):
    hora_inicio = models.TimeField(verbose_name='Hora de inicio')
    hora_fin = models.TimeField(verbose_name='Hora de terminar')

    class Meta:
        ordering = ['hora_inicio']
        verbose_name_plural = 'Horario disponibilidades'

    def __unicode__(self):
        return unicode(str(self.hora_inicio) + ' - ' + str(self.hora_fin))

    def __str__(self):
        return str(self.hora_inicio) + ' - ' + str(self.hora_fin)


class SalaReuniones(models.Model):
    nombre = models.CharField(max_length=50)
    ubicacion = models.CharField(max_length=100, verbose_name=u'Ubicación')
    capacidad = models.IntegerField()
    horario_disponibilidad = models.ManyToManyField(HorarioDisponibilidad)
    insumos = models.ManyToManyField(Insumo, default=['Proyector', u'Pizarrón'], blank=True)

    class Meta:
        ordering = ['nombre']
        verbose_name_plural = 'Sala de reuniones'

    def __unicode__(self):
        return unicode(self.nombre)

    def __str__(self):
        return self.nombre


class Reserva(models.Model):
    NO_DISPONIBLE = 'nd'
    DISPONIBLE = 'd'
    RESERVADA = 'r'
    CONFIRMADA = 'c'

    ESTADO_CHOICES = (
        (NO_DISPONIBLE, 'No disponible'),
        (DISPONIBLE, 'Disponible'),
        (RESERVADA, 'Reservada'),
        (CONFIRMADA, 'Confirmada')
    )

    fecha = models.DateField()
    hora_inicio = models.TimeField(verbose_name='Hora inicial')
    hora_final = models.TimeField(verbose_name='Hora final')
    capacidad = models.IntegerField(verbose_name='Capacidad de personas')
    sala_reuniones = models.ForeignKey(SalaReuniones)
    confirmada = models.BooleanField(default=False)
    user = models.ForeignKey(settings.AUTH_USER_MODEL)
    estado = models.CharField(max_length=20, choices=ESTADO_CHOICES, default=DISPONIBLE)

    class Meta:
        ordering = ['fecha', 'sala_reuniones']

    def __str__(self):
        return (str(self.fecha) + ' ' + self.sala_reuniones.nombre + ' ' + str(self.hora_inicio.strftime('%H:%M')) + ' ' + str(self.hora_final))
        # .strftime('%d-%b-%Y')
<file_sep>/sala_reuniones/forms.py
# -*- encoding:utf-8 -*-
# -*- coding:utf-8 -*-

from datetime import datetime

from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User

from .models import Reserva, SalaReuniones
from .widgets import DatePicker, TimePicker


class UserRegisterForm(UserCreationForm):
    email = forms.EmailField()

    class Meta:
        model = User
        fields = ['username', 'email', '<PASSWORD>', '<PASSWORD>']


class ReservaForm(forms.ModelForm):
    use_required_attribute = False

    class Meta:
        model = Reserva
        fields = ['fecha', 'hora_inicio', 'hora_final', 'capacidad', 'sala_reuniones', 'confirmada', 'user']
        widgets = {
            'fecha': DatePicker,
            'hora_inicio': TimePicker,
            'hora_final': TimePicker
        }

    def __init__(self, *args, **kwargs):

        if 'pk' in kwargs:
            pk_sala = kwargs.pop('pk')

        super(ReservaForm, self).__init__(*args, **kwargs)
        if not self.instance.id:
            sala_reunion = SalaReuniones.objects.get(pk=pk_sala)
            self.fields['user'].required = False
            self.fields['sala_reuniones'].initial = sala_reunion

    def clean_fecha(self):
        fecha = self.cleaned_data['fecha']

        if fecha < datetime.now().date():
            raise forms.ValidationError('Este campo no admite fechas en el pasado.')

        return fecha

    def clean_hora_final(self):
        hora_final = self.cleaned_data['hora_final']

        try:
            hora_inicio = self.cleaned_data['hora_inicio']
        except KeyError:
            hora_inicio = ''

        if hora_inicio:
            if hora_final < hora_inicio:
                raise forms.ValidationError('La hora final no puede ser menor que la hora inicial.')

        return hora_final

    def clean_sala_reuniones(self):
        sala_reunion = self.cleaned_data['sala_reuniones']

        try:
            hora_inicio = self.cleaned_data['hora_inicio']
            hora_final = self.cleaned_data['hora_final']
        except KeyError:
            return sala_reunion

        for horario in sala_reunion.horario_disponibilidad.all():
            if hora_inicio < horario.hora_inicio or hora_inicio > horario.hora_fin:
                self.add_error('hora_inicio', 'No hay disponibilidad a esta hora.')
            if hora_final < horario.hora_inicio or hora_final > horario.hora_fin:
                self.add_error('hora_final', 'No hay disponibilidad en este horario.')

        return sala_reunion

    def clean(self):

        try:
            fecha = self.cleaned_data['fecha']
            hora_inicio = self.cleaned_data['hora_inicio']
            hora_final = self.cleaned_data['hora_final']

        except KeyError:
            return self.cleaned_data

        reserva = Reserva.objects.filter(fecha=fecha, hora_inicio=hora_inicio, hora_final=hora_final)

        if reserva:
            raise forms.ValidationError('Ya existe una reserva en esa fecha y rango de horarios.')

        return self.cleaned_data
<file_sep>/sala_reuniones/admin.py
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.contrib import admin
from .models import HorarioDisponibilidad, SalaReuniones, Insumo, Reserva

# Register your models here.
admin.site.register(SalaReuniones)
admin.site.register(Insumo)
admin.site.register(HorarioDisponibilidad)
admin.site.register(Reserva)<file_sep>/sala_reuniones/views.py
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.shortcuts import render, redirect
from django.views.generic import ListView, CreateView, View, TemplateView, UpdateView, DeleteView
from django.urls import reverse, reverse_lazy
from django.contrib import messages
from django.contrib.auth.models import User

from .models import SalaReuniones, Reserva
from .forms import UserRegisterForm, ReservaForm

from braces.views import LoginRequiredMixin, FormValidMessageMixin

# Create your views here.


class HomeView(ListView):
    model = SalaReuniones
    template_name = 'sala_reuniones/home.html'
    context_object_name = 'salas_reuniones'


class RegisterView(View):
    template_name = 'sala_reuniones/register.html'

    def get(self, request, *args, **kwargs):
        form = UserRegisterForm()
        return render(request, self.template_name, {'form': form})

    def post(self, request):
        form = UserRegisterForm(request.POST)
        if form.is_valid():
            username = form.cleaned_data['username']
            messages.success(request, 'Cuenta creada para %s !!!' % username)
            form.save()
            return redirect('home')
        return render(request, self.template_name, {'form': form})


class AdicionarReservaView(LoginRequiredMixin, CreateView):
    model = Reserva
    form_class = ReservaForm
    success_url = reverse_lazy('sala_reuniones:listar_reservas')

    def form_valid(self, form):
        formulario = form.save(commit=False)
        formulario.user = self.request.user

        if formulario.confirmada:
            formulario.estado = Reserva.CONFIRMADA
        else:
            formulario.estado = Reserva.RESERVADA

        formulario.save()

        return super(AdicionarReservaView, self).form_valid(form)

    def get_context_data(self, *args, **kwargs):
        context_data = super(AdicionarReservaView, self).get_context_data(*args, **kwargs)
        sala_reunion = SalaReuniones.objects.get(pk=self.kwargs['pk'])
        context_data['sala_reunion'] = sala_reunion
        context_data['horarios'] = sala_reunion.horario_disponibilidad.all()

        return context_data

    def get_form_kwargs(self):
        kwargs = super(AdicionarReservaView, self).get_form_kwargs()
        kwargs['pk'] = self.kwargs['pk']
        return kwargs


class ListarReservasViews(ListView):
    model = Reserva
    context_object_name = 'reservas'


class ReservasFullcalendario(TemplateView):
    template_name = 'sala_reuniones/fullcalendar.html'

    def get_context_data(self, *args, **kwargs):
        context_data = super(ReservasFullcalendario, self).get_context_data(*args, **kwargs)
        context_data['reservas'] = Reserva.objects.all()

        return context_data


class EditarReservaView(LoginRequiredMixin, FormValidMessageMixin, UpdateView):
    model = Reserva
    form_class = ReservaForm
    form_valid_message = 'Se ha editado la reserva satisfactoriamente.'
    success_url = reverse_lazy('sala_reuniones:listar_reservas')

    def get_context_data(self, *args, **kwargs):
        reserva = Reserva.objects.get(pk=self.kwargs['pk'])

        context_data = super(EditarReservaView, self).get_context_data(*args, **kwargs)
        context_data['sala_reunion'] = reserva.sala_reuniones
        context_data['horarios'] = reserva.sala_reuniones.horario_disponibilidad.all()
        context_data['editar'] = True
        context_data['pk'] = self.object.pk

        return context_data


class EliminarReservasView(LoginRequiredMixin, DeleteView):
    model = Reserva
    success_url = reverse_lazy('sala_reuniones:listar_reservas')
