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…
	
	Add table
		Add a link
		
	
		Reference in a new issue