From 2eb2c90b1fbf53601bce9e8605624c46c5eaebf2 Mon Sep 17 00:00:00 2001 From: Levi Date: Tue, 30 Aug 2016 21:32:45 -0500 Subject: [PATCH] Added membership pricing view. Added membership pricing html. Added membership pricing url. Started booking view. Started integrating booking.js. Added calendar date range js lib. Fixing date picker. Added function to calculate remaining free days. Updated function to calculate booking price. Added BookingDatesForm. Added backend validation for booking dates. fixed booking form. adding pricing to booking payment view. Added free days to booking payment view. Started booking payment stripe flow. Redefined dispatch method to booking view. Now login is required for payment selecting dates and booking. Added date range to booking payment. Fixed booking select dates view. Added form validations to booking form. Created a order after a confirm a booking. Added free_days to booking model in order to facilitate free_days Availability for the next booking. Creating a Stripe charge. Creating Booking model instance. Refactor booking payment views. Associated an order to a stripe charge. Associated booking order instance with a booking instance. --- digitalglarus/forms.py | 45 ++++- ...0009_booking_bookingorder_bookingprices.py | 52 ++++++ .../migrations/0010_auto_20160828_1745.py | 19 ++ .../0011_bookingprice_special_price_offer.py | 21 +++ .../migrations/0012_booking_free_days.py | 20 ++ .../0013_remove_booking_membership.py | 19 ++ digitalglarus/mixins.py | 25 +++ digitalglarus/models.py | 78 +++++++- .../static/digitalglarus/js/booking.js | 22 +++ .../templates/digitalglarus/booking.html | 53 ++++++ .../digitalglarus/booking_payment.html | 176 ++++++++++++++++++ .../digitalglarus/membership_pricing.html | 87 +++++++++ .../templates/digitalglarus/signup.html | 2 +- digitalglarus/templates/new_base_glarus.html | 29 ++- digitalglarus/urls.py | 9 +- digitalglarus/views.py | 151 ++++++++++++++- 16 files changed, 783 insertions(+), 25 deletions(-) create mode 100644 digitalglarus/migrations/0009_booking_bookingorder_bookingprices.py create mode 100644 digitalglarus/migrations/0010_auto_20160828_1745.py create mode 100644 digitalglarus/migrations/0011_bookingprice_special_price_offer.py create mode 100644 digitalglarus/migrations/0012_booking_free_days.py create mode 100644 digitalglarus/migrations/0013_remove_booking_membership.py create mode 100644 digitalglarus/mixins.py create mode 100644 digitalglarus/static/digitalglarus/js/booking.js create mode 100644 digitalglarus/templates/digitalglarus/booking.html create mode 100644 digitalglarus/templates/digitalglarus/booking_payment.html create mode 100644 digitalglarus/templates/digitalglarus/membership_pricing.html diff --git a/digitalglarus/forms.py b/digitalglarus/forms.py index 10f73b31..03a5e6cd 100644 --- a/digitalglarus/forms.py +++ b/digitalglarus/forms.py @@ -1,6 +1,6 @@ from django import forms from django.utils.translation import ugettext_lazy as _ - +from datetime import datetime from utils.models import BillingAddress from utils.forms import LoginFormMixin, SignupFormMixin, BillingAddressForm @@ -34,3 +34,46 @@ class MembershipBillingForm(BillingAddressForm): 'postal_code': _('Postal Code'), '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 diff --git a/digitalglarus/migrations/0009_booking_bookingorder_bookingprices.py b/digitalglarus/migrations/0009_booking_bookingorder_bookingprices.py new file mode 100644 index 00000000..784c1f54 --- /dev/null +++ b/digitalglarus/migrations/0009_booking_bookingorder_bookingprices.py @@ -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()), + ], + ), + ] diff --git a/digitalglarus/migrations/0010_auto_20160828_1745.py b/digitalglarus/migrations/0010_auto_20160828_1745.py new file mode 100644 index 00000000..b526562f --- /dev/null +++ b/digitalglarus/migrations/0010_auto_20160828_1745.py @@ -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', + ), + ] diff --git a/digitalglarus/migrations/0011_bookingprice_special_price_offer.py b/digitalglarus/migrations/0011_bookingprice_special_price_offer.py new file mode 100644 index 00000000..08a75e39 --- /dev/null +++ b/digitalglarus/migrations/0011_bookingprice_special_price_offer.py @@ -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, + ), + ] diff --git a/digitalglarus/migrations/0012_booking_free_days.py b/digitalglarus/migrations/0012_booking_free_days.py new file mode 100644 index 00000000..17d95319 --- /dev/null +++ b/digitalglarus/migrations/0012_booking_free_days.py @@ -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), + ), + ] diff --git a/digitalglarus/migrations/0013_remove_booking_membership.py b/digitalglarus/migrations/0013_remove_booking_membership.py new file mode 100644 index 00000000..7b2ffa24 --- /dev/null +++ b/digitalglarus/migrations/0013_remove_booking_membership.py @@ -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', + ), + ] diff --git a/digitalglarus/mixins.py b/digitalglarus/mixins.py new file mode 100644 index 00000000..6d555f24 --- /dev/null +++ b/digitalglarus/mixins.py @@ -0,0 +1,25 @@ +from django.db import models +from membership.models import StripeCustomer +from utils.models import BillingAddress + + +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 + return instance diff --git a/digitalglarus/models.py b/digitalglarus/models.py index e5b3ab88..e229fabd 100644 --- a/digitalglarus/models.py +++ b/digitalglarus/models.py @@ -6,9 +6,10 @@ from cms.models import CMSPlugin from filer.fields.image import FilerImageField 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 +# from membership.models import StripeCustomer +# from utils.models import BillingAddress class MembershipType(models.Model): @@ -64,15 +65,8 @@ class Membership(models.Model): return instance -class MembershipOrder(models.Model): +class MembershipOrder(Ordereable, models.Model): membership = models.ForeignKey(Membership) - 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) @classmethod def create(cls, data): @@ -84,6 +78,70 @@ class MembershipOrder(models.Model): 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) + + @classmethod + def create(cls, data): + instance = cls.objects.create(**data) + return instance + + @classmethod + def get_ramaining_free_days(cls, user): + # ZERO_DAYS = 0 + # ONE_DAY = 1 + TWO_DAYS = 2 + + current_date = datetime.today() + current_month_bookings = cls.objects.filter(bookingorder__customer__user=user, + start_date__month=current_date.month) + free_days = TWO_DAYS - sum(map(lambda x: x.days, current_month_bookings)) + return free_days + + # free_days = ZERO_DAYS if current_month_bookings.count() > 2 else TWO_DAYS + # if current_month_bookings.count() == 1: + # booking = current_month_bookings.get() + # booked_days = (booking.end_date - booking.start_date).days + # free_days = ONE_DAY if booked_days == 1 else ZERO_DAYS + # return free_days + + # free_days = ZERO_DAYS if current_month_bookings.count() > 2 else TWO_DAYS + # return free_days + + @classmethod + def booking_price(cls, user, start_date, end_date): + """ + Calculate the booking price for requested dates + How it does: + 1. Check if the user has booked the current month + 2. Get how many days user wants to book + 3. Get price per day from BookingPrices instance + 4. Get available free days + 5. Calculate price by this formula -> (booking_days - free_days) * price_per_day + """ + booking_prices = BookingPrice.objects.last() + price_per_day = booking_prices.price_per_day + booking_days = (end_date - start_date).days + + free_days = cls.get_ramaining_free_days(user) + final_booking_price = (booking_days - free_days) * price_per_day + original_booking_price = (booking_days) * price_per_day + + return original_booking_price, final_booking_price, free_days + + +class BookingOrder(Ordereable, models.Model): + booking = models.OneToOneField(Booking) + + class Supporter(models.Model): name = models.CharField(max_length=200) description = models.TextField(null=True, blank=True) diff --git a/digitalglarus/static/digitalglarus/js/booking.js b/digitalglarus/static/digitalglarus/js/booking.js new file mode 100644 index 00000000..ed1929d4 --- /dev/null +++ b/digitalglarus/static/digitalglarus/js/booking.js @@ -0,0 +1,22 @@ +$( document ).ready(function() { + + // $('#booking-date-range').daterangepicker(); + + + $('#booking-date-range').daterangepicker({ + autoUpdateInput: false, + locale: { + cancelLabel: 'Clear' + } + }); + + + $('#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'); + }); + +}); \ No newline at end of file diff --git a/digitalglarus/templates/digitalglarus/booking.html b/digitalglarus/templates/digitalglarus/booking.html new file mode 100644 index 00000000..6a8d4374 --- /dev/null +++ b/digitalglarus/templates/digitalglarus/booking.html @@ -0,0 +1,53 @@ +{% extends "new_base_glarus.html" %} +{% load staticfiles cms_tags bootstrap3%} +{% block title %}crowdfunding{% endblock %} + +{% block content %} + +
+ +
+ +
+
+
+
+
+ Digital Glarus
+ In der Au 7 Schwanden 8762 Switzerland +
info@digitalglarus.ch +
+ (044) 534-66-22 +

 

+
+
+

 

+
+
+
+
+{% endblock %} \ No newline at end of file diff --git a/digitalglarus/templates/digitalglarus/booking_payment.html b/digitalglarus/templates/digitalglarus/booking_payment.html new file mode 100644 index 00000000..7faee9c9 --- /dev/null +++ b/digitalglarus/templates/digitalglarus/booking_payment.html @@ -0,0 +1,176 @@ +{% extends "new_base_glarus.html" %} +{% load staticfiles bootstrap3 i18n %} +{% block content %} + + + +
+ + + + +
+ + + +
+
+
+
+
+ Digital Glarus
+ In der Au 7 Schwanden 8762 Switzerland +
info@digitalglarus.ch +
+ (044) 534-66-22 +

 

+
+
+

 

+
+
+
+
+ + +{% if stripe_key %} + + +{%endif%} + +{% endblock %} \ No newline at end of file diff --git a/digitalglarus/templates/digitalglarus/membership_pricing.html b/digitalglarus/templates/digitalglarus/membership_pricing.html new file mode 100644 index 00000000..fec32399 --- /dev/null +++ b/digitalglarus/templates/digitalglarus/membership_pricing.html @@ -0,0 +1,87 @@ +{% extends "new_base_glarus.html" %} +{% load staticfiles cms_tags bootstrap3%} +{% block title %}crowdfunding{% endblock %} + +{% block content %} +
+
+
+
+
+ +

Digital Glarus Membership

+

{{membership_type.price}}CHF/month
(free working 2days included)

+
+
+
+ Get your Digital Glarus Membership for only + {{membership_type.price}}CHF + 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 15CHF + 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 290CHF/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. +

+ +
+ +
+
+
+
+
+ +
+
+
+
+ + Become our member + +
+

Our membership includes:

+
+
  • +
    Super-fast Internet
    +
    Any workspace in our common areas
    +
    Free 2 working day passes
    +
    Access to any of our great workshops
    +
    Special invitation to our fondue nights, cooking & hacking sessions, coworking & cohiking, and many more cool stuff.
    +
  • + +
    +
    +
    + +
    +
    +
    +
    +
    +
    + Digital Glarus
    + In der Au 7 Schwanden 8762 Switzerland +
    info@digitalglarus.ch +
    + (044) 534-66-22 +

     

    +
    +
    +

     

    +
    +
    +
    +
    +{% endblock %} \ No newline at end of file diff --git a/digitalglarus/templates/digitalglarus/signup.html b/digitalglarus/templates/digitalglarus/signup.html index 118057f8..aea83f4e 100644 --- a/digitalglarus/templates/digitalglarus/signup.html +++ b/digitalglarus/templates/digitalglarus/signup.html @@ -18,7 +18,7 @@
    {% csrf_token %} - + {% for field in form %} {% bootstrap_field field show_label=False type='fields'%} {% endfor %} diff --git a/digitalglarus/templates/new_base_glarus.html b/digitalglarus/templates/new_base_glarus.html index 74bcaf1d..b7223997 100644 --- a/digitalglarus/templates/new_base_glarus.html +++ b/digitalglarus/templates/new_base_glarus.html @@ -93,7 +93,7 @@ Log In
  • - Sign Up + Sign Up
  • @@ -167,11 +167,24 @@ - - - - - - - + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/digitalglarus/urls.py b/digitalglarus/urls.py index e81bd8b5..45884468 100644 --- a/digitalglarus/urls.py +++ b/digitalglarus/urls.py @@ -3,7 +3,8 @@ from django.utils.translation import ugettext_lazy as _ from . import views from .views import ContactView, IndexView, AboutView, HistoryView, LoginView, SignupView,\ - PasswordResetView, PasswordResetConfirmView, MembershipPaymentView, MembershipActivatedView + PasswordResetView, PasswordResetConfirmView, MembershipPaymentView, MembershipActivatedView,\ + MembershipPricingView, BookingSelectDatesView, BookingPaymentView # from membership.views import LoginRegistrationView urlpatterns = [ @@ -11,13 +12,19 @@ urlpatterns = [ url(_(r'contact/?$'), ContactView.as_view(), name='contact'), url(_(r'login/?$'), LoginView.as_view(), name='login'), 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-confirm/(?P[0-9A-Za-z]+)-(?P.+)/$', PasswordResetConfirmView.as_view(), name='reset_password_confirm'), url(_(r'history/?$'), HistoryView.as_view(), name='history'), + url(_(r'booking/?$'), BookingSelectDatesView.as_view(), name='booking'), + url(_(r'booking/payment/?$'), BookingPaymentView.as_view(), name='booking_payment'), 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'calendar_api/(?P\d+)/(?P\d+)?$', views.CalendarApi.as_view(),name='calendar_api_1'), url(r'calendar_api/', views.CalendarApi.as_view(),name='calendar_api'), diff --git a/digitalglarus/views.py b/digitalglarus/views.py index d0edcd05..479eadfc 100644 --- a/digitalglarus/views.py +++ b/digitalglarus/views.py @@ -28,8 +28,11 @@ from utils.forms import PasswordResetRequestForm from utils.stripe_utils import StripeUtils -from .forms import LoginForm, SignupForm, MembershipBillingForm -from .models import MembershipType, Membership, MembershipOrder +from .forms import LoginForm, SignupForm, MembershipBillingForm, BookingDateForm,\ + BookingBillingForm + +from .models import MembershipType, Membership, MembershipOrder, Booking, BookingPrice,\ + BookingOrder class IndexView(TemplateView): @@ -63,7 +66,7 @@ class PasswordResetConfirmView(PasswordResetConfirmViewMixin): class HistoryView(TemplateView): 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) supporters = Supporter.objects.all() context.update({ @@ -72,9 +75,149 @@ class HistoryView(TemplateView): return context +class BookingSelectDatesView(LoginRequiredMixin, FormView): + template_name = "digitalglarus/booking.html" + form_class = BookingDateForm + 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 + 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, FormView): + template_name = "digitalglarus/booking_payment.html" + form_class = BookingBillingForm + 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_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') + + original_price, discount_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=original_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': discount_price, + } + booking = Booking.create(booking_data) + + # Create membership order + order_data = { + 'booking': booking, + 'customer': customer, + 'billing_address': billing_address, + 'stripe_charge': charge + } + BookingOrder.create(order_data) + + # request.session.update({ + # 'membership_price': membership.type.first_month_price, + # 'membership_dates': membership.type.first_month_formated_range + # }) + 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): template_name = "digitalglarus/membership_payment.html" - login_url = reverse_lazy('digitalglarus:login') + login_url = reverse_lazy('digitalglarus:signup') form_class = MembershipBillingForm def get_form_kwargs(self):