updated subscription 2
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
# Generated by Django 5.0.2 on 2024-03-18 11:46
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("accounts", "0003_iamprincipal_player_id"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="iamprincipallocation",
|
||||
name="latitude",
|
||||
field=models.DecimalField(decimal_places=15, max_digits=18),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="iamprincipallocation",
|
||||
name="longitude",
|
||||
field=models.DecimalField(decimal_places=15, max_digits=18),
|
||||
),
|
||||
]
|
||||
@@ -371,8 +371,8 @@ class IAmPrincipalLocation(BaseModel):
|
||||
principal = models.ForeignKey(
|
||||
IAmPrincipal, related_name="principal_location", on_delete=models.CASCADE
|
||||
)
|
||||
latitude = models.DecimalField(max_digits=14, decimal_places=8)
|
||||
longitude = models.DecimalField(max_digits=14, decimal_places=8)
|
||||
latitude = models.DecimalField(max_digits=18, decimal_places=15)
|
||||
longitude = models.DecimalField(max_digits=18, decimal_places=15)
|
||||
|
||||
class Meta:
|
||||
db_table = "iam_principal_location"
|
||||
|
||||
@@ -332,6 +332,7 @@ CRONJOBS = [
|
||||
]
|
||||
|
||||
GOOGLE_MAPS_API_KEY = env.str("GOOGLE_MAPS_API_KEY")
|
||||
|
||||
PLACES_MAPS_API_KEY = env.str("GOOGLE_MAPS_API_KEY")
|
||||
PLACES_MAP_WIDGET_HEIGHT = 480
|
||||
PLACES_MAP_OPTIONS = '{"center": { "lat": 38.971584, "lng": -95.235072 }, "zoom": 10}'
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from rest_framework import serializers
|
||||
from accounts.models import IAmPrincipalLocation
|
||||
from manage_events.utils import get_location_info
|
||||
from accounts.api.serializers import ProfileSerializer
|
||||
from manage_events.models import (
|
||||
EventMaster,
|
||||
@@ -167,6 +168,26 @@ class IAmPrincipalLocationSerializer(serializers.ModelSerializer):
|
||||
|
||||
def create(self, validated_data):
|
||||
principal = self.context["request"].user
|
||||
latitude = validated_data.get("latitude")
|
||||
longitude = validated_data.get("longitude")
|
||||
location = get_location_info(latitude=latitude, longitude=longitude)
|
||||
print("location: ", location)
|
||||
city = location.get("city")
|
||||
state = location.get("state")
|
||||
country = location.get("country")
|
||||
country_code = location.get("country_code")
|
||||
|
||||
if hasattr(principal, "city"):
|
||||
principal.city = city or state # Use state as city if city is not found
|
||||
if hasattr(principal, "state"):
|
||||
principal.state = state
|
||||
if hasattr(principal, "country"):
|
||||
principal.country = country
|
||||
if hasattr(principal, "address_line1"):
|
||||
principal.address_line1 = country_code
|
||||
|
||||
# save the principal object after making changes
|
||||
principal.save()
|
||||
return IAmPrincipalLocation.objects.create(
|
||||
principal=principal, **validated_data
|
||||
)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import math
|
||||
from accounts.models import IAmPrincipalLocation
|
||||
from manage_events.models import Event, Venue
|
||||
from django.utils.timezone import now
|
||||
import googlemaps
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
def haversine(lon1, lat1, lon2, lat2):
|
||||
@@ -68,5 +70,37 @@ def haversine_one(lon1, lat1, lon2, lat2):
|
||||
return R * c
|
||||
|
||||
|
||||
# Example usage:
|
||||
API_KEY = settings.GOOGLE_MAPS_API_KEY
|
||||
gmaps = googlemaps.Client(key=API_KEY)
|
||||
|
||||
|
||||
def get_location_info(latitude, longitude):
|
||||
reverse_geocode_result = gmaps.reverse_geocode((latitude, longitude))
|
||||
|
||||
if reverse_geocode_result:
|
||||
location = reverse_geocode_result[0]
|
||||
city = None
|
||||
state = None
|
||||
country = None
|
||||
|
||||
for component in location.get("address_components", []):
|
||||
types = component.get("types", [])
|
||||
print("types: ", types)
|
||||
if "locality" in types:
|
||||
city = component.get("long_name")
|
||||
elif "administrative_area_level_1" in types:
|
||||
state = component.get("long_name")
|
||||
elif "country" in types:
|
||||
country = component.get("long_name")
|
||||
country_code = component.get("short_name")
|
||||
|
||||
if city is None and state is not None:
|
||||
city = state
|
||||
return {
|
||||
"city": city,
|
||||
"state": state,
|
||||
"country": country,
|
||||
"country_code": country_code,
|
||||
}
|
||||
else:
|
||||
return {}
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
from django.utils.timezone import now
|
||||
|
||||
import googlemaps
|
||||
from manage_subscriptions.models import PrincipalSubscription, SubscriptionStatus
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
API_KEY = settings.GOOGLE_MAPS_API_KEY
|
||||
gmaps = googlemaps.Client(key=API_KEY)
|
||||
|
||||
|
||||
def get_active_subscription_id_for_principal(principal):
|
||||
@@ -8,7 +13,10 @@ def get_active_subscription_id_for_principal(principal):
|
||||
active_subscriptions = PrincipalSubscription.objects.filter(
|
||||
principal=principal,
|
||||
status=SubscriptionStatus.ACTIVE,
|
||||
is_paid=True,
|
||||
cancelled=False,
|
||||
deleted=False,
|
||||
active=True,
|
||||
end_date__gte=now().date(), # Ensure the subscription hasn't expired
|
||||
).order_by(
|
||||
"-end_date"
|
||||
@@ -18,3 +26,27 @@ def get_active_subscription_id_for_principal(principal):
|
||||
# Return the ID of the most recent active subscription
|
||||
return active_subscriptions.first().id
|
||||
return None
|
||||
|
||||
|
||||
def get_location_info(latitude, longitude):
|
||||
reverse_geocode_result = gmaps.reverse_geocode((latitude, longitude))
|
||||
|
||||
if reverse_geocode_result:
|
||||
location = reverse_geocode_result[0]
|
||||
city = None
|
||||
state = None
|
||||
country = None
|
||||
|
||||
for component in location.get("address_components", []):
|
||||
types = component.get("types", [])
|
||||
print("types: ", types)
|
||||
if "locality" in types:
|
||||
city = component.get("long_name")
|
||||
elif "administrative_area_level_1" in types:
|
||||
state = component.get("long_name")
|
||||
elif "country" in types:
|
||||
country = component.get("long_name")
|
||||
|
||||
return {"city": city, "state": state, "country": country}
|
||||
else:
|
||||
return {}
|
||||
|
||||
@@ -438,23 +438,23 @@ def create_checkout_session(request):
|
||||
)
|
||||
|
||||
try:
|
||||
customer = stripe.Customer.create(
|
||||
email=request.user.email,
|
||||
shipping={
|
||||
"name": request.user.first_name,
|
||||
"address": {
|
||||
"line1": "Test Address",
|
||||
"city": "Test City",
|
||||
"postal_code": "SW1A 2AA",
|
||||
"country": "GB", # Adjust accordingly
|
||||
},
|
||||
},
|
||||
)
|
||||
# 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
|
||||
# customer=customer.id, # Optional: Link the session to the Stripe customer created above
|
||||
line_items=[
|
||||
{
|
||||
"price_data": {
|
||||
|
||||
@@ -259,6 +259,63 @@ header nav ul li a:hover:after {
|
||||
color: var(--white-other);
|
||||
}
|
||||
|
||||
.plan-box {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.your-plan {
|
||||
width: 280px;
|
||||
height: 100%;
|
||||
background-color: white;
|
||||
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
|
||||
border-radius: 8px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.your-plans-main {
|
||||
padding: 15px 20px 30px;
|
||||
}
|
||||
|
||||
.your-plans-main .head {
|
||||
font-size: 25px;
|
||||
color: black;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.your-plans-main .monthly-div-main {
|
||||
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
|
||||
padding: 15px 20px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.your-plans-main .monthly-div-main .monthly-div {
|
||||
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
|
||||
padding: 6px 10px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid rgb(215 169 72 / 28%);
|
||||
}
|
||||
|
||||
.your-plans-main .your-heading {
|
||||
color: var(--main-yellow);
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.your-plans-main .your-subheading {
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.your-plans-main .your-subheading span {
|
||||
font-size: 18px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.your-plans-btn {
|
||||
text-align: center;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.baner-btn {
|
||||
margin-top: 24px;
|
||||
@@ -588,8 +645,17 @@ div#accordionExample {
|
||||
}
|
||||
|
||||
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.plan-box {
|
||||
display: block;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.baner-btn {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ptb {
|
||||
padding: 20px 0 40px 0;
|
||||
}
|
||||
|
||||
@@ -71,8 +71,26 @@
|
||||
</div>
|
||||
|
||||
<div class="baner-btn">
|
||||
<button class="common-btn" id="submitBtn">Join now</button>
|
||||
<button class="common-btn" id="popup-payment">Join now</button>
|
||||
</div>
|
||||
<div class="plan-box">
|
||||
<div class="your-plan">
|
||||
<div class="your-plans-main">
|
||||
<p class="head">Your Plans</p>
|
||||
<div class="monthly-div-main">
|
||||
<div class="monthly-div">
|
||||
<p class="your-heading">Monthly</p>
|
||||
<p class="your-subheading">$5.55 /<span> month</span></p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="your-plans-btn">
|
||||
<button class="common-btn" id="submitBtn">Join now</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
@@ -251,15 +269,15 @@
|
||||
<div class="accordion-body">
|
||||
<strong>This is the second item's accordion
|
||||
body.</strong> It is hidden by default,
|
||||
until the collapse plugin adds the
|
||||
appropriate classes that we use to style
|
||||
each element. These classes control the
|
||||
overall appearance, as well as the showing
|
||||
and hiding via CSS transitions. You can
|
||||
modify any of this with custom CSS or
|
||||
overriding our default variables. It's also
|
||||
worth noting that just about any HTML can go
|
||||
within the transition does limit overflow.
|
||||
until the collapse plugin adds the
|
||||
appropriate classes that we use to style
|
||||
each element. These classes control the
|
||||
overall appearance, as well as the showing
|
||||
and hiding via CSS transitions. You can
|
||||
modify any of this with custom CSS or
|
||||
overriding our default variables. It's also
|
||||
worth noting that just about any HTML can go
|
||||
within the transition does limit overflow.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -275,15 +293,15 @@
|
||||
<div class="accordion-body">
|
||||
<strong>This is the third item's accordion
|
||||
body.</strong> It is hidden by default,
|
||||
until the collapse plugin adds the
|
||||
appropriate classes that we use to style
|
||||
each element. These classes control the
|
||||
overall appearance, as well as the showing
|
||||
and hiding via CSS transitions. You can
|
||||
modify any of this with custom CSS or
|
||||
overriding our default variables. It's also
|
||||
worth noting that just about any HTML can go
|
||||
within the transition does limit overflow.
|
||||
until the collapse plugin adds the
|
||||
appropriate classes that we use to style
|
||||
each element. These classes control the
|
||||
overall appearance, as well as the showing
|
||||
and hiding via CSS transitions. You can
|
||||
modify any of this with custom CSS or
|
||||
overriding our default variables. It's also
|
||||
worth noting that just about any HTML can go
|
||||
within the transition does limit overflow.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -299,15 +317,15 @@
|
||||
<div class="accordion-body">
|
||||
<strong>This is the third item's accordion
|
||||
body.</strong> It is hidden by default,
|
||||
until the collapse plugin adds the
|
||||
appropriate classes that we use to style
|
||||
each element. These classes control the
|
||||
overall appearance, as well as the showing
|
||||
and hiding via CSS transitions. You can
|
||||
modify any of this with custom CSS or
|
||||
overriding our default variables. It's also
|
||||
worth noting that just about any HTML can go
|
||||
within the transition does limit overflow.
|
||||
until the collapse plugin adds the
|
||||
appropriate classes that we use to style
|
||||
each element. These classes control the
|
||||
overall appearance, as well as the showing
|
||||
and hiding via CSS transitions. You can
|
||||
modify any of this with custom CSS or
|
||||
overriding our default variables. It's also
|
||||
worth noting that just about any HTML can go
|
||||
within the transition does limit overflow.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user