refator(subscription): update functionality, list view, subscription design
This commit is contained in:
@@ -11,6 +11,7 @@ class SubscriptionForm(forms.ModelForm):
|
||||
fields = [
|
||||
"title",
|
||||
"short_description",
|
||||
"long_description",
|
||||
"interval",
|
||||
"interval_count",
|
||||
"high_amount",
|
||||
@@ -20,6 +21,7 @@ class SubscriptionForm(forms.ModelForm):
|
||||
"active",
|
||||
"is_free",
|
||||
]
|
||||
exclude = []
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(SubscriptionForm, self).__init__(*args, **kwargs)
|
||||
@@ -29,6 +31,23 @@ class SubscriptionForm(forms.ModelForm):
|
||||
id__in=[event_user.id, event_manager.id]
|
||||
)
|
||||
|
||||
if self.instance:
|
||||
# If there is an instance (i.e. we're editing an existing subscription)
|
||||
|
||||
# Use a dictionary comprehension to create a new dictionary of fields
|
||||
# that excludes the readonly fields
|
||||
self.fields = {
|
||||
field_name: field
|
||||
for field_name, field in self.fields.items()
|
||||
if field_name not in [
|
||||
"interval",
|
||||
"interval_count",
|
||||
"amount",
|
||||
"high_amount",
|
||||
"principal_types",
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
class PrincipalSubscriptionForm(forms.ModelForm):
|
||||
class Meta:
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
# Generated by Django 5.0.2 on 2024-08-25 10:39
|
||||
|
||||
import django_quill.fields
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('manage_subscriptions', '0013_remove_subscription_plan_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='subscription',
|
||||
name='long_description',
|
||||
field=django_quill.fields.QuillField(),
|
||||
),
|
||||
]
|
||||
@@ -4,6 +4,7 @@ from django.db import models
|
||||
from django.core.exceptions import ValidationError
|
||||
from accounts.models import BaseModel, IAmPrincipal, IAmPrincipalType
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django_quill.fields import QuillField
|
||||
|
||||
|
||||
class Subscription(BaseModel):
|
||||
@@ -22,7 +23,7 @@ class Subscription(BaseModel):
|
||||
price_id = models.CharField(max_length=255, blank=True, null=True)
|
||||
product_id = models.CharField(max_length=255, blank=True, null=True)
|
||||
short_description = models.CharField(max_length=255, null=True, blank=True)
|
||||
long_description = models.TextField(null=True, blank=True)
|
||||
long_description = QuillField()
|
||||
image = models.ImageField(upload_to="subscription_img", null=True, blank=True)
|
||||
interval = models.CharField(max_length=10, choices=INTERVAL_TYPES)
|
||||
interval_count = models.IntegerField(default=1)
|
||||
@@ -56,19 +57,40 @@ class Subscription(BaseModel):
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
from goodtimes.services import StripeService
|
||||
|
||||
if not self.delete:
|
||||
self.clean()
|
||||
|
||||
if not self.is_free:
|
||||
if self.price_id:
|
||||
# Stipe dont provide to update the price record except active and deactive
|
||||
if self.is_free:
|
||||
# If is_free is True, set amounts to 0 and remove Stripe price and product IDs
|
||||
self.high_amount = 0.00
|
||||
self.amount = 0.00
|
||||
self.price_id = None
|
||||
self.product_id = None
|
||||
else:
|
||||
if self.id and self.price_id: # Update existing subscription
|
||||
# Retrieve existing price and product from Stripe
|
||||
price = StripeService.retrieve_price(self.price_id)
|
||||
if not price["success"]:
|
||||
raise Exception(price['message'])
|
||||
|
||||
# Update price active status if it differs from local active status
|
||||
if self.active != price["data"].active:
|
||||
StripeService.update_price(price_id=self.price_id, active=self.active)
|
||||
else:
|
||||
|
||||
# Retrieve existing product from Stripe
|
||||
product = StripeService.retrive_product(self.product_id)
|
||||
if not product["success"]:
|
||||
raise Exception(product['message'])
|
||||
|
||||
# Update product data if it has changed
|
||||
if product["data"].name != self.title or product["data"].description != self.short_description:
|
||||
StripeService.update_product(
|
||||
product_id=self.product_id,
|
||||
name=self.title,
|
||||
description=self.short_description
|
||||
)
|
||||
else: # Create new subscription
|
||||
# Create new product and price
|
||||
price = StripeService.create_price(
|
||||
product_data={
|
||||
@@ -89,7 +111,7 @@ class Subscription(BaseModel):
|
||||
if not price["success"]:
|
||||
raise Exception(price['message'])
|
||||
|
||||
# add the id in record
|
||||
# Add the IDs to the record
|
||||
self.price_id = price["data"].id
|
||||
self.product_id = price["data"].product
|
||||
|
||||
@@ -105,8 +127,6 @@ class Subscription(BaseModel):
|
||||
return count[self.interval] * self.interval_count
|
||||
|
||||
|
||||
|
||||
|
||||
class SubscriptionStatus(models.TextChoices):
|
||||
ACTIVE = "active", _("Active")
|
||||
EXPIRED = "expired", _("Expired")
|
||||
@@ -146,6 +166,17 @@ class PrincipalSubscription(BaseModel):
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.subscription} - {self.principal.first_name}"
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
# If the subscription status is expired or inactive, set the active flag to False
|
||||
if self.status in [SubscriptionStatus.EXPIRED, SubscriptionStatus.INACTIVE]:
|
||||
self.active = False
|
||||
|
||||
# If the active flag is False, set the status to inactive
|
||||
if not self.active:
|
||||
self.status = SubscriptionStatus.INACTIVE
|
||||
super.save(*args, **kwargs)
|
||||
|
||||
|
||||
def generate_order_id(email):
|
||||
return f"order_{str(timezone.localtime().timestamp())}{str(email)}"
|
||||
|
||||
@@ -12,6 +12,11 @@ urlpatterns = [
|
||||
views.SubscriptionCreateOrUpdateView.as_view(),
|
||||
name="subscription_add",
|
||||
),
|
||||
path(
|
||||
"subscription/edit/<int:pk>/",
|
||||
views.SubscriptionCreateOrUpdateView.as_view(),
|
||||
name="subscription_edit",
|
||||
),
|
||||
path("subscription/<int:pk>/", views.SubscriptionDetailView.as_view(), name="subscription_detail"),
|
||||
path(
|
||||
"subscription/delete/<int:pk>",
|
||||
|
||||
@@ -126,7 +126,7 @@ class SubscriptionView(LoginRequiredMixin, generic.ListView):
|
||||
queryset = (
|
||||
super()
|
||||
.get_queryset()
|
||||
.filter(deleted=False, active=True)
|
||||
.filter(deleted=False)
|
||||
.prefetch_related("principal_types")
|
||||
)
|
||||
return queryset.order_by("-created_on")
|
||||
|
||||
Reference in New Issue
Block a user