Preparing a bunch of views for partners

Adding superior ratings
Use Nominatim for location lookups
Implement hotel registration
This commit is contained in:
Kumi 2021-04-11 16:19:43 +02:00
parent 73c13841c6
commit 41d71d313f
14 changed files with 123 additions and 32 deletions

View file

@ -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):
URL = "https://maps.googleapis.com/maps/api/geocode/json"
api_key = api_key or getValue("google.api.key")
def name_to_coords(name):
geocoder = Nominatim(user_agent="JourneyJoker.at")
payload = {"address": name, "key": api_key}
response = requests.get(URL, params=payload).json()
result = geocoder.geocode(name, exactly_one=True)
try:
result = response["results"][0]
return result["geometry"]["location"]["lat"], result["geometry"]["location"]["lng"]
except:
raise ValueError(response)
return result.latitude, result.longitude
def profile_to_coords(profile):
return name_to_coords("%s, %s, %s, %s" % (profile.address, profile.city, profile.zip, profile.country))

View file

@ -17,3 +17,11 @@ DB_PASS = "postgresql_password"
# Email address of system administrator
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"

View file

@ -11,6 +11,7 @@ class Establishment(models.Model):
owner = models.ForeignKey(PartnerProfile, models.CASCADE)
name = models.CharField(max_length=64)
stars = models.IntegerField(null=True, blank=True)
superior = models.BooleanField(default=False)
street = models.CharField(max_length=64)
city = models.CharField(max_length=64)
zip = models.CharField(max_length=16)

View file

@ -3,7 +3,7 @@ from django import template
register = template.Library()
@register.simple_tag
def stars(number, color=""):
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.")
@ -13,6 +13,9 @@ def stars(number, color=""):
for i in range(5):
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
@register.simple_tag

View file

@ -1,6 +1,6 @@
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"
@ -8,6 +8,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/register/', EstablishmentRequestView.as_view(), name="establishment_register"),
path('bidding/<int:id>/', BiddingListView.as_view(), name="bidding"),
path('bidding/', BiddingListView.as_view(), name="bidding"),
path('offers/', OffersListView.as_view(), name="offers"),

View file

@ -2,7 +2,8 @@ from django.views.generic import CreateView, UpdateView, ListView
from django.urls import reverse_lazy
from django.http import HttpResponseRedirect
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 .mixins import PartnerProfileRequiredMixin
@ -67,10 +68,15 @@ class BiddingListView(InConstructionMixin, PartnerProfileRequiredMixin, ListView
model = Inquiry
template_name = "partners/bidding_list.html"
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
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}
@ -78,10 +84,14 @@ class BiddingListView(InConstructionMixin, PartnerProfileRequiredMixin, ListView
if 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):
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):
model = Offer
@ -97,6 +107,7 @@ class EstablishmentsListView(InConstructionMixin, PartnerProfileRequiredMixin, L
def get_queryset(self):
return self.request.user.partnerprofile.establishment_set
class EstablishmentRequestView(InConstructionMixin, PartnerProfileRequiredMixin, ListView):
class EstablishmentRequestView(InConstructionMixin, PartnerProfileRequiredMixin, CreateView):
model = Establishment
template_name = "partners/establishment_edit.html"
template_name = "partners/establishment_register.html"
fields = ["name", "stars", "superior", "street", "city", "zip", "state", "country"]

View file

@ -9,3 +9,6 @@ paypal-checkout-serversdk
python-dateutil
qrcode
requests
django-storages
boto3
geopy

View file

@ -177,7 +177,7 @@
<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 rating">
{% autoescape off %}{% stars 5 "orange" %}{% endautoescape %}
{% autoescape off %}{% stars 5 1 "orange" %}{% endautoescape %}
{% autoescape off %}{% hearts 5 "red" %}{% endautoescape %}
</li>
</ul>

View 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 %}

View 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 %}

View 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 %}

View file

@ -9,10 +9,11 @@
<div class="row d-flex justify-content-center">
<div class="col-md-12 col-lg-8 col-lg-offset-2">
<h2>{% trans "Profildaten" %}</h2>
<form method="POST">
{% csrf_token %}
{% bootstrap_form form %}
<button class="btn btn-orange btn-block">{% trans "Anwenden" %}</button>
<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 -->

View file

@ -10,13 +10,13 @@
<div class="col-md-12 col-lg-8 col-lg-offset-2">
<h2>{% trans "Als Partner registrieren" %}</h2>
<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>Nach einer kurzen Überprüfung Ihrer Daten können Sie dann Ihre Unterkunft in unserem System anlegen und schon kann es losgehen!</p>
<p>Füllen Sie einfach folgendes Formular aus, um sich zu registrieren!</p>
<form method="POST">
{% csrf_token %}
{% 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 row -->
</div><!-- end container -->

View file

@ -121,3 +121,8 @@ LOGIN_REDIRECT_URL = "/"
LOGIN_URL = "localauth:login"
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'