Flow improvements
Dynamic displaying of received offers
This commit is contained in:
parent
f51350f28f
commit
81f7d6eb66
20 changed files with 256 additions and 45 deletions
|
@ -1,3 +1,6 @@
|
|||
from django.contrib import admin
|
||||
from urlaubsauktion.admin import joker_admin as admin
|
||||
|
||||
# Register your models here.
|
||||
from .models import Inquiry, Offer
|
||||
|
||||
admin.register(Inquiry)
|
||||
admin.register(Offer)
|
|
@ -1,8 +1,11 @@
|
|||
from django.contrib.gis.db import models
|
||||
from django.utils import timezone
|
||||
from django.conf import settings
|
||||
|
||||
from clients.models import ClientProfile
|
||||
from partners.models import Establishment
|
||||
from partners.models import Establishment, RoomCategory
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
import uuid
|
||||
|
||||
|
@ -37,10 +40,19 @@ class Inquiry(models.Model):
|
|||
self.activated = timezone.now()
|
||||
self.save()
|
||||
|
||||
@property
|
||||
def expiry(self):
|
||||
if self.activated:
|
||||
return self.activated + relativedelta(days=settings.INQUIRY_RUNTIME)
|
||||
|
||||
@property
|
||||
def expired(self):
|
||||
return self.expiry and (self.expiry < timezone.now())
|
||||
|
||||
@property
|
||||
def active(self):
|
||||
try:
|
||||
return bool(self.activated)
|
||||
return bool(self.activated) and not self.expired
|
||||
except:
|
||||
return False
|
||||
|
||||
|
@ -52,9 +64,18 @@ class Inquiry(models.Model):
|
|||
return qset[0]
|
||||
|
||||
class Offer(models.Model):
|
||||
uuid = models.UUIDField(default=uuid.uuid4, unique=True)
|
||||
inquiry = models.ForeignKey(Inquiry, models.PROTECT)
|
||||
establishment = models.ForeignKey(Establishment, models.PROTECT)
|
||||
nights = models.IntegerField()
|
||||
roomcategory = models.ForeignKey(RoomCategory, models.PROTECT)
|
||||
departure = models.DateField()
|
||||
comment = models.TextField(null=True, blank=True)
|
||||
accepted = models.BooleanField(default=False)
|
||||
hidden = models.BooleanField(default=False)
|
||||
|
||||
@property
|
||||
def establishment(self):
|
||||
return self.roomcategory.establishment
|
||||
|
||||
@property
|
||||
def nights(self):
|
||||
return (self.departure - self.inquiry.arrival).days
|
|
@ -1,7 +1,7 @@
|
|||
from django.views.generic import CreateView, UpdateView, View, ListView, DetailView
|
||||
from django.shortcuts import redirect, get_object_or_404
|
||||
from django.contrib import messages
|
||||
from django.urls import reverse
|
||||
from django.urls import reverse, reverse_lazy
|
||||
from django.contrib.gis.geos import Point
|
||||
from django.contrib.gis.db.models.functions import Distance
|
||||
from django.conf import settings
|
||||
|
@ -110,14 +110,16 @@ class OfferSelectionTableView(InConstructionMixin, ListView):
|
|||
|
||||
def get_queryset(self):
|
||||
inquiry = get_object_or_404(Inquiry, uuid=self.kwargs["uuid"])
|
||||
return inquiry.offer_set.all()
|
||||
|
||||
class OfferCreationView(InConstructionMixin, PartnerProfileRequiredMixin, CreateView):
|
||||
model = Offer
|
||||
template_name = "auction/offer_create.html"
|
||||
fields = []
|
||||
fields = ["roomcategory", "departure", "comment"]
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.establishment = self.get_establishment()
|
||||
self.inquiry = self.get_inquiry()
|
||||
|
||||
if not self.establishment:
|
||||
messages.warning(request, "Um bieten zu können, muss zuerst eine Unterkunft im System hinterlegt werden!")
|
||||
|
@ -135,12 +137,23 @@ class OfferCreationView(InConstructionMixin, PartnerProfileRequiredMixin, Create
|
|||
else:
|
||||
return Establishment.objects.filter(**kwargs).first()
|
||||
|
||||
def get_inquiry(self):
|
||||
return get_object_or_404(Inquiry, uuid=self.kwargs.get("inquiry"))
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["establishment"] = self.establishment
|
||||
context["inquiry"] = get_object_or_404(Inquiry, uuid=self.kwargs.get("inquiry"))
|
||||
context["inquiry"] = self.inquiry
|
||||
return context
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.inquiry = self.inquiry
|
||||
return super().form_valid(form)
|
||||
|
||||
def get_success_url(self):
|
||||
messages.success(self.request, "Angebot erfolgreich erstellt! Viel Erfolg!")
|
||||
return reverse_lazy("auction:bidding", args=[self.establishment.id])
|
||||
|
||||
class BiddingListView(InConstructionMixin, PartnerProfileRequiredMixin, ListView):
|
||||
model = Inquiry
|
||||
template_name = "auction/bidding_list.html"
|
||||
|
@ -166,7 +179,8 @@ class BiddingListView(InConstructionMixin, PartnerProfileRequiredMixin, ListView
|
|||
|
||||
def get_queryset(self):
|
||||
establishment = self.get_establishment()
|
||||
return Inquiry.objects.annotate(distance=Distance("destination_coords", establishment.coords)).exclude(activated__isnull=True)
|
||||
excluded = [offer.inquiry.id for offer in establishment.offer_set.all()]
|
||||
return Inquiry.objects.annotate(distance=Distance("destination_coords", establishment.coords)).exclude(activated__isnull=True).exclude(id__in=excluded)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
|
|
@ -35,3 +35,7 @@ JOKER_COUNTRIES = ["AT"]
|
|||
CURRENCY_SYMBOL = "€"
|
||||
CURRENCY_CODE = "EUR"
|
||||
CURRENCY_NAME = "Euro"
|
||||
|
||||
# Run time of inquiries in days
|
||||
|
||||
INQUIRY_RUNTIME = 7
|
|
@ -1,3 +1,7 @@
|
|||
from django.contrib import admin
|
||||
from urlaubsauktion.admin import joker_admin as admin
|
||||
|
||||
# Register your models here.
|
||||
from .models import PartnerProfile, Establishment, RoomCategory
|
||||
|
||||
admin.register(PartnerProfile)
|
||||
admin.register(Establishment)
|
||||
admin.register(RoomCategory)
|
|
@ -18,7 +18,7 @@ class Establishment(LocationMixin, ImageMixin, PhoneMixin):
|
|||
superior = models.BooleanField("Superior", default=False)
|
||||
verified = models.BooleanField(default=False)
|
||||
active = models.BooleanField(default=True)
|
||||
featureset = models.OneToOneField(FeatureSet, models.PROTECT, null=True)
|
||||
featureset = models.OneToOneField(FeatureSet, models.PROTECT, null=True, blank=True)
|
||||
|
||||
@property
|
||||
def user(self):
|
||||
|
@ -32,7 +32,16 @@ class Establishment(LocationMixin, ImageMixin, PhoneMixin):
|
|||
def booking_set(self):
|
||||
return self.offer_set.filter(accepted=True)
|
||||
|
||||
@property
|
||||
def offer_set(self):
|
||||
querysets = []
|
||||
for roomcategory in self.roomcategory_set.all():
|
||||
querysets.append(roomcategory.offer_set.all())
|
||||
|
||||
return querysets[0].union(*querysets[1:])
|
||||
|
||||
class RoomCategory(ImageMixin):
|
||||
establishment = models.ForeignKey(Establishment, models.CASCADE)
|
||||
name = models.CharField(max_length=64)
|
||||
average_price = models.DecimalField(max_digits=10, decimal_places=2)
|
||||
name = models.CharField("Name", max_length=64)
|
||||
average_price = models.DecimalField("Durchschnittspreis / Nacht", max_digits=10, decimal_places=2)
|
||||
active = models.BooleanField(default=True)
|
|
@ -5,8 +5,8 @@ register = template.Library()
|
|||
@register.simple_tag
|
||||
def stars(number, superior=False, color=""):
|
||||
number = int(number)
|
||||
if not 1 <= number <= 5:
|
||||
raise ValueError("Number of stars must be between 1 and 5.")
|
||||
if not 0 <= number <= 5:
|
||||
raise ValueError("Number of stars must be between 0 and 5.")
|
||||
|
||||
output = ""
|
||||
|
||||
|
@ -22,7 +22,7 @@ def stars(number, superior=False, color=""):
|
|||
def hearts(number, color=""):
|
||||
number = int(number)
|
||||
if not 1 <= number <= 5:
|
||||
raise ValueError("Number of hearts must be between 1 and 5.")
|
||||
raise ValueError("Number of hearts must be between 0 and 5.")
|
||||
|
||||
output = ""
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django.urls import path, reverse_lazy
|
||||
from django.views.generic import RedirectView
|
||||
|
||||
from .views import PartnerRegistrationView, PartnerProfileView, OffersListView, EstablishmentsListView, EstablishmentRequestView, PartnerDashboardView, EstablishmentVerificationView
|
||||
from .views import PartnerRegistrationView, PartnerProfileView, OffersListView, EstablishmentsListView, EstablishmentRequestView, PartnerDashboardView, EstablishmentVerificationView, RoomCategoryListView
|
||||
|
||||
app_name = "partners"
|
||||
|
||||
|
@ -9,6 +9,7 @@ urlpatterns = [
|
|||
path('register/', PartnerRegistrationView.as_view(), name="register"),
|
||||
path('profile/', PartnerProfileView.as_view(), name="profile"),
|
||||
path('establishments/', EstablishmentsListView.as_view(), name="establishments"),
|
||||
path('establishments/<int:id>/', RoomCategoryListView.as_view(), name="roomcategories"),
|
||||
path('establishments/validate/', EstablishmentVerificationView.as_view(), name="establishment_verify"),
|
||||
path('establishments/register/', EstablishmentRequestView.as_view(), name="establishment_register"),
|
||||
path('offers/', OffersListView.as_view(), name="offers"),
|
||||
|
|
|
@ -4,7 +4,7 @@ from django.http import HttpResponseRedirect
|
|||
from django.shortcuts import get_list_or_404, redirect, get_object_or_404
|
||||
from django.contrib import messages
|
||||
|
||||
from .models import PartnerProfile, Establishment
|
||||
from .models import PartnerProfile, Establishment, RoomCategory
|
||||
from .mixins import PartnerProfileRequiredMixin
|
||||
from .forms import VerificationForm
|
||||
|
||||
|
@ -82,6 +82,46 @@ class EstablishmentsListView(InConstructionMixin, PartnerProfileRequiredMixin, L
|
|||
def get_queryset(self):
|
||||
return self.request.user.partnerprofile.establishment_set.all()
|
||||
|
||||
class RoomCategoryListView(InConstructionMixin, PartnerProfileRequiredMixin, CreateView, ListView):
|
||||
model = RoomCategory
|
||||
template_name = "partners/roomcategory_list.html"
|
||||
fields = ["name", "average_price"]
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.establishment = self.get_establishment()
|
||||
|
||||
if not self.establishment:
|
||||
messages.warning(request, "Um bieten zu können, muss zuerst eine Unterkunft im System hinterlegt werden!")
|
||||
return redirect("partners:establishment_register")
|
||||
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_establishment(self):
|
||||
establishment = self.kwargs.get("id", None)
|
||||
kwargs = {"owner": self.request.user.partnerprofile}
|
||||
|
||||
if establishment:
|
||||
kwargs["id"] = establishment
|
||||
return get_object_or_404(Establishment, **kwargs)
|
||||
else:
|
||||
return Establishment.objects.filter(**kwargs).first()
|
||||
|
||||
def get_queryset(self):
|
||||
establishment = self.establishment
|
||||
return RoomCategory.objects.filter(establishment=establishment)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["establishment"] = self.establishment
|
||||
return context
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.establishment = self.establishment
|
||||
return super().form_valid(form)
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse_lazy("partners:roomcategories", args=[self.establishment.id])
|
||||
|
||||
class EstablishmentRequestView(InConstructionMixin, PartnerProfileRequiredMixin, CreateView):
|
||||
model = Establishment
|
||||
template_name = "partners/establishment_register.html"
|
||||
|
@ -112,4 +152,4 @@ class EstablishmentVerificationView(SuperUserRequiredMixin, FormView):
|
|||
|
||||
messages.success(self.request, "Unterkunft %s bestätigt!" % eobj[0].name)
|
||||
|
||||
return HttpResponseRedirect(resolve_url("partners:establishment_verify"))
|
||||
return HttpResponseRedirect(reverse_lazy("partners:establishment_verify"))
|
|
@ -16,4 +16,5 @@ phonenumbers
|
|||
googlemaps
|
||||
Babel
|
||||
staticmap
|
||||
django-mathfilters
|
||||
git+https://kumig.it/kumisystems/PyInvoice
|
|
@ -15,7 +15,11 @@
|
|||
<div class="row d-flex justify-content-center">
|
||||
<div class="col-md-12 col-lg-12 col-lg-offset-2">
|
||||
<h2>{% trans "Verfügbare Anfragen" %}</h2>
|
||||
<div>für {{ establishment.name }}</div>
|
||||
<div>für <select id="id_establishment" name="establishment" class="">
|
||||
{% for e in request.user.partnerprofile.establishment_set.all %}
|
||||
<option value="{{ e.id }}" {% if e == establishment %}selected{% endif %}>{{ e.name }}</option>
|
||||
{% endfor %}
|
||||
</select> </div>
|
||||
<table id="biddingtable">
|
||||
<thead>
|
||||
<td>ID</td>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
{% load static %}
|
||||
{% load mapimage %}
|
||||
{% load dbsetting %}
|
||||
{% load mathfilters %}
|
||||
{% block "content" %}
|
||||
<!--================== PAGE-COVER ================-->
|
||||
<section class="page-cover" id="cover-hotel-booking">
|
||||
|
@ -51,6 +52,10 @@
|
|||
<td>{% trans "Anreisedatum" %}</td>
|
||||
<td>{{ inquiry.arrival|date:"SHORT_DATE_FORMAT" }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans "Aufenthaltsdauer" %}</td>
|
||||
<td>{% if inquiry.min_nights == 0 %}Egal!{% elif inquiry.min_nights == 1 %}Kurztrip (2 – 3 Nächte){% else %}min. 3 Nächte{% endif %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans "Erwachsene" %}</td>
|
||||
<td>{{ inquiry.adults }}</td>
|
||||
|
@ -112,7 +117,9 @@
|
|||
<div class="form-group">
|
||||
<label>{% trans "Zimmerkategorie" %}</label>
|
||||
<select class="form-control" id="id_roomcategory" name="roomcategory">
|
||||
<option value="0">Standardzimmer</option>
|
||||
{% for roomcategory in establishment.roomcategory_set.all %}
|
||||
<option value="{{ roomcategory.id }}">{{ roomcategory.name }} (€ {{ roomcategory.average_price }}/Nacht – {{ inquiry.budget|intdiv:roomcategory.average_price }} Nächte)</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div><!-- end columns -->
|
||||
|
@ -145,10 +152,10 @@
|
|||
</div><!-- end row -->
|
||||
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" {% if request.user.is_authenticated %}required{% else %}disabled{% endif %} id="id_terms" name="terms"> {% trans "Ich erkläre mich einverstanden mit den" %} <a href="#">{% trans "Allgemeinen Geschäftsbedingungen" %}</a> {% trans "und der" %} <a href="#">{% trans "Datenschutzerklärung" %}</a>. Ich verstehe insbesondere, dass ich an dieses Angebot gebunden bin und dieses nach Annahme durch die anfragende Person nicht mehr zurückziehen kann.</label>
|
||||
<label><input type="checkbox" required id="id_terms" name="terms"> {% trans "Ich erkläre mich einverstanden mit den" %} <a href="#">{% trans "Allgemeinen Geschäftsbedingungen" %}</a> {% trans "und der" %} <a href="#">{% trans "Datenschutzerklärung" %}</a>. Ich verstehe insbesondere, dass ich an dieses Angebot gebunden bin und dieses nach Annahme durch die anfragende Person nicht mehr zurückziehen kann.</label>
|
||||
</div><!-- end checkbox -->
|
||||
<div class="col-md-12 text-center" id="result_msg"></div>
|
||||
<button type="submit" onclick="setPaymentMethod(); return true;" class="btn btn-orange" name="submit" id="submit">{% trans "Zahlung durchführen" %}</button>
|
||||
<button type="submit" class="btn btn-orange" name="submit" id="submit">{% trans "Angebot erstellen" %}</button>
|
||||
</form>
|
||||
|
||||
</div><!-- end columns -->
|
||||
|
|
|
@ -14,7 +14,13 @@
|
|||
<div class="col-md-12 col-lg-8 col-lg-offset-2">
|
||||
<div class="payment-success-text">
|
||||
<h1>Angebote vergleichen</h1>
|
||||
{% if object.offer_set.all %}
|
||||
<div id="offers" style="text-align: center;"></div>
|
||||
{% else %}
|
||||
<div class="alert alert-warning alert-dismissible text-center" role="alert">
|
||||
Leider sind zu deiner Anfrage bislang noch keine Angebote eingegangen. Komm doch einfach später nochmal vorbei!
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div><!-- end columns -->
|
||||
</div><!-- end row -->
|
||||
|
|
|
@ -6,30 +6,40 @@
|
|||
{
|
||||
from: "",
|
||||
tableHeader: [
|
||||
['Habbo Hotel<br/>{% autoescape off %}{% stars 3 1 orange %}{% endautoescape %}<br/><img style="max-height:100px;max-width:100%;" src="https://logoeps.com/wp-content/uploads/2012/12/habbo-logo-vector.png"></img>'],
|
||||
['Kumi Systems<br/>{% autoescape off %}{% stars 1 0 orange %}{% endautoescape %}<br/><img style="max-height:100px;max-width:100%;" src="https://kumi.systems/wp-content/uploads/2020/12/schrift_logo.png"></img>'],
|
||||
{% for offer in object_list %}['{{ offer.roomcategory.establishment.name }}<br/>{% autoescape off %}{% stars offer.roomcategory.establishment.stars offer.roomcategory.establishment.superior orange %}{% endautoescape %}{% if offer.roomcategory.establishment.image %}<br/><img style="max-height:100px;max-width:100%;" src="{{ offer.roomcategory.establishment.image.url }}"></img>{% endif %}'],{% endfor %}
|
||||
],
|
||||
rows : [
|
||||
{
|
||||
rowVal: [["1. Mai 2021", "1. Mai 2021"],["3. Mai 2021", "10. Mai 2021"],["2 Nächte", "9 Nächte"]],
|
||||
rowVal: [
|
||||
[{% for offer in object_list %}'{{ offer.inquiry.arrival }}',{% endfor %}],
|
||||
[{% for offer in object_list %}'{{ offer.departure }}',{% endfor %}],
|
||||
[{% for offer in object_list %}'{{ offer.nights }} Nächte',{% endfor %}]
|
||||
],
|
||||
rowDesc: ["Anreise", "Abreise", "Dauer"]
|
||||
},
|
||||
{
|
||||
rowVal: [[{% autoescape off %}'{% hearts 3 red %} (304)', '{% hearts 5 red %} (1)'{% endautoescape %}]],
|
||||
rowVal: [
|
||||
[{% for offer in object_list %}{% autoescape off %}'{% hearts 3 red %} (304)'{% endautoescape %},{% endfor %}]
|
||||
],
|
||||
rowDesc: ["Bewertungen"]
|
||||
},
|
||||
{
|
||||
rowVal: [['Doppelzimmer Luxus', 'Wohnzimmer'], ["1 King-Size Bett", "1 Couch"]],
|
||||
rowVal: [
|
||||
[{% for offer in object_list %}'{{ offer.roomcategory.name }}',{% endfor %}],
|
||||
[{% for offer in object_list %}' ',{% endfor %}]
|
||||
],
|
||||
rowDesc: ["Zimmerart", "Betten"]
|
||||
},
|
||||
{
|
||||
rowVal: [['Romantikpaket inkl. Frühstück am Bett, 2x 60 Minuten Hot-Stone-Massage, 0,75l Prosecco, Obstschale, Zugang zum Spa', 'Gratis Arbeitsgelegenheit inklusive!']],
|
||||
rowVal: [
|
||||
[{% for offer in object_list %}'{{ offer.comment }}',{% endfor %}]
|
||||
],
|
||||
rowDesc: ["Zusätzliche Angaben"]
|
||||
},
|
||||
{
|
||||
rowVal: [
|
||||
[200, 200],
|
||||
['<button class="btn btn-orange btn-block">Zahlungspflichtig buchen!</button>', '<button class="btn btn-orange btn-block">Zahlungspflichtig buchen!</button>']
|
||||
[{% for offer in object_list %}'€ {{ offer.inquiry.budget }}',{% endfor %}],
|
||||
[{% for offer in object_list %}'<a href="#{{ offer.uuid }}" class="btn btn-orange btn-block">Zahlungspflichtig buchen!</button>',{% endfor %}]
|
||||
],
|
||||
rowDesc: ["Fixpreis", ""]
|
||||
}
|
||||
|
|
|
@ -55,6 +55,10 @@
|
|||
<td>{% trans "Anreisedatum" %}</td>
|
||||
<td>{{ object.arrival|date:"SHORT_DATE_FORMAT" }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans "Aufenthaltsdauer" %}</td>
|
||||
<td>{% if object.min_nights == 0 %}Egal!{% elif object.min_nights == 1 %}Kurztrip (2 – 3 Nächte){% else %}min. 3 Nächte{% endif %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans "Erwachsene" %}</td>
|
||||
<td>{{ object.adults }}</td>
|
||||
|
@ -254,7 +258,7 @@
|
|||
<img src="{% static "frontend/images/paypal.png" %}" class="img-fluid" alt="stripe" />
|
||||
<div class="paypal-text">
|
||||
<p>{% trans "Die Zahlung per Kreditkarte wird durch unseren Zahlungsdienstleister Stripe abgewickelt." %}</p>
|
||||
<p>{% trans "Der gebotene Betrag wird autorisiert und erst bei verbindlicher Buchung einer Reise tatsächlich von Ihrer Kreditkarte abgebucht." %}</p>
|
||||
<p>{% trans "Der gebotene Betrag wird autorisiert und erst bei verbindlicher Buchung einer Reise tatsächlich von Ihrer Kreditkarte abgebucht. Bei Auslaufen oder Stornierung Ihres Angebots wird der Betrag ohne Abzug wieder freigegeben." %}</p>
|
||||
</div><!-- end paypal-text -->
|
||||
|
||||
<div class="clearfix"></div>
|
||||
|
|
|
@ -28,19 +28,29 @@
|
|||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<tbody>
|
||||
{% for inquiry in object_list %}
|
||||
<tr>
|
||||
<td class="dash-list-icon booking-list-date"><div class="b-date"><h3>12</h3><p>April 2021</p></div></td>
|
||||
<td class="dash-list-icon booking-list-date"><div class="b-date"><h3>{{ inquiry.arrival.day }}</h3><p>{{ inquiry.arrival|date:"E Y" }}</p></div></td>
|
||||
<td class="dash-list-text booking-list-detail">
|
||||
<h3>Habbo Hotel</h3>
|
||||
<h3>{% if inquiry.accepted %}{{ inquiry.accepted.name }} ({{ inquiry.destination_name }}){% else %}{{ inquiry.destination_name }}{% endif %}</h3>
|
||||
<ul class="list-unstyled booking-info">
|
||||
<li><span>Ankunft:</span> 12. April 2021</li>
|
||||
<li><span>Abreise:</span> 19. April 2021</li>
|
||||
<li><span>Preis:</span> € 500,00</li>
|
||||
<li><span>Ankunft:</span> {{ inquiry.arrival }}</li>
|
||||
<li><span>{% if inquiry.accepted %}Abreise{% else %}Dauer{% endif %}:</span> {% if inquiry.accepted %}{{ inquiry.accepted.departure }}{% elif inquiry.min_nights == 0 %}Egal!{% elif inquiry.min_nights == 1 %}Kurztrip (2 – 3 Nächte){% elif inquiry.min_nights == 2 %}min. 3 Nächte{% endif %}</li>
|
||||
<li><span>Preis:</span> € {{ inquiry.budget }}</li>
|
||||
<li><span>Status:</span> {% if inquiry.accepted %}Fixiert{% elif inquiry.active %}In Gebotsphase ({{ inquiry.offer_set.all|length }} Gebote){% else %}Inaktiv{% endif %}</li>
|
||||
</ul>
|
||||
<button class="btn btn-orange">Details</button>
|
||||
{% if inquiry.accepted %}
|
||||
<button class="btn btn-orange">Buchungsdetails</button>
|
||||
{% elif inquiry.active %}
|
||||
<a href="{% url "auction:offer_selection" inquiry.uuid %}" class="btn btn-orange">Gebote ansehen</a>
|
||||
{% elif inquiry.expired %}
|
||||
{% else %}
|
||||
<a href="{% url "auction:process_inquiry" inquiry.uuid %}" class="btn btn-orange">Zahlung abschließen</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="dash-list-btn"><button class="btn btn-orange">Stornieren</button><button class="btn">PDF-Bestätigung</button></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div><!-- end table-responsive -->
|
||||
|
|
|
@ -35,9 +35,9 @@
|
|||
<li><span>Buchungen:</span> {{ establishment.bookings | length }}</li>
|
||||
<li><span>Status:</span> {% if establishment.is_active %}aktiv{% else %}inaktiv{% endif %}</li>
|
||||
</ul>
|
||||
<button class="btn btn-orange">Details</button>
|
||||
<a href="{% url "partners:roomcategories" establishment.id %}" class="btn btn-orange">Zimmer und Ausstattung bearbeiten</button>
|
||||
</td>
|
||||
<td class="dash-list-btn"><a href="{% url "partners:bidding" 1 %}" class="btn btn-orange">Bieten</a><button class="btn">Deaktivieren</button></td>
|
||||
<td class="dash-list-btn"><a href="{% url "auction:bidding" establishment.id %}" class="btn btn-orange">Bieten</a><button class="btn">Deaktivieren</button></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% extends "clients/base.html" %}
|
||||
{% extends "partners/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load bootstrap4 %}
|
||||
{% block "dashboardcontent" %}
|
||||
|
|
71
templates/partners/roomcategory_list.html
Normal file
71
templates/partners/roomcategory_list.html
Normal file
|
@ -0,0 +1,71 @@
|
|||
{% extends "partners/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load bootstrap4 %}
|
||||
{% block "dashboardcontent" %}
|
||||
<div class="col-12 col-md-10 col-lg-10 dashboard-content booking-trips">
|
||||
<h2 class="dash-content-title">Deine Zimmerkategorien</h2>
|
||||
<div class="dash-content-title"><small>für {{ establishment.name }}</small></div>
|
||||
<div class="dash-content-title"><button class="btn" data-toggle="modal" data-target="#create-category">Kategorie hinzufügen</button></div>
|
||||
<div class="dashboard-listing booking-listing">
|
||||
<div class="dash-listing-heading">
|
||||
<div class="custom-radio">
|
||||
<input type="radio" id="radio01" name="radio" checked/>
|
||||
<label for="radio01"><span></span>Alle Kategorien</label>
|
||||
</div><!-- end custom-radio -->
|
||||
|
||||
<div class="custom-radio">
|
||||
<input type="radio" id="radio02" name="radio" />
|
||||
<label for="radio02"><span></span>Aktiv</label>
|
||||
</div><!-- end custom-radio -->
|
||||
|
||||
<div class="custom-radio">
|
||||
<input type="radio" id="radio03" name="radio" />
|
||||
<label for="radio03"><span></span>Inaktiv</label>
|
||||
</div><!-- end custom-radio -->
|
||||
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<tbody>
|
||||
{% for roomcategory in object_list %}
|
||||
<tr>
|
||||
<td class="dash-list-text booking-list-detail">
|
||||
<h3>{{ roomcategory.name }}</h3>
|
||||
<ul class="list-unstyled booking-info">
|
||||
<li><span>Durchschnittspreis:</span> {{ roomcategory.average_price }}</li>
|
||||
<li><span>Buchungen:</span> {{ roomcategory.bookings | length }}</li>
|
||||
<li><span>Status:</span> {% if roomcategory.active %}aktiv{% else %}inaktiv{% endif %}</li>
|
||||
</ul>
|
||||
<a href="{% url "partners:roomcategories" establishment.id %}" class="btn btn-orange">Zimmer und Ausstattung bearbeiten</button>
|
||||
</td>
|
||||
<td class="dash-list-btn"><a href="{% url "auction:bidding" establishment.id %}" class="btn btn-orange">Bieten</a><button class="btn">Deaktivieren</button></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div><!-- end table-responsive -->
|
||||
</div><!-- end booking-listings -->
|
||||
|
||||
</div><!-- end columns -->
|
||||
{% endblock %}
|
||||
{% block "modal" %}
|
||||
<div id="create-category" class="modal custom-modal fade" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">Profildaten</h3>
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
</div><!-- end modal-header -->
|
||||
|
||||
<div class="modal-body">
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form form %}
|
||||
<button class="btn btn-orange btn-block">Anwenden</button>
|
||||
</form>
|
||||
</div><!-- end modal-bpdy -->
|
||||
</div><!-- end modal-content -->
|
||||
</div><!-- end modal-dialog -->
|
||||
</div><!-- end edit-profile -->
|
||||
{% endblock %}
|
|
@ -14,6 +14,7 @@ INSTALLED_APPS = [
|
|||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'django.contrib.gis',
|
||||
'phonenumber_field',
|
||||
'localauth',
|
||||
'public',
|
||||
|
@ -24,6 +25,7 @@ INSTALLED_APPS = [
|
|||
'auction',
|
||||
'bootstrap4',
|
||||
'django_countries',
|
||||
'mathfilters',
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
|
|
Loading…
Reference in a new issue