feat: added customer addresses and shipping method

This commit is contained in:
2024-12-23 13:27:00 +01:00
parent b2f8febdb6
commit a1f6983148
7 changed files with 279 additions and 426 deletions
+27
View File
@@ -13,6 +13,8 @@ from shop.models import (
Provider,
Tag,
Tax,
ShippingMethod,
CustomerAddress,
)
@@ -115,3 +117,28 @@ class ProductBatchAdmin(ModelAdmin):
"product",
"quantity",
)
@admin.register(ShippingMethod)
class ShippingMethodAdmin(ModelAdmin):
list_display = (
"id",
"name",
"description",
)
@admin.register(CustomerAddress)
class CustomerAddressAdmin(ModelAdmin):
list_display = (
"id",
"user",
"vat_id",
"address",
"address_state",
"address_zip",
)
def get_queryset(self, request):
qs = super().get_queryset(request)
return qs.filter(hidden=False)
+63 -2
View File
@@ -1,4 +1,4 @@
# Generated by Django 5.1.3 on 2024-12-07 10:15
# Generated by Django 5.1.3 on 2024-12-23 12:01
import django.db.models.deletion
import django.utils.timezone
@@ -233,6 +233,10 @@ class Migration(migrations.Migration):
verbose_name="número de identificación fiscal",
),
),
(
"full_name",
models.CharField(max_length=128, verbose_name="dirección"),
),
("address", models.CharField(max_length=128, verbose_name="dirección")),
(
"address_town",
@@ -271,10 +275,20 @@ class Migration(migrations.Migration):
verbose_name="tipo de dirección",
),
),
("default", models.BooleanField(default=True)),
(
"default",
models.BooleanField(default=True, verbose_name="por defecto"),
),
(
"hidden",
models.BooleanField(
db_index=True, default=False, verbose_name="oculto"
),
),
(
"user",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
to=settings.AUTH_USER_MODEL,
verbose_name="usuario",
@@ -471,6 +485,12 @@ class Migration(migrations.Migration):
verbose_name="Slug",
),
),
(
"hidden",
models.BooleanField(
db_index=True, default=False, verbose_name="oculto"
),
),
(
"brand",
models.ForeignKey(
@@ -697,6 +717,47 @@ class Migration(migrations.Migration):
"verbose_name_plural": "remesas de productos",
},
),
migrations.CreateModel(
name="ShippingMethod",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=64, verbose_name="nombre")),
(
"description",
models.CharField(
blank=True,
default="",
max_length=256,
verbose_name="description",
),
),
("url", models.URLField(blank=True, default="", verbose_name="url")),
(
"enabled",
models.BooleanField(default=True, verbose_name="habilitado"),
),
(
"shipping_product",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="shop.product",
verbose_name="producto de envío",
),
),
],
options={
"verbose_name": "método de envío",
"verbose_name_plural": "métodos de envío",
},
),
migrations.CreateModel(
name="ProductPrice",
fields=[
+23 -2
View File
@@ -78,6 +78,7 @@ class Product(TimestampedModel):
slug = models.SlugField(
default="", blank=True, null=True, max_length=128, verbose_name=_("Slug")
)
hidden = models.BooleanField(default=False, db_index=True, verbose_name=_("oculto"))
def __str__(self):
return self.name
@@ -414,7 +415,7 @@ class CustomerAddress(models.Model):
BILLING = "BILL", _("facturación")
SHIPPING = "SHIP", _("envío")
user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name=_("usuario"))
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, verbose_name=_("usuario"))
vat_id = models.CharField(
max_length=16,
blank=True,
@@ -422,6 +423,9 @@ class CustomerAddress(models.Model):
default="",
verbose_name=_("número de identificación fiscal"),
)
full_name = models.CharField(
max_length=128, blank=False, null=False, verbose_name=_("dirección")
)
address = models.CharField(
max_length=128, blank=False, null=False, verbose_name=_("dirección")
)
@@ -451,8 +455,25 @@ class CustomerAddress(models.Model):
default=Types.SHIPPING,
verbose_name=_("tipo de dirección"),
)
default = models.BooleanField(default=True)
default = models.BooleanField(default=True, verbose_name=_("por defecto"))
hidden = models.BooleanField(default=False, db_index=True, verbose_name=_("oculto"))
class Meta:
verbose_name = _("dirección de cliente")
verbose_name_plural = _("direcciones de cliente")
class ShippingMethod(models.Model):
name = models.CharField(max_length=64, verbose_name=_("nombre"))
description = models.CharField(
max_length=256, default="", blank=True, verbose_name=_("description")
)
url = models.URLField(default="", blank=True, verbose_name=_("url"))
shipping_product = models.ForeignKey(
"shop.Product", on_delete=models.CASCADE, verbose_name=_("producto de envío")
)
enabled = models.BooleanField(default=True, verbose_name=_("habilitado"))
class Meta:
verbose_name = _("método de envío")
verbose_name_plural = _("métodos de envío")
+74 -1
View File
@@ -1,6 +1,15 @@
from decimal import Decimal
from shop.models import Order, OrderLine, Product, ProductBatch
from shop.models import (
Order,
OrderLine,
Product,
ProductBatch,
Cart,
CustomerAddress,
ShippingMethod,
ProductPrice,
)
from django.contrib.auth import get_user_model
User = get_user_model()
@@ -59,3 +68,67 @@ def delete_product_batch(batch: ProductBatch):
product.stock = max(product.stock - batch.quantity, 0)
product.save()
batch.delete()
def create_order_from_cart(
cart: Cart,
billing_address: CustomerAddress,
shipping_address: CustomerAddress,
shipping_method: ShippingMethod,
):
order = Order.objects.create(
billing_address=billing_address.address,
billing_city=billing_address.address_town,
billing_state=billing_address.address_state,
billing_country=billing_address.address_country,
billing_zip=billing_address.address_zip,
shipping_address=shipping_address.address,
shipping_city=shipping_address.address_town,
shipping_state=shipping_address.address_state,
shipping_country=shipping_address.address_country,
shipping_zip=shipping_address.address_zip,
)
for item in cart.items.all():
product = item.product
price: ProductPrice = product.price
base_total = price.price * item.quantity
tax_value = price.tax.value
taxes = base_total * (tax_value / 100)
total = base_total + taxes
OrderLine.objects.create(
order=order,
product=product,
quantity=item.quantity,
price=price.price,
base_total=base_total,
tax_value=tax_value,
taxes=taxes,
total=total,
)
order.calculate_total_from_lines()
add_shipping_order_line(order, shipping_method)
return order
def add_shipping_order_line(order, shipping_method):
shipping_price: ProductPrice = shipping_method.shipping_product.price
shipping_base_total = shipping_price.price
shipping_tax_value = shipping_price.tax.value
shipping_taxes = shipping_base_total * (shipping_tax_value / 100)
shipping_total = shipping_base_total + shipping_taxes
OrderLine.objects.create(
order=order,
product=shipping_method.shipping_product,
quantity=1,
price=shipping_price.price,
base_total=shipping_base_total,
tax_value=shipping_tax_value,
taxes=shipping_taxes,
total=shipping_total,
)
order.calculate_total_from_lines()