Merge pull request #133 from levivm/feature/new_digitalglarus
Feature/new digitalglarus
This commit is contained in:
commit
8b75ddd64f
14 changed files with 201 additions and 87 deletions
41
digitalglarus/migrations/0021_auto_20161017_1958.py
Normal file
41
digitalglarus/migrations/0021_auto_20161017_1958.py
Normal file
|
@ -0,0 +1,41 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.9.4 on 2016-10-17 19:58
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import datetime
|
||||
from django.db import migrations, models
|
||||
from django.utils.timezone import utc
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('digitalglarus', '0020_auto_20161013_0253'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='membership',
|
||||
name='end_date',
|
||||
field=models.DateField(default=datetime.datetime(2016, 10, 17, 19, 58, 0, 209303, tzinfo=utc)),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='membership',
|
||||
name='start_date',
|
||||
field=models.DateField(default=datetime.datetime(2016, 10, 17, 19, 58, 7, 361473, tzinfo=utc)),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='membershiporder',
|
||||
name='end_date',
|
||||
field=models.DateField(default=datetime.datetime(2016, 10, 17, 19, 58, 15, 657240, tzinfo=utc)),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='membershiporder',
|
||||
name='start_date',
|
||||
field=models.DateField(default=datetime.datetime(2016, 10, 17, 19, 58, 16, 897120, tzinfo=utc)),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
|
@ -62,6 +62,13 @@ class MembershipType(models.Model):
|
|||
class Membership(models.Model):
|
||||
type = models.ForeignKey(MembershipType)
|
||||
active = models.BooleanField(default=True)
|
||||
start_date = models.DateField()
|
||||
end_date = models.DateField()
|
||||
|
||||
@classmethod
|
||||
def get_by_user(cls, user):
|
||||
return cls.objects.\
|
||||
filter(membershiporder__customer__user=user).last()
|
||||
|
||||
@classmethod
|
||||
def create(cls, data):
|
||||
|
@ -79,6 +86,11 @@ class Membership(models.Model):
|
|||
return cls.objects.filter(has_order_past_month | has_order_current_month).\
|
||||
filter(active_membership).exists()
|
||||
|
||||
def update_dates(self, start_date, end_date):
|
||||
self.start_date = start_date
|
||||
self.end_date = end_date
|
||||
self.save()
|
||||
|
||||
def deactivate(self):
|
||||
self.active = False
|
||||
self.save()
|
||||
|
@ -86,17 +98,19 @@ class Membership(models.Model):
|
|||
|
||||
class MembershipOrder(Ordereable, models.Model):
|
||||
membership = models.ForeignKey(Membership)
|
||||
start_date = models.DateField()
|
||||
end_date = models.DateField()
|
||||
|
||||
@classmethod
|
||||
def current_membership(cls, user):
|
||||
last_payment = cls.objects.\
|
||||
last_membership_payment = cls.objects.\
|
||||
filter(customer__user=user).last()
|
||||
start_date = last_payment.created_at
|
||||
_, days_in_month = calendar.monthrange(start_date.year,
|
||||
start_date.month)
|
||||
start_date.replace(day=1)
|
||||
end_date = start_date + timedelta(days=days_in_month)
|
||||
return start_date, end_date
|
||||
# start_date = last_payment.created_at
|
||||
# _, days_in_month = calendar.monthrange(start_date.year,
|
||||
# start_date.month)
|
||||
# start_date.replace(day=1)
|
||||
# end_date = start_date + timedelta(days=days_in_month)
|
||||
return last_membership_payment.start_date, last_membership_payment.end_date
|
||||
|
||||
def first_membership_range_date(self):
|
||||
start_date = self.created_at
|
||||
|
|
|
@ -1172,11 +1172,11 @@ footer {
|
|||
}
|
||||
|
||||
.map-caption{
|
||||
text-transform: none;
|
||||
text-transform:uppercase;
|
||||
font-size: 13px;
|
||||
font-family:"Montserrat","Helvetica Neue",Helvetica, Arial,sans-serif;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
font-size: 14px;
|
||||
letter-spacing: 1px;
|
||||
text-align:center;
|
||||
}
|
||||
|
|
|
@ -18,4 +18,6 @@ $( document ).ready(function() {
|
|||
|
||||
});
|
||||
|
||||
|
||||
|
||||
});
|
|
@ -55,8 +55,13 @@
|
|||
<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>
|
||||
<br>
|
||||
|
||||
<p class="order-bottom-text">
|
||||
View my bookings <a href="{% url 'digitalglarus:booking_orders_list' %}">Go to my page</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-sm-4 col-lg-4 wow fadeInDown hidden-print">
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
<th>#</th>
|
||||
<th>Booking dates</th>
|
||||
<th>Days</th>
|
||||
<th>Membership Required Months</th>
|
||||
<th>Invoice</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -33,6 +34,7 @@
|
|||
<th scope="row">{{order.id}}</th>
|
||||
<td>{{order.booking.start_date}}-{{order.booking.end_date}}</td>
|
||||
<td>{{order.booking_days}}</td>
|
||||
<td>{{order.membership_required_months}}</td>
|
||||
<td><a class="btn btn-xs btn-primary btn-darkgrey" href="{% url 'digitalglarus:booking_orders_detail' order.id %}">View</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
padding: .5em;
|
||||
padding-right: 1.5em
|
||||
}
|
||||
|
||||
.order-bottom-text a{
|
||||
margin-left: 0px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<section id="price">
|
||||
|
@ -140,9 +144,10 @@
|
|||
<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/>
|
||||
|
||||
<h3 class="col-xs-6 order-item">Dates {{start_date}} - {{end_date}}</h3>
|
||||
<p class="order-bottom-text">
|
||||
<a href="{{request.META.HTTP_REFERER}}">Change dates</a>
|
||||
</p>
|
||||
<hr class="greyline">
|
||||
<h2 class="col-xs-6 payment-total">Total days: {{booking_days}} </h2>
|
||||
<h2 class="order-sum">{{original_price|floatformat}}CHF</h2>
|
||||
|
@ -168,7 +173,7 @@
|
|||
<div class="button-box">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<button id="payment_button" class="btn btn-primary btn-lg btn-blck " type="submit">Book</button>
|
||||
<button id="payment_button" class="btn btn-primary btn-md btn-blck " type="submit">Book</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -3,6 +3,15 @@
|
|||
{% block title %}crowdfunding{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
#cancel-subscription-modal{
|
||||
margin-top:10%;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<section id="price">
|
||||
<div class="signup-container">
|
||||
<div class="col-xs-12 col-sm-3 col-lg-4 text-center wow fadeInDown"> </div>
|
||||
|
@ -25,6 +34,7 @@
|
|||
<button type="button" class="btn btn-primary btn-blue" data-toggle="modal" data-target="#cancel-subscription-modal">Cancel my Membership</button>
|
||||
|
||||
|
||||
|
||||
<div class="modal fade bs-example-modal-sm" id="cancel-subscription-modal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
|
@ -36,7 +46,7 @@
|
|||
<p>Do you want to cancel your subscription?</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">No</button>
|
||||
<button type="button" class="btn btn-primary btn-grey" data-dismiss="modal">No</button>
|
||||
<button type="submit" class="btn btn-primary">Yes</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
|
@ -49,7 +59,7 @@
|
|||
</div>
|
||||
<div class="notice-box text-left">
|
||||
<p class="order-bottom-text">
|
||||
Your membership wouldn't be automatically renewed each month.
|
||||
Your membership wouldn't be automatically renewed each month. <a href="{{request.META.HTTP_REFERER}}">Go back</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<div class="signup-container">
|
||||
<div class="col-xs-12 col-sm-6 col-lg-8 text-center wow fadeInDown">
|
||||
<div class="payment-box">
|
||||
<h2 class="section-heading payment-head">Your membership invoice for {{order.created_at|date:"F"}}</h2>
|
||||
<h2 class="section-heading payment-head">Your membership invoice for {{order.created_at|date:"Y-m"}}</h2>
|
||||
<hr class="greyline-long">
|
||||
<h2 class="billing-head">Invoice<btn class="btn btn-primary btn-grey btn-edit print hidden-print" data-print="price">Get PDF</btn></h2>
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<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="order-head">Current Membership</h2>
|
||||
<h2 class="member-name">{{membership_start_date|date}}-{{membership_end_date|date}}</h2>
|
||||
<hr class="greyline-long">
|
||||
<h2 class="order-head">Orders history</h2>
|
||||
|
|
|
@ -91,6 +91,13 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<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="col-xs-12">
|
||||
<button class="btn btn-primary btn-md btn-blck " type="submit">Purchase membership</button>
|
||||
</div>
|
||||
|
@ -132,12 +139,6 @@
|
|||
<h2 class="col-xs-6 payment-total">Total</h2>
|
||||
<h2 class="order-result">{{membership_type.first_month_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>
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
{% 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="row col-md-2 text-center wow fadeInDown"></div>
|
||||
<div class="row col-md-8 text-center wow fadeInDown">
|
||||
<div class="price-box">
|
||||
<span class="glyphicon glyphicon-star"></span>
|
||||
<h2 class="section-heading">Digital Glarus Membership</h2>
|
||||
|
@ -39,7 +39,7 @@
|
|||
|
||||
</div>
|
||||
</div>
|
||||
<div class="row col-md-3 text-center wow fadeInDown"></div>
|
||||
<div class="row col-md-2 text-center wow fadeInDown"></div>
|
||||
</div>
|
||||
</section>
|
||||
<!--membership includes-->
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
<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">Billing Address Info</h2>
|
||||
<h2 class="section-heading payment-head">Billing Address</h2>
|
||||
<!-- <h2 class="membership-amount">35CHF</h2> -->
|
||||
<hr class="greyline-long">
|
||||
<h2 class="billing-head">Billing Adress</h2>
|
||||
|
@ -35,6 +35,7 @@
|
|||
{% bootstrap_field field show_label=False type='fields'%}
|
||||
{% endfor %}
|
||||
{% bootstrap_form_errors form type='non_fields'%}
|
||||
<input type="hidden" name="next" value="{{request.META.HTTP_REFERER}}">
|
||||
<br>
|
||||
|
||||
<div class="row">
|
||||
|
@ -44,7 +45,7 @@
|
|||
<h2 class="signup-lead text-center">{{ message }}</h2>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
<button id="payment_button" class="btn btn-primary btn-lg btn-blck " type="submit">Save</button>
|
||||
<button id="payment_button" class="btn btn-primary btn-md btn-blck " type="submit">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -209,63 +209,83 @@ class BookingPaymentView(LoginRequiredMixin, MembershipRequiredMixin, FormView):
|
|||
form.add_error("__all__", "Invalid credit card")
|
||||
return self.render_to_response(self.get_context_data(form=form))
|
||||
|
||||
if is_free:
|
||||
billing_address = form.save()
|
||||
# if is_free:
|
||||
# billing_address = form.save()
|
||||
|
||||
# Create Billing Address for User if he does not have one
|
||||
if not customer.user.billing_addresses.count():
|
||||
data.update({
|
||||
'user': customer.user.id
|
||||
# # Create Billing Address for User if he does not have one
|
||||
# if not customer.user.billing_addresses.count():
|
||||
# data.update({
|
||||
# 'user': customer.user.id
|
||||
# })
|
||||
# billing_address_user_form = UserBillingAddressForm(data)
|
||||
# billing_address_user_form.is_valid()
|
||||
# billing_address_user_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,
|
||||
# 'amount': final_price,
|
||||
# 'original_price': normal_price,
|
||||
# 'special_month_price': BookingPrice.objects.last().special_month_price,
|
||||
# 'membership_required_months': membership_required_months,
|
||||
# 'membership_required_months_price': membership_required_months_price,
|
||||
# }
|
||||
# order = BookingOrder.create(order_data)
|
||||
|
||||
# return HttpResponseRedirect(self.get_success_url(order.id))
|
||||
|
||||
# If booking is not free, make the stripe charge
|
||||
if not is_free:
|
||||
# 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
|
||||
})
|
||||
billing_address_user_form = UserBillingAddressForm(data)
|
||||
billing_address_user_form.is_valid()
|
||||
billing_address_user_form.save()
|
||||
return render(self.request, self.template_name, context)
|
||||
|
||||
# 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,
|
||||
'amount': final_price,
|
||||
'original_price': normal_price,
|
||||
'special_month_price': BookingPrice.objects.last().special_month_price,
|
||||
'membership_required_months': membership_required_months,
|
||||
'membership_required_months_price': membership_required_months_price,
|
||||
}
|
||||
order = BookingOrder.create(order_data)
|
||||
|
||||
return HttpResponseRedirect(self.get_success_url(order.id))
|
||||
|
||||
# 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')
|
||||
charge = charge_response.get('response_object')
|
||||
|
||||
# Create Billing Address for Membership Order
|
||||
billing_address = form.save()
|
||||
|
||||
# Check if user had to pay membership months in advaced
|
||||
# if membership_required_months:
|
||||
|
||||
# # Get current user membership
|
||||
# membership = Membership.get_by_user(self.request.user)
|
||||
|
||||
# # Create membership order
|
||||
# order_data = {
|
||||
# 'membership': membership,
|
||||
# 'customer': customer,
|
||||
# 'billing_address': billing_address,
|
||||
# 'amount': membership_required_months_price,
|
||||
# 'start_date': start_date,
|
||||
# 'end_date': end_date
|
||||
# }
|
||||
|
||||
# MembershipOrder.create(order_data)
|
||||
|
||||
# Create Billing Address for User if he does not have one
|
||||
if not customer.user.billing_addresses.count():
|
||||
data.update({
|
||||
|
@ -275,7 +295,7 @@ class BookingPaymentView(LoginRequiredMixin, MembershipRequiredMixin, FormView):
|
|||
billing_address_user_form.is_valid()
|
||||
billing_address_user_form.save()
|
||||
|
||||
# Create membership plan
|
||||
# Create Booking
|
||||
booking_data = {
|
||||
'start_date': start_date,
|
||||
'end_date': end_date,
|
||||
|
@ -286,7 +306,7 @@ class BookingPaymentView(LoginRequiredMixin, MembershipRequiredMixin, FormView):
|
|||
}
|
||||
booking = Booking.create(booking_data)
|
||||
|
||||
# Create membership order
|
||||
# Create Booking order
|
||||
order_data = {
|
||||
'booking': booking,
|
||||
'customer': customer,
|
||||
|
@ -383,8 +403,15 @@ class MembershipPaymentView(LoginRequiredMixin, IsNotMemberMixin, FormView):
|
|||
billing_address_user_form.is_valid()
|
||||
billing_address_user_form.save()
|
||||
|
||||
# Get membership dates
|
||||
membership_start_date, membership_end_date = membership_type.first_month_range
|
||||
|
||||
# Create membership plan
|
||||
membership_data = {'type': membership_type}
|
||||
membership_data = {
|
||||
'type': membership_type,
|
||||
'start_date': membership_start_date,
|
||||
'end_date': membership_end_date
|
||||
}
|
||||
membership = Membership.create(membership_data)
|
||||
|
||||
# Create membership order
|
||||
|
@ -393,7 +420,9 @@ class MembershipPaymentView(LoginRequiredMixin, IsNotMemberMixin, FormView):
|
|||
'customer': customer,
|
||||
'billing_address': billing_address,
|
||||
'stripe_charge': charge,
|
||||
'amount': membership_type.first_month_price
|
||||
'amount': membership_type.first_month_price,
|
||||
'start_date': membership_start_date,
|
||||
'end_date': membership_end_date
|
||||
}
|
||||
|
||||
membership_order = MembershipOrder.create(order_data)
|
||||
|
@ -403,13 +432,11 @@ class MembershipPaymentView(LoginRequiredMixin, IsNotMemberMixin, FormView):
|
|||
'membership_dates': membership.type.first_month_formated_range
|
||||
})
|
||||
|
||||
start_m_date, end_m_date = membership_order.first_membership_range_date()
|
||||
|
||||
context = {
|
||||
'membership': membership,
|
||||
'order': membership_order,
|
||||
'membership_start_date': start_m_date,
|
||||
'membership_end_date': end_m_date,
|
||||
'membership_start_date': membership_start_date,
|
||||
'membership_end_date': membership_end_date,
|
||||
'base_url': "{0}://{1}".format(request.scheme, request.get_host())
|
||||
|
||||
}
|
||||
|
@ -475,6 +502,12 @@ class UserBillingAddressView(LoginRequiredMixin, UpdateView):
|
|||
success_url = reverse_lazy('digitalglarus:user_billing_address')
|
||||
success_message = "Billing Address Updated"
|
||||
|
||||
def get_success_url(self):
|
||||
next_url = self.request.POST.get('next') if self.request.POST.get('next')\
|
||||
else self.success_url
|
||||
|
||||
return next_url
|
||||
|
||||
def form_valid(self, form):
|
||||
"""
|
||||
If the form is valid, save the associated model.
|
||||
|
|
Loading…
Reference in a new issue