Preparing a bunch of views for partners
Adding superior ratings Use Nominatim for location lookups Implement hotel registration
This commit is contained in:
parent
73c13841c6
commit
41d71d313f
14 changed files with 123 additions and 32 deletions
|
@ -1,16 +1,13 @@
|
||||||
from dbsettings.functions import getValue
|
from django.conf import settings
|
||||||
|
|
||||||
import requests
|
from geopy.geocoders import Nominatim
|
||||||
|
|
||||||
def name_to_coords(name, api_key=None):
|
def name_to_coords(name):
|
||||||
URL = "https://maps.googleapis.com/maps/api/geocode/json"
|
geocoder = Nominatim(user_agent="JourneyJoker.at")
|
||||||
api_key = api_key or getValue("google.api.key")
|
|
||||||
|
|
||||||
payload = {"address": name, "key": api_key}
|
result = geocoder.geocode(name, exactly_one=True)
|
||||||
response = requests.get(URL, params=payload).json()
|
|
||||||
|
|
||||||
try:
|
return result.latitude, result.longitude
|
||||||
result = response["results"][0]
|
|
||||||
return result["geometry"]["location"]["lat"], result["geometry"]["location"]["lng"]
|
def profile_to_coords(profile):
|
||||||
except:
|
return name_to_coords("%s, %s, %s, %s" % (profile.address, profile.city, profile.zip, profile.country))
|
||||||
raise ValueError(response)
|
|
|
@ -16,4 +16,12 @@ DB_PASS = "postgresql_password"
|
||||||
|
|
||||||
# Email address of system administrator
|
# Email address of system administrator
|
||||||
|
|
||||||
ADMIN_EMAIL = "recipient@example.com"
|
ADMIN_EMAIL = "recipient@example.com"
|
||||||
|
|
||||||
|
# S3 Bucket Configuration (add options as documented at https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html)
|
||||||
|
|
||||||
|
ENABLE_S3_STORAGE = False
|
||||||
|
|
||||||
|
AWS_ACCESS_KEY_ID = "AWS Key ID"
|
||||||
|
AWS_SECRET_ACCESS_KEY = "AWS Secret Key"
|
||||||
|
AWS_STORAGE_BUCKET_NAME = "AWS Bucket"
|
|
@ -11,6 +11,7 @@ class Establishment(models.Model):
|
||||||
owner = models.ForeignKey(PartnerProfile, models.CASCADE)
|
owner = models.ForeignKey(PartnerProfile, models.CASCADE)
|
||||||
name = models.CharField(max_length=64)
|
name = models.CharField(max_length=64)
|
||||||
stars = models.IntegerField(null=True, blank=True)
|
stars = models.IntegerField(null=True, blank=True)
|
||||||
|
superior = models.BooleanField(default=False)
|
||||||
street = models.CharField(max_length=64)
|
street = models.CharField(max_length=64)
|
||||||
city = models.CharField(max_length=64)
|
city = models.CharField(max_length=64)
|
||||||
zip = models.CharField(max_length=16)
|
zip = models.CharField(max_length=16)
|
||||||
|
|
|
@ -3,7 +3,7 @@ from django import template
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
|
|
||||||
@register.simple_tag
|
@register.simple_tag
|
||||||
def stars(number, color=""):
|
def stars(number, superior=False, color=""):
|
||||||
number = int(number)
|
number = int(number)
|
||||||
if not 1 <= number <= 5:
|
if not 1 <= number <= 5:
|
||||||
raise ValueError("Number of stars must be between 1 and 5.")
|
raise ValueError("Number of stars must be between 1 and 5.")
|
||||||
|
@ -13,6 +13,9 @@ def stars(number, color=""):
|
||||||
for i in range(5):
|
for i in range(5):
|
||||||
output += '<span><i class="fa%s fa-star" style="color:%s;"></i></span>' % (("" if i < number else "r"), color)
|
output += '<span><i class="fa%s fa-star" style="color:%s;"></i></span>' % (("" if i < number else "r"), color)
|
||||||
|
|
||||||
|
if superior:
|
||||||
|
output += '<span style="color:%s;">S</span>' % color
|
||||||
|
|
||||||
return output
|
return output
|
||||||
|
|
||||||
@register.simple_tag
|
@register.simple_tag
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
|
||||||
from .views import PartnerRegistrationView, PartnerProfileView, BiddingListView, OffersListView, EstablishmentsListView
|
from .views import PartnerRegistrationView, PartnerProfileView, BiddingListView, OffersListView, EstablishmentsListView, EstablishmentRequestView
|
||||||
|
|
||||||
app_name = "partners"
|
app_name = "partners"
|
||||||
|
|
||||||
|
@ -8,6 +8,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/register/', EstablishmentRequestView.as_view(), name="establishment_register"),
|
||||||
path('bidding/<int:id>/', BiddingListView.as_view(), name="bidding"),
|
path('bidding/<int:id>/', BiddingListView.as_view(), name="bidding"),
|
||||||
path('bidding/', BiddingListView.as_view(), name="bidding"),
|
path('bidding/', BiddingListView.as_view(), name="bidding"),
|
||||||
path('offers/', OffersListView.as_view(), name="offers"),
|
path('offers/', OffersListView.as_view(), name="offers"),
|
||||||
|
|
|
@ -2,7 +2,8 @@ from django.views.generic import CreateView, UpdateView, ListView
|
||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
from django.db.models import F
|
from django.db.models import F
|
||||||
from django.shortcuts import get_list_or_404
|
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
|
||||||
from .mixins import PartnerProfileRequiredMixin
|
from .mixins import PartnerProfileRequiredMixin
|
||||||
|
@ -67,10 +68,15 @@ class BiddingListView(InConstructionMixin, PartnerProfileRequiredMixin, ListView
|
||||||
model = Inquiry
|
model = Inquiry
|
||||||
template_name = "partners/bidding_list.html"
|
template_name = "partners/bidding_list.html"
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
self.establishment = self.get_establishment()
|
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):
|
def get_establishment(self):
|
||||||
establishment = self.kwargs.get("id", None)
|
establishment = self.kwargs.get("id", None)
|
||||||
kwargs = {"owner": self.request.user.partnerprofile}
|
kwargs = {"owner": self.request.user.partnerprofile}
|
||||||
|
@ -78,10 +84,14 @@ class BiddingListView(InConstructionMixin, PartnerProfileRequiredMixin, ListView
|
||||||
if establishment:
|
if establishment:
|
||||||
kwargs["id"] = establishment
|
kwargs["id"] = establishment
|
||||||
|
|
||||||
return get_list_or_404(Establishment, **kwargs).first()
|
if establishment:
|
||||||
|
return get_object_or_404(Establishment, **kwargs)
|
||||||
|
else:
|
||||||
|
return Establishment.objects.filter(**kwargs).first()
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return Inquiry.objects.filter(active=True).distance(self.establishment.coords).filter(distance__lte=F("destination_radius"))
|
establishment = self.get_establishment()
|
||||||
|
return Inquiry.objects.filter(active=True).distance(establishment.coords).filter(distance__lte=F("destination_radius"))
|
||||||
|
|
||||||
class OffersListView(InConstructionMixin, PartnerProfileRequiredMixin, ListView):
|
class OffersListView(InConstructionMixin, PartnerProfileRequiredMixin, ListView):
|
||||||
model = Offer
|
model = Offer
|
||||||
|
@ -97,6 +107,7 @@ class EstablishmentsListView(InConstructionMixin, PartnerProfileRequiredMixin, L
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return self.request.user.partnerprofile.establishment_set
|
return self.request.user.partnerprofile.establishment_set
|
||||||
|
|
||||||
class EstablishmentRequestView(InConstructionMixin, PartnerProfileRequiredMixin, ListView):
|
class EstablishmentRequestView(InConstructionMixin, PartnerProfileRequiredMixin, CreateView):
|
||||||
model = Establishment
|
model = Establishment
|
||||||
template_name = "partners/establishment_edit.html"
|
template_name = "partners/establishment_register.html"
|
||||||
|
fields = ["name", "stars", "superior", "street", "city", "zip", "state", "country"]
|
|
@ -8,4 +8,7 @@ django-countries
|
||||||
paypal-checkout-serversdk
|
paypal-checkout-serversdk
|
||||||
python-dateutil
|
python-dateutil
|
||||||
qrcode
|
qrcode
|
||||||
requests
|
requests
|
||||||
|
django-storages
|
||||||
|
boto3
|
||||||
|
geopy
|
||||||
|
|
|
@ -177,7 +177,7 @@
|
||||||
<ul class="list-unstyled list-inline offer-price-1">
|
<ul class="list-unstyled list-inline offer-price-1">
|
||||||
<li class="list-inline-item price">12<span class="divider">|</span><span class="pkg">Buchungen diese Woche</span></li>
|
<li class="list-inline-item price">12<span class="divider">|</span><span class="pkg">Buchungen diese Woche</span></li>
|
||||||
<li class="list-inline-item rating">
|
<li class="list-inline-item rating">
|
||||||
{% autoescape off %}{% stars 5 "orange" %}{% endautoescape %}
|
{% autoescape off %}{% stars 5 1 "orange" %}{% endautoescape %}
|
||||||
{% autoescape off %}{% hearts 5 "red" %}{% endautoescape %}
|
{% autoescape off %}{% hearts 5 "red" %}{% endautoescape %}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
18
templates/partners/establishment_list.html
Normal file
18
templates/partners/establishment_list.html
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
{% extends "frontend/base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load bootstrap4 %}
|
||||||
|
{% block "content" %}
|
||||||
|
<!--===== INNERPAGE-WRAPPER ====-->
|
||||||
|
<section class="innerpage-wrapper">
|
||||||
|
<div id="payment-success" class="section-padding">
|
||||||
|
<div class="container text-center">
|
||||||
|
<div class="row d-flex justify-content-center">
|
||||||
|
<div class="col-md-12 col-lg-8 col-lg-offset-2">
|
||||||
|
<h2>{% trans "Deine Unterkünfte" %}</h2>
|
||||||
|
|
||||||
|
</div><!-- end columns -->
|
||||||
|
</div><!-- end row -->
|
||||||
|
</div><!-- end container -->
|
||||||
|
</div><!-- end coming-soon-text -->
|
||||||
|
</section><!-- end innerpage-wrapper -->
|
||||||
|
{% endblock %}
|
25
templates/partners/establishment_register.html
Normal file
25
templates/partners/establishment_register.html
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
{% extends "frontend/base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load bootstrap4 %}
|
||||||
|
{% block "content" %}
|
||||||
|
<!--===== INNERPAGE-WRAPPER ====-->
|
||||||
|
<section class="innerpage-wrapper">
|
||||||
|
<div id="payment-success" class="section-padding">
|
||||||
|
<div class="container text-center">
|
||||||
|
<div class="row d-flex justify-content-center">
|
||||||
|
<div class="col-md-12 col-lg-8 col-lg-offset-2">
|
||||||
|
<h2>{% trans "Unterkunft registrieren" %}</h2>
|
||||||
|
<p>Bitte geben Sie hier die Daten der Unterkunft ein, die Sie in JourneyJoker anbieten möchten.</p>
|
||||||
|
<p>Nach einer kurzen Überprüfung Ihrer Daten kann es dann schon losgehen!</p>
|
||||||
|
|
||||||
|
<form method="POST">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% bootstrap_form form %}
|
||||||
|
<button class="btn btn-orange btn-block">{% trans "Anwenden" %}</button>
|
||||||
|
</form>
|
||||||
|
</div><!-- end columns -->
|
||||||
|
</div><!-- end row -->
|
||||||
|
</div><!-- end container -->
|
||||||
|
</div><!-- end coming-soon-text -->
|
||||||
|
</section><!-- end innerpage-wrapper -->
|
||||||
|
{% endblock %}
|
18
templates/partners/offer_list.html
Normal file
18
templates/partners/offer_list.html
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
{% extends "frontend/base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load bootstrap4 %}
|
||||||
|
{% block "content" %}
|
||||||
|
<!--===== INNERPAGE-WRAPPER ====-->
|
||||||
|
<section class="innerpage-wrapper">
|
||||||
|
<div id="payment-success" class="section-padding">
|
||||||
|
<div class="container text-center">
|
||||||
|
<div class="row d-flex justify-content-center">
|
||||||
|
<div class="col-md-12 col-lg-8 col-lg-offset-2">
|
||||||
|
<h2>{% trans "Deine Angebote" %}</h2>
|
||||||
|
|
||||||
|
</div><!-- end columns -->
|
||||||
|
</div><!-- end row -->
|
||||||
|
</div><!-- end container -->
|
||||||
|
</div><!-- end coming-soon-text -->
|
||||||
|
</section><!-- end innerpage-wrapper -->
|
||||||
|
{% endblock %}
|
|
@ -9,10 +9,11 @@
|
||||||
<div class="row d-flex justify-content-center">
|
<div class="row d-flex justify-content-center">
|
||||||
<div class="col-md-12 col-lg-8 col-lg-offset-2">
|
<div class="col-md-12 col-lg-8 col-lg-offset-2">
|
||||||
<h2>{% trans "Profildaten" %}</h2>
|
<h2>{% trans "Profildaten" %}</h2>
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{% bootstrap_form form %}
|
{% bootstrap_form form %}
|
||||||
<button class="btn btn-orange btn-block">{% trans "Anwenden" %}</button>
|
<button class="btn btn-orange btn-block">{% trans "Anwenden" %}</button>
|
||||||
|
</form>
|
||||||
</div><!-- end columns -->
|
</div><!-- end columns -->
|
||||||
</div><!-- end row -->
|
</div><!-- end row -->
|
||||||
</div><!-- end container -->
|
</div><!-- end container -->
|
||||||
|
|
|
@ -10,13 +10,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">
|
||||||
<h2>{% trans "Als Partner registrieren" %}</h2>
|
<h2>{% trans "Als Partner registrieren" %}</h2>
|
||||||
<p>Sie haben Interesse, mit Ihrem Hotel an JourneyJoker teilzunehmen?</p>
|
<p>Sie haben Interesse, mit Ihrem Hotel an JourneyJoker teilzunehmen?</p>
|
||||||
<p>Füllen Sie einfach folgendes Formular aus, um sich zu registrieren.</p>
|
<p>Füllen Sie einfach folgendes Formular aus, um sich zu registrieren!</p>
|
||||||
<p>Nach einer kurzen Überprüfung Ihrer Daten können Sie dann Ihre Unterkunft in unserem System anlegen und schon kann es losgehen!</p>
|
|
||||||
|
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{% bootstrap_form form %}
|
{% bootstrap_form form %}
|
||||||
<button class="btn btn-orange btn-block">{% trans "Anwenden" %}</button>
|
<button class="btn btn-orange btn-block">{% trans "Anwenden" %}</button>
|
||||||
|
</form>
|
||||||
</div><!-- end columns -->
|
</div><!-- end columns -->
|
||||||
</div><!-- end row -->
|
</div><!-- end row -->
|
||||||
</div><!-- end container -->
|
</div><!-- end container -->
|
||||||
|
|
|
@ -120,4 +120,9 @@ REGISTER_REDIRECT_URL = "/"
|
||||||
LOGIN_REDIRECT_URL = "/"
|
LOGIN_REDIRECT_URL = "/"
|
||||||
|
|
||||||
LOGIN_URL = "localauth:login"
|
LOGIN_URL = "localauth:login"
|
||||||
LOGOUT_URL = "localauth:logout"
|
LOGOUT_URL = "localauth:logout"
|
||||||
|
|
||||||
|
DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage' if not ENABLE_S3_STORAGE else 'storages.backends.s3boto3.S3Boto3Storage'
|
||||||
|
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3StaticStorage' if ENABLE_S3_STORAGE else 'django.contrib.staticfiles.storage.StaticFilesStorage'
|
||||||
|
|
||||||
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
Loading…
Reference in a new issue