Merge branch 'feature/remove-address-model' into develop

This commit is contained in:
Nathan Chapman 2023-07-14 23:02:51 -06:00
commit 9108c7ea1a
28 changed files with 1392 additions and 1445 deletions

View File

@ -2,7 +2,7 @@ from django.contrib import admin
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin from django.contrib.auth.admin import UserAdmin
from .models import Address, User from .models import User
from .forms import AccountCreateForm, AccountUpdateForm from .forms import AccountCreateForm, AccountUpdateForm
class UserAdmin(UserAdmin): class UserAdmin(UserAdmin):
@ -12,5 +12,4 @@ class UserAdmin(UserAdmin):
list_display = ['email', 'username',] list_display = ['email', 'username',]
admin.site.register(Address)
admin.site.register(User, UserAdmin) admin.site.register(User, UserAdmin)

View File

@ -9,3 +9,4 @@ class AccountsConfig(AppConfig):
from .signals import ( from .signals import (
user_saved user_saved
) )

View File

@ -2,21 +2,7 @@ from django import forms
from django.contrib.auth.forms import UserCreationForm, UserChangeForm from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from allauth.account.forms import SignupForm from allauth.account.forms import SignupForm
from captcha.fields import CaptchaField from captcha.fields import CaptchaField
from .models import Address, User from .models import User
class AddressForm(forms.ModelForm):
class Meta:
model = Address
fields = (
'first_name',
'last_name',
'street_address_1',
'street_address_2',
'city',
'state',
'postal_code',
)
class AccountCreateForm(UserCreationForm): class AccountCreateForm(UserCreationForm):
@ -32,23 +18,26 @@ class AccountUpdateForm(UserChangeForm):
'first_name', 'first_name',
'last_name', 'last_name',
'email', 'email',
'default_shipping_address', 'shipping_street_address_1',
'addresses', 'shipping_street_address_2',
'shipping_city',
'shipping_state',
'shipping_postal_code',
) )
class CustomerUpdateForm(forms.ModelForm): class CustomerUpdateForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['default_shipping_address'].queryset = kwargs['instance'].addresses
class Meta: class Meta:
model = User model = User
fields = ( fields = (
'first_name', 'first_name',
'last_name', 'last_name',
'email', 'email',
'default_shipping_address', 'shipping_street_address_1',
'shipping_street_address_2',
'shipping_city',
'shipping_state',
'shipping_postal_code',
) )
@ -62,3 +51,4 @@ class UserSignupForm(SignupForm):
widget=forms.TextInput(attrs={'placeholder': 'Last name'}) widget=forms.TextInput(attrs={'placeholder': 'Last name'})
) )
captcha = CaptchaField() captcha = CaptchaField()

View File

@ -0,0 +1,38 @@
# Generated by Django 4.1.6 on 2023-07-15 02:46
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0002_address_accounts_address_all_key'),
]
operations = [
migrations.AddField(
model_name='user',
name='shipping_city',
field=models.CharField(blank=True, max_length=256),
),
migrations.AddField(
model_name='user',
name='shipping_postal_code',
field=models.CharField(blank=True, max_length=20),
),
migrations.AddField(
model_name='user',
name='shipping_state',
field=models.CharField(blank=True, choices=[('AL', 'Alabama'), ('AK', 'Alaska'), ('AS', 'American Samoa'), ('AZ', 'Arizona'), ('AR', 'Arkansas'), ('AA', 'Armed Forces Americas'), ('AE', 'Armed Forces Europe'), ('AP', 'Armed Forces Pacific'), ('CA', 'California'), ('CO', 'Colorado'), ('CT', 'Connecticut'), ('DE', 'Delaware'), ('DC', 'District of Columbia'), ('FM', 'Federated States of Micronesia'), ('FL', 'Florida'), ('GA', 'Georgia'), ('GU', 'Guam'), ('HI', 'Hawaii'), ('ID', 'Idaho'), ('IL', 'Illinois'), ('IN', 'Indiana'), ('IA', 'Iowa'), ('KS', 'Kansas'), ('KY', 'Kentucky'), ('LA', 'Louisiana'), ('ME', 'Maine'), ('MH', 'Marshall Islands'), ('MD', 'Maryland'), ('MA', 'Massachusetts'), ('MI', 'Michigan'), ('MN', 'Minnesota'), ('MS', 'Mississippi'), ('MO', 'Missouri'), ('MT', 'Montana'), ('NE', 'Nebraska'), ('NV', 'Nevada'), ('NH', 'New Hampshire'), ('NJ', 'New Jersey'), ('NM', 'New Mexico'), ('NY', 'New York'), ('NC', 'North Carolina'), ('ND', 'North Dakota'), ('MP', 'Northern Mariana Islands'), ('OH', 'Ohio'), ('OK', 'Oklahoma'), ('OR', 'Oregon'), ('PW', 'Palau'), ('PA', 'Pennsylvania'), ('PR', 'Puerto Rico'), ('RI', 'Rhode Island'), ('SC', 'South Carolina'), ('SD', 'South Dakota'), ('TN', 'Tennessee'), ('TX', 'Texas'), ('UT', 'Utah'), ('VT', 'Vermont'), ('VI', 'Virgin Islands'), ('VA', 'Virginia'), ('WA', 'Washington'), ('WV', 'West Virginia'), ('WI', 'Wisconsin'), ('WY', 'Wyoming')], max_length=2),
),
migrations.AddField(
model_name='user',
name='shipping_street_address_1',
field=models.CharField(blank=True, max_length=256),
),
migrations.AddField(
model_name='user',
name='shipping_street_address_2',
field=models.CharField(blank=True, max_length=256),
),
]

View File

@ -0,0 +1,27 @@
# Generated by Django 4.1.6 on 2023-07-15 02:56
from django.db import migrations
def copy_default_address_to_user(apps, schema_editor):
User = apps.get_model("accounts", "User")
for user in User.objects.all():
if user.default_shipping_address:
user.shipping_street_address_1 = user.default_shipping_address.street_address_1
user.shipping_street_address_2 = user.default_shipping_address.street_address_2
user.shipping_city = user.default_shipping_address.city
user.shipping_state = user.default_shipping_address.state
user.shipping_postal_code = user.default_shipping_address.postal_code
user.save()
class Migration(migrations.Migration):
dependencies = [
('accounts', '0003_user_shipping_city_user_shipping_postal_code_and_more'),
]
operations = [
migrations.RunPython(copy_default_address_to_user)
]

View File

@ -0,0 +1,29 @@
# Generated by Django 4.1.6 on 2023-07-15 03:27
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('core', '0008_remove_order_billing_address_and_more'),
('accounts', '0004_transfer_address_data_to_user_model'),
]
operations = [
migrations.RemoveField(
model_name='user',
name='addresses',
),
migrations.RemoveField(
model_name='user',
name='default_billing_address',
),
migrations.RemoveField(
model_name='user',
name='default_shipping_address',
),
migrations.DeleteModel(
name='Address',
),
]

View File

@ -5,76 +5,29 @@ from django.contrib.auth.models import AbstractUser
from localflavor.us.us_states import USPS_CHOICES from localflavor.us.us_states import USPS_CHOICES
class Address(models.Model): class User(AbstractUser):
first_name = models.CharField(max_length=256, blank=True) stripe_id = models.CharField(max_length=255, blank=True)
last_name = models.CharField(max_length=256, blank=True)
street_address_1 = models.CharField(max_length=256, blank=True) # Shipping address
street_address_2 = models.CharField(max_length=256, blank=True) shipping_street_address_1 = models.CharField(max_length=256, blank=True)
city = models.CharField(max_length=256, blank=True) shipping_street_address_2 = models.CharField(max_length=256, blank=True)
state = models.CharField( shipping_city = models.CharField(max_length=256, blank=True)
shipping_state = models.CharField(
max_length=2, max_length=2,
choices=USPS_CHOICES, choices=USPS_CHOICES,
blank=True blank=True
) )
postal_code = models.CharField(max_length=20, blank=True) shipping_postal_code = models.CharField(max_length=20, blank=True)
def as_stripe_dict(self): @property
return { def has_shipping_address(self):
'name': f'{self.first_name} {self.last_name}', if (self.shipping_street_address_1 != ''
'address': { and self.shipping_street_address_2 != ''
'line1': self.street_address_1, and self.shipping_city != ''
'line2': self.street_address_2, and self.shipping_state != ''
'city': self.city, and self.shipping_postal_code != ''):
'state': self.state, return True
'postal_code': self.postal_code return False
}
}
def __str__(self):
return f"""
{self.first_name} {self.last_name}
{self.street_address_1}
{self.street_address_2}
{self.city}, {self.state}, {self.postal_code}
"""
def __iter__(self):
yield ('address_line_1', self.street_address_1),
yield ('address_line_2', self.street_address_2),
yield ('admin_area_2', self.city),
yield ('admin_area_1', self.state),
yield ('postal_code', self.postal_code),
yield ('country_code', 'US')
class Meta:
constraints = [
models.UniqueConstraint(
name='accounts_address_all_key',
fields=[
'first_name',
'last_name',
'street_address_1',
'street_address_2',
'city',
'state',
'postal_code'
],
violation_error_message='Duplicate: Address already exists.'
)
]
class User(AbstractUser):
addresses = models.ManyToManyField(
Address, blank=True, related_name="user_addresses"
)
default_shipping_address = models.ForeignKey(
Address, related_name="+", null=True, blank=True, on_delete=models.SET_NULL
)
default_billing_address = models.ForeignKey(
Address, related_name="+", null=True, blank=True, on_delete=models.SET_NULL
)
stripe_id = models.CharField(max_length=255, blank=True)
def get_or_create_stripe_id(self): def get_or_create_stripe_id(self):
if not self.stripe_id: if not self.stripe_id:

View File

@ -5,7 +5,7 @@ from django.dispatch import receiver
from django.db import models from django.db import models
from django.conf import settings from django.conf import settings
from .models import Address, User from .models import User
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
stripe.api_key = settings.STRIPE_API_KEY stripe.api_key = settings.STRIPE_API_KEY
@ -16,3 +16,4 @@ def user_saved(sender, instance, created, **kwargs):
logger.info('User was saved') logger.info('User was saved')
if created or not instance.stripe_id: if created or not instance.stripe_id:
instance.get_or_create_stripe_id() instance.get_or_create_stripe_id()

View File

@ -1,26 +1,9 @@
from allauth.account.models import EmailAddress from .models import User
from .models import Address, User
from .tasks import send_account_created_email
def get_or_create_customer(request, shipping_address): def get_or_create_customer(request, shipping_address):
address, a_created = Address.objects.get_or_create(
first_name=shipping_address['first_name'],
last_name=shipping_address['last_name'],
street_address_1=shipping_address['street_address_1'],
street_address_2=shipping_address['street_address_2'],
city=shipping_address['city'],
state=shipping_address['state'],
postal_code=shipping_address['postal_code']
)
if request.user.is_authenticated: if request.user.is_authenticated:
user = request.user user = request.user
user.addresses.add(address)
if not user.default_shipping_address:
user.default_shipping_address = address
user.save()
else: else:
user, u_created = User.objects.get_or_create( user, u_created = User.objects.get_or_create(
email=shipping_address['email'].lower(), email=shipping_address['email'].lower(),
@ -29,27 +12,17 @@ def get_or_create_customer(request, shipping_address):
'is_staff': False, 'is_staff': False,
'is_active': True, 'is_active': True,
'is_superuser': False, 'is_superuser': False,
'first_name': address.first_name, 'first_name': shipping_address['first_name'],
'last_name': address.last_name, 'last_name': shipping_address['last_name'],
'default_shipping_address': address, 'shipping_street_address_1': shipping_address['street_address_1'],
'shipping_street_address_2': shipping_address['street_address_2'],
'shipping_city': shipping_address['city'],
'shipping_state': shipping_address['state'],
'shipping_postal_code': shipping_address['postal_code']
} }
) )
if u_created: if u_created:
password = User.objects.make_random_password() user.make_random_password()
user.set_password(password)
user.addresses.add(address)
user.save() user.save()
EmailAddress.objects.create( return user
user=user, email=user.email, primary=True, verified=False
)
u = {
'full_name': user.get_full_name(),
'email': user.email,
'password': password
}
send_account_created_email.delay(u)
return user, address

View File

@ -0,0 +1,63 @@
# Generated by Django 4.1.6 on 2023-07-15 02:46
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0003_rename_max_order_per_customer_productvariant_order_limit'),
]
operations = [
migrations.AddField(
model_name='order',
name='shipping_city',
field=models.CharField(blank=True, max_length=256),
),
migrations.AddField(
model_name='order',
name='shipping_postal_code',
field=models.CharField(blank=True, max_length=20),
),
migrations.AddField(
model_name='order',
name='shipping_state',
field=models.CharField(blank=True, choices=[('AL', 'Alabama'), ('AK', 'Alaska'), ('AS', 'American Samoa'), ('AZ', 'Arizona'), ('AR', 'Arkansas'), ('AA', 'Armed Forces Americas'), ('AE', 'Armed Forces Europe'), ('AP', 'Armed Forces Pacific'), ('CA', 'California'), ('CO', 'Colorado'), ('CT', 'Connecticut'), ('DE', 'Delaware'), ('DC', 'District of Columbia'), ('FM', 'Federated States of Micronesia'), ('FL', 'Florida'), ('GA', 'Georgia'), ('GU', 'Guam'), ('HI', 'Hawaii'), ('ID', 'Idaho'), ('IL', 'Illinois'), ('IN', 'Indiana'), ('IA', 'Iowa'), ('KS', 'Kansas'), ('KY', 'Kentucky'), ('LA', 'Louisiana'), ('ME', 'Maine'), ('MH', 'Marshall Islands'), ('MD', 'Maryland'), ('MA', 'Massachusetts'), ('MI', 'Michigan'), ('MN', 'Minnesota'), ('MS', 'Mississippi'), ('MO', 'Missouri'), ('MT', 'Montana'), ('NE', 'Nebraska'), ('NV', 'Nevada'), ('NH', 'New Hampshire'), ('NJ', 'New Jersey'), ('NM', 'New Mexico'), ('NY', 'New York'), ('NC', 'North Carolina'), ('ND', 'North Dakota'), ('MP', 'Northern Mariana Islands'), ('OH', 'Ohio'), ('OK', 'Oklahoma'), ('OR', 'Oregon'), ('PW', 'Palau'), ('PA', 'Pennsylvania'), ('PR', 'Puerto Rico'), ('RI', 'Rhode Island'), ('SC', 'South Carolina'), ('SD', 'South Dakota'), ('TN', 'Tennessee'), ('TX', 'Texas'), ('UT', 'Utah'), ('VT', 'Vermont'), ('VI', 'Virgin Islands'), ('VA', 'Virginia'), ('WA', 'Washington'), ('WV', 'West Virginia'), ('WI', 'Wisconsin'), ('WY', 'Wyoming')], max_length=2),
),
migrations.AddField(
model_name='order',
name='shipping_street_address_1',
field=models.CharField(blank=True, max_length=256),
),
migrations.AddField(
model_name='order',
name='shipping_street_address_2',
field=models.CharField(blank=True, max_length=256),
),
migrations.AddField(
model_name='subscription',
name='shipping_city',
field=models.CharField(blank=True, max_length=256),
),
migrations.AddField(
model_name='subscription',
name='shipping_postal_code',
field=models.CharField(blank=True, max_length=20),
),
migrations.AddField(
model_name='subscription',
name='shipping_state',
field=models.CharField(blank=True, choices=[('AL', 'Alabama'), ('AK', 'Alaska'), ('AS', 'American Samoa'), ('AZ', 'Arizona'), ('AR', 'Arkansas'), ('AA', 'Armed Forces Americas'), ('AE', 'Armed Forces Europe'), ('AP', 'Armed Forces Pacific'), ('CA', 'California'), ('CO', 'Colorado'), ('CT', 'Connecticut'), ('DE', 'Delaware'), ('DC', 'District of Columbia'), ('FM', 'Federated States of Micronesia'), ('FL', 'Florida'), ('GA', 'Georgia'), ('GU', 'Guam'), ('HI', 'Hawaii'), ('ID', 'Idaho'), ('IL', 'Illinois'), ('IN', 'Indiana'), ('IA', 'Iowa'), ('KS', 'Kansas'), ('KY', 'Kentucky'), ('LA', 'Louisiana'), ('ME', 'Maine'), ('MH', 'Marshall Islands'), ('MD', 'Maryland'), ('MA', 'Massachusetts'), ('MI', 'Michigan'), ('MN', 'Minnesota'), ('MS', 'Mississippi'), ('MO', 'Missouri'), ('MT', 'Montana'), ('NE', 'Nebraska'), ('NV', 'Nevada'), ('NH', 'New Hampshire'), ('NJ', 'New Jersey'), ('NM', 'New Mexico'), ('NY', 'New York'), ('NC', 'North Carolina'), ('ND', 'North Dakota'), ('MP', 'Northern Mariana Islands'), ('OH', 'Ohio'), ('OK', 'Oklahoma'), ('OR', 'Oregon'), ('PW', 'Palau'), ('PA', 'Pennsylvania'), ('PR', 'Puerto Rico'), ('RI', 'Rhode Island'), ('SC', 'South Carolina'), ('SD', 'South Dakota'), ('TN', 'Tennessee'), ('TX', 'Texas'), ('UT', 'Utah'), ('VT', 'Vermont'), ('VI', 'Virgin Islands'), ('VA', 'Virginia'), ('WA', 'Washington'), ('WV', 'West Virginia'), ('WI', 'Wisconsin'), ('WY', 'Wyoming')], max_length=2),
),
migrations.AddField(
model_name='subscription',
name='shipping_street_address_1',
field=models.CharField(blank=True, max_length=256),
),
migrations.AddField(
model_name='subscription',
name='shipping_street_address_2',
field=models.CharField(blank=True, max_length=256),
),
]

View File

@ -0,0 +1,41 @@
# Generated by Django 4.1.6 on 2023-07-15 02:59
from django.db import migrations
def copy_address_to_order(apps, schema_editor):
Order = apps.get_model("core", "Order")
for order in Order.objects.all():
if order.shipping_address:
order.shipping_street_address_1 = order.shipping_address.street_address_1
order.shipping_street_address_2 = order.shipping_address.street_address_2
order.shipping_city = order.shipping_address.city
order.shipping_state = order.shipping_address.state
order.shipping_postal_code = order.shipping_address.postal_code
order.save()
def copy_address_to_subscription(apps, schema_editor):
Subscription = apps.get_model("core", "Subscription")
for subscription in Subscription.objects.all():
if subscription.shipping_address:
subscription.shipping_street_address_1 = subscription.shipping_address.street_address_1
subscription.shipping_street_address_2 = subscription.shipping_address.street_address_2
subscription.shipping_city = subscription.shipping_address.city
subscription.shipping_state = subscription.shipping_address.state
subscription.shipping_postal_code = subscription.shipping_address.postal_code
subscription.save()
class Migration(migrations.Migration):
dependencies = [
('core', '0004_order_shipping_city_order_shipping_postal_code_and_more'),
]
operations = [
migrations.RunPython(copy_address_to_order),
migrations.RunPython(copy_address_to_subscription)
]

View File

@ -0,0 +1,33 @@
# Generated by Django 4.1.6 on 2023-07-15 03:20
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0005_transfer_address_data_to_order_and_subscription_models'),
]
operations = [
migrations.AddField(
model_name='order',
name='shipping_first_name',
field=models.CharField(blank=True, max_length=256),
),
migrations.AddField(
model_name='order',
name='shipping_last_name',
field=models.CharField(blank=True, max_length=256),
),
migrations.AddField(
model_name='subscription',
name='shipping_first_name',
field=models.CharField(blank=True, max_length=256),
),
migrations.AddField(
model_name='subscription',
name='shipping_last_name',
field=models.CharField(blank=True, max_length=256),
),
]

View File

@ -0,0 +1,35 @@
# Generated by Django 4.1.6 on 2023-07-15 03:20
from django.db import migrations
def copy_address_to_order(apps, schema_editor):
Order = apps.get_model("core", "Order")
for order in Order.objects.all():
if order.shipping_address:
order.shipping_first_name = order.shipping_address.first_name
order.shipping_last_name = order.shipping_address.last_name
order.save()
def copy_address_to_subscription(apps, schema_editor):
Subscription = apps.get_model("core", "Subscription")
for subscription in Subscription.objects.all():
if subscription.shipping_address:
subscription.shipping_first_name = subscription.shipping_address.first_name
subscription.shipping_last_name = subscription.shipping_address.last_name
subscription.save()
class Migration(migrations.Migration):
dependencies = [
('core', '0006_order_shipping_first_name_order_shipping_last_name_and_more'),
]
operations = [
migrations.RunPython(copy_address_to_order),
migrations.RunPython(copy_address_to_subscription)
]

View File

@ -0,0 +1,25 @@
# Generated by Django 4.1.6 on 2023-07-15 03:27
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('core', '0007_transfer_address_first_and_last_names_to_order_and_subscriptions'),
]
operations = [
migrations.RemoveField(
model_name='order',
name='billing_address',
),
migrations.RemoveField(
model_name='order',
name='shipping_address',
),
migrations.RemoveField(
model_name='subscription',
name='shipping_address',
),
]

View File

@ -16,8 +16,9 @@ from django.contrib.postgres.fields import ArrayField, HStoreField
from django.forms.models import model_to_dict from django.forms.models import model_to_dict
from django_measurement.models import MeasurementField from django_measurement.models import MeasurementField
from localflavor.us.us_states import USPS_CHOICES
from accounts.models import User, Address from accounts.models import User
from . import ( from . import (
DiscountValueType, DiscountValueType,
@ -337,20 +338,18 @@ class Order(models.Model):
default=OrderStatus.UNFULFILLED, default=OrderStatus.UNFULFILLED,
choices=OrderStatus.CHOICES choices=OrderStatus.CHOICES
) )
billing_address = models.ForeignKey( # Shipping address
Address, shipping_first_name = models.CharField(max_length=256, blank=True)
related_name="+", shipping_last_name = models.CharField(max_length=256, blank=True)
editable=False, shipping_street_address_1 = models.CharField(max_length=256, blank=True)
null=True, shipping_street_address_2 = models.CharField(max_length=256, blank=True)
on_delete=models.SET_NULL shipping_city = models.CharField(max_length=256, blank=True)
) shipping_state = models.CharField(
shipping_address = models.ForeignKey( max_length=2,
Address, choices=USPS_CHOICES,
related_name="+", blank=True
editable=False,
null=True,
on_delete=models.SET_NULL
) )
shipping_postal_code = models.CharField(max_length=20, blank=True)
coupon = models.ForeignKey( coupon = models.ForeignKey(
Coupon, Coupon,
related_name='orders', related_name='orders',
@ -544,13 +543,18 @@ class Subscription(models.Model):
on_delete=models.SET_NULL, on_delete=models.SET_NULL,
null=True null=True
) )
shipping_address = models.ForeignKey( # Shipping address
Address, shipping_first_name = models.CharField(max_length=256, blank=True)
related_name='+', shipping_last_name = models.CharField(max_length=256, blank=True)
editable=False, shipping_street_address_1 = models.CharField(max_length=256, blank=True)
null=True, shipping_street_address_2 = models.CharField(max_length=256, blank=True)
on_delete=models.SET_NULL shipping_city = models.CharField(max_length=256, blank=True)
shipping_state = models.CharField(
max_length=2,
choices=USPS_CHOICES,
blank=True
) )
shipping_postal_code = models.CharField(max_length=20, blank=True)
items = ArrayField( items = ArrayField(
models.JSONField(blank=True, null=True), models.JSONField(blank=True, null=True),
default=list default=list

View File

@ -53,13 +53,13 @@ def transaction_created(sender, instance, created, **kwargs):
'shipping_total': str(instance.order.shipping_total), 'shipping_total': str(instance.order.shipping_total),
'total_amount': str(instance.order.total_amount), 'total_amount': str(instance.order.total_amount),
'shipping_address': { 'shipping_address': {
'first_name': instance.order.shipping_address.first_name, 'first_name': instance.order.shipping_first_name,
'last_name': instance.order.shipping_address.last_name, 'last_name': instance.order.shipping_last_name,
'street_address_1': instance.order.shipping_address.street_address_1, 'street_address_1': instance.order.shipping_street_address_1,
'street_address_2': instance.order.shipping_address.street_address_2, 'street_address_2': instance.order.shipping_street_address_2,
'city': instance.order.shipping_address.city, 'city': instance.order.shipping_city,
'state': instance.order.shipping_address.state, 'state': instance.order.shipping_state,
'postal_code': instance.order.shipping_address.postal_code 'postal_code': instance.order.shipping_postal_code
}, },
'line_items': list( 'line_items': list(
format_order_lines(instance.order.lines.all()) format_order_lines(instance.order.lines.all())

View File

@ -26,18 +26,11 @@
<dt>Default shipping address</dt> <dt>Default shipping address</dt>
<dd> <dd>
{% include 'dashboard/partials/_address.html' with address=customer.default_shipping_address %} {% include 'dashboard/partials/_address.html' with address=customer %}
</dd>
<dt>All addresses</dt>
<dd>
{% for address in customer.addresses.all %}
{% include 'dashboard/partials/_address.html' with address=address %}
{% endfor %}
</dd> </dd>
</dl> </dl>
</section> </section>
<section class="panel"> <section class="panel">
<header class="panel-header"> <header class="panel-header">
<h4>Orders</h4> <h4>Orders</h4>

View File

@ -133,7 +133,7 @@
<div class="panel-section panel-shipping"> <div class="panel-section panel-shipping">
<div> <div>
<strong>Shipping address</strong> <strong>Shipping address</strong>
{% include 'dashboard/partials/_address.html' with address=order.shipping_address %} {% include 'dashboard/partials/_address.html' with address=order %}
</div> </div>
<table> <table>
<thead> <thead>

View File

@ -17,7 +17,7 @@
</header> </header>
<div class="panel-section"> <div class="panel-section">
<strong>Shipping address</strong> <strong>Shipping address</strong>
{% include 'dashboard/partials/_address.html' with address=order.shipping_address %} {% include 'dashboard/partials/_address.html' with address=order %}
</div> </div>
<form method="POST"> <form method="POST">
{% csrf_token %} {% csrf_token %}

View File

@ -1,9 +1,7 @@
<address> <address>
{{address.first_name}} {{address.shipping_street_address_1}}<br>
{{address.last_name}}<br> {% if address.shipping_street_address_2 %}
{{address.street_address_1}}<br> {{address.shipping_street_address_2}}<br>
{% if address.street_address_2 %}
{{address.street_address_2}}<br>
{% endif %} {% endif %}
{{address.city}}, {{address.state}}, {{address.postal_code}} {{address.shipping_city}}, {{address.shipping_state}}, {{address.shipping_postal_code}}
</address> </address>

View File

@ -31,7 +31,6 @@ from django.db.models.functions import Coalesce
from accounts.models import User from accounts.models import User
from accounts.utils import get_or_create_customer from accounts.utils import get_or_create_customer
from accounts.forms import AddressForm
from core.models import ( from core.models import (
ProductCategory, ProductCategory,
Product, Product,
@ -259,8 +258,6 @@ class OrderDetailView(LoginRequiredMixin, DetailView):
self.kwargs.get(self.pk_url_kwarg) self.kwargs.get(self.pk_url_kwarg)
).select_related( ).select_related(
'customer', 'customer',
'billing_address',
'shipping_address'
).prefetch_related( ).prefetch_related(
'lines__variant__product__productphoto_set' 'lines__variant__product__productphoto_set'
) )
@ -717,9 +714,11 @@ class CustomerUpdateView(
'first_name', 'first_name',
'last_name', 'last_name',
'email', 'email',
'is_staff', 'shipping_street_address_1',
'addresses', 'shipping_street_address_2',
'default_shipping_address' 'shipping_city',
'shipping_state',
'shipping_postal_code',
) )
def get_success_url(self): def get_success_url(self):

View File

@ -25,7 +25,7 @@ services:
- redis - redis
web: web:
build: . build: .
command: sh -c "python manage.py migrate && python manage.py collectstatic --no-input && gunicorn --bind :8000 --reload ptcoffee.wsgi:application" command: gunicorn --bind :8000 --reload ptcoffee.wsgi:application
volumes: volumes:
- .:/app - .:/app
- ./static/:/var/www/static - ./static/:/var/www/static

2109
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -72,10 +72,7 @@ INSTALLED_APPS = [
# 3rd Party # 3rd Party
'django_filters', 'django_filters',
'storages',
'localflavor', 'localflavor',
'django_celery_beat',
'django_celery_results',
'anymail', 'anymail',
'compressor', 'compressor',
'allauth', 'allauth',

View File

@ -11,12 +11,9 @@ django = "^4.1.5"
celery = {extras = ["redis"], version = "^5.2.7"} celery = {extras = ["redis"], version = "^5.2.7"}
django-allauth = "^0.52.0" django-allauth = "^0.52.0"
django-anymail = {extras = ["mailgun"], version = "^9.0"} django-anymail = {extras = ["mailgun"], version = "^9.0"}
django-celery-beat = "^2.4.0"
django-celery-results = "^2.4.0"
django-compressor = "^4.1" django-compressor = "^4.1"
django-filter = "^22.1" django-filter = "^22.1"
django-measurement = "^3.2.4" django-measurement = "^3.2.4"
django-storages = "^1.13.2"
django-templated-email = "^3.0.1" django-templated-email = "^3.0.1"
paypal-checkout-serversdk = "^1.0.1" paypal-checkout-serversdk = "^1.0.1"
pillow = "^9.4.0" pillow = "^9.4.0"

View File

@ -18,45 +18,17 @@
<a href="{% url 'account_email' %}">Manage</a> <a href="{% url 'account_email' %}">Manage</a>
</div> </div>
<div> <div>
<strong>Default shipping address</strong> <strong>Shipping address</strong>
{% with shipping_address=customer.default_shipping_address %} <address>
<address> {{customer.shipping_street_address_1}}<br>
{{shipping_address.first_name}} {% if shipping_street_address_2 %}
{{shipping_address.last_name}}<br> {{customer.shipping_street_address_2}}<br>
{{shipping_address.street_address_1}}<br> {% endif %}
{% if shipping_address.street_address_2 %} {{customer.shipping_city}}, {{customer.shipping_state}}, {{customer.shipping_postal_code}}
{{shipping_address.street_address_2}}<br> </address>
{% endif %}
{{shipping_address.city}}, {{shipping_address.state}}, {{shipping_address.postal_code}}
</address>
{% endwith %}
</div> </div>
</div> </div>
</section> </section>
<section>
<h4>Your addresses</h4>
<p>
<a href="{% url 'storefront:customer-address-create' user.pk %}" class="btn">+ New address</a>
</p>
<div>
{% for address in customer.addresses.all %}
<p>
<address>
{{address.first_name}}
{{address.last_name}}<br>
{{address.street_address_1}}<br>
{% if address.street_address_2 %}
{{address.street_address_2}}<br>
{% endif %}
{{address.city}}, {{address.state}}, {{address.postal_code}}
</address>
<a href="{% url 'storefront:address-update' customer.pk address.pk %}">Edit</a>
</p>
{% empty %}
<p>No other addresses.</p>
{% endfor %}
</div>
</section>
{% if customer.subscriptions.count > 0 %} {% if customer.subscriptions.count > 0 %}
<section> <section>
<h3>Your subscriptions</h3> <h3>Your subscriptions</h3>

View File

@ -89,26 +89,11 @@ urlpatterns = [
views.CustomerUpdateView.as_view(), views.CustomerUpdateView.as_view(),
name='customer-update', name='customer-update',
), ),
# path(
# 'delete/',
# views.CustomerDeleteView.as_view(),
# name='customer-delete'
# ),
path( path(
'orders/<int:order_pk>/', 'orders/<int:order_pk>/',
views.OrderDetailView.as_view(), views.OrderDetailView.as_view(),
name='order-detail', name='order-detail',
), ),
path(
'addresses/new/',
views.CustomerAddressCreateView.as_view(),
name='customer-address-create',
),
path(
'addresses/<int:address_pk>/update/',
views.CustomerAddressUpdateView.as_view(),
name='address-update',
)
])), ])),
path( path(

View File

@ -34,11 +34,9 @@ from paypalcheckoutsdk.orders import OrdersCreateRequest, OrdersCaptureRequest
from paypalcheckoutsdk.core import PayPalHttpClient, SandboxEnvironment from paypalcheckoutsdk.core import PayPalHttpClient, SandboxEnvironment
from moneyed import Money, USD from moneyed import Money, USD
from accounts.models import User, Address from accounts.models import User
from accounts.utils import get_or_create_customer from accounts.utils import get_or_create_customer
from accounts.forms import ( from accounts.forms import CustomerUpdateForm
AddressForm as AccountAddressForm, CustomerUpdateForm
)
from core.models import ( from core.models import (
ProductCategory, Product, ProductVariant, ProductOption, ProductCategory, Product, ProductVariant, ProductOption,
Order, Transaction, OrderLine, Coupon, ShippingRate, Order, Transaction, OrderLine, Coupon, ShippingRate,
@ -252,16 +250,15 @@ class CheckoutAddressView(FormView):
def get_initial(self): def get_initial(self):
user = self.request.user user = self.request.user
initial = None initial = None
if user.is_authenticated and user.default_shipping_address: if user.is_authenticated:
address = user.default_shipping_address
initial = { initial = {
'full_name': address.first_name + ' ' + address.last_name, 'full_name': user.first_name + ' ' + user.last_name,
'email': user.email, 'email': user.email,
'street_address_1': address.street_address_1, 'street_address_1': user.shipping_street_address_1,
'street_address_2': address.street_address_2, 'street_address_2': user.shipping_street_address_2,
'city': address.city, 'city': user.shipping_city,
'state': address.state, 'state': user.shipping_state,
'postal_code': address.postal_code 'postal_code': user.shipping_postal_code
} }
elif self.request.session.get('shipping_address'): elif self.request.session.get('shipping_address'):
address = self.request.session.get('shipping_address') address = self.request.session.get('shipping_address')
@ -413,7 +410,14 @@ class OrderCreateView(CreateView):
shipping_container = cart.get_shipping_container() shipping_container = cart.get_shipping_container()
form.instance.shipping_total = cart.get_shipping_price(shipping_container) form.instance.shipping_total = cart.get_shipping_price(shipping_container)
shipping_address = self.request.session.get('shipping_address') shipping_address = self.request.session.get('shipping_address')
form.instance.customer, form.instance.shipping_address = get_or_create_customer(self.request, shipping_address) form.instance.shipping_first_name = shipping_address['first_name']
form.instance.shipping_last_name = shipping_address['last_name']
form.instance.shipping_street_address_1 = shipping_address['street_address_1']
form.instance.shipping_street_address_2 = shipping_address['street_address_2']
form.instance.shipping_city = shipping_address['city']
form.instance.shipping_state = shipping_address['state']
form.instance.shipping_postal_code = shipping_address['postal_code']
form.instance.customer = get_or_create_customer(self.request, shipping_address)
form.instance.status = OrderStatus.DRAFT form.instance.status = OrderStatus.DRAFT
self.object = form.save() self.object = form.save()
bulk_list = cart.build_bulk_list(self.object) bulk_list = cart.build_bulk_list(self.object)
@ -443,7 +447,14 @@ class FreeOrderCreateView(CreateView):
shipping_container = cart.get_shipping_container() shipping_container = cart.get_shipping_container()
form.instance.shipping_total = cart.get_shipping_price(shipping_container) form.instance.shipping_total = cart.get_shipping_price(shipping_container)
shipping_address = self.request.session.get('shipping_address') shipping_address = self.request.session.get('shipping_address')
form.instance.customer, form.instance.shipping_address = get_or_create_customer(self.request, shipping_address) form.instance.shipping_first_name = shipping_address['first_name']
form.instance.shipping_last_name = shipping_address['last_name']
form.instance.shipping_street_address_1 = shipping_address['street_address_1']
form.instance.shipping_street_address_2 = shipping_address['street_address_2']
form.instance.shipping_city = shipping_address['city']
form.instance.shipping_state = shipping_address['state']
form.instance.shipping_postal_code = shipping_address['postal_code']
form.instance.customer = get_or_create_customer(self.request, shipping_address)
form.instance.status = OrderStatus.UNFULFILLED form.instance.status = OrderStatus.UNFULFILLED
self.object = form.save() self.object = form.save()
bulk_list = cart.build_bulk_list(self.object) bulk_list = cart.build_bulk_list(self.object)
@ -562,58 +573,6 @@ class OrderDetailView(UserPassesTestMixin, LoginRequiredMixin, DetailView):
return context return context
class CustomerAddressCreateView(
UserPassesTestMixin, LoginRequiredMixin, CreateView
):
model = Address
template_name = 'storefront/address_create_form.html'
form_class = AccountAddressForm
permission_denied_message = 'Not authorized.'
raise_exception = True
def test_func(self):
return self.request.user.pk == self.kwargs['pk']
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['customer'] = User.objects.get(pk=self.kwargs['pk'])
return context
def form_valid(self, form):
customer = User.objects.get(pk=self.kwargs['pk'])
self.object = form.save()
customer.addresses.add(self.object)
return super().form_valid(form)
def get_success_url(self):
return reverse(
'storefront:customer-detail', kwargs={'pk': self.kwargs['pk']}
)
class CustomerAddressUpdateView(
UserPassesTestMixin, LoginRequiredMixin, UpdateView
):
model = Address
pk_url_kwarg = 'address_pk'
template_name = 'storefront/address_form.html'
form_class = AccountAddressForm
permission_denied_message = 'Not authorized.'
raise_exception = True
def test_func(self):
return self.request.user.pk == self.kwargs['pk']
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['customer'] = User.objects.get(pk=self.kwargs['pk'])
return context
def get_success_url(self):
return reverse('storefront:customer-detail', kwargs={'pk': self.kwargs['pk']})
class AboutView(TemplateView): class AboutView(TemplateView):
template_name = 'storefront/about.html' template_name = 'storefront/about.html'
@ -754,7 +713,7 @@ class SubscriptionCreateView(SuccessMessageMixin, CreateView):
).get('recurring') ).get('recurring')
shipping_cost = get_shipping_cost( shipping_cost = get_shipping_cost(
self.object.total_weight, self.object.total_weight,
self.object.shipping_address.postal_code self.object.shipping_postal_code
) * 100 ) * 100
line_items.append({ line_items.append({
'price_data': { 'price_data': {
@ -789,7 +748,16 @@ class SubscriptionCreateView(SuccessMessageMixin, CreateView):
def form_valid(self, form): def form_valid(self, form):
shipping_address = self.request.session.get('shipping_address') shipping_address = self.request.session.get('shipping_address')
subscription = self.request.session.get('subscription') subscription = self.request.session.get('subscription')
form.instance.customer, form.instance.shipping_address = get_or_create_customer(self.request, shipping_address) form.instance.shipping_first_name = shipping_address['first_name']
form.instance.shipping_last_name = shipping_address['last_name']
form.instance.shipping_street_address_1 = shipping_address['street_address_1']
form.instance.shipping_street_address_2 = shipping_address['street_address_2']
form.instance.shipping_city = shipping_address['city']
form.instance.shipping_state = shipping_address['state']
form.instance.shipping_postal_code = shipping_address['postal_code']
form.instance.customer = get_or_create_customer(
self.request, shipping_address
)
weight, unit = subscription['metadata']['total_weight'].split(':') weight, unit = subscription['metadata']['total_weight'].split(':')
form.instance.total_weight = guess( form.instance.total_weight = guess(
float(weight), unit, measures=[Weight] float(weight), unit, measures=[Weight]
@ -855,3 +823,4 @@ def stripe_webhook(request):
subscription.create_order(event.data.object) subscription.create_order(event.data.object)
return JsonResponse({'status': 'success'}) return JsonResponse({'status': 'success'})