Merge pull request #120 from levivm/feature/new_digitalglarus
Feature/new digitalglarus
This commit is contained in:
commit
e245c1d092
24 changed files with 1290 additions and 49 deletions
|
@ -1,6 +1,6 @@
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
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
|
||||||
|
@ -34,3 +34,46 @@ class MembershipBillingForm(BillingAddressForm):
|
||||||
'postal_code': _('Postal Code'),
|
'postal_code': _('Postal Code'),
|
||||||
'country': _('Country'),
|
'country': _('Country'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class BookingBillingForm(BillingAddressForm):
|
||||||
|
token = forms.CharField(widget=forms.HiddenInput())
|
||||||
|
start_date = forms.DateField(widget=forms.HiddenInput())
|
||||||
|
end_date = forms.DateField(widget=forms.HiddenInput())
|
||||||
|
price = forms.FloatField(widget=forms.HiddenInput())
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = BillingAddress
|
||||||
|
fields = ['start_date', 'end_date', 'price', 'street_address',
|
||||||
|
'city', 'postal_code', 'country']
|
||||||
|
labels = {
|
||||||
|
'street_address': _('Street Address'),
|
||||||
|
'city': _('City'),
|
||||||
|
'postal_code': _('Postal Code'),
|
||||||
|
'country': _('Country'),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class BookingDateForm(forms.Form):
|
||||||
|
start_date = forms.DateField(required=False)
|
||||||
|
end_date = forms.DateField(required=False)
|
||||||
|
date_range = forms.CharField(required=False)
|
||||||
|
|
||||||
|
def clean_date_range(self):
|
||||||
|
date_range = self.cleaned_data.get('date_range')
|
||||||
|
dates = date_range.replace(' ', '').split('-')
|
||||||
|
try:
|
||||||
|
start_date, end_date = [datetime.strptime(date_string, "%m/%d/%Y").date()
|
||||||
|
for date_string in dates]
|
||||||
|
except ValueError:
|
||||||
|
raise forms.ValidationError("Submit valid dates.")
|
||||||
|
|
||||||
|
if start_date > end_date:
|
||||||
|
raise forms.ValidationError("Your end date must be greather than your start date.")
|
||||||
|
return start_date, end_date
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
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
|
||||||
|
|
30
digitalglarus/migrations/0008_auto_20160820_1959.py
Normal file
30
digitalglarus/migrations/0008_auto_20160820_1959.py
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.9.4 on 2016-08-20 19:59
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('utils', '0002_billingaddress'),
|
||||||
|
('membership', '0006_auto_20160526_0445'),
|
||||||
|
('digitalglarus', '0007_auto_20160820_0408'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='membershiporder',
|
||||||
|
name='billing_address',
|
||||||
|
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='utils.BillingAddress'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='membershiporder',
|
||||||
|
name='customer',
|
||||||
|
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='membership.StripeCustomer'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,52 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.9.4 on 2016-08-25 05:11
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('utils', '0002_billingaddress'),
|
||||||
|
('membership', '0006_auto_20160526_0445'),
|
||||||
|
('digitalglarus', '0008_auto_20160820_1959'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Booking',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('start_date', models.DateField()),
|
||||||
|
('end_date', models.DateField()),
|
||||||
|
('price', models.FloatField()),
|
||||||
|
('membership', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='digitalglarus.Membership')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='BookingOrder',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('approved', models.BooleanField(default=False)),
|
||||||
|
('last4', models.CharField(max_length=4)),
|
||||||
|
('cc_brand', models.CharField(max_length=10)),
|
||||||
|
('stripe_charge_id', models.CharField(max_length=100, null=True)),
|
||||||
|
('billing_address', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='utils.BillingAddress')),
|
||||||
|
('booking', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='digitalglarus.Booking')),
|
||||||
|
('customer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='membership.StripeCustomer')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='BookingPrices',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('price_per_day', models.FloatField()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
19
digitalglarus/migrations/0010_auto_20160828_1745.py
Normal file
19
digitalglarus/migrations/0010_auto_20160828_1745.py
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.9.4 on 2016-08-28 17:45
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('digitalglarus', '0009_booking_bookingorder_bookingprices'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameModel(
|
||||||
|
old_name='BookingPrices',
|
||||||
|
new_name='BookingPrice',
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,21 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.9.4 on 2016-08-28 21:35
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('digitalglarus', '0010_auto_20160828_1745'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='bookingprice',
|
||||||
|
name='special_price_offer',
|
||||||
|
field=models.FloatField(default=290.0),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
20
digitalglarus/migrations/0012_booking_free_days.py
Normal file
20
digitalglarus/migrations/0012_booking_free_days.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.9.4 on 2016-08-30 03:28
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('digitalglarus', '0011_bookingprice_special_price_offer'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='booking',
|
||||||
|
name='free_days',
|
||||||
|
field=models.IntegerField(default=0),
|
||||||
|
),
|
||||||
|
]
|
19
digitalglarus/migrations/0013_remove_booking_membership.py
Normal file
19
digitalglarus/migrations/0013_remove_booking_membership.py
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.9.4 on 2016-08-30 04:56
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('digitalglarus', '0012_booking_free_days'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='booking',
|
||||||
|
name='membership',
|
||||||
|
),
|
||||||
|
]
|
21
digitalglarus/migrations/0014_booking_final_price.py
Normal file
21
digitalglarus/migrations/0014_booking_final_price.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.9.4 on 2016-09-02 03:49
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('digitalglarus', '0013_remove_booking_membership'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='booking',
|
||||||
|
name='final_price',
|
||||||
|
field=models.FloatField(default=250),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
38
digitalglarus/mixins.py
Normal file
38
digitalglarus/mixins.py
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
from django.db import models
|
||||||
|
from django.http import HttpResponseRedirect
|
||||||
|
from membership.models import StripeCustomer
|
||||||
|
from utils.models import BillingAddress
|
||||||
|
|
||||||
|
|
||||||
|
class MembershipRequired(object):
|
||||||
|
membership_redirect_url = None
|
||||||
|
|
||||||
|
def dispatch(self, request, *args, **kwargs):
|
||||||
|
from .models import Membership
|
||||||
|
if not Membership.is_digitalglarus_member(request.user):
|
||||||
|
return HttpResponseRedirect(self.membership_redirect_url)
|
||||||
|
|
||||||
|
return super(MembershipRequired, self).dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class Ordereable(models.Model):
|
||||||
|
customer = models.ForeignKey(StripeCustomer)
|
||||||
|
billing_address = models.ForeignKey(BillingAddress)
|
||||||
|
created_at = models.DateTimeField(auto_now_add=True)
|
||||||
|
approved = models.BooleanField(default=False)
|
||||||
|
last4 = models.CharField(max_length=4)
|
||||||
|
cc_brand = models.CharField(max_length=10)
|
||||||
|
stripe_charge_id = models.CharField(max_length=100, null=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create(cls, data):
|
||||||
|
stripe_charge = data.pop('stripe_charge', None)
|
||||||
|
instance = cls.objects.create(**data)
|
||||||
|
instance.stripe_charge_id = stripe_charge.id
|
||||||
|
instance.last4 = stripe_charge.source.last4
|
||||||
|
instance.cc_brand = stripe_charge.source.brand
|
||||||
|
instance.save()
|
||||||
|
return instance
|
|
@ -1,7 +1,17 @@
|
||||||
|
|
||||||
|
import calendar
|
||||||
|
from datetime import datetime, date, timedelta
|
||||||
|
from dateutil.relativedelta import relativedelta
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.db.models import Q
|
||||||
from cms.models import CMSPlugin
|
from cms.models import CMSPlugin
|
||||||
from filer.fields.image import FilerImageField
|
from filer.fields.image import FilerImageField
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
|
from django.utils.functional import cached_property
|
||||||
|
from .mixins import Ordereable
|
||||||
|
|
||||||
|
# from membership.models import StripeCustomer
|
||||||
|
# from utils.models import BillingAddress
|
||||||
|
|
||||||
|
|
||||||
class MembershipType(models.Model):
|
class MembershipType(models.Model):
|
||||||
|
@ -13,24 +23,132 @@ class MembershipType(models.Model):
|
||||||
name = models.CharField(choices=MEMBERSHIP_TYPES, max_length=20)
|
name = models.CharField(choices=MEMBERSHIP_TYPES, max_length=20)
|
||||||
price = models.FloatField()
|
price = models.FloatField()
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def days_left(self):
|
||||||
|
current_date = date.today()
|
||||||
|
_, days_in_month = calendar.monthrange(current_date.year, current_date.month)
|
||||||
|
pass_days = current_date.day
|
||||||
|
days_left = days_in_month - pass_days + 1
|
||||||
|
return days_left
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def first_month_price(self):
|
||||||
|
current_date = date.today()
|
||||||
|
_, days_in_month = calendar.monthrange(current_date.year, current_date.month)
|
||||||
|
pass_days = current_date.day
|
||||||
|
days_left = days_in_month - pass_days + 1
|
||||||
|
percentage = days_left / days_in_month
|
||||||
|
membership_price = self.price
|
||||||
|
final_price = membership_price * percentage
|
||||||
|
return final_price
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def first_month_range(self):
|
||||||
|
current_date = date.today()
|
||||||
|
_, days_in_month = calendar.monthrange(current_date.year, current_date.month)
|
||||||
|
pass_days = current_date.day
|
||||||
|
days_left = days_in_month - pass_days
|
||||||
|
end_date = current_date + timedelta(days=days_left)
|
||||||
|
return current_date, end_date
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def first_month_formated_range(self):
|
||||||
|
start_date, end_date = self.first_month_range
|
||||||
|
return "{} - {}".format(datetime.strftime(start_date, "%b, %d %Y"),
|
||||||
|
datetime.strftime(end_date, "%b, %d %Y"))
|
||||||
|
|
||||||
|
|
||||||
class Membership(models.Model):
|
class Membership(models.Model):
|
||||||
type = models.ForeignKey(MembershipType)
|
type = models.ForeignKey(MembershipType)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, data, user):
|
def is_digitalglarus_member(cls, user):
|
||||||
|
past_month = (datetime.today() - relativedelta(months=1)).month
|
||||||
|
has_booking_current_month = Q(membershiporder__created_at__month=datetime.today().month)
|
||||||
|
has_booking_past_month = Q(membershiporder__customer__user=user,
|
||||||
|
membershiporder__created_at__month=past_month)
|
||||||
|
return cls.objects.filter(has_booking_past_month | has_booking_current_month).exists()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create(cls, data):
|
||||||
instance = cls.objects.create(**data)
|
instance = cls.objects.create(**data)
|
||||||
instance.assign_permissions(user)
|
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
|
|
||||||
class MembershipOrder(models.Model):
|
class MembershipOrder(Ordereable, models.Model):
|
||||||
membership = models.ForeignKey(Membership)
|
membership = models.ForeignKey(Membership)
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
|
||||||
approved = models.BooleanField(default=False)
|
@classmethod
|
||||||
last4 = models.CharField(max_length=4)
|
def create(cls, data):
|
||||||
cc_brand = models.CharField(max_length=10)
|
stripe_charge = data.pop('stripe_charge', None)
|
||||||
stripe_charge_id = models.CharField(max_length=100, null=True)
|
instance = cls.objects.create(**data)
|
||||||
|
instance.stripe_charge_id = stripe_charge.id
|
||||||
|
instance.last4 = stripe_charge.source.last4
|
||||||
|
instance.cc_brand = stripe_charge.source.brand
|
||||||
|
return instance
|
||||||
|
|
||||||
|
|
||||||
|
class BookingPrice(models.Model):
|
||||||
|
price_per_day = models.FloatField()
|
||||||
|
special_price_offer = models.FloatField()
|
||||||
|
|
||||||
|
|
||||||
|
class Booking(models.Model):
|
||||||
|
start_date = models.DateField()
|
||||||
|
end_date = models.DateField()
|
||||||
|
price = models.FloatField()
|
||||||
|
free_days = models.IntegerField(default=0)
|
||||||
|
final_price = models.FloatField()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create(cls, data):
|
||||||
|
instance = cls.objects.create(**data)
|
||||||
|
return instance
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_ramaining_free_days(cls, user, start_date, end_date):
|
||||||
|
|
||||||
|
TWO_DAYS = 2
|
||||||
|
|
||||||
|
start_month = start_date.month
|
||||||
|
end_month = end_date.month
|
||||||
|
months = abs(start_month - (end_month + 12) if end_month < start_month
|
||||||
|
else end_month - start_month)
|
||||||
|
current_date = datetime.today()
|
||||||
|
current_month_bookings = cls.objects.filter(bookingorder__customer__user=user,
|
||||||
|
start_date__month=current_date.month)
|
||||||
|
free_days_this_month = TWO_DAYS - sum(map(lambda x: x.free_days, current_month_bookings))
|
||||||
|
total_free_days = months * TWO_DAYS + free_days_this_month
|
||||||
|
return total_free_days
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def booking_price(cls, user, start_date, end_date):
|
||||||
|
|
||||||
|
MAX_MONTH_PRICE = 290
|
||||||
|
MAX_MONTH_DAYS_PROMOTION = 31
|
||||||
|
MIN_MONTH_DAYS_PROMOTION = 19
|
||||||
|
|
||||||
|
booking_prices = BookingPrice.objects.last()
|
||||||
|
price_per_day = booking_prices.price_per_day
|
||||||
|
booking_days = (end_date - start_date).days + 1
|
||||||
|
months = booking_days // MAX_MONTH_DAYS_PROMOTION
|
||||||
|
remanent_days = booking_days % MAX_MONTH_DAYS_PROMOTION
|
||||||
|
months_prices = months * MAX_MONTH_PRICE
|
||||||
|
remanent_days_price = remanent_days * price_per_day \
|
||||||
|
if remanent_days <= MIN_MONTH_DAYS_PROMOTION else MAX_MONTH_PRICE
|
||||||
|
normal_price = months_prices + remanent_days_price
|
||||||
|
|
||||||
|
free_days = cls.get_ramaining_free_days(user, start_date, end_date)
|
||||||
|
final_booking_price = normal_price - (free_days * price_per_day)
|
||||||
|
|
||||||
|
return normal_price, final_booking_price, free_days
|
||||||
|
|
||||||
|
|
||||||
|
class BookingOrder(Ordereable, models.Model):
|
||||||
|
booking = models.OneToOneField(Booking)
|
||||||
|
|
||||||
|
def booking_days(self):
|
||||||
|
return (self.booking.end_date - self.booking.start_date).days + 1
|
||||||
|
|
||||||
|
|
||||||
class Supporter(models.Model):
|
class Supporter(models.Model):
|
||||||
|
@ -44,9 +162,6 @@ class Supporter(models.Model):
|
||||||
return reverse('dgSupporters_view', args=[self.pk])
|
return reverse('dgSupporters_view', args=[self.pk])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class DGGallery(models.Model):
|
class DGGallery(models.Model):
|
||||||
parent = models.ForeignKey('self', blank=True, null=True)
|
parent = models.ForeignKey('self', blank=True, null=True)
|
||||||
name = models.CharField(max_length=30)
|
name = models.CharField(max_length=30)
|
||||||
|
|
25
digitalglarus/static/digitalglarus/js/booking.js
Normal file
25
digitalglarus/static/digitalglarus/js/booking.js
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
$( document ).ready(function() {
|
||||||
|
|
||||||
|
|
||||||
|
// $('#booking-date-range').daterangepicker();
|
||||||
|
|
||||||
|
var tomorrow = new Date(new Date().getTime() + 24 * 60 * 60 * 1000);
|
||||||
|
// var tomorrow = today.setDate(today.getDate() + 1);
|
||||||
|
$('#booking-date-range').daterangepicker({
|
||||||
|
autoUpdateInput: false,
|
||||||
|
locale: {
|
||||||
|
cancelLabel: 'Clear'
|
||||||
|
},
|
||||||
|
minDate: tomorrow,
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$('#booking-date-range').on('apply.daterangepicker', function(ev, picker) {
|
||||||
|
$(this).val(picker.startDate.format('MM/DD/YYYY') + ' - ' + picker.endDate.format('MM/DD/YYYY'));
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#booking-date-range').on('cancel.daterangepicker', function(ev, picker) {
|
||||||
|
$(this).val('Select your dates');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
21
digitalglarus/static/digitalglarus/js/utils.js
Normal file
21
digitalglarus/static/digitalglarus/js/utils.js
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
$( document ).ready(function() {
|
||||||
|
|
||||||
|
|
||||||
|
function printDiv(divName) {
|
||||||
|
var printContents = document.getElementById(divName).innerHTML;
|
||||||
|
var originalContents = document.body.innerHTML;
|
||||||
|
|
||||||
|
document.body.innerHTML = printContents;
|
||||||
|
|
||||||
|
window.print();
|
||||||
|
|
||||||
|
document.body.innerHTML = originalContents;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$('.print').on('click', function(e){
|
||||||
|
printDiv(e.target.getAttribute("data-print") );
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
53
digitalglarus/templates/digitalglarus/booking.html
Normal file
53
digitalglarus/templates/digitalglarus/booking.html
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
{% extends "new_base_glarus.html" %}
|
||||||
|
{% load staticfiles cms_tags bootstrap3%}
|
||||||
|
{% block title %}crowdfunding{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<section id="price">
|
||||||
|
<div class="signup-container">
|
||||||
|
<div class="col-xs-12 col-sm-3 col-lg-4 text-center wow fadeInDown"> </div>
|
||||||
|
<div class="col-xs-12 col-sm-6 col-lg-4 text-center wow fadeInDown">
|
||||||
|
<div class="signup-box">
|
||||||
|
<span class="glyphicon glyphicon-plus"></span>
|
||||||
|
<h2 class="section-heading">Booking</h2>
|
||||||
|
<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>
|
||||||
|
<hr class="primary">
|
||||||
|
|
||||||
|
<div class="signup-form form-group row">
|
||||||
|
<input type="hidden" name="next" value="{{ request.GET.next }}">
|
||||||
|
<form action="" method="post" class="form" novalidate>
|
||||||
|
{% csrf_token %}
|
||||||
|
<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>
|
||||||
|
</form>
|
||||||
|
<br>
|
||||||
|
<div class="notice-box">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-12 col-sm-3 col-lg-4 text-center wow fadeInDown"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="contact">
|
||||||
|
<div class="fill">
|
||||||
|
<div class="row" class="wow fadeInDown">
|
||||||
|
<div class="col-lg-12 text-center wow fadeInDown">
|
||||||
|
<div class="col-md-4 map-title">
|
||||||
|
Digital Glarus<br>
|
||||||
|
<span class="map-caption">In der Au 7 Schwanden 8762 Switzerland
|
||||||
|
<br>info@digitalglarus.ch
|
||||||
|
<br>
|
||||||
|
(044) 534-66-22
|
||||||
|
<p> </p>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<p> </p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{% endblock %}
|
|
@ -0,0 +1,88 @@
|
||||||
|
{% 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 Booking 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: {{start_date}} - {{end_date}}<br>
|
||||||
|
</h2>
|
||||||
|
<h2 class="col-xs-6 payment-total text-left">Total days {{booking_days}}</h2>
|
||||||
|
<h2 class="order-sum">{{original_price|floatformat}}CHF</h2>
|
||||||
|
{% if free_days %}
|
||||||
|
<h2 class="col-xs-6 payment-total text-left">Free days {{free_days}} </h2>
|
||||||
|
<h2 class="order-sum">-{{total_discount|floatformat}}CHF</h2>
|
||||||
|
{% endif %}
|
||||||
|
<hr class="greyline-long">
|
||||||
|
<h2 class="col-xs-6 payment-total text-left"> Total</h2>
|
||||||
|
<h2 class="order-result">{{final_price|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: {{start_date}} - {{end_date}}<br></h2>
|
||||||
|
|
||||||
|
<h2 class="col-xs-6 payment-total">Total days {{booking_days}}</h2>
|
||||||
|
<h2 class="order-sum">{{original_price|floatformat}}CHF</h2>
|
||||||
|
{% if free_days %}
|
||||||
|
<h2 class="col-xs-6 payment-total">Free days {{free_days}}</h2>
|
||||||
|
<h2 class="order-sum">-{{total_discount|floatformat}}CHF</h2>
|
||||||
|
{% endif %}
|
||||||
|
<hr class="greyline">
|
||||||
|
<h2 class="col-xs-6 payment-total">Total</h2>
|
||||||
|
<h2 class="order-result">{{final_price|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">2016.11.13-2016.12.13</h2>
|
||||||
|
<hr class="greyline-long">
|
||||||
|
<h2 class="order-head">Booking history</h2>
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>#</th>
|
||||||
|
<th>Booking dates</th>
|
||||||
|
<th>Days</th>
|
||||||
|
<th>Invoice</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for order in orders%}
|
||||||
|
<tr>
|
||||||
|
<th scope="row">{{order.id}}</th>
|
||||||
|
<td>{{order.booking.start_date}}-{{order.booking.end_date}}</td>
|
||||||
|
<td>{{order.booking_days}}</td>
|
||||||
|
<td><a class="btn btn-xs btn-primary btn-darkgrey" href="{% url 'digitalglarus:booking_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 %}
|
186
digitalglarus/templates/digitalglarus/booking_payment.html
Normal file
186
digitalglarus/templates/digitalglarus/booking_payment.html
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
{% extends "new_base_glarus.html" %}
|
||||||
|
{% load staticfiles bootstrap3 i18n %}
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
|
||||||
|
.nopadding {
|
||||||
|
padding: 0 !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control#id_country{
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
background-position: right 50%;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAMCAYAAABSgIzaAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDZFNDEwNjlGNzFEMTFFMkJEQ0VDRTM1N0RCMzMyMkIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDZFNDEwNkFGNzFEMTFFMkJEQ0VDRTM1N0RCMzMyMkIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo0NkU0MTA2N0Y3MUQxMUUyQkRDRUNFMzU3REIzMzIyQiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo0NkU0MTA2OEY3MUQxMUUyQkRDRUNFMzU3REIzMzIyQiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PuGsgwQAAAA5SURBVHjaYvz//z8DOYCJgUxAf42MQIzTk0D/M+KzkRGPoQSdykiKJrBGpOhgJFYTWNEIiEeAAAMAzNENEOH+do8AAAAASUVORK5CYII=);
|
||||||
|
padding: .5em;
|
||||||
|
padding-right: 1.5em
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<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">Booking</h2>
|
||||||
|
<!-- <h2 class="membership-amount">35CHF</h2> -->
|
||||||
|
<hr class="greyline-long">
|
||||||
|
<h2 class="billing-head">Billing Adress</h2>
|
||||||
|
<h2 class="membership-lead">
|
||||||
|
Your Digital Glarus Membership enables
|
||||||
|
you to use our coworking space and it includes
|
||||||
|
2 working days for the month you signed up.
|
||||||
|
The membership fee is a monthly subscription.
|
||||||
|
Additional day costs
|
||||||
|
15CHF per day. More than 17 days a month it
|
||||||
|
will charge only 290CHF/month.
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div class="signup-form form-group row">
|
||||||
|
<form role="form" id="billing-form" method="post" action="{% url 'digitalglarus:booking_payment' %}" novalidate>
|
||||||
|
{% for field in form %}
|
||||||
|
{% csrf_token %}
|
||||||
|
{% bootstrap_field field show_label=False type='fields'%}
|
||||||
|
{% endfor %}
|
||||||
|
{% bootstrap_form_errors form type='non_fields'%}
|
||||||
|
{{form.errors}}
|
||||||
|
|
||||||
|
<br>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<h2 class="billing-head">Credit Card</h2>
|
||||||
|
<div class="signup-form form-group row">
|
||||||
|
<form role="form" id="payment-form" novalidate>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-9 col-md-12">
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" class="form-control" name="cardName" placeholder="Name on card" required autofocus data-stripe="name" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-9 col-md-12">
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" class="form-control" name="cardNumber" placeholder="Valid Card Number" required data-stripe="number" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-6 col-md-6 nopadding">
|
||||||
|
<label for="expMonth">EXPIRATION DATE</label><br/>
|
||||||
|
<div class="col-xs-6 col-lg-6 col-md-6">
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" class="form-control" name="expMonth" placeholder="MM" required data-stripe="exp_month" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-6 col-lg-6 col-md-6 pl-ziro">
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" class="form-control" name="expYear" placeholder="YY" required data-stripe="exp_year" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-4 col-md-6 pull-right">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="cvCode">CV CODE</label>
|
||||||
|
<input type="password" class="form-control" name="cvCode" placeholder="CV" required data-stripe="cvc" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-12">
|
||||||
|
<button class="btn btn-primary btn-lg btn-blck " type="submit">Book</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row" style="display:none;">
|
||||||
|
<div class="col-xs-12">
|
||||||
|
<p class="payment-errors"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% if paymentError %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-12">
|
||||||
|
<p>
|
||||||
|
{% bootstrap_alert paymentError alert_type='danger' %}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
</form>
|
||||||
|
<br>
|
||||||
|
</div>
|
||||||
|
</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">Booking Summary</h2>
|
||||||
|
</div>
|
||||||
|
<div class="order-box">
|
||||||
|
<h3 class="col-xs-6 order-item">Dates {{start_date}} - {{end_date}}</h3>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<hr class="greyline">
|
||||||
|
<h2 class="col-xs-6 payment-total">Total days {{booking_days}} </h2>
|
||||||
|
<h2 class="order-sum">{{original_price|floatformat}}CHF</h2>
|
||||||
|
{% if free_days %}
|
||||||
|
<h2 class="col-xs-6 payment-total">Free days {{free_days}}</h2>
|
||||||
|
<h2 class="order-sum"><span class="text-danger">-{{total_discount|floatformat}}CHF</span></h2>
|
||||||
|
{% endif %}
|
||||||
|
<hr class="greyline">
|
||||||
|
<h2 class="col-xs-6 payment-total">Total</h2>
|
||||||
|
<h2 class="order-result">{{discount_price|floatformat}}CHF</h2>
|
||||||
|
<div class="text-center">
|
||||||
|
<label class="custom-control custom-checkbox">
|
||||||
|
<br/>
|
||||||
|
<input type="checkbox" class="custom-control-input">
|
||||||
|
<span class="custom-control-indicator"></span>
|
||||||
|
<span class="custom-control-description">I accept the Digital Glarus <a href=#>Terms and Conditions</a>, <a href=#>Community Guidelines</a> and <a href=#>Privacy Policy</a></span>
|
||||||
|
</label>
|
||||||
|
<div class="button-box">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="button-box">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<section id="contact">
|
||||||
|
<div class="fill">
|
||||||
|
<div class="row" class="wow fadeInDown">
|
||||||
|
<div class="col-lg-12 text-center wow fadeInDown">
|
||||||
|
<div class="col-md-4 map-title">
|
||||||
|
Digital Glarus<br>
|
||||||
|
<span class="map-caption">In der Au 7 Schwanden 8762 Switzerland
|
||||||
|
<br>info@digitalglarus.ch
|
||||||
|
<br>
|
||||||
|
(044) 534-66-22
|
||||||
|
<p> </p>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<p> </p>
|
||||||
|
</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,57 @@
|
||||||
|
{% extends "new_base_glarus.html" %}
|
||||||
|
{% load staticfiles cms_tags bootstrap3%}
|
||||||
|
{% block title %}crowdfunding{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<section id="price">
|
||||||
|
<div class="signup-container">
|
||||||
|
<div class="col-xs-12 col-sm-3 col-lg-4 text-center wow fadeInDown"> </div>
|
||||||
|
<div class="col-xs-12 col-sm-6 col-lg-4 text-center wow fadeInDown">
|
||||||
|
|
||||||
|
<!-- <span class="glyphicon glyphicon-user"></span> -->
|
||||||
|
<div class="payment-box">
|
||||||
|
<h2 class="billing-head">Membership Activated</h2>
|
||||||
|
<hr class="greyline-long">
|
||||||
|
<h2 class="membership-lead">Your Digital Glarus membership is successfully activated for the following date.</h2>
|
||||||
|
<div class="date-box">
|
||||||
|
<h2 class="date-oneline">{{membership_dates}}</h2>
|
||||||
|
<h2 class="activation-lead">Now you can book your next coworking!</h2>
|
||||||
|
</div>
|
||||||
|
<!--<hr class="primary">-->
|
||||||
|
<div class="signup-form form-group row">
|
||||||
|
|
||||||
|
<div class="button-booking-box form-inline row">
|
||||||
|
<a class="btn btn-primary btn-blue" href={% url 'digitalglarus:booking' %}>Go to Booking</a>
|
||||||
|
</div>
|
||||||
|
<div class="notice-box text-left">
|
||||||
|
<p class="order-bottom-text">Your membership will be automatically renewed each month. For deactivating go to<a href=#>my page</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-12 col-sm-3 col-lg-4 text-center wow fadeInDown"> </div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section id="contact">
|
||||||
|
<div class="fill">
|
||||||
|
<div class="row" class="wow fadeInDown">
|
||||||
|
<div class="col-lg-12 text-center wow fadeInDown">
|
||||||
|
<div class="col-md-4 map-title">
|
||||||
|
Digital Glarus<br>
|
||||||
|
<span class="map-caption">In der Au 7 Schwanden 8762 Switzerland
|
||||||
|
<br>info@digitalglarus.ch
|
||||||
|
<br>
|
||||||
|
(044) 534-66-22
|
||||||
|
<p> </p>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<p> </p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{% endblock %}
|
|
@ -8,6 +8,16 @@
|
||||||
padding: 0 !important;
|
padding: 0 !important;
|
||||||
margin: 0 !important;
|
margin: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.form-control#id_country{
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
background-position: right 50%;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAMCAYAAABSgIzaAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDZFNDEwNjlGNzFEMTFFMkJEQ0VDRTM1N0RCMzMyMkIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDZFNDEwNkFGNzFEMTFFMkJEQ0VDRTM1N0RCMzMyMkIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo0NkU0MTA2N0Y3MUQxMUUyQkRDRUNFMzU3REIzMzIyQiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo0NkU0MTA2OEY3MUQxMUUyQkRDRUNFMzU3REIzMzIyQiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PuGsgwQAAAA5SURBVHjaYvz//z8DOYCJgUxAf42MQIzTk0D/M+KzkRGPoQSdykiKJrBGpOhgJFYTWNEIiEeAAAMAzNENEOH+do8AAAAASUVORK5CYII=);
|
||||||
|
padding: .5em;
|
||||||
|
padding-right: 1.5em
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<section id="price">
|
<section id="price">
|
||||||
|
@ -23,9 +33,13 @@
|
||||||
Additional day costs
|
Additional day costs
|
||||||
15CHF per day. More than 17 days a month it
|
15CHF per day. More than 17 days a month it
|
||||||
will charge only 290CHF/month.</h2>
|
will charge only 290CHF/month.</h2>
|
||||||
|
<h2 class="membership-lead">
|
||||||
|
You will be charged on the first of the month until you
|
||||||
|
cancel your subscription. Previous charges won't be refunded.
|
||||||
|
</h2>
|
||||||
<hr class="greyline-long">
|
<hr class="greyline-long">
|
||||||
<h2 class="billing-head">Member Name</h2>
|
<h2 class="billing-head">Member Name</h2>
|
||||||
<h2 class="member-name">Nico Schottelius</h2>
|
<h2 class="member-name">{{request.user.name}}</h2>
|
||||||
<hr class="greyline-long">
|
<hr class="greyline-long">
|
||||||
<h2 class="billing-head">Billing Adress</h2>
|
<h2 class="billing-head">Billing Adress</h2>
|
||||||
<div class="signup-form form-group row">
|
<div class="signup-form form-group row">
|
||||||
|
@ -44,20 +58,14 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-9 col-md-12">
|
<div class="col-xs-9 col-md-12">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control" name="cardName" placeholder="Name on card" required autofocus data-stripe="name" />
|
<input type="text" class="form-control" name="cardName" placeholder="Name on card" required autofocus data-stripe="name" />
|
||||||
<span class="input-group-addon"><i class="fa fa-user" aria-hidden="true"></i></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-9 col-md-12">
|
<div class="col-xs-9 col-md-12">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control" name="cardNumber" placeholder="Valid Card Number" required data-stripe="number" />
|
<input type="text" class="form-control" name="cardNumber" placeholder="Valid Card Number" required data-stripe="number" />
|
||||||
<span class="input-group-addon"><i class="fa fa-credit-card"></i></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -75,7 +83,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-4 col-md-6 pull-right nopadding">
|
<div class="col-xs-4 col-md-6 pull-right">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="cvCode">CV CODE</label>
|
<label for="cvCode">CV CODE</label>
|
||||||
<input type="password" class="form-control" name="cvCode" placeholder="CV" required data-stripe="cvc" />
|
<input type="password" class="form-control" name="cvCode" placeholder="CV" required data-stripe="cvc" />
|
||||||
|
@ -84,7 +92,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-12">
|
<div class="col-xs-12">
|
||||||
<button class="btn btn-success btn-lg btn-block" type="submit">Purchase membership</button>
|
<button class="btn btn-primary btn-lg btn-blck " type="submit">Purchase membership</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row" style="display:none;">
|
<div class="row" style="display:none;">
|
||||||
|
@ -115,25 +123,25 @@
|
||||||
<div class="order-box">
|
<div class="order-box">
|
||||||
<h2 class="col-xs-6 order-item">Digital Glarus Membership</h2>
|
<h2 class="col-xs-6 order-item">Digital Glarus Membership</h2>
|
||||||
<br>
|
<br>
|
||||||
<h2 class="col-xs-6 order-duration">valid 2016.09.08 - 2016.10.08</h2>
|
<h2 class="col-xs-6 order-duration">valid {{membership_type.first_month_formated_range}}</h2>
|
||||||
|
<br/>
|
||||||
<h2 class="order-person">1 person</h2>
|
<h2 class="order-person">1 person</h2>
|
||||||
<h2 class="col-xs-6 payment-total">Today's Total</h2>
|
<h2 class="col-xs-6 payment-total">Today's Total for {{membership_type.days_left}} days </h2>
|
||||||
<h2 class="order-sum">0.00CHF</h2>
|
<h2 class="order-sum">{{membership_type.first_month_price|floatformat}}CHF</h2>
|
||||||
<hr class="greyline">
|
<hr class="greyline">
|
||||||
<h2 class="col-xs-6 payment-total">Total</h2>
|
<h2 class="col-xs-6 payment-total">Total</h2>
|
||||||
<h2 class="order-result">35CHF</h2>
|
<h2 class="order-result">{{membership_type.first_month_price|floatformat}}CHF</h2>
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<label class="custom-control custom-checkbox">
|
<label class="custom-control custom-checkbox">
|
||||||
|
<br/>
|
||||||
<input type="checkbox" class="custom-control-input">
|
<input type="checkbox" class="custom-control-input">
|
||||||
<span class="custom-control-indicator"></span>
|
<span class="custom-control-indicator"></span>
|
||||||
<span class="custom-control-description">I accept the Digital Glarus <a href=#>Terms and Conditions</a>, <a href=#>Community Guidelines</a> and <a href=#>Privacy Policy</a></span>
|
<span class="custom-control-description">I accept the Digital Glarus <a href=#>Terms and Conditions</a>, <a href=#>Community Guidelines</a> and <a href=#>Privacy Policy</a></span>
|
||||||
</label>
|
</label>
|
||||||
<div class="button-box">
|
<div class="button-box">
|
||||||
<button type="submit" class="btn btn-primary">Continue to Review</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="button-box">
|
<div class="button-box">
|
||||||
<p class="order-bottom-text">You can checkout on the next page</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
{% extends "new_base_glarus.html" %}
|
||||||
|
{% load staticfiles cms_tags bootstrap3%}
|
||||||
|
{% block title %}crowdfunding{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<section id="price">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row col-md-3 text-center wow fadeInDown"></div>
|
||||||
|
<div class="row col-md-6 text-center wow fadeInDown">
|
||||||
|
<div class="price-box">
|
||||||
|
<span class="glyphicon glyphicon-star"></span>
|
||||||
|
<h2 class="section-heading">Digital Glarus Membership</h2>
|
||||||
|
<h2 class="price"><strong>{{membership_type.price}}CHF</strong>/month<br> (free working 2days included)</h2>
|
||||||
|
<hr class="primary">
|
||||||
|
<img src="{% static 'digitalglarus/img/graph.png' %}" width="450" height="396" class="img-responsive center-block graph"><br>
|
||||||
|
<div class="price-exp-box"
|
||||||
|
<p class="carousel-text text-left supporter-black">
|
||||||
|
Get your Digital Glarus Membership for only
|
||||||
|
<strong>{{membership_type.price}}CHF</strong>
|
||||||
|
and get 2 working days for free!
|
||||||
|
The membership fee is a monthly subscription and
|
||||||
|
with every payment you help us to create a better
|
||||||
|
workspace.
|
||||||
|
You want to work more than 2 days per month in our
|
||||||
|
coworking space? Great! It's only <strong> 15CHF</strong>
|
||||||
|
per additional day.
|
||||||
|
You want more? That's really cool!
|
||||||
|
If you work 17 days a month or EVERY DAY of a month,
|
||||||
|
you can do so for <strong> 290CHF</strong>/month..
|
||||||
|
And the best? The discount is
|
||||||
|
applied automatically!
|
||||||
|
Just become a member, book your
|
||||||
|
working day and we will take care of the rest.
|
||||||
|
</p>
|
||||||
|
<div class="text-center">
|
||||||
|
<a class="btn btn-primary btn-blue" href="{% url 'digitalglarus:membership_payment' %}">become a member</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row col-md-3 text-center wow fadeInDown"></div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<!--membership includes-->
|
||||||
|
<section id="membership-includes">
|
||||||
|
<div class="container">
|
||||||
|
<div class="intro-price text-center wow fadeInDown">
|
||||||
|
<div class="intro-headline-small">
|
||||||
|
<span class="intro-headline-small">
|
||||||
|
Become our member
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<h3 class="intro-smaller">Our membership includes:</h3>
|
||||||
|
<div class="col-lg-12 price-list">
|
||||||
|
<li class="list-group-item row price-list">
|
||||||
|
<div class="price-list"><span class="glyphicon glyphicon-ok "></span>Super-fast Internet</div>
|
||||||
|
<div class="price-list"><span class="glyphicon glyphicon-ok glyphicon-inverse"></span>Any workspace in our common areas</div>
|
||||||
|
<div class="price-list"><span class="glyphicon glyphicon-ok "></span>Free 2 working day passes</div>
|
||||||
|
<div class="price-list"><span class="glyphicon glyphicon-ok glyphicon-inverse"></span>Access to any of our great workshops</div>
|
||||||
|
<div class="price-list"><span class="glyphicon glyphicon-ok "></span>Special invitation to our fondue nights, cooking & hacking sessions, coworking & cohiking, and many more cool stuff.</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section id="contact">
|
||||||
|
<div class="fill">
|
||||||
|
<div class="row" class="wow fadeInDown">
|
||||||
|
<div class="col-lg-12 text-center wow fadeInDown">
|
||||||
|
<div class="col-md-4 map-title">
|
||||||
|
Digital Glarus<br>
|
||||||
|
<span class="map-caption">In der Au 7 Schwanden 8762 Switzerland
|
||||||
|
<br>info@digitalglarus.ch
|
||||||
|
<br>
|
||||||
|
(044) 534-66-22
|
||||||
|
<p> </p>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<p> </p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{% endblock %}
|
|
@ -18,7 +18,7 @@
|
||||||
<div class="signup-form form-group row">
|
<div class="signup-form form-group row">
|
||||||
<form action="{% url 'digitalglarus:signup' %}" method="post" class="form" novalidate>
|
<form action="{% url 'digitalglarus:signup' %}" method="post" class="form" novalidate>
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<input type="hidden" name="" value="{{ request.GET.next }}">
|
<input type="hidden" name="next" value="{{ request.GET.next }}">
|
||||||
{% for field in form %}
|
{% for field in form %}
|
||||||
{% bootstrap_field field show_label=False type='fields'%}
|
{% bootstrap_field field show_label=False type='fields'%}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
@ -93,7 +93,7 @@
|
||||||
<a class="page-scroll" href="{% url 'digitalglarus:login' %}">Log In</a>
|
<a class="page-scroll" href="{% url 'digitalglarus:login' %}">Log In</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a class="page-scroll" href="{% url 'digitalglarus:login' %}">Sign Up</a>
|
<a class="page-scroll" href="{% url 'digitalglarus:signup' %}">Sign Up</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -167,6 +167,22 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Include Required Prerequisites -->
|
||||||
|
<script type="text/javascript" src="//cdn.jsdelivr.net/jquery/1/jquery.min.js"></script>
|
||||||
|
<script type="text/javascript" src="//cdn.jsdelivr.net/momentjs/latest/moment.min.js"></script>
|
||||||
|
<!-- <link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/bootstrap/latest/css/bootstrap.css" />
|
||||||
|
-->
|
||||||
|
<!-- Include Date Range Picker -->
|
||||||
|
<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 -->
|
||||||
|
<script src="{% static 'digitalglarus/js/booking.js' %}"></script>
|
||||||
|
|
||||||
|
<!-- Utils JavaScript -->
|
||||||
|
<script src="{% static 'digitalglarus/js/utils.js' %}"></script>
|
||||||
|
|
||||||
<!-- Custom Fonts -->
|
<!-- Custom Fonts -->
|
||||||
<link href="//fonts.googleapis.com/css?family=Raleway" rel="stylesheet" type="text/css">
|
<link href="//fonts.googleapis.com/css?family=Raleway" rel="stylesheet" type="text/css">
|
||||||
<link href="{% static 'digitalglarus/font-awesome-4.1.0/css/font-awesome.min.css' %}" rel="stylesheet" type="text/css">
|
<link href="{% static 'digitalglarus/font-awesome-4.1.0/css/font-awesome.min.css' %}" rel="stylesheet" type="text/css">
|
||||||
|
|
|
@ -3,7 +3,9 @@ from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
from .views import ContactView, IndexView, AboutView, HistoryView, LoginView, SignupView,\
|
from .views import ContactView, IndexView, AboutView, HistoryView, LoginView, SignupView,\
|
||||||
PasswordResetView, PasswordResetConfirmView, MembershipPaymentView
|
PasswordResetView, PasswordResetConfirmView, MembershipPaymentView, MembershipActivatedView,\
|
||||||
|
MembershipPricingView, BookingSelectDatesView, BookingPaymentView, OrdersBookingDetailView,\
|
||||||
|
BookingOrdersListView
|
||||||
# from membership.views import LoginRegistrationView
|
# from membership.views import LoginRegistrationView
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
|
@ -11,11 +13,23 @@ urlpatterns = [
|
||||||
url(_(r'contact/?$'), ContactView.as_view(), name='contact'),
|
url(_(r'contact/?$'), ContactView.as_view(), name='contact'),
|
||||||
url(_(r'login/?$'), LoginView.as_view(), name='login'),
|
url(_(r'login/?$'), LoginView.as_view(), name='login'),
|
||||||
url(_(r'signup/?$'), SignupView.as_view(), name='signup'),
|
url(_(r'signup/?$'), SignupView.as_view(), name='signup'),
|
||||||
|
url(r'^logout/?$', 'django.contrib.auth.views.logout',
|
||||||
|
{'next_page': '/digitalglarus/login?logged_out=true'}, name='logout'),
|
||||||
url(r'reset-password/?$', PasswordResetView.as_view(), name='reset_password'),
|
url(r'reset-password/?$', PasswordResetView.as_view(), name='reset_password'),
|
||||||
url(r'reset-password-confirm/(?P<uidb64>[0-9A-Za-z]+)-(?P<token>.+)/$',
|
url(r'reset-password-confirm/(?P<uidb64>[0-9A-Za-z]+)-(?P<token>.+)/$',
|
||||||
PasswordResetConfirmView.as_view(), name='reset_password_confirm'),
|
PasswordResetConfirmView.as_view(), name='reset_password_confirm'),
|
||||||
url(_(r'history/?$'), HistoryView.as_view(), name='history'),
|
url(_(r'history/?$'), HistoryView.as_view(), name='history'),
|
||||||
url(_(r'membership/payment?$'), MembershipPaymentView.as_view(), name='membership_payment'),
|
url(_(r'booking/?$'), BookingSelectDatesView.as_view(), name='booking'),
|
||||||
|
url(_(r'booking/payment/?$'), BookingPaymentView.as_view(), name='booking_payment'),
|
||||||
|
url(_(r'booking/orders/(?P<pk>\d+)/?$'), OrdersBookingDetailView.as_view(),
|
||||||
|
name='booking_orders_detail'),
|
||||||
|
url(_(r'booking/orders/?$'), BookingOrdersListView.as_view(),
|
||||||
|
name='booking_orders_list'),
|
||||||
|
url(_(r'membership/payment/?$'), MembershipPaymentView.as_view(), name='membership_payment'),
|
||||||
|
url(_(r'membership/activated/?$'), MembershipActivatedView.as_view(),
|
||||||
|
name='membership_activated'),
|
||||||
|
url(_(r'membership/pricing/?$'), MembershipPricingView.as_view(),
|
||||||
|
name='membership_pricing'),
|
||||||
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'),
|
||||||
|
|
|
@ -13,13 +13,13 @@ from django.utils.translation import get_language
|
||||||
from djangocms_blog.models import Post
|
from djangocms_blog.models import Post
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.http import JsonResponse
|
from django.http import JsonResponse
|
||||||
from django.views.generic import View
|
from django.views.generic import View, DetailView, ListView
|
||||||
|
|
||||||
from .models import Supporter
|
from .models import Supporter
|
||||||
from utils.forms import ContactUsForm
|
from utils.forms import ContactUsForm
|
||||||
from django.views.generic.edit import FormView
|
from django.views.generic.edit import FormView
|
||||||
from membership.calendar.calendar import BookCalendar
|
from membership.calendar.calendar import BookCalendar
|
||||||
from membership.models import Calendar as CalendarModel, CustomUser, StripeCustomer
|
from membership.models import Calendar as CalendarModel, StripeCustomer
|
||||||
|
|
||||||
|
|
||||||
from utils.views import LoginViewMixin, SignupViewMixin, \
|
from utils.views import LoginViewMixin, SignupViewMixin, \
|
||||||
|
@ -28,8 +28,13 @@ from utils.forms import PasswordResetRequestForm
|
||||||
from utils.stripe_utils import StripeUtils
|
from utils.stripe_utils import StripeUtils
|
||||||
|
|
||||||
|
|
||||||
from .forms import LoginForm, SignupForm, MembershipBillingForm
|
from .forms import LoginForm, SignupForm, MembershipBillingForm, BookingDateForm,\
|
||||||
from .models import MembershipType
|
BookingBillingForm
|
||||||
|
|
||||||
|
from .models import MembershipType, Membership, MembershipOrder, Booking, BookingPrice,\
|
||||||
|
BookingOrder
|
||||||
|
|
||||||
|
from .mixins import MembershipRequired
|
||||||
|
|
||||||
|
|
||||||
class IndexView(TemplateView):
|
class IndexView(TemplateView):
|
||||||
|
@ -63,7 +68,7 @@ class PasswordResetConfirmView(PasswordResetConfirmViewMixin):
|
||||||
class HistoryView(TemplateView):
|
class HistoryView(TemplateView):
|
||||||
template_name = "digitalglarus/history.html"
|
template_name = "digitalglarus/history.html"
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, *args, **kwargs):
|
||||||
context = super(HistoryView, self).get_context_data(**kwargs)
|
context = super(HistoryView, self).get_context_data(**kwargs)
|
||||||
supporters = Supporter.objects.all()
|
supporters = Supporter.objects.all()
|
||||||
context.update({
|
context.update({
|
||||||
|
@ -72,28 +77,177 @@ class HistoryView(TemplateView):
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
class BookingSelectDatesView(LoginRequiredMixin, MembershipRequired, FormView):
|
||||||
|
template_name = "digitalglarus/booking.html"
|
||||||
|
form_class = BookingDateForm
|
||||||
|
membership_redirect_url = reverse_lazy('digitalglarus:membership_pricing')
|
||||||
|
login_url = reverse_lazy('digitalglarus:login')
|
||||||
|
success_url = reverse_lazy('digitalglarus:booking_payment')
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
user = self.request.user
|
||||||
|
start_date = form.cleaned_data.get('start_date')
|
||||||
|
end_date = form.cleaned_data.get('end_date')
|
||||||
|
booking_days = (end_date - start_date).days + 1
|
||||||
|
original_price, discount_price, free_days = Booking.\
|
||||||
|
booking_price(user, start_date, end_date)
|
||||||
|
self.request.session.update({
|
||||||
|
'original_price': original_price,
|
||||||
|
'discount_price': discount_price,
|
||||||
|
'booking_days': booking_days,
|
||||||
|
'free_days': free_days,
|
||||||
|
'start_date': start_date.strftime('%m/%d/%Y'),
|
||||||
|
'end_date': end_date.strftime('%m/%d/%Y'),
|
||||||
|
})
|
||||||
|
return super(BookingSelectDatesView, self).form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
|
class BookingPaymentView(LoginRequiredMixin, MembershipRequired, FormView):
|
||||||
|
template_name = "digitalglarus/booking_payment.html"
|
||||||
|
form_class = BookingBillingForm
|
||||||
|
membership_redirect_url = reverse_lazy('digitalglarus:membership_pricing')
|
||||||
|
# success_url = reverse_lazy('digitalglarus:booking_payment')
|
||||||
|
booking_needed_fields = ['original_price', 'discount_price', 'booking_days', 'free_days',
|
||||||
|
'start_date', 'end_date']
|
||||||
|
|
||||||
|
def dispatch(self, request, *args, **kwargs):
|
||||||
|
from_booking = all(field in request.session.keys()
|
||||||
|
for field in self.booking_needed_fields)
|
||||||
|
if not from_booking:
|
||||||
|
return HttpResponseRedirect(reverse('digitalglarus:booking'))
|
||||||
|
|
||||||
|
return super(BookingPaymentView, self).dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
|
def get_success_url(self, order_id):
|
||||||
|
return reverse('digitalglarus:booking_orders_datail', kwargs={'pk': order_id})
|
||||||
|
|
||||||
|
def get_form_kwargs(self):
|
||||||
|
form_kwargs = super(BookingPaymentView, self).get_form_kwargs()
|
||||||
|
form_kwargs.update({
|
||||||
|
'initial': {
|
||||||
|
'start_date': self.request.session.get('start_date'),
|
||||||
|
'end_date': self.request.session.get('end_date'),
|
||||||
|
'price': self.request.session.get('discount_price'),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return form_kwargs
|
||||||
|
|
||||||
|
def get_context_data(self, *args, **kwargs):
|
||||||
|
context = super(BookingPaymentView, self).get_context_data(*args, **kwargs)
|
||||||
|
|
||||||
|
booking_data = {key: self.request.session.get(key)
|
||||||
|
for key in self.booking_needed_fields}
|
||||||
|
booking_price_per_day = BookingPrice.objects.get().price_per_day
|
||||||
|
total_discount = booking_price_per_day * booking_data.get('free_days')
|
||||||
|
booking_data.update({
|
||||||
|
'booking_price_per_day': booking_price_per_day,
|
||||||
|
'total_discount': total_discount,
|
||||||
|
'stripe_key': settings.STRIPE_API_PUBLIC_KEY
|
||||||
|
})
|
||||||
|
context.update(booking_data)
|
||||||
|
return context
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
data = form.cleaned_data
|
||||||
|
context = self.get_context_data()
|
||||||
|
token = data.get('token')
|
||||||
|
start_date = data.get('start_date')
|
||||||
|
end_date = data.get('end_date')
|
||||||
|
|
||||||
|
normal_price, final_price, free_days = Booking.\
|
||||||
|
booking_price(self.request.user, start_date, end_date)
|
||||||
|
|
||||||
|
# Get or create stripe customer
|
||||||
|
customer = StripeCustomer.get_or_create(email=self.request.user.email,
|
||||||
|
token=token)
|
||||||
|
if not customer:
|
||||||
|
form.add_error("__all__", "Invalid credit card")
|
||||||
|
return self.render_to_response(self.get_context_data(form=form))
|
||||||
|
|
||||||
|
# Make stripe charge to a customer
|
||||||
|
stripe_utils = StripeUtils()
|
||||||
|
charge_response = stripe_utils.make_charge(amount=final_price,
|
||||||
|
customer=customer.stripe_id)
|
||||||
|
charge = charge_response.get('response_object')
|
||||||
|
|
||||||
|
# Check if the payment was approved
|
||||||
|
if not charge:
|
||||||
|
context.update({
|
||||||
|
'paymentError': charge_response.get('error'),
|
||||||
|
'form': form
|
||||||
|
})
|
||||||
|
return render(self.request, self.template_name, context)
|
||||||
|
|
||||||
|
charge = charge_response.get('response_object')
|
||||||
|
|
||||||
|
# Create Billing Address
|
||||||
|
billing_address = form.save()
|
||||||
|
|
||||||
|
# Create membership plan
|
||||||
|
booking_data = {
|
||||||
|
'start_date': start_date,
|
||||||
|
'end_date': end_date,
|
||||||
|
'start_date': start_date,
|
||||||
|
'free_days': free_days,
|
||||||
|
'price': normal_price,
|
||||||
|
'final_price': final_price,
|
||||||
|
}
|
||||||
|
booking = Booking.create(booking_data)
|
||||||
|
|
||||||
|
# Create membership order
|
||||||
|
order_data = {
|
||||||
|
'booking': booking,
|
||||||
|
'customer': customer,
|
||||||
|
'billing_address': billing_address,
|
||||||
|
'stripe_charge': charge
|
||||||
|
}
|
||||||
|
order = BookingOrder.create(order_data)
|
||||||
|
|
||||||
|
# request.session.update({
|
||||||
|
# 'membership_price': membership.type.first_month_price,
|
||||||
|
# 'membership_dates': membership.type.first_month_formated_range
|
||||||
|
# })
|
||||||
|
return HttpResponseRedirect(self.get_success_url(order.id))
|
||||||
|
return super(BookingPaymentView, self).form_valid(form)
|
||||||
|
# return HttpResponseRedirect(reverse('digitalglarus:membership_activated'))
|
||||||
|
|
||||||
|
|
||||||
|
class MembershipPricingView(TemplateView):
|
||||||
|
template_name = "digitalglarus/membership_pricing.html"
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super(MembershipPricingView, self).get_context_data(**kwargs)
|
||||||
|
membership_type = MembershipType.objects.last()
|
||||||
|
context.update({
|
||||||
|
'membership_type': membership_type
|
||||||
|
})
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
class MembershipPaymentView(LoginRequiredMixin, FormView):
|
class MembershipPaymentView(LoginRequiredMixin, FormView):
|
||||||
template_name = "digitalglarus/membership_payment.html"
|
template_name = "digitalglarus/membership_payment.html"
|
||||||
login_url = reverse_lazy('digitalglarus:login')
|
login_url = reverse_lazy('digitalglarus:signup')
|
||||||
form_class = MembershipBillingForm
|
form_class = MembershipBillingForm
|
||||||
|
|
||||||
def get_form_kwargs(self):
|
def get_form_kwargs(self):
|
||||||
membership_type = MembershipType.objects.get(name='standard')
|
self.membership_type = MembershipType.objects.get(name='standard')
|
||||||
form_kwargs = super(MembershipPaymentView, self).get_form_kwargs()
|
form_kwargs = super(MembershipPaymentView, self).get_form_kwargs()
|
||||||
form_kwargs.update({
|
form_kwargs.update({
|
||||||
'initial': {'membership_type': membership_type.id}
|
'initial': {
|
||||||
|
'membership_type': self.membership_type.id
|
||||||
|
}
|
||||||
})
|
})
|
||||||
return form_kwargs
|
return form_kwargs
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(MembershipPaymentView, self).get_context_data(**kwargs)
|
context = super(MembershipPaymentView, self).get_context_data(**kwargs)
|
||||||
context.update({
|
context.update({
|
||||||
'stripe_key': settings.STRIPE_API_PUBLIC_KEY
|
'stripe_key': settings.STRIPE_API_PUBLIC_KEY,
|
||||||
|
'membership_type': self.membership_type
|
||||||
})
|
})
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
import pdb;pdb.set_trace()
|
|
||||||
form = self.get_form()
|
form = self.get_form()
|
||||||
|
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
|
@ -111,7 +265,7 @@ class MembershipPaymentView(LoginRequiredMixin, FormView):
|
||||||
|
|
||||||
# Make stripe charge to a customer
|
# Make stripe charge to a customer
|
||||||
stripe_utils = StripeUtils()
|
stripe_utils = StripeUtils()
|
||||||
charge_response = stripe_utils.make_charge(amount=membership_type.price,
|
charge_response = stripe_utils.make_charge(amount=membership_type.first_month_price,
|
||||||
customer=customer.stripe_id)
|
customer=customer.stripe_id)
|
||||||
charge = charge_response.get('response_object')
|
charge = charge_response.get('response_object')
|
||||||
|
|
||||||
|
@ -124,10 +278,93 @@ class MembershipPaymentView(LoginRequiredMixin, FormView):
|
||||||
return render(request, self.template_name, context)
|
return render(request, self.template_name, context)
|
||||||
|
|
||||||
charge = charge_response.get('response_object')
|
charge = charge_response.get('response_object')
|
||||||
|
|
||||||
|
# Create Billing Address
|
||||||
|
billing_address = form.save()
|
||||||
|
|
||||||
|
# Create membership plan
|
||||||
|
membership_data = {'type': membership_type}
|
||||||
|
membership = Membership.create(membership_data)
|
||||||
|
|
||||||
|
# Create membership order
|
||||||
|
order_data = {
|
||||||
|
'membership': membership,
|
||||||
|
'customer': customer,
|
||||||
|
'billing_address': billing_address,
|
||||||
|
'stripe_charge': charge
|
||||||
|
}
|
||||||
|
MembershipOrder.create(order_data)
|
||||||
|
|
||||||
|
request.session.update({
|
||||||
|
'membership_price': membership.type.first_month_price,
|
||||||
|
'membership_dates': membership.type.first_month_formated_range
|
||||||
|
})
|
||||||
|
return HttpResponseRedirect(reverse('digitalglarus:membership_activated'))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return self.form_invalid(form)
|
return self.form_invalid(form)
|
||||||
|
|
||||||
|
|
||||||
|
class MembershipActivatedView(TemplateView):
|
||||||
|
template_name = "digitalglarus/membership_activated.html"
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super(MembershipActivatedView, self).get_context_data(**kwargs)
|
||||||
|
membership_price = self.request.session.get('membership_price')
|
||||||
|
membership_dates = self.request.session.get('membership_dates')
|
||||||
|
context.update({
|
||||||
|
'membership_price': membership_price,
|
||||||
|
'membership_dates': membership_dates,
|
||||||
|
})
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
class OrdersBookingDetailView(LoginRequiredMixin, DetailView):
|
||||||
|
template_name = "digitalglarus/booking_orders_detail.html"
|
||||||
|
context_object_name = "order"
|
||||||
|
login_url = reverse_lazy('digitalglarus:login')
|
||||||
|
# permission_required = ['view_hostingorder']
|
||||||
|
model = BookingOrder
|
||||||
|
|
||||||
|
def get_context_data(self, *args, **kwargs):
|
||||||
|
|
||||||
|
context = super(OrdersBookingDetailView, self).get_context_data(**kwargs)
|
||||||
|
|
||||||
|
bookig_order = self.object
|
||||||
|
booking = bookig_order.booking
|
||||||
|
|
||||||
|
start_date = booking.start_date
|
||||||
|
end_date = booking.end_date
|
||||||
|
free_days = booking.free_days
|
||||||
|
|
||||||
|
booking_days = (end_date - start_date).days + 1
|
||||||
|
original_price = booking.price
|
||||||
|
final_price = booking.final_price
|
||||||
|
context.update({
|
||||||
|
'original_price': original_price,
|
||||||
|
'total_discount': original_price - final_price,
|
||||||
|
'final_price': final_price,
|
||||||
|
'booking_days': booking_days,
|
||||||
|
'free_days': free_days,
|
||||||
|
'start_date': start_date.strftime('%m/%d/%Y'),
|
||||||
|
'end_date': end_date.strftime('%m/%d/%Y'),
|
||||||
|
})
|
||||||
|
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
class BookingOrdersListView(LoginRequiredMixin, ListView):
|
||||||
|
template_name = "digitalglarus/booking_orders_list.html"
|
||||||
|
context_object_name = "orders"
|
||||||
|
login_url = reverse_lazy('digitalglarus:login')
|
||||||
|
model = BookingOrder
|
||||||
|
paginate_by = 10
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
queryset = super(BookingOrdersListView, self).get_queryset()
|
||||||
|
queryset = queryset.filter(customer__user=self.request.user)
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
############## OLD VIEWS
|
############## OLD VIEWS
|
||||||
class CalendarApi(View):
|
class CalendarApi(View):
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.contrib.auth.models import User, AbstractBaseUser, BaseUserManager, AbstractUser, PermissionsMixin
|
from django.contrib.auth.models import User, AbstractBaseUser, BaseUserManager, AbstractUser, PermissionsMixin
|
||||||
|
|
Loading…
Reference in a new issue