diff --git a/booking/tests/test_block_views.py b/booking/tests/test_block_views.py index 2752978f..eef55fd2 100644 --- a/booking/tests/test_block_views.py +++ b/booking/tests/test_block_views.py @@ -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 @@ -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): @@ -571,7 +574,7 @@ def test_delete_block_with_block_code(self): ) -class BlockModalTests(TestSetupMixin, TestCase): +class PaymentPlansModalTests(TestSetupMixin, TestCase): @classmethod def setUpTestData(cls): @@ -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) ) @@ -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] diff --git a/booking/urls.py b/booking/urls.py index 6003aab5..298eb467 100644 --- a/booking/urls.py +++ b/booking/urls.py @@ -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' @@ -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//', gift_voucher_details, name='gift_voucher_details'), path('gift-voucher//update/', GiftVoucherPurchaseView.as_view(), name='gift_voucher_update'), diff --git a/booking/views/__init__.py b/booking/views/__init__.py index c3573fc7..9ec9bf3d 100644 --- a/booking/views/__init__.py +++ b/booking/views/__init__.py @@ -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, \ @@ -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", ] diff --git a/booking/views/block_views.py b/booking/views/block_views.py index 01ec36a8..cfc86cc8 100644 --- a/booking/views/block_views.py +++ b/booking/views/block_views.py @@ -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') diff --git a/templates/base.html b/templates/base.html index 3ccb3218..16eb31b6 100644 --- a/templates/base.html +++ b/templates/base.html @@ -43,7 +43,7 @@ {% if request.user.is_authenticated %}
{% show_shopping_basket_menu request.user %} - {% include 'booking/includes/blocks_modal.html' %} + {% include 'booking/includes/payment_plans_modal.html' %}
{% endif %} {% endblock %} @@ -61,6 +61,8 @@ {% if room_hires %} {% endif %} + + @@ -75,7 +77,7 @@ {% if request.user.is_authenticated %} - + {% endif %} {% endblock %} diff --git a/templates/booking/add_block.html b/templates/booking/add_block.html index c0785eb3..9d92afee 100644 --- a/templates/booking/add_block.html +++ b/templates/booking/add_block.html @@ -7,12 +7,12 @@
-

New block booking

+

New block purchase

-

Block booking is only available for certain types of classes or events. Please select a block +

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.

-

After you choose a block you will be redirected to the Your Blocks page where you can make +

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.

Block types available:

diff --git a/templates/booking/includes/blocks_modal.html b/templates/booking/includes/blocks_modal.html deleted file mode 100644 index b7ac9d04..00000000 --- a/templates/booking/includes/blocks_modal.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/templates/booking/includes/payment_plans_modal.html b/templates/booking/includes/payment_plans_modal.html new file mode 100644 index 00000000..220dffb5 --- /dev/null +++ b/templates/booking/includes/payment_plans_modal.html @@ -0,0 +1 @@ + diff --git a/templates/booking/includes/blocks_modal_content.html b/templates/booking/includes/payment_plans_modal_content.html similarity index 59% rename from templates/booking/includes/blocks_modal_content.html rename to templates/booking/includes/payment_plans_modal_content.html index 31cc7b4f..7322868e 100644 --- a/templates/booking/includes/blocks_modal_content.html +++ b/templates/booking/includes/payment_plans_modal_content.html @@ -3,13 +3,26 @@