Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 67 additions & 1 deletion pms/forms.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
from datetime import datetime
from datetime import date, datetime
from django import forms
from django.forms import ModelForm

from .models import Booking, Customer

MAX_BOOKING_DATE = date(2026, 12, 31)



class RoomSearchForm(ModelForm):
class Meta:
Expand Down Expand Up @@ -56,3 +59,66 @@ class Meta:
'total': forms.HiddenInput(),
'state': forms.HiddenInput(),
}


class BookingDatesForm(forms.Form):
checkin = forms.DateField(
label="Check-in",
widget=forms.DateInput(attrs={
"type": "date",
"min": date.today().isoformat(),
"max": MAX_BOOKING_DATE.isoformat(),
"class": "form-control",
}),
)
checkout = forms.DateField(
label="Check-out",
widget=forms.DateInput(attrs={
"type": "date",
"min": date.today().isoformat(),
"max": MAX_BOOKING_DATE.isoformat(),
"class": "form-control",
}),
)

def __init__(self, *args, room, booking_id, **kwargs):
super().__init__(*args, **kwargs)
self._room = room
self._booking_id = booking_id

def clean(self):
cleaned_data = super().clean()
checkin = cleaned_data.get("checkin")
checkout = cleaned_data.get("checkout")

if not checkin or not checkout:
return cleaned_data

if checkout <= checkin:
raise forms.ValidationError(
"La fecha de check-out debe ser posterior al check-in."
)

if checkout > MAX_BOOKING_DATE:
raise forms.ValidationError(
f"La fecha máxima de check-out es {MAX_BOOKING_DATE.strftime('%d/%m/%Y')}."
)

overlaps = (
Booking.objects
.filter(
room=self._room,
state=Booking.NEW,
checkin__lt=checkout,
checkout__gt=checkin,
)
.exclude(pk=self._booking_id)
.exists()
)
if overlaps:
raise forms.ValidationError(
"No hay disponibilidad para las fechas seleccionadas."
)

return cleaned_data

5 changes: 4 additions & 1 deletion pms/templates/dashboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@ <h1 class="dashboard-value">{{dashboard.incoming_guests}}</h1>
<h5 class="small">Huéspedes saliendo</h5>
<h1 class="dashboard-value">{{dashboard.outcoming_guests}}</h1>
</div>

<div class="card text-white p-3 card-customization" style="background-color: #ff7f7f;">
<h5 class="small">Total facturado</h5>
<h1 class="dashboard-value">€ {% if dashboard.invoiced.total__sum == None %}0.00{% endif %} {{dashboard.invoiced.total__sum|floatformat:2}}</h1>
</div>
<div class="card text-white p-3 card-customization" style="background-color: #7b2d8b;">
<h5 class="small">Ocupación</h5>
<h1 class="dashboard-value">{{ dashboard.occupancy_rate }}%</h1>
</div>
</div>
</div>
{% endblock content%}
38 changes: 38 additions & 0 deletions pms/templates/edit_booking_dates.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{% extends "main.html" %}

{% block content %}
<div class="mt-4" style="max-width: 480px;">
<h1 class="mb-1">Editar fechas de reserva</h1>
<p class="text-muted mb-4">
Reserva <strong>{{ booking.code }}</strong> &mdash; {{ booking.room.name }}
</p>

{% if form.non_field_errors %}
<div class="alert alert-danger" role="alert">
{% for error in form.non_field_errors %}
{{ error }}
{% endfor %}
</div>
{% endif %}

<form method="post" action="" novalidate>
{% csrf_token %}
{% for field in form %}
<div class="mb-3">
<label for="{{ field.id_for_label }}" class="form-label fw-semibold">
{{ field.label }}
</label>
{{ field }}
{% if field.errors %}
<div class="text-danger small mt-1">{{ field.errors.0 }}</div>
{% endif %}
</div>
{% endfor %}

<div class="d-flex gap-2 mt-4">
<button type="submit" class="btn btn-primary">Guardar fechas</button>
<a href="{% url 'home' %}" class="btn btn-outline-secondary">Cancelar</a>
</div>
</form>
</div>
{% endblock content %}
5 changes: 3 additions & 2 deletions pms/templates/home.html
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,9 @@ <h3>Reservas Realizadas</h3>
<a href="{% url 'edit_booking' pk=booking.id%} " >Editar datos de contacto</a>
</div>
<div class="col">

</div>
{% if booking.state != "DEL" %}
<a href="{% url 'edit_booking_dates' pk=booking.id %}">Editar fechas</a>
{% endif %}
<div class="col">

{% if booking.state != "DEL" %}
Expand Down
52 changes: 43 additions & 9 deletions pms/templates/rooms.html
Original file line number Diff line number Diff line change
@@ -1,19 +1,53 @@
{% extends "main.html"%}

{% block content %}
<h1>Habitaciones del hotel</h1>
{% for room in rooms%}
<div class="d-flex justify-content-between align-items-center mt-4 mb-3">
<h1 class="mb-0">Habitaciones del hotel</h1>
</div>

<form method="GET" action="" class="mb-4">
<div class="input-group">
<input
type="search"
name="q"
class="form-control"
placeholder="Buscar por nombre de habitación…"
value="{{ query }}"
aria-label="Buscar habitación"
autocomplete="off"
>
<button class="btn btn-primary" type="submit">
<i class="bi bi-search me-1"></i> Buscar
</button>
{% if query %}
<a href="{% url 'rooms' %}" class="btn btn-outline-secondary">Limpiar</a>
{% endif %}
</div>
</form>

{% if query %}
<p class="text-muted small mb-3">
{% if rooms %}
{{ rooms|length }} resultado{{ rooms|length|pluralize:"s" }} para "<strong>{{ query }}</strong>"
{% else %}
No se encontraron habitaciones para "<strong>{{ query }}</strong>".
{% endif %}
</p>
{% endif %}

{% for room in rooms %}
<div class="row card mt-3 mb-3 hover-card bg-tr-250">
<div class="col p-3">
<div class="">
{{room.name}} ({{room.room_type__name}})
</div>
<div>{{ room.name }} ({{ room.room_type__name }})</div>
<div>
<a href="{% url 'room_details' pk=room.id%}">Ver detalles</a>
<a href="{% url 'room_details' pk=room.id %}">Ver detalles</a>
</div>

</div>

</div>
{% empty %}
{% if not query %}
<p class="text-muted mt-4">No hay habitaciones registradas.</p>
{% endif %}
{% endfor %}
{% endblock content%}
{% endblock content %}

Loading