diff --git a/manage_subscriptions/forms.py b/manage_subscriptions/forms.py index 0e99151..ae2fee1 100644 --- a/manage_subscriptions/forms.py +++ b/manage_subscriptions/forms.py @@ -22,6 +22,7 @@ class SubscriptionForm(forms.ModelForm): "title", "plan", "amount", + "principal_types", ] # Include all fields you want from the model diff --git a/manage_subscriptions/migrations/0002_subscription_principal_types.py b/manage_subscriptions/migrations/0002_subscription_principal_types.py new file mode 100644 index 0000000..9eaa780 --- /dev/null +++ b/manage_subscriptions/migrations/0002_subscription_principal_types.py @@ -0,0 +1,23 @@ +# Generated by Django 5.0.2 on 2024-04-07 10:07 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("accounts", "0006_iamprincipal_facebook_profile_and_more"), + ("manage_subscriptions", "0001_initial"), + ] + + operations = [ + migrations.AddField( + model_name="subscription", + name="principal_types", + field=models.ManyToManyField( + blank=True, + related_name="principal_type_subscriptions", + to="accounts.iamprincipaltype", + ), + ), + ] diff --git a/manage_subscriptions/models.py b/manage_subscriptions/models.py index cce114a..4e51f35 100644 --- a/manage_subscriptions/models.py +++ b/manage_subscriptions/models.py @@ -22,6 +22,11 @@ class Subscription(BaseModel): Plan, related_name="subscription_plan", on_delete=models.CASCADE ) amount = models.DecimalField(max_digits=14, decimal_places=2, default=0.00) + principal_types = models.ManyToManyField( + IAmPrincipalType, + related_name='principal_type_subscriptions', + blank=True + ) class Meta: db_table = "subscription" diff --git a/manage_subscriptions/views.py b/manage_subscriptions/views.py index f4f154f..67f8b21 100644 --- a/manage_subscriptions/views.py +++ b/manage_subscriptions/views.py @@ -1,4 +1,5 @@ from datetime import timedelta +import json from django.http import HttpResponseBadRequest, JsonResponse from django.shortcuts import get_object_or_404, redirect, render import stripe @@ -29,6 +30,7 @@ from django.urls import reverse_lazy from django.contrib import messages from goodtimes import constants from django.views.decorators.csrf import csrf_exempt +from django.views.decorators.http import require_POST from django.conf import settings from rest_framework.permissions import IsAuthenticated from django.views.generic.base import TemplateView @@ -382,19 +384,15 @@ class SubscriptionPageView(TemplateView): request = self.request if request.user.is_authenticated: print("request.user: ", request.user) - if request.user.principal_type.name == "event_user": - subscription_id = 2 - elif request.user.principal_type.name == "event_manager": - subscription_id = 1 - else: - subscription_id = None + subscriptions = Subscription.objects.filter( + principal_types=request.user.principal_type + ) - if subscription_id is not None: - subscription = Subscription.objects.get(id=subscription_id) - context['subscription_amount'] = subscription.amount + if subscriptions.exists(): + context["subscriptions"] = subscriptions else: - # Handle error or default case - context['error'] = "Invalid principal type or subscription not found." + # Handle the case where no subscriptions are found for the principal type. + context["error"] = "No subscriptions found for your user type." return context @@ -406,106 +404,108 @@ def stripe_config(request): @csrf_exempt +@require_POST def create_checkout_session(request): - if request.method == "GET": - stripe.api_key = settings.STRIPE_SECRET_KEY + stripe.api_key = settings.STRIPE_SECRET_KEY + data = json.loads(request.body) + subscription_id = data.get("subscription_id", None) + # if request.method == "GET": + # subscription_id = None # Assuming 3 is a default or fallback subscription ID - subscription_id = None # Assuming 3 is a default or fallback subscription ID + # if request.user.is_authenticated: + # print("request.user: ", request.user) + # if request.user.principal_type.name == "event_user": + # subscription_id = 2 + # elif request.user.principal_type.name == "event_manager": + # subscription_id = 1 - if request.user.is_authenticated: - print("request.user: ", request.user) - if request.user.principal_type.name == "event_user": - subscription_id = 2 - elif request.user.principal_type.name == "event_manager": - subscription_id = 1 - - try: - subscription = Subscription.objects.get(id=subscription_id) - except Subscription.DoesNotExist: - return ApiResponse.error( - status=status.HTTP_404_NOT_FOUND, message="Subscription not found." - ) - - order_id = ( - "order_" + str(timezone.localtime().timestamp()) + str(request.user.email) - ) - print("order_id: ", order_id) - - # Create a Transaction object with status INITIATE - transaction = Transaction.objects.create( - principal=request.user, - principal_subscription=None, # Since the subscription is not created yet - transaction_type=TransactionType.PAYMENT, # or PAYMENT, as applicable - payment_method=PaymentMethod.CARD, # Assuming CARD for this example - transaction_status=TransactionStatus.INITIATE, - amount=subscription.amount, # Fetching amount from the Subscription object - order_id=order_id, - comment="Principal Subscription Initiated", + try: + subscription = Subscription.objects.get(id=subscription_id) + except Subscription.DoesNotExist: + return ApiResponse.error( + status=status.HTTP_404_NOT_FOUND, message="Subscription not found." ) - subscription_days = subscription.plan.days - today = timezone.now().date() - last_date = today + timedelta(days=int(subscription_days)) + order_id = ( + "order_" + str(timezone.localtime().timestamp()) + str(request.user.email) + ) + print("order_id: ", order_id) - # To Avoid Duplicacy of Principal Subscription - principal_subscription = PrincipalSubscription.objects.create( - principal=request.user, - subscription=subscription, - is_paid=False, - order_id=order_id, - start_date=today, - end_date=last_date, - grace_period_end_date=last_date + timedelta(days=15), - ) + # Create a Transaction object with status INITIATE + transaction = Transaction.objects.create( + principal=request.user, + principal_subscription=None, # Since the subscription is not created yet + transaction_type=TransactionType.PAYMENT, # or PAYMENT, as applicable + payment_method=PaymentMethod.CARD, # Assuming CARD for this example + transaction_status=TransactionStatus.INITIATE, + amount=subscription.amount, # Fetching amount from the Subscription object + order_id=order_id, + comment="Principal Subscription Initiated", + ) - try: - # customer = stripe.Customer.create( - # email=request.user.email, - # shipping={ - # "name": request.user.first_name, - # "address": { - # "line1": request.user.city, - # "city": request.user.city, - # "postal_code": "SW1A 2AA", - # "country": request.user.address_line1, # Adjust accordingly - # }, - # }, - # ) + subscription_days = subscription.plan.days + today = timezone.now().date() + last_date = today + timedelta(days=int(subscription_days)) - # Create a checkout session - checkout_session = stripe.checkout.Session.create( - payment_method_types=["card"], - # customer=customer.id, # Optional: Link the session to the Stripe customer created above - line_items=[ - { - "price_data": { - "currency": "gbp", - "product_data": { - "name": subscription.title, # Adjust with your subscription/product name - }, - "unit_amount": int( - subscription.amount * 100 - ), # Unit amount in cents/pence - "tax_behavior": "inclusive", # or 'exclusive', based on your tax settings + # To Avoid Duplicacy of Principal Subscription + principal_subscription = PrincipalSubscription.objects.create( + principal=request.user, + subscription=subscription, + is_paid=False, + order_id=order_id, + start_date=today, + end_date=last_date, + grace_period_end_date=last_date + timedelta(days=15), + ) + + try: + # customer = stripe.Customer.create( + # email=request.user.email, + # shipping={ + # "name": request.user.first_name, + # "address": { + # "line1": request.user.city, + # "city": request.user.city, + # "postal_code": "SW1A 2AA", + # "country": request.user.address_line1, # Adjust accordingly + # }, + # }, + # ) + + # Create a checkout session + checkout_session = stripe.checkout.Session.create( + payment_method_types=["card"], + # customer=customer.id, # Optional: Link the session to the Stripe customer created above + line_items=[ + { + "price_data": { + "currency": "gbp", + "product_data": { + "name": subscription.title, # Adjust with your subscription/product name }, - "quantity": 1, - } - ], - mode="payment", - success_url=request.build_absolute_uri("/subscriptions/success/"), - cancel_url=request.build_absolute_uri("/subscriptions/cancel/"), - metadata={ - "principal": str(request.user.id), - "order_id": str(order_id), - # "subscription_id": str(subscription.id), - "transaction_id": str(transaction.id), - "principal_subscription_id": str(principal_subscription.id), - }, - # Optionally, set shipping options, allow promotion codes, etc. - ) - return JsonResponse({"sessionId": checkout_session["id"]}) - except Exception as e: - return JsonResponse({"error": str(e)}) + "unit_amount": int( + subscription.amount * 100 + ), # Unit amount in cents/pence + "tax_behavior": "inclusive", # or 'exclusive', based on your tax settings + }, + "quantity": 1, + } + ], + mode="payment", + success_url=request.build_absolute_uri("/subscriptions/success/"), + cancel_url=request.build_absolute_uri("/subscriptions/cancel/"), + metadata={ + "principal": str(request.user.id), + "order_id": str(order_id), + # "subscription_id": str(subscription.id), + "transaction_id": str(transaction.id), + "principal_subscription_id": str(principal_subscription.id), + }, + # Optionally, set shipping options, allow promotion codes, etc. + ) + return JsonResponse({"sessionId": checkout_session["id"]}) + except Exception as e: + return JsonResponse({"error": str(e)}) class SuccessView(TemplateView): diff --git a/manage_wallets/api/serializers.py b/manage_wallets/api/serializers.py index d8b9739..ef09c2a 100644 --- a/manage_wallets/api/serializers.py +++ b/manage_wallets/api/serializers.py @@ -94,3 +94,18 @@ class WithdrawalRequestSerializer(serializers.ModelSerializer): class Meta: model = models.WithdrawalRequest fields = ["notes"] + + +class WithdrawalRequestViewSerializer(serializers.ModelSerializer): + class Meta: + model = models.WithdrawalRequest + fields = [ + "id", + "coins", + "amount", + "notes", + "reply", + "status", + "created_on", + ] + read_only_fields = ["id", "created_on"] diff --git a/manage_wallets/api/urls.py b/manage_wallets/api/urls.py index 491cbec..4420ef1 100644 --- a/manage_wallets/api/urls.py +++ b/manage_wallets/api/urls.py @@ -13,8 +13,24 @@ urlpatterns = [ ), path("get-wallet/", views.GetWallet.as_view(), name="get_wallet"), path("get-transaction/", views.TransactionView.as_view(), name="transactions"), - - path("create-stripe-connect/", views.CreateStripeConnectAccount.as_view(), name="stripe_connect"), - path("add-bank-details/", views.PrincipalBankAccountCreateAPIView.as_view(), name="add_bank_account"), - path('withdrawal-request/', views.WithdrawalRequestCreateAPI.as_view(), name='withdrawal-request-create'), + path( + "create-stripe-connect/", + views.CreateStripeConnectAccount.as_view(), + name="stripe_connect", + ), + path( + "add-bank-details/", + views.PrincipalBankAccountCreateAPIView.as_view(), + name="add_bank_account", + ), + path( + "create-withdrawal-request/", + views.WithdrawalRequestCreateAPI.as_view(), + name="withdrawal-request-create", + ), + path( + "view-withdrawal-request/", + views.WithdrawalRequestView.as_view(), + name="withdrawal-request-view", + ), ] diff --git a/manage_wallets/api/views.py b/manage_wallets/api/views.py index aed0f04..e505c92 100644 --- a/manage_wallets/api/views.py +++ b/manage_wallets/api/views.py @@ -366,7 +366,7 @@ class WithdrawalRequestCreateAPI(APIView): # Check if the user has a wallet and sufficient coins if wallet is None or wallet.coins <= 0: return ApiResponse.error( - errors="Insufficient balance or no wallet found.", + errors="Insufficient balance.", status=status.HTTP_400_BAD_REQUEST, message=constants.FAILURE, ) @@ -389,7 +389,7 @@ class WithdrawalRequestCreateAPI(APIView): wallet.save() return ApiResponse.success( data=serializer.data, - status=status.HTTP_201_CREATED, + status=status.HTTP_200_OK, message=constants.SUCCESS, ) else: @@ -398,3 +398,24 @@ class WithdrawalRequestCreateAPI(APIView): status=status.HTTP_400_BAD_REQUEST, message=constants.FAILURE, ) + + +class WithdrawalRequestView(APIView): + authentication_classes = [JWTAuthentication] + permission_classes = [IsAuthenticated] + + def get(self, request): + # Get the logged-in principal + principal = request.user + # Filter withdrawal requests by the logged-in principal + withdrawal_requests = models.WithdrawalRequest.objects.filter( + principal=principal + ).order_by("-created_on") + serializer = serializers.WithdrawalRequestViewSerializer( + withdrawal_requests, many=True + ) + return ApiResponse.success( + data=serializer.data, + status=status.HTTP_200_OK, + message=constants.SUCCESS, + ) diff --git a/templates/stripe_html/index.html b/templates/stripe_html/index.html index 382bb79..e7b7c1f 100644 --- a/templates/stripe_html/index.html +++ b/templates/stripe_html/index.html @@ -77,22 +77,27 @@ + {% for subscription in subscriptions %}
-
Subscription Details +
{{ subscription.title }}
- -
Subscription Amount
-
-

£ {{ subscription_amount }}

-
+
Subscription Amount
+

£ {{ subscription.amount }}

- + +
+
+ {% empty %} +

No subscriptions available.

+ {% endfor %} + @@ -424,7 +429,7 @@ console.log("Sanity check!"); var button = document.getElementById("submitBtn"); -// Then, disable the button + // Then, disable the button // Get Stripe publishable key @@ -436,21 +441,50 @@ // new // Event handler - document.querySelector("#submitBtn").addEventListener("click", () => { - button.disabled = true; - // Get Checkout Session ID - fetch("https://goodtimes.betadelivery.com/subscriptions/create-checkout-session/") - .then((result) => { return result.json(); }) - .then((data) => { - console.log(data); - // Redirect to Stripe Checkout - return stripe.redirectToCheckout({ sessionId: data.sessionId }) + // document.querySelector("#submitBtn").addEventListener("click", () => { + // button.disabled = true; + // // Get Checkout Session ID + // fetch("https://goodtimes.betadelivery.com/subscriptions/create-checkout-session/") + // .then((result) => { return result.json(); }) + // .then((data) => { + // console.log(data); + // // Redirect to Stripe Checkout + // return stripe.redirectToCheckout({ sessionId: data.sessionId }) + // }) + // .then((res) => { + // console.log(res); + // }); + // }); + + document.querySelectorAll(".subscribe-btn").forEach(button => { + button.addEventListener("click", () => { + const subscriptionId = button.getAttribute("data-subscription-id"); + button.disabled = true; + // Create checkout session for the selected subscription + fetch("https://goodtimes.betadelivery.com/subscriptions/create-checkout-session/", { + // fetch("http://192.168.0.101:8000/subscriptions/create-checkout-session/", { + method: "POST", + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ subscriptionId: subscriptionId }), }) - .then((res) => { - console.log(res); - }); + .then((result) => { return result.json(); }) + .then((data) => { + // Redirect to Stripe Checkout + return stripe.redirectToCheckout({ sessionId: data.sessionId }) + }) + .catch((error) => { + console.error("Error:", error); + button.disabled = false; + }); + }); + }); + + + + }); - });