Flow improvements

Dynamic displaying of received offers
This commit is contained in:
Kumi 2021-04-20 08:36:59 +02:00
parent f51350f28f
commit 81f7d6eb66
20 changed files with 256 additions and 45 deletions

View file

@ -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)

View file

@ -1,8 +1,11 @@
from django.contrib.gis.db import models from django.contrib.gis.db import models
from django.utils import timezone from django.utils import timezone
from django.conf import settings
from clients.models import ClientProfile from clients.models import ClientProfile
from partners.models import Establishment from partners.models import Establishment, RoomCategory
from dateutil.relativedelta import relativedelta
import uuid import uuid
@ -37,10 +40,19 @@ class Inquiry(models.Model):
self.activated = timezone.now() self.activated = timezone.now()
self.save() 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 @property
def active(self): def active(self):
try: try:
return bool(self.activated) return bool(self.activated) and not self.expired
except: except:
return False return False
@ -52,9 +64,18 @@ class Inquiry(models.Model):
return qset[0] return qset[0]
class Offer(models.Model): class Offer(models.Model):
uuid = models.UUIDField(default=uuid.uuid4, unique=True)
inquiry = models.ForeignKey(Inquiry, models.PROTECT) inquiry = models.ForeignKey(Inquiry, models.PROTECT)
establishment = models.ForeignKey(Establishment, models.PROTECT) roomcategory = models.ForeignKey(RoomCategory, models.PROTECT)
nights = models.IntegerField() departure = models.DateField()
comment = models.TextField(null=True, blank=True) comment = models.TextField(null=True, blank=True)
accepted = models.BooleanField(default=False) accepted = models.BooleanField(default=False)
hidden = 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

View file

@ -1,7 +1,7 @@
from django.views.generic import CreateView, UpdateView, View, ListView, DetailView from django.views.generic import CreateView, UpdateView, View, ListView, DetailView
from django.shortcuts import redirect, get_object_or_404 from django.shortcuts import redirect, get_object_or_404
from django.contrib import messages 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.geos import Point
from django.contrib.gis.db.models.functions import Distance from django.contrib.gis.db.models.functions import Distance
from django.conf import settings from django.conf import settings
@ -110,14 +110,16 @@ class OfferSelectionTableView(InConstructionMixin, ListView):
def get_queryset(self): def get_queryset(self):
inquiry = get_object_or_404(Inquiry, uuid=self.kwargs["uuid"]) inquiry = get_object_or_404(Inquiry, uuid=self.kwargs["uuid"])
return inquiry.offer_set.all()
class OfferCreationView(InConstructionMixin, PartnerProfileRequiredMixin, CreateView): class OfferCreationView(InConstructionMixin, PartnerProfileRequiredMixin, CreateView):
model = Offer model = Offer
template_name = "auction/offer_create.html" template_name = "auction/offer_create.html"
fields = [] fields = ["roomcategory", "departure", "comment"]
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
self.establishment = self.get_establishment() self.establishment = self.get_establishment()
self.inquiry = self.get_inquiry()
if not self.establishment: if not self.establishment:
messages.warning(request, "Um bieten zu können, muss zuerst eine Unterkunft im System hinterlegt werden!") 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: else:
return Establishment.objects.filter(**kwargs).first() 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): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
context["establishment"] = self.establishment context["establishment"] = self.establishment
context["inquiry"] = get_object_or_404(Inquiry, uuid=self.kwargs.get("inquiry")) context["inquiry"] = self.inquiry
return context 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): class BiddingListView(InConstructionMixin, PartnerProfileRequiredMixin, ListView):
model = Inquiry model = Inquiry
template_name = "auction/bidding_list.html" template_name = "auction/bidding_list.html"
@ -166,7 +179,8 @@ class BiddingListView(InConstructionMixin, PartnerProfileRequiredMixin, ListView
def get_queryset(self): def get_queryset(self):
establishment = self.get_establishment() 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): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)

View file

@ -35,3 +35,7 @@ JOKER_COUNTRIES = ["AT"]
CURRENCY_SYMBOL = "" CURRENCY_SYMBOL = ""
CURRENCY_CODE = "EUR" CURRENCY_CODE = "EUR"
CURRENCY_NAME = "Euro" CURRENCY_NAME = "Euro"
# Run time of inquiries in days
INQUIRY_RUNTIME = 7

View file

@ -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)

View file

@ -18,7 +18,7 @@ class Establishment(LocationMixin, ImageMixin, PhoneMixin):
superior = models.BooleanField("Superior", default=False) superior = models.BooleanField("Superior", default=False)
verified = models.BooleanField(default=False) verified = models.BooleanField(default=False)
active = models.BooleanField(default=True) active = models.BooleanField(default=True)
featureset = models.OneToOneField(FeatureSet, models.PROTECT, null=True) featureset = models.OneToOneField(FeatureSet, models.PROTECT, null=True, blank=True)
@property @property
def user(self): def user(self):
@ -32,7 +32,16 @@ class Establishment(LocationMixin, ImageMixin, PhoneMixin):
def booking_set(self): def booking_set(self):
return self.offer_set.filter(accepted=True) 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): class RoomCategory(ImageMixin):
establishment = models.ForeignKey(Establishment, models.CASCADE) establishment = models.ForeignKey(Establishment, models.CASCADE)
name = models.CharField(max_length=64) name = models.CharField("Name", max_length=64)
average_price = models.DecimalField(max_digits=10, decimal_places=2) average_price = models.DecimalField("Durchschnittspreis / Nacht", max_digits=10, decimal_places=2)
active = models.BooleanField(default=True)

View file

@ -5,8 +5,8 @@ register = template.Library()
@register.simple_tag @register.simple_tag
def stars(number, superior=False, color=""): def stars(number, superior=False, color=""):
number = int(number) number = int(number)
if not 1 <= number <= 5: if not 0 <= number <= 5:
raise ValueError("Number of stars must be between 1 and 5.") raise ValueError("Number of stars must be between 0 and 5.")
output = "" output = ""
@ -22,7 +22,7 @@ def stars(number, superior=False, color=""):
def hearts(number, color=""): def hearts(number, color=""):
number = int(number) number = int(number)
if not 1 <= number <= 5: 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 = "" output = ""

View file

@ -1,7 +1,7 @@
from django.urls import path, reverse_lazy from django.urls import path, reverse_lazy
from django.views.generic import RedirectView 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" app_name = "partners"
@ -9,6 +9,7 @@ urlpatterns = [
path('register/', PartnerRegistrationView.as_view(), name="register"), path('register/', PartnerRegistrationView.as_view(), name="register"),
path('profile/', PartnerProfileView.as_view(), name="profile"), path('profile/', PartnerProfileView.as_view(), name="profile"),
path('establishments/', EstablishmentsListView.as_view(), name="establishments"), 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/validate/', EstablishmentVerificationView.as_view(), name="establishment_verify"),
path('establishments/register/', EstablishmentRequestView.as_view(), name="establishment_register"), path('establishments/register/', EstablishmentRequestView.as_view(), name="establishment_register"),
path('offers/', OffersListView.as_view(), name="offers"), path('offers/', OffersListView.as_view(), name="offers"),

View file

@ -4,7 +4,7 @@ from django.http import HttpResponseRedirect
from django.shortcuts import get_list_or_404, redirect, get_object_or_404 from django.shortcuts import get_list_or_404, redirect, get_object_or_404
from django.contrib import messages from django.contrib import messages
from .models import PartnerProfile, Establishment from .models import PartnerProfile, Establishment, RoomCategory
from .mixins import PartnerProfileRequiredMixin from .mixins import PartnerProfileRequiredMixin
from .forms import VerificationForm from .forms import VerificationForm
@ -82,6 +82,46 @@ class EstablishmentsListView(InConstructionMixin, PartnerProfileRequiredMixin, L
def get_queryset(self): def get_queryset(self):
return self.request.user.partnerprofile.establishment_set.all() 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): class EstablishmentRequestView(InConstructionMixin, PartnerProfileRequiredMixin, CreateView):
model = Establishment model = Establishment
template_name = "partners/establishment_register.html" 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) 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"))

View file

@ -16,4 +16,5 @@ phonenumbers
googlemaps googlemaps
Babel Babel
staticmap staticmap
django-mathfilters
git+https://kumig.it/kumisystems/PyInvoice git+https://kumig.it/kumisystems/PyInvoice

View file

@ -15,7 +15,11 @@
<div class="row d-flex justify-content-center"> <div class="row d-flex justify-content-center">
<div class="col-md-12 col-lg-12 col-lg-offset-2"> <div class="col-md-12 col-lg-12 col-lg-offset-2">
<h2>{% trans "Verfügbare Anfragen" %}</h2> <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"> <table id="biddingtable">
<thead> <thead>
<td>ID</td> <td>ID</td>

View file

@ -3,6 +3,7 @@
{% load static %} {% load static %}
{% load mapimage %} {% load mapimage %}
{% load dbsetting %} {% load dbsetting %}
{% load mathfilters %}
{% block "content" %} {% block "content" %}
<!--================== PAGE-COVER ================--> <!--================== PAGE-COVER ================-->
<section class="page-cover" id="cover-hotel-booking"> <section class="page-cover" id="cover-hotel-booking">
@ -51,6 +52,10 @@
<td>{% trans "Anreisedatum" %}</td> <td>{% trans "Anreisedatum" %}</td>
<td>{{ inquiry.arrival|date:"SHORT_DATE_FORMAT" }}</td> <td>{{ inquiry.arrival|date:"SHORT_DATE_FORMAT" }}</td>
</tr> </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> <tr>
<td>{% trans "Erwachsene" %}</td> <td>{% trans "Erwachsene" %}</td>
<td>{{ inquiry.adults }}</td> <td>{{ inquiry.adults }}</td>
@ -112,7 +117,9 @@
<div class="form-group"> <div class="form-group">
<label>{% trans "Zimmerkategorie" %}</label> <label>{% trans "Zimmerkategorie" %}</label>
<select class="form-control" id="id_roomcategory" name="roomcategory"> <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> </select>
</div> </div>
</div><!-- end columns --> </div><!-- end columns -->
@ -145,10 +152,10 @@
</div><!-- end row --> </div><!-- end row -->
<div class="checkbox"> <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><!-- end checkbox -->
<div class="col-md-12 text-center" id="result_msg"></div> <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> </form>
</div><!-- end columns --> </div><!-- end columns -->

View file

@ -14,7 +14,13 @@
<div class="col-md-12 col-lg-8 col-lg-offset-2"> <div class="col-md-12 col-lg-8 col-lg-offset-2">
<div class="payment-success-text"> <div class="payment-success-text">
<h1>Angebote vergleichen</h1> <h1>Angebote vergleichen</h1>
{% if object.offer_set.all %}
<div id="offers" style="text-align: center;"></div> <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>
</div><!-- end columns --> </div><!-- end columns -->
</div><!-- end row --> </div><!-- end row -->

View file

@ -6,30 +6,40 @@
{ {
from: "", from: "",
tableHeader: [ 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>'], {% 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 %}
['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>'],
], ],
rows : [ 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"] 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"] 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 %}'&nbsp;',{% endfor %}]
],
rowDesc: ["Zimmerart", "Betten"] 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"] rowDesc: ["Zusätzliche Angaben"]
}, },
{ {
rowVal: [ rowVal: [
[200, 200], [{% for offer in object_list %}'€ {{ offer.inquiry.budget }}',{% endfor %}],
['<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 %}'<a href="#{{ offer.uuid }}" class="btn btn-orange btn-block">Zahlungspflichtig buchen!</button>',{% endfor %}]
], ],
rowDesc: ["Fixpreis", ""] rowDesc: ["Fixpreis", ""]
} }

View file

@ -55,6 +55,10 @@
<td>{% trans "Anreisedatum" %}</td> <td>{% trans "Anreisedatum" %}</td>
<td>{{ object.arrival|date:"SHORT_DATE_FORMAT" }}</td> <td>{{ object.arrival|date:"SHORT_DATE_FORMAT" }}</td>
</tr> </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> <tr>
<td>{% trans "Erwachsene" %}</td> <td>{% trans "Erwachsene" %}</td>
<td>{{ object.adults }}</td> <td>{{ object.adults }}</td>
@ -254,7 +258,7 @@
<img src="{% static "frontend/images/paypal.png" %}" class="img-fluid" alt="stripe" /> <img src="{% static "frontend/images/paypal.png" %}" class="img-fluid" alt="stripe" />
<div class="paypal-text"> <div class="paypal-text">
<p>{% trans "Die Zahlung per Kreditkarte wird durch unseren Zahlungsdienstleister Stripe abgewickelt." %}</p> <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><!-- end paypal-text -->
<div class="clearfix"></div> <div class="clearfix"></div>

View file

@ -28,19 +28,29 @@
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-hover"> <table class="table table-hover">
<tbody> <tbody>
{% for inquiry in object_list %}
<tr> <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"> <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"> <ul class="list-unstyled booking-info">
<li><span>Ankunft:</span> 12. April 2021</li> <li><span>Ankunft:</span> {{ inquiry.arrival }}</li>
<li><span>Abreise:</span> 19. April 2021</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> € 500,00</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> </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>
<td class="dash-list-btn"><button class="btn btn-orange">Stornieren</button><button class="btn">PDF-Bestätigung</button></td> <td class="dash-list-btn"><button class="btn btn-orange">Stornieren</button><button class="btn">PDF-Bestätigung</button></td>
</tr> </tr>
{% endfor %}
</tbody> </tbody>
</table> </table>
</div><!-- end table-responsive --> </div><!-- end table-responsive -->

View file

@ -35,9 +35,9 @@
<li><span>Buchungen:</span> {{ establishment.bookings | length }}</li> <li><span>Buchungen:</span> {{ establishment.bookings | length }}</li>
<li><span>Status:</span> {% if establishment.is_active %}aktiv{% else %}inaktiv{% endif %}</li> <li><span>Status:</span> {% if establishment.is_active %}aktiv{% else %}inaktiv{% endif %}</li>
</ul> </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>
<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> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>

View file

@ -1,4 +1,4 @@
{% extends "clients/base.html" %} {% extends "partners/base.html" %}
{% load i18n %} {% load i18n %}
{% load bootstrap4 %} {% load bootstrap4 %}
{% block "dashboardcontent" %} {% block "dashboardcontent" %}

View 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">&times;</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 %}

View file

@ -14,6 +14,7 @@ INSTALLED_APPS = [
'django.contrib.sessions', 'django.contrib.sessions',
'django.contrib.messages', 'django.contrib.messages',
'django.contrib.staticfiles', 'django.contrib.staticfiles',
'django.contrib.gis',
'phonenumber_field', 'phonenumber_field',
'localauth', 'localauth',
'public', 'public',
@ -24,6 +25,7 @@ INSTALLED_APPS = [
'auction', 'auction',
'bootstrap4', 'bootstrap4',
'django_countries', 'django_countries',
'mathfilters',
] ]
MIDDLEWARE = [ MIDDLEWARE = [