Skip to content

Commit

Permalink
Payment plan page and menus
Browse files Browse the repository at this point in the history
  • Loading branch information
rebkwok committed Jul 10, 2024
1 parent ac82829 commit c604877
Show file tree
Hide file tree
Showing 10 changed files with 110 additions and 32 deletions.
34 changes: 28 additions & 6 deletions booking/tests/test_block_views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from datetime import datetime, timedelta
from datetime import timezone as dt_timezone
from unittest.mock import patch

from model_bakery import baker
import pytest

from django.conf import settings
from django.contrib.auth.models import User
Expand All @@ -17,7 +20,7 @@
from booking.views import BlockCreateView, BlockListView
from common.tests.helpers import _create_session, format_content, \
setup_view, TestSetupMixin, make_data_privacy_agreement

from stripe_payments.tests.mock_connector import MockConnector

class BlockCreateViewTests(TestSetupMixin, TestCase):

Expand Down Expand Up @@ -571,7 +574,7 @@ def test_delete_block_with_block_code(self):
)


class BlockModalTests(TestSetupMixin, TestCase):
class PaymentPlansModalTests(TestSetupMixin, TestCase):

@classmethod
def setUpTestData(cls):
Expand All @@ -582,14 +585,14 @@ def setUp(self):
super().setUp()
self.client.login(username=self.user.username, password='test')

def test_block_modal_no_blocks(self):
def test_block_modal_no_blocks_or_memberships(self):
resp = self.client.get(self.url)
self.assertEqual(resp.context['active_blocks'], [])
self.assertEqual(resp.context['unpaid_blocks'], [])
self.assertEqual(list(resp.context['active_memberships']), [])
self.assertTrue('can_book_block')

def test_block_modal_with_blocks(self):
unpaid_block = baker.make_recipe(
baker.make_recipe(
'booking.block_5', user=self.user, paid=False,
start_date=timezone.now()-timedelta(days=1)
)
Expand Down Expand Up @@ -617,4 +620,23 @@ def test_block_modal_with_blocks(self):
resp = self.client.get(self.url)

self.assertEqual(resp.context['active_blocks'], [paid_block])
self.assertEqual(resp.context['unpaid_blocks'], [unpaid_block])


@pytest.mark.django_db
@patch("booking.models.membership_models.StripeConnector", MockConnector)
def test_block_modal_with_memberships(client, seller, configured_user):
client.force_login(configured_user)
m1 = baker.make("booking.Membership", name="m1", active=True)
user_membership = baker.make("booking.UserMembership", membership=m1, user=configured_user, subscription_status="active")
user_membership1 = baker.make(
"booking.UserMembership", membership=m1, user=configured_user, subscription_status="active",
end_date=datetime.now() + timedelta(10)
)
baker.make(
"booking.UserMembership", membership=m1, user=configured_user, subscription_status="canceled",
end_date=datetime.now() - timedelta(10)
)

resp = client.get(reverse('booking:blocks_modal'))
# with end date first
assert list(resp.context['active_memberships']) == [user_membership1, user_membership]
3 changes: 2 additions & 1 deletion booking/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
submit_zero_booking_payment, update_shopping_basket_count, \
toggle_waiting_list, \
OnlineTutorialListView, PurchasedTutorialsListView, OnlineTutorialDetailView, \
check_total, toggle_ticketed_event_waiting_list
check_total, toggle_ticketed_event_waiting_list, payment_plans
app_name = 'booking'


Expand Down Expand Up @@ -144,6 +144,7 @@
'blocks_modal/',
blocks_modal, name='blocks_modal'
),
path('payment-plans/', payment_plans, name='payment_plans'),
path('gift-vouchers/', GiftVoucherPurchaseView.as_view(), name='buy_gift_voucher'),
path('gift-voucher/<voucher_code>/', gift_voucher_details, name='gift_voucher_details'),
path('gift-voucher/<voucher_code>/update/', GiftVoucherPurchaseView.as_view(), name='gift_voucher_update'),
Expand Down
5 changes: 3 additions & 2 deletions booking/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
has_active_block, cancellation_period_past, update_shopping_basket_count, \
toggle_waiting_list, PurchasedTutorialsListView
from booking.views.block_views import BlockCreateView, BlockDeleteView, \
BlockListView, blocks_modal
BlockListView, blocks_modal, payment_plans
from booking.views.checkout_views import stripe_checkout, check_total
from booking.views.gift_vouchers import GiftVoucherPurchaseView, gift_voucher_details, gift_voucher_delete
from booking.views.shopping_basket_views import shopping_basket, \
Expand Down Expand Up @@ -40,7 +40,8 @@
"OnlineTutorialListView", "PurchasedTutorialsListView", "OnlineTutorialDetailView",
"stripe_checkout", "check_total", "toggle_ticketed_event_waiting_list",
"membership_create", "stripe_subscription_checkout", "subscription_create",
"membership_status", "MembershipListView", "membership_change", "subscription_cancel"
"membership_status", "MembershipListView", "membership_change", "subscription_cancel",
"payment_plans",
]


Expand Down
19 changes: 13 additions & 6 deletions booking/views/block_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,17 @@ def blocks_modal(request):
# # already sorted by expiry date,
active_blocks = [block for block in blocks if block.active_block()]

unpaid_blocks = [
block for block in request.user.blocks.filter(expiry_date__gte=timezone.now(), paid=False, paypal_pending=False)
if not block.full
]
types_available_to_book = context_helpers.get_blocktypes_available_to_book(request.user)
context = {'active_blocks': active_blocks, 'unpaid_blocks': unpaid_blocks, 'can_book_block': types_available_to_book}
return render(request, 'booking/includes/blocks_modal_content.html', context)

active_memberships = request.user.memberships.filter(
subscription_status__in=["active", "past_due"],
).order_by("end_date")

context = {
"active_memberships": active_memberships,
'active_blocks': active_blocks, 'can_book_block': types_available_to_book}
return render(request, 'booking/includes/payment_plans_modal_content.html', context)


def payment_plans(request):
return render(request, 'booking/payment_plans.html')
6 changes: 4 additions & 2 deletions templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
{% if request.user.is_authenticated %}
<div class="d-inline-block d-md-none extra-collapsed-menu-icons">
<span class="shopping-basket-menu" id="shopping-basket-menu-xs">{% show_shopping_basket_menu request.user %}</span>
<span class="blocks-menu mr-4" id="blocks-menu-xs" title="View available blocks">{% include 'booking/includes/blocks_modal.html' %}</span>
<span class="blocks-menu mr-4" id="blocks-menu-xs" title="View your available payment methods">{% include 'booking/includes/payment_plans_modal.html' %}</span>
</div>
{% endif %}
{% endblock %}
Expand All @@ -61,6 +61,8 @@
{% if room_hires %}
<li class="nav-item"><a class="nav-link" href="{% url 'booking:room_hires' %}">Room Hire</a></li>
{% endif %}
<li class="nav-item"><a class="nav-link" href="{% url 'booking:payment_plans' %}">Payment Plans</a></li>

<li class="nav-item d-inline-block d-sm-none"><a class="nav-link" href="{% url 'booking:buy_gift_voucher' %}">Gift Vouchers</a></li>
<li class="nav-item d-inline-block d-sm-none"><a class="nav-link" href="{% url 'booking:ticketed_events' %}">Tickets</a></li>
<li class="nav-item d-inline-block d-sm-none"><a class="nav-link" href="{% url 'nonregistered_disclaimer_form' %}">Event Disclaimer</a></li>
Expand All @@ -75,7 +77,7 @@

{% if request.user.is_authenticated %}
<li class="pl-1 pt-2 nav-item d-none d-sm-block"><span id="shopping-basket-menu">{% show_shopping_basket_menu request.user %}</span></li>
<li id="blocks-menu" class="pt-2 ml-4 mr-2 nav-item d-none d-sm-block" title="View available blocks">{% include 'booking/includes/blocks_modal.html' %}</li>
<li id="blocks-menu" class="pt-2 ml-4 mr-2 nav-item d-none d-sm-block" title="View available payment plans">{% include 'booking/includes/payment_plans_modal.html' %}</li>
{% endif %}
{% endblock %}
</ul>
Expand Down
6 changes: 3 additions & 3 deletions templates/booking/add_block.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
<div class="col-sm-12">
<div class="card card-wm">
<div class="card-header">
<h2 class="card-title">New block booking</h2>
<h2 class="card-title">New block purchase</h2>
</div>
<div class="card-body">
<p>Block booking is only available for certain types of classes or events. Please select a block
<p>Blocks are only valid for certain types of classes or events. Please select a block
type from the dropdown list below. You can only have one active block of each available type.</p>
<p>After you choose a block you will be redirected to the Your Blocks page where you can make
<p>After you choose a block you will be redirected to your Blocks page where you can make
payment. Your block will not be activated until payment has been processed.</p>

<h4>Block types available:</h4>
Expand Down
1 change: 0 additions & 1 deletion templates/booking/includes/blocks_modal.html

This file was deleted.

1 change: 1 addition & 0 deletions templates/booking/includes/payment_plans_modal.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<a class="blockmodalbtn" href="#" data-url="{% url 'booking:blocks_modal' %}" role="button"><span class="fas fa-wallet fa-lg"></span></a>
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,26 @@
<div class="modal-dialog modal-">
<div class="modal-content">
<div class="modal-header">
<h5 id="blocksModalLabel">Blocks</h5>
<h4 id="blocksModalLabel">Available Payment Methods</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>

</div>
<div class="modal-body mb-2">
<h5>Memberships</h5>
<ul class="list-group">
{% if active_memberships %}
{% for active_membership in active_memberships %}
<li class="list-group-item list-group-item-success">{{ active_membership.membership.name }}{% if active_membership.end_date %} (ends {{ active_membership.end_date|date:"d M Y" }}){% endif %}</li>
{% endfor %}
<li class="list-group-item"><a href="{% url 'membership_list' %}" class="btn btn-wm btn-new-block">View/edit membership</a></li>
{% else %}
<li class="list-group-item">No active memberships</li>
<li class="list-group-item"><a href="{% url 'membership_create' %}" class="btn btn-wm btn-new-block">Get a new membership!</a></li>
{% endif %}
</ul>

<h5>Blocks</h5>
<ul class="list-group">
<h5>Active</h5>
{% if active_blocks %}
{% for block in active_blocks %}
<li class="list-group-item list-group-item-success">{{ block.block_type.event_type.subtype }}
Expand All @@ -22,16 +35,7 @@ <h5>Active</h5>
<li class="list-group-item"><a href="{% url 'booking:add_block' %}" class="btn btn-wm btn-new-block">Get a new block!</a></li>
{% endif %}
</ul>
{% if unpaid_blocks %}

<h5>Unpaid</h5>
<ul class="list-group">

{% for block in unpaid_blocks %}
<li class="list-group-item list-group-item-danger">{{ block.block_type.event_type.subtype }} expires {{ block.expiry_date | date:"d M Y" }}</li>
{% endfor %}
</ul>
{% endif %}
</div>


Expand Down
41 changes: 41 additions & 0 deletions templates/booking/payment_plans.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{% extends "base.html" %}
{% load static %}

{% block content %}

<div class="extra-top-margin container-fluid row">
<div class="col-sm-12">
<div class="card card-wm">
<div class="card-header">
<h2 class="card-title">Payment Plans</h2>
</div>
<div class="card-body">
<p>
You can book classes and pay on a pay-as-you-go basis. However, if you are a regular student, you'll
find it easier and more cost-effective to set up a membership or to purchase blocks.
</p>

<h4>Memberships</h4>
<p>
Memberships run continuously; you select the membership that best suits you, and set up a regular
subscription payment that will be taken from your specified payment card or payment method each month.
Depending on the membership you choose, you will be able to book a certain
number of classes per calendar month. If you want to book more than your allowance, you can purchase
a block to top up for that month.

Memberships give you some additional benefits, such as merchanise discounts and advance notice of
special classes and workshops.
</p>
<p><a href="{% url 'membership_create' %}">Set up a membership</a></p>
<h4>Blocks</h4>
<p>Purchasing a block effectively means purchasing a quantity of classes in advance. Blocks last for
a specific length of time (usually one or two months).
</p>
<p><a href="{% url 'booking:add_block' %}">Purchase a block</a></p>

</div>
</div>
</div>
</div>

{% endblock content %}

0 comments on commit c604877

Please sign in to comment.