Merge pull request #122 from levivm/feature/new_digitalglarus
Fixed cc brand bug, Added button to print/save pdf to booking order …
This commit is contained in:
commit
13d54ad8d3
12 changed files with 397 additions and 33 deletions
|
@ -1,5 +1,7 @@
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from .models import Supporter, DGGallery, DGPicture
|
from .models import Supporter, DGGallery, DGPicture, Booking, BookingPrice,\
|
||||||
|
MembershipOrder, Membership, MembershipType, BookingOrder
|
||||||
|
|
||||||
from utils.models import ContactMessage
|
from utils.models import ContactMessage
|
||||||
#
|
#
|
||||||
class DGPictureInline(admin.StackedInline):
|
class DGPictureInline(admin.StackedInline):
|
||||||
|
@ -10,4 +12,9 @@ class DGGalleryAdmin(admin.ModelAdmin):
|
||||||
|
|
||||||
admin.site.register(DGGallery, DGGalleryAdmin)
|
admin.site.register(DGGallery, DGGalleryAdmin)
|
||||||
admin.site.register(ContactMessage)
|
admin.site.register(ContactMessage)
|
||||||
admin.site.register(Supporter)
|
admin.site.register(Booking)
|
||||||
|
admin.site.register(BookingPrice)
|
||||||
|
admin.site.register(MembershipOrder)
|
||||||
|
admin.site.register(Membership)
|
||||||
|
admin.site.register(MembershipType)
|
||||||
|
admin.site.register(BookingOrder)
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
from django import forms
|
from django import forms
|
||||||
|
from django.db.models import Q
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
from utils.models import BillingAddress
|
from utils.models import BillingAddress
|
||||||
from utils.forms import LoginFormMixin, SignupFormMixin, BillingAddressForm
|
from utils.forms import LoginFormMixin, SignupFormMixin, BillingAddressForm
|
||||||
|
|
||||||
from .models import MembershipType
|
from .models import MembershipType
|
||||||
|
from .models import Booking
|
||||||
|
|
||||||
|
|
||||||
class LoginForm(LoginFormMixin):
|
class LoginForm(LoginFormMixin):
|
||||||
|
@ -55,9 +58,10 @@ class BookingBillingForm(BillingAddressForm):
|
||||||
|
|
||||||
|
|
||||||
class BookingDateForm(forms.Form):
|
class BookingDateForm(forms.Form):
|
||||||
start_date = forms.DateField(required=False)
|
start_date = forms.DateField(required=False, widget=forms.HiddenInput())
|
||||||
end_date = forms.DateField(required=False)
|
end_date = forms.DateField(required=False, widget=forms.HiddenInput())
|
||||||
date_range = forms.CharField(required=False)
|
date_range = forms.CharField(required=False,
|
||||||
|
widget=forms.TextInput(attrs={'id': 'booking-date-range'}))
|
||||||
|
|
||||||
def clean_date_range(self):
|
def clean_date_range(self):
|
||||||
date_range = self.cleaned_data.get('date_range')
|
date_range = self.cleaned_data.get('date_range')
|
||||||
|
@ -70,10 +74,19 @@ class BookingDateForm(forms.Form):
|
||||||
|
|
||||||
if start_date > end_date:
|
if start_date > end_date:
|
||||||
raise forms.ValidationError("Your end date must be greather than your start date.")
|
raise forms.ValidationError("Your end date must be greather than your start date.")
|
||||||
|
|
||||||
|
q1 = Q(start_date__lte=start_date, end_date__gte=start_date)
|
||||||
|
q2 = Q(start_date__gt=start_date, start_date__lte=end_date)
|
||||||
|
if Booking.objects.filter(q1 | q2).exists():
|
||||||
|
raise forms.ValidationError("You already have a booking in these dates.")
|
||||||
|
|
||||||
return start_date, end_date
|
return start_date, end_date
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
start_date, end_date = self.cleaned_data.get('date_range')
|
# import pdb
|
||||||
self.cleaned_data['start_date'] = start_date
|
# pdb.set_trace()
|
||||||
self.cleaned_data['end_date'] = end_date
|
if self.cleaned_data.get('date_range'):
|
||||||
|
start_date, end_date = self.cleaned_data.get('date_range')
|
||||||
|
self.cleaned_data['start_date'] = start_date
|
||||||
|
self.cleaned_data['end_date'] = end_date
|
||||||
return self.cleaned_data
|
return self.cleaned_data
|
||||||
|
|
27
digitalglarus/migrations/0015_auto_20160908_0149.py
Normal file
27
digitalglarus/migrations/0015_auto_20160908_0149.py
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.9.4 on 2016-09-08 01:49
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('digitalglarus', '0014_booking_final_price'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='bookingorder',
|
||||||
|
name='amount',
|
||||||
|
field=models.FloatField(default=35),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='membershiporder',
|
||||||
|
name='amount',
|
||||||
|
field=models.FloatField(default=35.0),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
32
digitalglarus/migrations/0016_auto_20160909_0110.py
Normal file
32
digitalglarus/migrations/0016_auto_20160909_0110.py
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.9.4 on 2016-09-09 01:10
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('digitalglarus', '0015_auto_20160908_0149'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='bookingprice',
|
||||||
|
old_name='special_price_offer',
|
||||||
|
new_name='special_month_price',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='bookingorder',
|
||||||
|
name='original_price',
|
||||||
|
field=models.FloatField(default=20),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='bookingorder',
|
||||||
|
name='special_month_price',
|
||||||
|
field=models.FloatField(default=290),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
|
@ -4,7 +4,7 @@ from membership.models import StripeCustomer
|
||||||
from utils.models import BillingAddress
|
from utils.models import BillingAddress
|
||||||
|
|
||||||
|
|
||||||
class MembershipRequired(object):
|
class MembershipRequiredMixin(object):
|
||||||
membership_redirect_url = None
|
membership_redirect_url = None
|
||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
|
@ -12,11 +12,23 @@ class MembershipRequired(object):
|
||||||
if not Membership.is_digitalglarus_member(request.user):
|
if not Membership.is_digitalglarus_member(request.user):
|
||||||
return HttpResponseRedirect(self.membership_redirect_url)
|
return HttpResponseRedirect(self.membership_redirect_url)
|
||||||
|
|
||||||
return super(MembershipRequired, self).dispatch(request, *args, **kwargs)
|
return super(MembershipRequiredMixin, self).dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class IsNotMemberMixin(object):
|
||||||
|
already_member_redirect_url = None
|
||||||
|
|
||||||
|
def dispatch(self, request, *args, **kwargs):
|
||||||
|
from .models import Membership
|
||||||
|
if Membership.is_digitalglarus_member(request.user):
|
||||||
|
return HttpResponseRedirect(self.already_member_redirect_url)
|
||||||
|
|
||||||
|
return super(MembershipRequiredMixin, self).dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class Ordereable(models.Model):
|
class Ordereable(models.Model):
|
||||||
customer = models.ForeignKey(StripeCustomer)
|
customer = models.ForeignKey(StripeCustomer)
|
||||||
|
amount = models.FloatField()
|
||||||
billing_address = models.ForeignKey(BillingAddress)
|
billing_address = models.ForeignKey(BillingAddress)
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
created_at = models.DateTimeField(auto_now_add=True)
|
||||||
approved = models.BooleanField(default=False)
|
approved = models.BooleanField(default=False)
|
||||||
|
|
|
@ -64,7 +64,8 @@ class Membership(models.Model):
|
||||||
@classmethod
|
@classmethod
|
||||||
def is_digitalglarus_member(cls, user):
|
def is_digitalglarus_member(cls, user):
|
||||||
past_month = (datetime.today() - relativedelta(months=1)).month
|
past_month = (datetime.today() - relativedelta(months=1)).month
|
||||||
has_booking_current_month = Q(membershiporder__created_at__month=datetime.today().month)
|
has_booking_current_month = Q(membershiporder__customer__user=user,
|
||||||
|
membershiporder__created_at__month=datetime.today().month)
|
||||||
has_booking_past_month = Q(membershiporder__customer__user=user,
|
has_booking_past_month = Q(membershiporder__customer__user=user,
|
||||||
membershiporder__created_at__month=past_month)
|
membershiporder__created_at__month=past_month)
|
||||||
return cls.objects.filter(has_booking_past_month | has_booking_current_month).exists()
|
return cls.objects.filter(has_booking_past_month | has_booking_current_month).exists()
|
||||||
|
@ -78,6 +79,25 @@ class Membership(models.Model):
|
||||||
class MembershipOrder(Ordereable, models.Model):
|
class MembershipOrder(Ordereable, models.Model):
|
||||||
membership = models.ForeignKey(Membership)
|
membership = models.ForeignKey(Membership)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def current_membership(cls, user):
|
||||||
|
last_payment = cls.objects.\
|
||||||
|
filter(customer__user=user).last()
|
||||||
|
start_date = last_payment.created_at
|
||||||
|
_, days_in_month = calendar.monthrange(start_date.year,
|
||||||
|
start_date.month)
|
||||||
|
start_date.replace(day=1)
|
||||||
|
end_date = start_date + timedelta(days=days_in_month)
|
||||||
|
return start_date, end_date
|
||||||
|
|
||||||
|
def get_membership_range_date(self):
|
||||||
|
start_date = self.created_at
|
||||||
|
_, days_in_month = calendar.monthrange(start_date.year,
|
||||||
|
start_date.month)
|
||||||
|
start_date.replace(day=1)
|
||||||
|
end_date = start_date + timedelta(days=days_in_month)
|
||||||
|
return start_date, end_date
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, data):
|
def create(cls, data):
|
||||||
stripe_charge = data.pop('stripe_charge', None)
|
stripe_charge = data.pop('stripe_charge', None)
|
||||||
|
@ -85,12 +105,13 @@ class MembershipOrder(Ordereable, models.Model):
|
||||||
instance.stripe_charge_id = stripe_charge.id
|
instance.stripe_charge_id = stripe_charge.id
|
||||||
instance.last4 = stripe_charge.source.last4
|
instance.last4 = stripe_charge.source.last4
|
||||||
instance.cc_brand = stripe_charge.source.brand
|
instance.cc_brand = stripe_charge.source.brand
|
||||||
|
instance.save()
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
|
|
||||||
class BookingPrice(models.Model):
|
class BookingPrice(models.Model):
|
||||||
price_per_day = models.FloatField()
|
price_per_day = models.FloatField()
|
||||||
special_price_offer = models.FloatField()
|
special_month_price = models.FloatField()
|
||||||
|
|
||||||
|
|
||||||
class Booking(models.Model):
|
class Booking(models.Model):
|
||||||
|
@ -124,7 +145,7 @@ class Booking(models.Model):
|
||||||
@classmethod
|
@classmethod
|
||||||
def booking_price(cls, user, start_date, end_date):
|
def booking_price(cls, user, start_date, end_date):
|
||||||
|
|
||||||
MAX_MONTH_PRICE = 290
|
MAX_MONTH_PRICE = BookingPrice.objects.last().special_month_price
|
||||||
MAX_MONTH_DAYS_PROMOTION = 31
|
MAX_MONTH_DAYS_PROMOTION = 31
|
||||||
MIN_MONTH_DAYS_PROMOTION = 19
|
MIN_MONTH_DAYS_PROMOTION = 19
|
||||||
|
|
||||||
|
@ -146,6 +167,8 @@ class Booking(models.Model):
|
||||||
|
|
||||||
class BookingOrder(Ordereable, models.Model):
|
class BookingOrder(Ordereable, models.Model):
|
||||||
booking = models.OneToOneField(Booking)
|
booking = models.OneToOneField(Booking)
|
||||||
|
original_price = models.FloatField()
|
||||||
|
special_month_price = models.FloatField()
|
||||||
|
|
||||||
def booking_days(self):
|
def booking_days(self):
|
||||||
return (self.booking.end_date - self.booking.start_date).days + 1
|
return (self.booking.end_date - self.booking.start_date).days + 1
|
||||||
|
|
|
@ -14,12 +14,17 @@
|
||||||
<h2 class="signup-lead">Start coworking at Digital Glarus! <br> Membership costs only
|
<h2 class="signup-lead">Start coworking at Digital Glarus! <br> Membership costs only
|
||||||
<strong>35CHF</strong> per month.<br> 2 free working days included!</h2>
|
<strong>35CHF</strong> per month.<br> 2 free working days included!</h2>
|
||||||
<hr class="primary">
|
<hr class="primary">
|
||||||
|
{% bootstrap_form_errors form layout='inline' %}
|
||||||
<div class="signup-form form-group row">
|
<div class="signup-form form-group row">
|
||||||
<input type="hidden" name="next" value="{{ request.GET.next }}">
|
<input type="hidden" name="next" value="{{ request.GET.next }}">
|
||||||
<form action="" method="post" class="form" novalidate>
|
<form action="" method="post" class="form" novalidate>
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<input class="form-control" placeholder="Select your dates" type="text" id="booking-date-range" name="date_range">
|
{% bootstrap_form_errors form layout='inline' %}
|
||||||
|
{% for field in form %}
|
||||||
|
{% bootstrap_field field show_label=False %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
<!-- <input class="form-control" placeholder="Select your dates" type="text" id="booking-date-range" name="date_range"> -->
|
||||||
<button type="submit" class="btn btn-primary btn-blue">Book</button>
|
<button type="submit" class="btn btn-primary btn-blue">Book</button>
|
||||||
</form>
|
</form>
|
||||||
<br>
|
<br>
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
{% extends "new_base_glarus.html" %}
|
||||||
|
{% load staticfiles bootstrap3 i18n %}
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
|
||||||
|
.invoice-title{
|
||||||
|
text-align: center !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<section id="price">
|
||||||
|
<div class="signup-container">
|
||||||
|
<div class="col-xs-12 col-sm-6 col-lg-8 text-center wow fadeInDown">
|
||||||
|
<div class="payment-box">
|
||||||
|
<h2 class="section-heading payment-head">Your Membership Order Detail</h2>
|
||||||
|
<hr class="greyline-long">
|
||||||
|
<h2 class="billing-head">Invoice<btn class="btn btn-primary btn-grey btn-edit print" data-print="price">Get PDF</btn></h2>
|
||||||
|
|
||||||
|
<h2 class="order-head">Order Number</h2>
|
||||||
|
<h2 class="member-name">#{{order.id}}</h2>
|
||||||
|
|
||||||
|
<h2 class="order-head">Billed to :</h2>
|
||||||
|
<h2 class="history-name">{{user.name}}<br>
|
||||||
|
{{order.billing_address.street_address}},{{order.billing_address.postal_code}}<br>
|
||||||
|
{{order.billing_address.city}}, {{order.billing_address.country}}.
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<h2 class="order-head">Payment Method</h2>
|
||||||
|
<h2 class="history-name">
|
||||||
|
{{order.cc_brand}} ending **** {{order.last4}}<br>
|
||||||
|
{{user.email}}
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<hr class="greyline-long">
|
||||||
|
<h2 class="order-head">Order Summary</h2>
|
||||||
|
<h2 class="history-name">
|
||||||
|
Dates: {{membership_start_date|date}} - {{membership_end_date|date}}<br>
|
||||||
|
</h2>
|
||||||
|
<h2 class="col-xs-6 payment-total text-left">Membership month {{order.created_at|date:"F"}}</h2>
|
||||||
|
<h2 class="order-sum">{{order.amount|floatformat}}CHF</h2>
|
||||||
|
<hr class="greyline-long">
|
||||||
|
<h2 class="col-xs-6 payment-total text-left"> Total</h2>
|
||||||
|
<h2 class="order-result">{{order.amount|floatformat}}CHF</h2>
|
||||||
|
<br>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-xs-12 col-sm-4 col-lg-4 wow fadeInDown">
|
||||||
|
<div class="order-summary">
|
||||||
|
<div class="header text-center">
|
||||||
|
<h2 class="order-name">Order Summary</h2>
|
||||||
|
</div>
|
||||||
|
<div class="order-box">
|
||||||
|
<h2 class="col-xs-6 order-item" style="padding-bottom:10px"> Dates: {{membership_start_date|date}} - {{membership_end_date|date}}<br><br></h2>
|
||||||
|
|
||||||
|
<h2 class="col-xs-6 payment-total">Membership month {{order.created_at|date:"F"}}</h2>
|
||||||
|
<h2 class="order-sum">{{order.amount|floatformat}}CHF</h2>
|
||||||
|
<hr class="greyline">
|
||||||
|
<h2 class="col-xs-6 payment-total">Total</h2>
|
||||||
|
<h2 class="order-result">{{order.amount|floatformat}}CHF</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- stripe key data -->
|
||||||
|
{% if stripe_key %}
|
||||||
|
<script type="text/javascript">
|
||||||
|
(function () {window.stripeKey = "{{stripe_key}}";})();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{%endif%}
|
||||||
|
|
||||||
|
{% endblock %}
|
|
@ -0,0 +1,68 @@
|
||||||
|
{% extends "new_base_glarus.html" %}
|
||||||
|
{% load staticfiles bootstrap3 i18n %}
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Header -->
|
||||||
|
<!-- Services Section -->
|
||||||
|
<section id="price">
|
||||||
|
<div class="signup-container">
|
||||||
|
<div class="col-xs-12 col-sm-6 col-lg-8 text-center wow fadeInDown">
|
||||||
|
<div class="payment-box">
|
||||||
|
<h2 class="section-heading payment-head">Your Order History</h2>
|
||||||
|
<hr class="greyline-long">
|
||||||
|
<h2 class="order-head">Member Name</h2>
|
||||||
|
<h2 class="member-name">{{request.user.name}}</h2>
|
||||||
|
<hr class="greyline-long">
|
||||||
|
<h2 class="order-head">Active Membership</h2>
|
||||||
|
<h2 class="member-name">{{membership_start_date|date}}-{{membership_end_date|date}}</h2>
|
||||||
|
<hr class="greyline-long">
|
||||||
|
<h2 class="order-head">Booking history</h2>
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>#</th>
|
||||||
|
<th>Valid Month</th>
|
||||||
|
<th>Date</th>
|
||||||
|
<th>Invoice</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for order in orders%}
|
||||||
|
<tr>
|
||||||
|
<th scope="row">{{order.id}}</th>
|
||||||
|
<td>{{order.created_at|date:"F"}}</td>
|
||||||
|
<td>{{order.created_at|date}}</td>
|
||||||
|
<td><a class="btn btn-xs btn-primary btn-darkgrey" href="{% url 'digitalglarus:membership_orders_detail' order.id %}">View</a></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2 class="order-head">Billing Adress<btn class="btn btn-primary btn-grey btn-edit">Edit</btn></h2>
|
||||||
|
<h2 class="history-name">Nico Schottelius<br>
|
||||||
|
In der Au 7 8762 Schwanden<br>
|
||||||
|
Switzerland
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="col-xs-12 col-sm-4 col-lg-4 wow fadeInDown">
|
||||||
|
<div class="order-summary">
|
||||||
|
<h2 class="thankyou">Thank You!</h2>
|
||||||
|
<div class="order-box">
|
||||||
|
<span class="glyphicon glyphicon-heart icon-up"></span>
|
||||||
|
<h2 class="signup-lead text-center">Digital Glarus lives with your love!<br>
|
||||||
|
Our coworking space is here because of your love and support.</h2>
|
||||||
|
|
||||||
|
<hr class="greyline">
|
||||||
|
|
||||||
|
<p class="order-bottom-text text-center">This box is here just to thank you</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
|
@ -25,6 +25,8 @@
|
||||||
<link href="{% static 'digitalglarus/css/ungleich.css' %}" rel="stylesheet">
|
<link href="{% static 'digitalglarus/css/ungleich.css' %}" rel="stylesheet">
|
||||||
<link href="{% static 'digitalglarus/css/history.css' %}" rel="stylesheet">
|
<link href="{% static 'digitalglarus/css/history.css' %}" rel="stylesheet">
|
||||||
<link href="{% static 'digitalglarus/css/price.css' %}" rel="stylesheet">
|
<link href="{% static 'digitalglarus/css/price.css' %}" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/bootstrap.daterangepicker/2/daterangepicker.css" />
|
||||||
|
|
||||||
<!-- <link href="css/bootstrap.min.css" rel="stylesheet"> -->
|
<!-- <link href="css/bootstrap.min.css" rel="stylesheet"> -->
|
||||||
<link href="{% static 'digitalglarus/css/lib/animate.min.css' %}" rel="stylesheet">
|
<link href="{% static 'digitalglarus/css/lib/animate.min.css' %}" rel="stylesheet">
|
||||||
<!-- <link href="{% static 'css/membership.css' %}" rel="stylesheet"> -->
|
<!-- <link href="{% static 'css/membership.css' %}" rel="stylesheet"> -->
|
||||||
|
@ -53,7 +55,32 @@
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<link rel="shortcut icon" href="img/favicon.ico" type="image/x-icon">
|
<link rel="shortcut icon" href="img/favicon.ico" type="image/x-icon">
|
||||||
<style id="igtranslator-color" type="text/css"></style></head>
|
<style id="igtranslator-color" type="text/css"></style>
|
||||||
|
<style type="text/css">
|
||||||
|
|
||||||
|
|
||||||
|
.navbar-default .nav .dropdown.open .dropdown-toggle {
|
||||||
|
background: none !important;
|
||||||
|
color: white !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.navbar-default .nav .dropdown li a{
|
||||||
|
color:#0f1221;
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-default .nav li a .glyphicon-user{
|
||||||
|
|
||||||
|
font-size: 15px;
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0px;
|
||||||
|
color:white;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<body id="page-top" class="index">
|
<body id="page-top" class="index">
|
||||||
|
|
||||||
|
@ -89,13 +116,39 @@
|
||||||
<li>
|
<li>
|
||||||
<a class="page-scroll" href="#contact">Contact</a>
|
<a class="page-scroll" href="#contact">Contact</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
<a class="page-scroll" href="{% url 'digitalglarus:login' %}">Log In</a>
|
{% if request.user.is_authenticated %}
|
||||||
</li>
|
<li class="dropdown home-dropdown">
|
||||||
<li>
|
<a class="dropdown-toggle" role="button" data-toggle="dropdown" href="#">
|
||||||
|
<i class="glyphicon glyphicon-user"></i>{{request.user.name}} <span class="caret"></span>
|
||||||
|
</a>
|
||||||
|
<ul id="g-account-menu" class="dropdown-menu" role="menu">
|
||||||
|
<li>
|
||||||
|
<a href="{% url 'digitalglarus:booking_orders_list' %}">
|
||||||
|
<i class="fa fa-home" aria-hidden="true"></i> {% trans "Bookings"%}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{% url 'digitalglarus:membership_orders_list' %}"><i class="fa fa-heart-o" aria-hidden="true"></i> {% trans "Membership"%}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{% url 'digitalglarus:logout' %}">
|
||||||
|
<i class="fa fa-lock" aria-hidden="true"></i>
|
||||||
|
{% trans "Logout"%}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
{% else %}
|
||||||
|
<li>
|
||||||
|
<a class="page-scroll" href="{% url 'digitalglarus:login' %}">Login</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
<!-- <li>
|
||||||
<a class="page-scroll" href="{% url 'digitalglarus:signup' %}">Sign Up</a>
|
<a class="page-scroll" href="{% url 'digitalglarus:signup' %}">Sign Up</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
--> </ul>
|
||||||
</div>
|
</div>
|
||||||
<!-- /.navbar-collapse -->
|
<!-- /.navbar-collapse -->
|
||||||
</div>
|
</div>
|
||||||
|
@ -174,8 +227,6 @@
|
||||||
-->
|
-->
|
||||||
<!-- Include Date Range Picker -->
|
<!-- Include Date Range Picker -->
|
||||||
<script type="text/javascript" src="//cdn.jsdelivr.net/bootstrap.daterangepicker/2/daterangepicker.js"></script>
|
<script type="text/javascript" src="//cdn.jsdelivr.net/bootstrap.daterangepicker/2/daterangepicker.js"></script>
|
||||||
<link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/bootstrap.daterangepicker/2/daterangepicker.css" />
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Booking JavaScript -->
|
<!-- Booking JavaScript -->
|
||||||
<script src="{% static 'digitalglarus/js/booking.js' %}"></script>
|
<script src="{% static 'digitalglarus/js/booking.js' %}"></script>
|
||||||
|
|
|
@ -5,7 +5,7 @@ from . import views
|
||||||
from .views import ContactView, IndexView, AboutView, HistoryView, LoginView, SignupView,\
|
from .views import ContactView, IndexView, AboutView, HistoryView, LoginView, SignupView,\
|
||||||
PasswordResetView, PasswordResetConfirmView, MembershipPaymentView, MembershipActivatedView,\
|
PasswordResetView, PasswordResetConfirmView, MembershipPaymentView, MembershipActivatedView,\
|
||||||
MembershipPricingView, BookingSelectDatesView, BookingPaymentView, OrdersBookingDetailView,\
|
MembershipPricingView, BookingSelectDatesView, BookingPaymentView, OrdersBookingDetailView,\
|
||||||
BookingOrdersListView
|
BookingOrdersListView, MembershipOrdersListView, OrdersMembershipDetailView
|
||||||
# from membership.views import LoginRegistrationView
|
# from membership.views import LoginRegistrationView
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
|
@ -30,6 +30,10 @@ urlpatterns = [
|
||||||
name='membership_activated'),
|
name='membership_activated'),
|
||||||
url(_(r'membership/pricing/?$'), MembershipPricingView.as_view(),
|
url(_(r'membership/pricing/?$'), MembershipPricingView.as_view(),
|
||||||
name='membership_pricing'),
|
name='membership_pricing'),
|
||||||
|
url(_(r'membership/orders/(?P<pk>\d+)/?$'), OrdersMembershipDetailView.as_view(),
|
||||||
|
name='membership_orders_detail'),
|
||||||
|
url(_(r'membership/orders/?$'), MembershipOrdersListView.as_view(),
|
||||||
|
name='membership_orders_list'),
|
||||||
url(_(r'supporters/?$'), views.supporters, name='supporters'),
|
url(_(r'supporters/?$'), views.supporters, name='supporters'),
|
||||||
url(r'calendar_api/(?P<month>\d+)/(?P<year>\d+)?$', views.CalendarApi.as_view(),name='calendar_api_1'),
|
url(r'calendar_api/(?P<month>\d+)/(?P<year>\d+)?$', views.CalendarApi.as_view(),name='calendar_api_1'),
|
||||||
url(r'calendar_api/', views.CalendarApi.as_view(),name='calendar_api'),
|
url(r'calendar_api/', views.CalendarApi.as_view(),name='calendar_api'),
|
||||||
|
|
|
@ -34,7 +34,7 @@ from .forms import LoginForm, SignupForm, MembershipBillingForm, BookingDateForm
|
||||||
from .models import MembershipType, Membership, MembershipOrder, Booking, BookingPrice,\
|
from .models import MembershipType, Membership, MembershipOrder, Booking, BookingPrice,\
|
||||||
BookingOrder
|
BookingOrder
|
||||||
|
|
||||||
from .mixins import MembershipRequired
|
from .mixins import MembershipRequiredMixin, IsNotMemberMixin
|
||||||
|
|
||||||
|
|
||||||
class IndexView(TemplateView):
|
class IndexView(TemplateView):
|
||||||
|
@ -44,7 +44,7 @@ class IndexView(TemplateView):
|
||||||
class LoginView(LoginViewMixin):
|
class LoginView(LoginViewMixin):
|
||||||
template_name = "digitalglarus/login.html"
|
template_name = "digitalglarus/login.html"
|
||||||
form_class = LoginForm
|
form_class = LoginForm
|
||||||
success_url = reverse_lazy('digitalglarus:landing')
|
success_url = reverse_lazy('digitalglarus:membership_pricing')
|
||||||
|
|
||||||
|
|
||||||
class SignupView(SignupViewMixin):
|
class SignupView(SignupViewMixin):
|
||||||
|
@ -77,7 +77,7 @@ class HistoryView(TemplateView):
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class BookingSelectDatesView(LoginRequiredMixin, MembershipRequired, FormView):
|
class BookingSelectDatesView(LoginRequiredMixin, MembershipRequiredMixin, FormView):
|
||||||
template_name = "digitalglarus/booking.html"
|
template_name = "digitalglarus/booking.html"
|
||||||
form_class = BookingDateForm
|
form_class = BookingDateForm
|
||||||
membership_redirect_url = reverse_lazy('digitalglarus:membership_pricing')
|
membership_redirect_url = reverse_lazy('digitalglarus:membership_pricing')
|
||||||
|
@ -102,7 +102,7 @@ class BookingSelectDatesView(LoginRequiredMixin, MembershipRequired, FormView):
|
||||||
return super(BookingSelectDatesView, self).form_valid(form)
|
return super(BookingSelectDatesView, self).form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
class BookingPaymentView(LoginRequiredMixin, MembershipRequired, FormView):
|
class BookingPaymentView(LoginRequiredMixin, MembershipRequiredMixin, FormView):
|
||||||
template_name = "digitalglarus/booking_payment.html"
|
template_name = "digitalglarus/booking_payment.html"
|
||||||
form_class = BookingBillingForm
|
form_class = BookingBillingForm
|
||||||
membership_redirect_url = reverse_lazy('digitalglarus:membership_pricing')
|
membership_redirect_url = reverse_lazy('digitalglarus:membership_pricing')
|
||||||
|
@ -199,7 +199,10 @@ class BookingPaymentView(LoginRequiredMixin, MembershipRequired, FormView):
|
||||||
'booking': booking,
|
'booking': booking,
|
||||||
'customer': customer,
|
'customer': customer,
|
||||||
'billing_address': billing_address,
|
'billing_address': billing_address,
|
||||||
'stripe_charge': charge
|
'stripe_charge': charge,
|
||||||
|
'amount': final_price,
|
||||||
|
'original_price': normal_price,
|
||||||
|
'special_month_price': BookingPrice.objects.last().special_month_price
|
||||||
}
|
}
|
||||||
order = BookingOrder.create(order_data)
|
order = BookingOrder.create(order_data)
|
||||||
|
|
||||||
|
@ -208,8 +211,6 @@ class BookingPaymentView(LoginRequiredMixin, MembershipRequired, FormView):
|
||||||
# 'membership_dates': membership.type.first_month_formated_range
|
# 'membership_dates': membership.type.first_month_formated_range
|
||||||
# })
|
# })
|
||||||
return HttpResponseRedirect(self.get_success_url(order.id))
|
return HttpResponseRedirect(self.get_success_url(order.id))
|
||||||
return super(BookingPaymentView, self).form_valid(form)
|
|
||||||
# return HttpResponseRedirect(reverse('digitalglarus:membership_activated'))
|
|
||||||
|
|
||||||
|
|
||||||
class MembershipPricingView(TemplateView):
|
class MembershipPricingView(TemplateView):
|
||||||
|
@ -224,10 +225,11 @@ class MembershipPricingView(TemplateView):
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class MembershipPaymentView(LoginRequiredMixin, FormView):
|
class MembershipPaymentView(LoginRequiredMixin, IsNotMemberMixin, FormView):
|
||||||
template_name = "digitalglarus/membership_payment.html"
|
template_name = "digitalglarus/membership_payment.html"
|
||||||
login_url = reverse_lazy('digitalglarus:signup')
|
login_url = reverse_lazy('digitalglarus:signup')
|
||||||
form_class = MembershipBillingForm
|
form_class = MembershipBillingForm
|
||||||
|
already_member_redirect_url = reverse_lazy('digitalglarus:membership_orders_list')
|
||||||
|
|
||||||
def get_form_kwargs(self):
|
def get_form_kwargs(self):
|
||||||
self.membership_type = MembershipType.objects.get(name='standard')
|
self.membership_type = MembershipType.objects.get(name='standard')
|
||||||
|
@ -291,7 +293,8 @@ class MembershipPaymentView(LoginRequiredMixin, FormView):
|
||||||
'membership': membership,
|
'membership': membership,
|
||||||
'customer': customer,
|
'customer': customer,
|
||||||
'billing_address': billing_address,
|
'billing_address': billing_address,
|
||||||
'stripe_charge': charge
|
'stripe_charge': charge,
|
||||||
|
'amount': membership_type.first_month_price
|
||||||
}
|
}
|
||||||
MembershipOrder.create(order_data)
|
MembershipOrder.create(order_data)
|
||||||
|
|
||||||
|
@ -319,6 +322,45 @@ class MembershipActivatedView(TemplateView):
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
class MembershipOrdersListView(LoginRequiredMixin, ListView):
|
||||||
|
template_name = "digitalglarus/membership_orders_list.html"
|
||||||
|
context_object_name = "orders"
|
||||||
|
login_url = reverse_lazy('digitalglarus:login')
|
||||||
|
model = MembershipOrder
|
||||||
|
paginate_by = 10
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super(MembershipOrdersListView, self).get_context_data(**kwargs)
|
||||||
|
start_date, end_date = MembershipOrder.current_membership(self.request.user)
|
||||||
|
context.update({
|
||||||
|
'membership_start_date': start_date,
|
||||||
|
'membership_end_date': end_date,
|
||||||
|
})
|
||||||
|
return context
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
queryset = super(MembershipOrdersListView, self).get_queryset()
|
||||||
|
queryset = queryset.filter(customer__user=self.request.user)
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
|
class OrdersMembershipDetailView(LoginRequiredMixin, DetailView):
|
||||||
|
template_name = "digitalglarus/membership_orders_detail.html"
|
||||||
|
context_object_name = "order"
|
||||||
|
login_url = reverse_lazy('digitalglarus:login')
|
||||||
|
# permission_required = ['view_hostingorder']
|
||||||
|
model = MembershipOrder
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super(OrdersMembershipDetailView, self).get_context_data(**kwargs)
|
||||||
|
start_date, end_date = self.object.get_membership_range_date()
|
||||||
|
context.update({
|
||||||
|
'membership_start_date': start_date,
|
||||||
|
'membership_end_date': end_date,
|
||||||
|
})
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
class OrdersBookingDetailView(LoginRequiredMixin, DetailView):
|
class OrdersBookingDetailView(LoginRequiredMixin, DetailView):
|
||||||
template_name = "digitalglarus/booking_orders_detail.html"
|
template_name = "digitalglarus/booking_orders_detail.html"
|
||||||
context_object_name = "order"
|
context_object_name = "order"
|
||||||
|
|
Loading…
Reference in a new issue