diff --git a/digitalglarus/forms.py b/digitalglarus/forms.py index 03a5e6cd..db3aab94 100644 --- a/digitalglarus/forms.py +++ b/digitalglarus/forms.py @@ -68,7 +68,7 @@ class BookingDateForm(forms.Form): except ValueError: raise forms.ValidationError("Submit valid dates.") - if start_date >= end_date: + if start_date > end_date: raise forms.ValidationError("Your end date must be greather than your start date.") return start_date, end_date diff --git a/digitalglarus/migrations/0014_booking_final_price.py b/digitalglarus/migrations/0014_booking_final_price.py new file mode 100644 index 00000000..f417b714 --- /dev/null +++ b/digitalglarus/migrations/0014_booking_final_price.py @@ -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, + ), + ] diff --git a/digitalglarus/mixins.py b/digitalglarus/mixins.py index 6d555f24..13329f73 100644 --- a/digitalglarus/mixins.py +++ b/digitalglarus/mixins.py @@ -1,8 +1,20 @@ 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) @@ -22,4 +34,5 @@ class Ordereable(models.Model): instance.stripe_charge_id = stripe_charge.id instance.last4 = stripe_charge.source.last4 instance.cc_brand = stripe_charge.source.brand + instance.save() return instance diff --git a/digitalglarus/models.py b/digitalglarus/models.py index e229fabd..49d1327f 100644 --- a/digitalglarus/models.py +++ b/digitalglarus/models.py @@ -1,7 +1,9 @@ import calendar from datetime import datetime, date, timedelta +from dateutil.relativedelta import relativedelta from django.db import models +from django.db.models import Q from cms.models import CMSPlugin from filer.fields.image import FilerImageField from django.core.urlresolvers import reverse @@ -59,6 +61,14 @@ class MembershipType(models.Model): class Membership(models.Model): type = models.ForeignKey(MembershipType) + @classmethod + 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) @@ -88,6 +98,7 @@ class Booking(models.Model): end_date = models.DateField() price = models.FloatField() free_days = models.IntegerField(default=0) + final_price = models.FloatField() @classmethod def create(cls, data): @@ -95,52 +106,50 @@ class Booking(models.Model): return instance @classmethod - def get_ramaining_free_days(cls, user): - # ZERO_DAYS = 0 - # ONE_DAY = 1 + 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 = 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 + 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): - """ - 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 - """ + + 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 + 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) - final_booking_price = (booking_days - free_days) * price_per_day - original_booking_price = (booking_days) * price_per_day + free_days = cls.get_ramaining_free_days(user, start_date, end_date) + final_booking_price = normal_price - (free_days * price_per_day) - return original_booking_price, final_booking_price, free_days + 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): name = models.CharField(max_length=200) diff --git a/digitalglarus/static/digitalglarus/js/booking.js b/digitalglarus/static/digitalglarus/js/booking.js index ed1929d4..0cb97667 100644 --- a/digitalglarus/static/digitalglarus/js/booking.js +++ b/digitalglarus/static/digitalglarus/js/booking.js @@ -1,13 +1,16 @@ $( 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, }); diff --git a/digitalglarus/static/digitalglarus/js/utils.js b/digitalglarus/static/digitalglarus/js/utils.js new file mode 100644 index 00000000..d780fc25 --- /dev/null +++ b/digitalglarus/static/digitalglarus/js/utils.js @@ -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") ); + + }); + +}); \ No newline at end of file diff --git a/digitalglarus/templates/digitalglarus/booking_orders_detail.html b/digitalglarus/templates/digitalglarus/booking_orders_detail.html new file mode 100644 index 00000000..6dcb604a --- /dev/null +++ b/digitalglarus/templates/digitalglarus/booking_orders_detail.html @@ -0,0 +1,88 @@ +{% extends "new_base_glarus.html" %} +{% load staticfiles bootstrap3 i18n %} +{% block content %} + + + + + +
+
+
+
+

Your Booking Detail

+
+

InvoiceGet PDF

+ +

Order Number

+

#{{order.id}}

+ +

Billed to :

+

{{user.name}}
+ {{order.billing_address.street_address}},{{order.billing_address.postal_code}}
+ {{order.billing_address.city}}, {{order.billing_address.country}}. +

+ +

Payment Method

+

+ {{order.cc_brand}} ending **** {{order.last4}}
+ {{user.email}} +

+ +
+

Order Summary

+

+ Dates: {{start_date}} - {{end_date}}
+

+

Total days {{booking_days}}

+

{{original_price|floatformat}}CHF

+ {% if free_days %} +

Free days {{free_days}}

+

-{{total_discount|floatformat}}CHF

+ {% endif %} +
+

Total

+

{{final_price|floatformat}}CHF

+
+
+
+ +
+
+
+

Order Summary

+
+
+

Dates: {{start_date}} - {{end_date}}

+ +

Total days {{booking_days}}

+

{{original_price|floatformat}}CHF

+ {% if free_days %} +

Free days {{free_days}}

+

-{{total_discount|floatformat}}CHF

+ {% endif %} +
+

Total

+

{{final_price|floatformat}}CHF

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

Your Order History

+
+

Member Name

+

{{request.user.name}}

+
+

Active Membership

+

2016.11.13-2016.12.13

+
+

Booking history

+ + + + + + + + + + + {% for order in orders%} + + + + + + + {% endfor %} + +
#Booking datesDaysInvoice
{{order.id}}{{order.booking.start_date}}-{{order.booking.end_date}}{{order.booking_days}}View
+ +

Billing AdressEdit

+

Nico Schottelius
+ In der Au 7 8762 Schwanden
+ Switzerland +

+ +
+
+ + +
+
+

Thank You!

+
+ + + +
+ +

This box is here just to thank you

+
+ +
+
+ +{% endblock %} \ No newline at end of file diff --git a/digitalglarus/templates/digitalglarus/booking_payment.html b/digitalglarus/templates/digitalglarus/booking_payment.html index 7faee9c9..ff639a92 100644 --- a/digitalglarus/templates/digitalglarus/booking_payment.html +++ b/digitalglarus/templates/digitalglarus/booking_payment.html @@ -27,7 +27,17 @@

Booking


-

Billing Adress

+

Billing Adress

+

+ 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. +

+