From 48d39f55babdb91c2f5bf8be5ab4c2bff41c768c Mon Sep 17 00:00:00 2001
From: Pablo Moreno
Date: Sat, 7 Dec 2024 10:10:14 +0100
Subject: [PATCH] feat: reset migrations and created customer address model
---
config/settings/environ.py | 1 +
shop/api/v1/serializers.py | 2 +-
shop/migrations/0001_initial.py | 353 ++++++++---
...rice_options_alter_tax_options_and_more.py | 34 --
...0003_alter_brand_creation_date_and_more.py | 555 ------------------
...0004_alter_product_options_product_slug.py | 40 --
.../0005_productprice_price_with_tax.py | 24 -
shop/migrations/0006_cart_cartitem.py | 91 ---
shop/models.py | 48 +-
shop/tests/api/test_api_orders.py | 105 ++--
shop/tests/api/test_shop_models.py | 53 +-
shop/utils.py | 7 +-
web/templates/components/cart/cart.html | 10 +-
.../components/cart/cart_navbar.html | 1 -
.../components/users/user_dropdown.html | 2 +-
web/templates/users/user_details.html | 436 ++++++++++++++
web/urls.py | 3 +-
web/views/users.py | 6 +
18 files changed, 863 insertions(+), 908 deletions(-)
delete mode 100644 shop/migrations/0002_alter_productprice_options_alter_tax_options_and_more.py
delete mode 100644 shop/migrations/0003_alter_brand_creation_date_and_more.py
delete mode 100644 shop/migrations/0004_alter_product_options_product_slug.py
delete mode 100644 shop/migrations/0005_productprice_price_with_tax.py
delete mode 100644 shop/migrations/0006_cart_cartitem.py
create mode 100644 web/templates/users/user_details.html
diff --git a/config/settings/environ.py b/config/settings/environ.py
index 8818fed..386d2e8 100644
--- a/config/settings/environ.py
+++ b/config/settings/environ.py
@@ -55,3 +55,4 @@ REDSYS_CURRENCY_CODE = env.str("REDSYS_CURRENCY_CODE", "978")
REDSYS_TPV_DOMAIN = env.str("REDSYS_TPV_DOMAIN", "")
ITEMS_PER_PAGE = env.int("ITEMS_PER_PAGE", 20)
+SHOP_COUNTRY = env.str("SHOP_COUNTRY", "ESPAÑA")
diff --git a/shop/api/v1/serializers.py b/shop/api/v1/serializers.py
index 7368cc0..e0a4597 100644
--- a/shop/api/v1/serializers.py
+++ b/shop/api/v1/serializers.py
@@ -228,7 +228,7 @@ class OrderSerializer(serializers.ModelSerializer):
"last_modification_date",
"base_total",
"total",
- "customer",
+ "user",
"billing_address",
"billing_city",
"billing_state",
diff --git a/shop/migrations/0001_initial.py b/shop/migrations/0001_initial.py
index 5258f49..ea2650e 100644
--- a/shop/migrations/0001_initial.py
+++ b/shop/migrations/0001_initial.py
@@ -1,10 +1,10 @@
-# Generated by Django 5.0.6 on 2024-05-21 17:19
-
-import uuid
-from decimal import Decimal
+# Generated by Django 5.1.3 on 2024-12-07 08:59
import django.db.models.deletion
import django.utils.timezone
+import uuid
+from decimal import Decimal
+from django.conf import settings
from django.db import migrations, models
@@ -14,6 +14,7 @@ class Migration(migrations.Migration):
dependencies = [
("files", "0001_initial"),
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
@@ -32,19 +33,19 @@ class Migration(migrations.Migration):
(
"creation_date",
models.DateTimeField(
- auto_now_add=True, verbose_name="Fecha de creación"
+ auto_now_add=True, verbose_name="fecha de creación"
),
),
(
"last_modification_date",
models.DateTimeField(
- auto_now=True, verbose_name="Fecha de última modificación"
+ auto_now=True, verbose_name="fecha de última modificación"
),
),
(
"name",
models.CharField(
- max_length=100, unique=True, verbose_name="Nombre"
+ max_length=100, unique=True, verbose_name="nombre"
),
),
],
@@ -68,13 +69,13 @@ class Migration(migrations.Migration):
(
"creation_date",
models.DateTimeField(
- auto_now_add=True, verbose_name="Fecha de creación"
+ auto_now_add=True, verbose_name="fecha de creación"
),
),
(
"last_modification_date",
models.DateTimeField(
- auto_now=True, verbose_name="Fecha de última modificación"
+ auto_now=True, verbose_name="fecha de última modificación"
),
),
(
@@ -82,20 +83,20 @@ class Migration(migrations.Migration):
models.CharField(
max_length=32,
unique=True,
- verbose_name="Documento de identidad",
+ verbose_name="documento de identidad",
),
),
- ("first_name", models.CharField(max_length=64, verbose_name="Nombre")),
+ ("first_name", models.CharField(max_length=64, verbose_name="nombre")),
(
"last_name",
- models.CharField(max_length=64, verbose_name="Apellidos"),
+ models.CharField(max_length=64, verbose_name="apellidos"),
),
- ("email", models.EmailField(max_length=254, verbose_name="E-mail")),
- ("address", models.CharField(max_length=255, verbose_name="Dirección")),
- ("city", models.CharField(max_length=64, verbose_name="Ciudad")),
- ("state", models.CharField(max_length=64, verbose_name="Región")),
- ("country", models.CharField(max_length=64, verbose_name="País")),
- ("zip", models.CharField(max_length=32, verbose_name="Código postal")),
+ ("email", models.EmailField(max_length=254, verbose_name="e-mail")),
+ ("address", models.CharField(max_length=255, verbose_name="dirección")),
+ ("city", models.CharField(max_length=64, verbose_name="ciudad")),
+ ("state", models.CharField(max_length=64, verbose_name="región")),
+ ("country", models.CharField(max_length=64, verbose_name="país")),
+ ("zip", models.CharField(max_length=32, verbose_name="código postal")),
],
options={
"verbose_name": "cliente",
@@ -117,13 +118,13 @@ class Migration(migrations.Migration):
(
"creation_date",
models.DateTimeField(
- auto_now_add=True, verbose_name="Fecha de creación"
+ auto_now_add=True, verbose_name="fecha de creación"
),
),
(
"last_modification_date",
models.DateTimeField(
- auto_now=True, verbose_name="Fecha de última modificación"
+ auto_now=True, verbose_name="fecha de última modificación"
),
),
(
@@ -131,14 +132,14 @@ class Migration(migrations.Migration):
models.CharField(
max_length=32,
unique=True,
- verbose_name="Documento de identidad",
+ verbose_name="documento de identidad",
),
),
- ("name", models.CharField(max_length=64, verbose_name="Nombre")),
+ ("name", models.CharField(max_length=64, verbose_name="nombre")),
(
"email",
models.EmailField(
- max_length=254, verbose_name="E-mail de contacto"
+ max_length=254, verbose_name="e-mail de contacto"
),
),
(
@@ -151,11 +152,11 @@ class Migration(migrations.Migration):
verbose_name="Teléfono de contacto",
),
),
- ("address", models.CharField(max_length=255, verbose_name="Dirección")),
- ("city", models.CharField(max_length=64, verbose_name="Ciudad")),
- ("state", models.CharField(max_length=64, verbose_name="Región")),
- ("country", models.CharField(max_length=64, verbose_name="País")),
- ("zip", models.CharField(max_length=32, verbose_name="Código postal")),
+ ("address", models.CharField(max_length=255, verbose_name="dirección")),
+ ("city", models.CharField(max_length=64, verbose_name="ciudad")),
+ ("state", models.CharField(max_length=64, verbose_name="región")),
+ ("country", models.CharField(max_length=64, verbose_name="país")),
+ ("zip", models.CharField(max_length=32, verbose_name="código postal")),
],
options={
"verbose_name": "proveedor",
@@ -197,31 +198,141 @@ class Migration(migrations.Migration):
(
"creation_date",
models.DateTimeField(
- auto_now_add=True, verbose_name="Fecha de creación"
+ auto_now_add=True, verbose_name="fecha de creación"
),
),
(
"last_modification_date",
models.DateTimeField(
- auto_now=True, verbose_name="Fecha de última modificación"
+ auto_now=True, verbose_name="fecha de última modificación"
),
),
(
"code",
models.CharField(
- max_length=8, unique=True, verbose_name="Código de impuesto"
+ max_length=8, unique=True, verbose_name="código de impuesto"
),
),
(
"value",
models.PositiveIntegerField(
- verbose_name="Valor entero (porcentaje)"
+ verbose_name="valor entero (porcentaje)"
),
),
],
options={
"verbose_name": "impuesto",
"verbose_name_plural": "impuestos",
+ "ordering": ("id",),
+ },
+ ),
+ migrations.CreateModel(
+ name="Cart",
+ fields=[
+ (
+ "uuid",
+ models.UUIDField(
+ default=uuid.uuid4,
+ primary_key=True,
+ serialize=False,
+ verbose_name="uuid",
+ ),
+ ),
+ (
+ "creation_date",
+ models.DateTimeField(
+ auto_now_add=True, verbose_name="fecha de creación"
+ ),
+ ),
+ (
+ "user",
+ models.ForeignKey(
+ blank=True,
+ null=True,
+ on_delete=django.db.models.deletion.CASCADE,
+ to=settings.AUTH_USER_MODEL,
+ verbose_name="usuario",
+ ),
+ ),
+ ],
+ options={
+ "verbose_name": "carrito",
+ "verbose_name_plural": "carritos",
+ },
+ ),
+ migrations.CreateModel(
+ name="CustomerAddress",
+ fields=[
+ (
+ "id",
+ models.BigAutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name="ID",
+ ),
+ ),
+ (
+ "vat_id",
+ models.CharField(
+ blank=True,
+ default="",
+ max_length=16,
+ null=True,
+ verbose_name="número de identificación fiscal",
+ ),
+ ),
+ ("address", models.CharField(max_length=128, verbose_name="dirección")),
+ (
+ "address_town",
+ models.CharField(max_length=64, verbose_name="localidad"),
+ ),
+ (
+ "address_zip",
+ models.CharField(max_length=16, verbose_name="código postal"),
+ ),
+ (
+ "address_state",
+ models.CharField(max_length=64, verbose_name="provincia"),
+ ),
+ (
+ "address_country",
+ models.CharField(
+ default="ESPAÑA", max_length=64, verbose_name="país"
+ ),
+ ),
+ (
+ "address_phone",
+ models.CharField(
+ blank=True,
+ default="",
+ max_length=16,
+ null=True,
+ verbose_name="teléfono",
+ ),
+ ),
+ (
+ "address_type",
+ models.CharField(
+ choices=[("BILL", "facturación"), ("SHIP", "envío")],
+ default="SHIP",
+ max_length=4,
+ verbose_name="tipo de dirección",
+ ),
+ ),
+ ("default", models.BooleanField(default=True)),
+ (
+ "user",
+ models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ to=settings.AUTH_USER_MODEL,
+ verbose_name="usuario",
+ ),
+ ),
+ ],
+ options={
+ "verbose_name": "dirección de cliente",
+ "verbose_name_plural": "direcciones de cliente",
},
),
migrations.CreateModel(
@@ -239,13 +350,13 @@ class Migration(migrations.Migration):
(
"creation_date",
models.DateTimeField(
- auto_now_add=True, verbose_name="Fecha de creación"
+ auto_now_add=True, verbose_name="fecha de creación"
),
),
(
"last_modification_date",
models.DateTimeField(
- auto_now=True, verbose_name="Fecha de última modificación"
+ auto_now=True, verbose_name="fecha de última modificación"
),
),
(
@@ -257,7 +368,7 @@ class Migration(migrations.Migration):
(
"status",
models.CharField(
- default="PEN", max_length=3, verbose_name="Estado"
+ default="PEN", max_length=3, verbose_name="estado"
),
),
(
@@ -266,7 +377,7 @@ class Migration(migrations.Migration):
decimal_places=2,
default=Decimal("0"),
max_digits=13,
- verbose_name="Base imponible",
+ verbose_name="base imponible",
),
),
(
@@ -275,69 +386,69 @@ class Migration(migrations.Migration):
decimal_places=2,
default=Decimal("0"),
max_digits=13,
- verbose_name="Total",
+ verbose_name="total",
),
),
(
"billing_address",
models.CharField(
- max_length=255, verbose_name="Dirección de facturación"
+ max_length=255, verbose_name="dirección de facturación"
),
),
(
"billing_city",
models.CharField(
- max_length=64, verbose_name="Ciudad de facturación"
+ max_length=64, verbose_name="ciudad de facturación"
),
),
(
"billing_state",
models.CharField(
- max_length=64, verbose_name="Región de facturación"
+ max_length=64, verbose_name="región de facturación"
),
),
(
"billing_country",
- models.CharField(max_length=64, verbose_name="País de facturación"),
+ models.CharField(max_length=64, verbose_name="país de facturación"),
),
(
"billing_zip",
models.CharField(
- max_length=32, verbose_name="Código postal de facturación"
+ max_length=32, verbose_name="código postal de facturación"
),
),
(
"shipping_address",
- models.CharField(max_length=255, verbose_name="Dirección"),
+ models.CharField(max_length=255, verbose_name="dirección"),
),
(
"shipping_city",
- models.CharField(max_length=64, verbose_name="Ciudad"),
+ models.CharField(max_length=64, verbose_name="ciudad"),
),
(
"shipping_state",
- models.CharField(max_length=64, verbose_name="Región"),
+ models.CharField(max_length=64, verbose_name="región"),
),
(
"shipping_country",
- models.CharField(max_length=64, verbose_name="País"),
+ models.CharField(max_length=64, verbose_name="país"),
),
(
"shipping_zip",
- models.CharField(max_length=32, verbose_name="Código postal"),
+ models.CharField(max_length=32, verbose_name="código postal"),
),
(
"contact_phone",
models.CharField(
- blank=True, max_length=32, verbose_name="Teléfono de contacto"
+ blank=True, max_length=32, verbose_name="teléfono de contacto"
),
),
(
- "customer",
+ "user",
models.ForeignKey(
on_delete=django.db.models.deletion.PROTECT,
- to="shop.customer",
- verbose_name="Cliente",
+ to=settings.AUTH_USER_MODEL,
+ verbose_name="cliente",
),
),
],
@@ -361,29 +472,26 @@ class Migration(migrations.Migration):
(
"creation_date",
models.DateTimeField(
- auto_now_add=True, verbose_name="Fecha de creación"
+ auto_now_add=True, verbose_name="fecha de creación"
),
),
(
"last_modification_date",
models.DateTimeField(
- auto_now=True, verbose_name="Fecha de última modificación"
+ auto_now=True, verbose_name="fecha de última modificación"
),
),
(
"sku",
models.CharField(
- max_length=64, unique=True, verbose_name="Código de referencia"
+ max_length=64, unique=True, verbose_name="código de referencia"
),
),
- ("name", models.CharField(max_length=96, verbose_name="Nombre")),
+ ("name", models.CharField(max_length=96, verbose_name="nombre")),
(
"description",
- models.CharField(
- blank=True,
- default="",
- max_length=1000,
- verbose_name="Descripción",
+ models.TextField(
+ blank=True, default="", verbose_name="descripción"
),
),
(
@@ -392,11 +500,26 @@ class Migration(migrations.Migration):
decimal_places=4,
default=Decimal("0"),
max_digits=13,
- verbose_name="Stock",
+ verbose_name="stock",
+ ),
+ ),
+ (
+ "is_digital_asset",
+ models.BooleanField(
+ default=False, verbose_name="es un activo digital"
),
),
- ("is_digital_asset", models.BooleanField(default=False)),
("url", models.URLField(blank=True, verbose_name="URL de descarga")),
+ (
+ "slug",
+ models.SlugField(
+ blank=True,
+ default="",
+ max_length=128,
+ null=True,
+ verbose_name="Slug",
+ ),
+ ),
(
"brand",
models.ForeignKey(
@@ -404,26 +527,26 @@ class Migration(migrations.Migration):
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="shop.brand",
- verbose_name="Marca",
+ verbose_name="marca",
),
),
(
"images",
models.ManyToManyField(
- blank=True, to="files.fileupload", verbose_name="Imágenes"
+ blank=True, to="files.fileupload", verbose_name="imágenes"
),
),
(
"tags",
models.ManyToManyField(
- blank=True, to="shop.tag", verbose_name="Etiquetas"
+ blank=True, to="shop.tag", verbose_name="etiquetas"
),
),
],
options={
"verbose_name": "producto",
"verbose_name_plural": "productos",
- "ordering": ("-id",),
+ "ordering": ("id",),
},
),
migrations.CreateModel(
@@ -441,13 +564,13 @@ class Migration(migrations.Migration):
(
"creation_date",
models.DateTimeField(
- auto_now_add=True, verbose_name="Fecha de creación"
+ auto_now_add=True, verbose_name="fecha de creación"
),
),
(
"last_modification_date",
models.DateTimeField(
- auto_now=True, verbose_name="Fecha de última modificación"
+ auto_now=True, verbose_name="fecha de última modificación"
),
),
(
@@ -456,13 +579,13 @@ class Migration(migrations.Migration):
decimal_places=4,
default=Decimal("1"),
max_digits=13,
- verbose_name="Cantidad",
+ verbose_name="cantidad",
),
),
(
"price",
models.DecimalField(
- decimal_places=4, max_digits=13, verbose_name="Precio"
+ decimal_places=4, max_digits=13, verbose_name="precio"
),
),
(
@@ -471,23 +594,23 @@ class Migration(migrations.Migration):
decimal_places=4,
default=Decimal("0"),
max_digits=13,
- verbose_name="Total sin impuestos",
+ verbose_name="total sin impuestos",
),
),
(
"tax_value",
- models.PositiveIntegerField(verbose_name="Valor de impuestos"),
+ models.PositiveIntegerField(verbose_name="valor de impuestos"),
),
(
"taxes",
models.DecimalField(
- decimal_places=4, max_digits=13, verbose_name="Impuestos"
+ decimal_places=4, max_digits=13, verbose_name="impuestos"
),
),
(
"total",
models.DecimalField(
- decimal_places=4, max_digits=13, verbose_name="Total"
+ decimal_places=4, max_digits=13, verbose_name="total"
),
),
(
@@ -496,7 +619,7 @@ class Migration(migrations.Migration):
on_delete=django.db.models.deletion.CASCADE,
related_name="lines",
to="shop.order",
- verbose_name="Pedido",
+ verbose_name="pedido",
),
),
(
@@ -504,7 +627,7 @@ class Migration(migrations.Migration):
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="shop.product",
- verbose_name="Producto",
+ verbose_name="producto",
),
),
],
@@ -513,6 +636,45 @@ class Migration(migrations.Migration):
"verbose_name_plural": "líneas de pedido",
},
),
+ migrations.CreateModel(
+ name="CartItem",
+ fields=[
+ (
+ "id",
+ models.BigAutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name="ID",
+ ),
+ ),
+ (
+ "quantity",
+ models.PositiveIntegerField(default=1, verbose_name="cantidad"),
+ ),
+ (
+ "cart",
+ models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name="items",
+ to="shop.cart",
+ verbose_name="carrito",
+ ),
+ ),
+ (
+ "product",
+ models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ to="shop.product",
+ verbose_name="producto",
+ ),
+ ),
+ ],
+ options={
+ "verbose_name": "línea de carrito",
+ "verbose_name_plural": "líneas de carrito",
+ },
+ ),
migrations.CreateModel(
name="ProductBatch",
fields=[
@@ -528,19 +690,19 @@ class Migration(migrations.Migration):
(
"creation_date",
models.DateTimeField(
- auto_now_add=True, verbose_name="Fecha de creación"
+ auto_now_add=True, verbose_name="fecha de creación"
),
),
(
"last_modification_date",
models.DateTimeField(
- auto_now=True, verbose_name="Fecha de última modificación"
+ auto_now=True, verbose_name="fecha de última modificación"
),
),
(
"code",
models.CharField(
- db_index=True, max_length=32, unique=True, verbose_name="Código"
+ db_index=True, max_length=32, unique=True, verbose_name="código"
),
),
(
@@ -549,7 +711,7 @@ class Migration(migrations.Migration):
decimal_places=4,
default=Decimal("1"),
max_digits=13,
- verbose_name="Cantidad",
+ verbose_name="cantidad",
),
),
(
@@ -557,7 +719,7 @@ class Migration(migrations.Migration):
models.DateField(
blank=True,
null=True,
- verbose_name="Fecha de caducidad / consumo preferente",
+ verbose_name="fecha de caducidad / consumo preferente",
),
),
(
@@ -565,7 +727,7 @@ class Migration(migrations.Migration):
models.ForeignKey(
on_delete=django.db.models.deletion.PROTECT,
to="shop.product",
- verbose_name="Producto",
+ verbose_name="producto",
),
),
(
@@ -575,7 +737,7 @@ class Migration(migrations.Migration):
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="shop.provider",
- verbose_name="Proveedor",
+ verbose_name="proveedor",
),
),
],
@@ -599,31 +761,41 @@ class Migration(migrations.Migration):
(
"creation_date",
models.DateTimeField(
- auto_now_add=True, verbose_name="Fecha de creación"
+ auto_now_add=True, verbose_name="fecha de creación"
),
),
(
"last_modification_date",
models.DateTimeField(
- auto_now=True, verbose_name="Fecha de última modificación"
+ auto_now=True, verbose_name="fecha de última modificación"
),
),
(
"price",
models.DecimalField(
- decimal_places=2, max_digits=11, verbose_name="Precio"
+ decimal_places=2, max_digits=11, verbose_name="precio"
),
),
(
"date",
models.DateTimeField(
- default=django.utils.timezone.now, verbose_name="Fecha"
+ default=django.utils.timezone.now, verbose_name="fecha"
+ ),
+ ),
+ (
+ "price_with_tax",
+ models.DecimalField(
+ blank=True,
+ decimal_places=2,
+ max_digits=11,
+ null=True,
+ verbose_name="precio con impuestos",
),
),
(
"current",
models.BooleanField(
- default=False, verbose_name="Es el precio actual"
+ default=False, verbose_name="es el precio actual"
),
),
(
@@ -632,7 +804,7 @@ class Migration(migrations.Migration):
on_delete=django.db.models.deletion.CASCADE,
related_name="prices",
to="shop.product",
- verbose_name="Producto",
+ verbose_name="producto",
),
),
(
@@ -640,13 +812,14 @@ class Migration(migrations.Migration):
models.ForeignKey(
on_delete=django.db.models.deletion.PROTECT,
to="shop.tax",
- verbose_name="Impuesto aplicable",
+ verbose_name="impuesto aplicable",
),
),
],
options={
"verbose_name": "precio de producto",
"verbose_name_plural": "precio de producto",
+ "ordering": ("-date",),
},
),
]
diff --git a/shop/migrations/0002_alter_productprice_options_alter_tax_options_and_more.py b/shop/migrations/0002_alter_productprice_options_alter_tax_options_and_more.py
deleted file mode 100644
index 0b6148c..0000000
--- a/shop/migrations/0002_alter_productprice_options_alter_tax_options_and_more.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# Generated by Django 5.0.6 on 2024-05-26 11:16
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ("shop", "0001_initial"),
- ]
-
- operations = [
- migrations.AlterModelOptions(
- name="productprice",
- options={
- "ordering": ("-date",),
- "verbose_name": "precio de producto",
- "verbose_name_plural": "precio de producto",
- },
- ),
- migrations.AlterModelOptions(
- name="tax",
- options={
- "ordering": ("id",),
- "verbose_name": "impuesto",
- "verbose_name_plural": "impuestos",
- },
- ),
- migrations.AlterField(
- model_name="product",
- name="description",
- field=models.TextField(blank=True, default="", verbose_name="Descripción"),
- ),
- ]
diff --git a/shop/migrations/0003_alter_brand_creation_date_and_more.py b/shop/migrations/0003_alter_brand_creation_date_and_more.py
deleted file mode 100644
index 12a52de..0000000
--- a/shop/migrations/0003_alter_brand_creation_date_and_more.py
+++ /dev/null
@@ -1,555 +0,0 @@
-# Generated by Django 5.0.6 on 2024-06-02 19:47
-
-from decimal import Decimal
-
-import django.db.models.deletion
-import django.utils.timezone
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ("files", "0001_initial"),
- ("shop", "0002_alter_productprice_options_alter_tax_options_and_more"),
- ]
-
- operations = [
- migrations.AlterField(
- model_name="brand",
- name="creation_date",
- field=models.DateTimeField(
- auto_now_add=True, verbose_name="fecha de creación"
- ),
- ),
- migrations.AlterField(
- model_name="brand",
- name="last_modification_date",
- field=models.DateTimeField(
- auto_now=True, verbose_name="fecha de última modificación"
- ),
- ),
- migrations.AlterField(
- model_name="brand",
- name="name",
- field=models.CharField(max_length=100, unique=True, verbose_name="nombre"),
- ),
- migrations.AlterField(
- model_name="customer",
- name="address",
- field=models.CharField(max_length=255, verbose_name="dirección"),
- ),
- migrations.AlterField(
- model_name="customer",
- name="city",
- field=models.CharField(max_length=64, verbose_name="ciudad"),
- ),
- migrations.AlterField(
- model_name="customer",
- name="country",
- field=models.CharField(max_length=64, verbose_name="país"),
- ),
- migrations.AlterField(
- model_name="customer",
- name="creation_date",
- field=models.DateTimeField(
- auto_now_add=True, verbose_name="fecha de creación"
- ),
- ),
- migrations.AlterField(
- model_name="customer",
- name="email",
- field=models.EmailField(max_length=254, verbose_name="e-mail"),
- ),
- migrations.AlterField(
- model_name="customer",
- name="first_name",
- field=models.CharField(max_length=64, verbose_name="nombre"),
- ),
- migrations.AlterField(
- model_name="customer",
- name="last_modification_date",
- field=models.DateTimeField(
- auto_now=True, verbose_name="fecha de última modificación"
- ),
- ),
- migrations.AlterField(
- model_name="customer",
- name="last_name",
- field=models.CharField(max_length=64, verbose_name="apellidos"),
- ),
- migrations.AlterField(
- model_name="customer",
- name="state",
- field=models.CharField(max_length=64, verbose_name="región"),
- ),
- migrations.AlterField(
- model_name="customer",
- name="vat_id",
- field=models.CharField(
- max_length=32, unique=True, verbose_name="documento de identidad"
- ),
- ),
- migrations.AlterField(
- model_name="customer",
- name="zip",
- field=models.CharField(max_length=32, verbose_name="código postal"),
- ),
- migrations.AlterField(
- model_name="order",
- name="base_total",
- field=models.DecimalField(
- decimal_places=2,
- default=Decimal("0"),
- max_digits=13,
- verbose_name="base imponible",
- ),
- ),
- migrations.AlterField(
- model_name="order",
- name="billing_address",
- field=models.CharField(
- max_length=255, verbose_name="dirección de facturación"
- ),
- ),
- migrations.AlterField(
- model_name="order",
- name="billing_city",
- field=models.CharField(max_length=64, verbose_name="ciudad de facturación"),
- ),
- migrations.AlterField(
- model_name="order",
- name="billing_country",
- field=models.CharField(max_length=64, verbose_name="país de facturación"),
- ),
- migrations.AlterField(
- model_name="order",
- name="billing_state",
- field=models.CharField(max_length=64, verbose_name="región de facturación"),
- ),
- migrations.AlterField(
- model_name="order",
- name="billing_zip",
- field=models.CharField(
- max_length=32, verbose_name="código postal de facturación"
- ),
- ),
- migrations.AlterField(
- model_name="order",
- name="contact_phone",
- field=models.CharField(
- blank=True, max_length=32, verbose_name="teléfono de contacto"
- ),
- ),
- migrations.AlterField(
- model_name="order",
- name="creation_date",
- field=models.DateTimeField(
- auto_now_add=True, verbose_name="fecha de creación"
- ),
- ),
- migrations.AlterField(
- model_name="order",
- name="customer",
- field=models.ForeignKey(
- on_delete=django.db.models.deletion.PROTECT,
- to="shop.customer",
- verbose_name="cliente",
- ),
- ),
- migrations.AlterField(
- model_name="order",
- name="last_modification_date",
- field=models.DateTimeField(
- auto_now=True, verbose_name="fecha de última modificación"
- ),
- ),
- migrations.AlterField(
- model_name="order",
- name="shipping_address",
- field=models.CharField(max_length=255, verbose_name="dirección"),
- ),
- migrations.AlterField(
- model_name="order",
- name="shipping_city",
- field=models.CharField(max_length=64, verbose_name="ciudad"),
- ),
- migrations.AlterField(
- model_name="order",
- name="shipping_country",
- field=models.CharField(max_length=64, verbose_name="país"),
- ),
- migrations.AlterField(
- model_name="order",
- name="shipping_state",
- field=models.CharField(max_length=64, verbose_name="región"),
- ),
- migrations.AlterField(
- model_name="order",
- name="shipping_zip",
- field=models.CharField(max_length=32, verbose_name="código postal"),
- ),
- migrations.AlterField(
- model_name="order",
- name="status",
- field=models.CharField(default="PEN", max_length=3, verbose_name="estado"),
- ),
- migrations.AlterField(
- model_name="order",
- name="total",
- field=models.DecimalField(
- decimal_places=2,
- default=Decimal("0"),
- max_digits=13,
- verbose_name="total",
- ),
- ),
- migrations.AlterField(
- model_name="orderline",
- name="base_total",
- field=models.DecimalField(
- decimal_places=4,
- default=Decimal("0"),
- max_digits=13,
- verbose_name="total sin impuestos",
- ),
- ),
- migrations.AlterField(
- model_name="orderline",
- name="creation_date",
- field=models.DateTimeField(
- auto_now_add=True, verbose_name="fecha de creación"
- ),
- ),
- migrations.AlterField(
- model_name="orderline",
- name="last_modification_date",
- field=models.DateTimeField(
- auto_now=True, verbose_name="fecha de última modificación"
- ),
- ),
- migrations.AlterField(
- model_name="orderline",
- name="order",
- field=models.ForeignKey(
- on_delete=django.db.models.deletion.CASCADE,
- related_name="lines",
- to="shop.order",
- verbose_name="pedido",
- ),
- ),
- migrations.AlterField(
- model_name="orderline",
- name="price",
- field=models.DecimalField(
- decimal_places=4, max_digits=13, verbose_name="precio"
- ),
- ),
- migrations.AlterField(
- model_name="orderline",
- name="product",
- field=models.ForeignKey(
- on_delete=django.db.models.deletion.CASCADE,
- to="shop.product",
- verbose_name="producto",
- ),
- ),
- migrations.AlterField(
- model_name="orderline",
- name="quantity",
- field=models.DecimalField(
- decimal_places=4,
- default=Decimal("1"),
- max_digits=13,
- verbose_name="cantidad",
- ),
- ),
- migrations.AlterField(
- model_name="orderline",
- name="tax_value",
- field=models.PositiveIntegerField(verbose_name="valor de impuestos"),
- ),
- migrations.AlterField(
- model_name="orderline",
- name="taxes",
- field=models.DecimalField(
- decimal_places=4, max_digits=13, verbose_name="impuestos"
- ),
- ),
- migrations.AlterField(
- model_name="orderline",
- name="total",
- field=models.DecimalField(
- decimal_places=4, max_digits=13, verbose_name="total"
- ),
- ),
- migrations.AlterField(
- model_name="product",
- name="brand",
- field=models.ForeignKey(
- blank=True,
- null=True,
- on_delete=django.db.models.deletion.SET_NULL,
- to="shop.brand",
- verbose_name="marca",
- ),
- ),
- migrations.AlterField(
- model_name="product",
- name="creation_date",
- field=models.DateTimeField(
- auto_now_add=True, verbose_name="fecha de creación"
- ),
- ),
- migrations.AlterField(
- model_name="product",
- name="description",
- field=models.TextField(blank=True, default="", verbose_name="descripción"),
- ),
- migrations.AlterField(
- model_name="product",
- name="images",
- field=models.ManyToManyField(
- blank=True, to="files.fileupload", verbose_name="imágenes"
- ),
- ),
- migrations.AlterField(
- model_name="product",
- name="is_digital_asset",
- field=models.BooleanField(
- default=False, verbose_name="es un activo digital"
- ),
- ),
- migrations.AlterField(
- model_name="product",
- name="last_modification_date",
- field=models.DateTimeField(
- auto_now=True, verbose_name="fecha de última modificación"
- ),
- ),
- migrations.AlterField(
- model_name="product",
- name="name",
- field=models.CharField(max_length=96, verbose_name="nombre"),
- ),
- migrations.AlterField(
- model_name="product",
- name="sku",
- field=models.CharField(
- max_length=64, unique=True, verbose_name="código de referencia"
- ),
- ),
- migrations.AlterField(
- model_name="product",
- name="stock",
- field=models.DecimalField(
- decimal_places=4,
- default=Decimal("0"),
- max_digits=13,
- verbose_name="stock",
- ),
- ),
- migrations.AlterField(
- model_name="product",
- name="tags",
- field=models.ManyToManyField(
- blank=True, to="shop.tag", verbose_name="etiquetas"
- ),
- ),
- migrations.AlterField(
- model_name="productbatch",
- name="code",
- field=models.CharField(
- db_index=True, max_length=32, unique=True, verbose_name="código"
- ),
- ),
- migrations.AlterField(
- model_name="productbatch",
- name="creation_date",
- field=models.DateTimeField(
- auto_now_add=True, verbose_name="fecha de creación"
- ),
- ),
- migrations.AlterField(
- model_name="productbatch",
- name="expiration_date",
- field=models.DateField(
- blank=True,
- null=True,
- verbose_name="fecha de caducidad / consumo preferente",
- ),
- ),
- migrations.AlterField(
- model_name="productbatch",
- name="last_modification_date",
- field=models.DateTimeField(
- auto_now=True, verbose_name="fecha de última modificación"
- ),
- ),
- migrations.AlterField(
- model_name="productbatch",
- name="product",
- field=models.ForeignKey(
- on_delete=django.db.models.deletion.PROTECT,
- to="shop.product",
- verbose_name="producto",
- ),
- ),
- migrations.AlterField(
- model_name="productbatch",
- name="provider",
- field=models.ForeignKey(
- blank=True,
- null=True,
- on_delete=django.db.models.deletion.SET_NULL,
- to="shop.provider",
- verbose_name="proveedor",
- ),
- ),
- migrations.AlterField(
- model_name="productbatch",
- name="quantity",
- field=models.DecimalField(
- decimal_places=4,
- default=Decimal("1"),
- max_digits=13,
- verbose_name="cantidad",
- ),
- ),
- migrations.AlterField(
- model_name="productprice",
- name="creation_date",
- field=models.DateTimeField(
- auto_now_add=True, verbose_name="fecha de creación"
- ),
- ),
- migrations.AlterField(
- model_name="productprice",
- name="current",
- field=models.BooleanField(
- default=False, verbose_name="es el precio actual"
- ),
- ),
- migrations.AlterField(
- model_name="productprice",
- name="date",
- field=models.DateTimeField(
- default=django.utils.timezone.now, verbose_name="fecha"
- ),
- ),
- migrations.AlterField(
- model_name="productprice",
- name="last_modification_date",
- field=models.DateTimeField(
- auto_now=True, verbose_name="fecha de última modificación"
- ),
- ),
- migrations.AlterField(
- model_name="productprice",
- name="price",
- field=models.DecimalField(
- decimal_places=2, max_digits=11, verbose_name="precio"
- ),
- ),
- migrations.AlterField(
- model_name="productprice",
- name="product",
- field=models.ForeignKey(
- on_delete=django.db.models.deletion.CASCADE,
- related_name="prices",
- to="shop.product",
- verbose_name="producto",
- ),
- ),
- migrations.AlterField(
- model_name="productprice",
- name="tax",
- field=models.ForeignKey(
- on_delete=django.db.models.deletion.PROTECT,
- to="shop.tax",
- verbose_name="impuesto aplicable",
- ),
- ),
- migrations.AlterField(
- model_name="provider",
- name="address",
- field=models.CharField(max_length=255, verbose_name="dirección"),
- ),
- migrations.AlterField(
- model_name="provider",
- name="city",
- field=models.CharField(max_length=64, verbose_name="ciudad"),
- ),
- migrations.AlterField(
- model_name="provider",
- name="country",
- field=models.CharField(max_length=64, verbose_name="país"),
- ),
- migrations.AlterField(
- model_name="provider",
- name="creation_date",
- field=models.DateTimeField(
- auto_now_add=True, verbose_name="fecha de creación"
- ),
- ),
- migrations.AlterField(
- model_name="provider",
- name="email",
- field=models.EmailField(max_length=254, verbose_name="e-mail de contacto"),
- ),
- migrations.AlterField(
- model_name="provider",
- name="last_modification_date",
- field=models.DateTimeField(
- auto_now=True, verbose_name="fecha de última modificación"
- ),
- ),
- migrations.AlterField(
- model_name="provider",
- name="name",
- field=models.CharField(max_length=64, verbose_name="nombre"),
- ),
- migrations.AlterField(
- model_name="provider",
- name="state",
- field=models.CharField(max_length=64, verbose_name="región"),
- ),
- migrations.AlterField(
- model_name="provider",
- name="vat_id",
- field=models.CharField(
- max_length=32, unique=True, verbose_name="documento de identidad"
- ),
- ),
- migrations.AlterField(
- model_name="provider",
- name="zip",
- field=models.CharField(max_length=32, verbose_name="código postal"),
- ),
- migrations.AlterField(
- model_name="tax",
- name="code",
- field=models.CharField(
- max_length=8, unique=True, verbose_name="código de impuesto"
- ),
- ),
- migrations.AlterField(
- model_name="tax",
- name="creation_date",
- field=models.DateTimeField(
- auto_now_add=True, verbose_name="fecha de creación"
- ),
- ),
- migrations.AlterField(
- model_name="tax",
- name="last_modification_date",
- field=models.DateTimeField(
- auto_now=True, verbose_name="fecha de última modificación"
- ),
- ),
- migrations.AlterField(
- model_name="tax",
- name="value",
- field=models.PositiveIntegerField(verbose_name="valor entero (porcentaje)"),
- ),
- ]
diff --git a/shop/migrations/0004_alter_product_options_product_slug.py b/shop/migrations/0004_alter_product_options_product_slug.py
deleted file mode 100644
index 06df414..0000000
--- a/shop/migrations/0004_alter_product_options_product_slug.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# Generated by Django 5.1.3 on 2024-11-22 19:53
-
-from django.db import migrations, models
-from django.utils.text import slugify
-
-
-def add_product_slug(apps, schema_editor):
- Product = apps.get_model("shop", "Product")
-
- for product in Product.objects.all():
- product.slug = slugify(product.name)[:128]
- product.save()
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ("shop", "0003_alter_brand_creation_date_and_more"),
- ]
-
- operations = [
- migrations.AlterModelOptions(
- name="product",
- options={
- "ordering": ("id",),
- "verbose_name": "producto",
- "verbose_name_plural": "productos",
- },
- ),
- migrations.AddField(
- model_name="product",
- name="slug",
- field=models.SlugField(
- blank=True, default="", max_length=128, null=True, verbose_name="Slug"
- ),
- ),
- migrations.RunPython(
- add_product_slug,
- ),
- ]
diff --git a/shop/migrations/0005_productprice_price_with_tax.py b/shop/migrations/0005_productprice_price_with_tax.py
deleted file mode 100644
index 042ddf3..0000000
--- a/shop/migrations/0005_productprice_price_with_tax.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Generated by Django 5.1.3 on 2024-11-24 12:26
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ("shop", "0004_alter_product_options_product_slug"),
- ]
-
- operations = [
- migrations.AddField(
- model_name="productprice",
- name="price_with_tax",
- field=models.DecimalField(
- blank=True,
- decimal_places=2,
- max_digits=11,
- null=True,
- verbose_name="precio con impuestos",
- ),
- ),
- ]
diff --git a/shop/migrations/0006_cart_cartitem.py b/shop/migrations/0006_cart_cartitem.py
deleted file mode 100644
index 7fd0bcf..0000000
--- a/shop/migrations/0006_cart_cartitem.py
+++ /dev/null
@@ -1,91 +0,0 @@
-# Generated by Django 5.1.3 on 2024-11-27 12:10
-
-import uuid
-
-import django.db.models.deletion
-from django.conf import settings
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ("shop", "0005_productprice_price_with_tax"),
- migrations.swappable_dependency(settings.AUTH_USER_MODEL),
- ]
-
- operations = [
- migrations.CreateModel(
- name="Cart",
- fields=[
- (
- "uuid",
- models.UUIDField(
- default=uuid.uuid4,
- primary_key=True,
- serialize=False,
- verbose_name="uuid",
- ),
- ),
- (
- "creation_date",
- models.DateTimeField(
- auto_now_add=True, verbose_name="fecha de creación"
- ),
- ),
- (
- "user",
- models.ForeignKey(
- blank=True,
- null=True,
- on_delete=django.db.models.deletion.CASCADE,
- to=settings.AUTH_USER_MODEL,
- verbose_name="usuario",
- ),
- ),
- ],
- options={
- "verbose_name": "carrito",
- "verbose_name_plural": "carritos",
- },
- ),
- migrations.CreateModel(
- name="CartItem",
- fields=[
- (
- "id",
- models.BigAutoField(
- auto_created=True,
- primary_key=True,
- serialize=False,
- verbose_name="ID",
- ),
- ),
- (
- "quantity",
- models.PositiveIntegerField(default=1, verbose_name="cantidad"),
- ),
- (
- "cart",
- models.ForeignKey(
- on_delete=django.db.models.deletion.CASCADE,
- related_name="items",
- to="shop.cart",
- verbose_name="carrito",
- ),
- ),
- (
- "product",
- models.ForeignKey(
- on_delete=django.db.models.deletion.CASCADE,
- to="shop.product",
- verbose_name="producto",
- ),
- ),
- ],
- options={
- "verbose_name": "línea de carrito",
- "verbose_name_plural": "líneas de carrito",
- },
- ),
- ]
diff --git a/shop/models.py b/shop/models.py
index eb3b564..f505926 100644
--- a/shop/models.py
+++ b/shop/models.py
@@ -1,6 +1,7 @@
from decimal import Decimal
from uuid import uuid4
+from django.conf import settings
from django.contrib.auth import get_user_model
from django.db import models
from django.utils import timezone
@@ -346,9 +347,8 @@ class Order(TimestampedModel):
default=Decimal("0"), max_digits=13, decimal_places=2, verbose_name=_("total")
)
- # Customer reference
- customer = models.ForeignKey(
- "shop.Customer", on_delete=models.PROTECT, verbose_name=_("cliente")
+ user = models.ForeignKey(
+ User, on_delete=models.PROTECT, verbose_name=_("cliente")
)
# Billing information
@@ -436,3 +436,45 @@ class CartItem(models.Model):
class Meta:
verbose_name = _("línea de carrito")
verbose_name_plural = _("líneas de carrito")
+
+
+class CustomerAddress(models.Model):
+ class Types(models.TextChoices):
+ BILLING = "BILL", _("facturación")
+ SHIPPING = "SHIP", _("envío")
+
+ user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name=_("usuario"))
+ vat_id = models.CharField(
+ max_length=16,
+ blank=True,
+ null=True,
+ default="",
+ verbose_name=_("número de identificación fiscal"),
+ )
+ address = models.CharField(
+ max_length=128, blank=False, null=False, verbose_name=_("dirección")
+ )
+ address_town = models.CharField(
+ max_length=64, blank=False, null=False, verbose_name=_("localidad")
+ )
+ address_zip = models.CharField(
+ max_length=16, blank=False, null=False, verbose_name=_("código postal")
+ )
+ address_state = models.CharField(
+ max_length=64, blank=False, null=False, verbose_name=_("provincia")
+ )
+ address_country = models.CharField(
+ max_length=64, default=settings.SHOP_COUNTRY, blank=False, null=False, verbose_name=_("país")
+ )
+ address_phone = models.CharField(
+ max_length=16, blank=True, null=True, default="", verbose_name=_("teléfono")
+ )
+
+ address_type = models.CharField(
+ max_length=4, choices=Types.choices, default=Types.SHIPPING, verbose_name=_("tipo de dirección")
+ )
+ default = models.BooleanField(default=True)
+
+ class Meta:
+ verbose_name = _("dirección de cliente")
+ verbose_name_plural = _("direcciones de cliente")
diff --git a/shop/tests/api/test_api_orders.py b/shop/tests/api/test_api_orders.py
index 08f562a..b7c8776 100644
--- a/shop/tests/api/test_api_orders.py
+++ b/shop/tests/api/test_api_orders.py
@@ -1,10 +1,13 @@
from decimal import Decimal
+from django.contrib.auth import get_user_model
from rest_framework import status
from rest_framework.test import APITestCase
from config.tests.mixins import TestUserAuthenticationMixin
-from shop.models import Customer, Product, ProductPrice, Tax
+from shop.models import Product, ProductPrice, Tax, Customer, CustomerAddress
+
+User = get_user_model()
class TestOrdersAPI(APITestCase, TestUserAuthenticationMixin):
@@ -16,16 +19,32 @@ class TestOrdersAPI(APITestCase, TestUserAuthenticationMixin):
code="IVA",
value=21,
)
- self.customer = Customer.objects.create(
- vat_id="11111111H",
+ self.customer = get_user_model().objects.create_user(
+ username="11111111H",
first_name="Darth",
last_name="Maull",
email="darth@maul.com",
+ password="dathomir",
+ )
+
+ self.customer_shipping_address = CustomerAddress.objects.create(
+ user=self.customer,
address="Dathomir",
- city="Dathomir",
- state="Dathomir",
- country="Dathomir",
- zip="00001",
+ address_town="Dathomir",
+ address_zip="00001",
+ address_state="Dathomir",
+ address_phone="900000000",
+ address_type=CustomerAddress.Types.SHIPPING,
+ )
+
+ self.customer_billing_address = CustomerAddress.objects.create(
+ user=self.customer,
+ address="Dathomir",
+ address_town="Dathomir",
+ address_zip="00001",
+ address_state="Dathomir",
+ address_phone="900000000",
+ address_type=CustomerAddress.Types.BILLING,
)
self.create_products()
@@ -49,18 +68,18 @@ class TestOrdersAPI(APITestCase, TestUserAuthenticationMixin):
response = self.client.post(
f"/api/v1/shop/orders/",
{
- "customer": self.customer.pk,
- "billing_address": self.customer.address,
- "billing_city": self.customer.city,
- "billing_state": self.customer.state,
- "billing_country": self.customer.country,
- "billing_zip": self.customer.zip,
- "shipping_address": self.customer.address,
- "shipping_city": self.customer.city,
- "shipping_state": self.customer.state,
- "shipping_country": self.customer.country,
- "shipping_zip": self.customer.zip,
- "contact_phone": "612345678",
+ "user": self.user.pk,
+ "billing_address": self.customer_billing_address.address,
+ "billing_city": self.customer_billing_address.address_town,
+ "billing_state": self.customer_billing_address.address_state,
+ "billing_country": self.customer_billing_address.address_country,
+ "billing_zip": self.customer_billing_address.address_zip,
+ "shipping_address": self.customer_shipping_address.address,
+ "shipping_city": self.customer_shipping_address.address_town,
+ "shipping_state": self.customer_shipping_address.address_state,
+ "shipping_country": self.customer_shipping_address.address_country,
+ "shipping_zip": self.customer_shipping_address.address_zip,
+ "contact_phone": self.customer_shipping_address.address_phone,
},
)
@@ -76,18 +95,18 @@ class TestOrdersAPI(APITestCase, TestUserAuthenticationMixin):
response = self.client.post(
f"/api/v1/shop/orders/",
{
- "customer": self.customer.pk,
- "billing_address": self.customer.address,
- "billing_city": self.customer.city,
- "billing_state": self.customer.state,
- "billing_country": self.customer.country,
- "billing_zip": self.customer.zip,
- "shipping_address": self.customer.address,
- "shipping_city": self.customer.city,
- "shipping_state": self.customer.state,
- "shipping_country": self.customer.country,
- "shipping_zip": self.customer.zip,
- "contact_phone": "612345678",
+ "user": self.user.pk,
+ "billing_address": self.customer_billing_address.address,
+ "billing_city": self.customer_billing_address.address_town,
+ "billing_state": self.customer_billing_address.address_state,
+ "billing_country": self.customer_billing_address.address_country,
+ "billing_zip": self.customer_billing_address.address_zip,
+ "shipping_address": self.customer_shipping_address.address,
+ "shipping_city": self.customer_shipping_address.address_town,
+ "shipping_state": self.customer_shipping_address.address_state,
+ "shipping_country": self.customer_shipping_address.address_country,
+ "shipping_zip": self.customer_shipping_address.address_zip,
+ "contact_phone": self.customer_shipping_address.address_phone,
},
)
@@ -126,18 +145,18 @@ class TestOrdersAPI(APITestCase, TestUserAuthenticationMixin):
response = self.client.post(
f"/api/v1/shop/orders/",
{
- "customer": self.customer.pk,
- "billing_address": self.customer.address,
- "billing_city": self.customer.city,
- "billing_state": self.customer.state,
- "billing_country": self.customer.country,
- "billing_zip": self.customer.zip,
- "shipping_address": self.customer.address,
- "shipping_city": self.customer.city,
- "shipping_state": self.customer.state,
- "shipping_country": self.customer.country,
- "shipping_zip": self.customer.zip,
- "contact_phone": "612345678",
+ "user": self.user.pk,
+ "billing_address": self.customer_billing_address.address,
+ "billing_city": self.customer_billing_address.address_town,
+ "billing_state": self.customer_billing_address.address_state,
+ "billing_country": self.customer_billing_address.address_country,
+ "billing_zip": self.customer_billing_address.address_zip,
+ "shipping_address": self.customer_shipping_address.address,
+ "shipping_city": self.customer_shipping_address.address_town,
+ "shipping_state": self.customer_shipping_address.address_state,
+ "shipping_country": self.customer_shipping_address.address_country,
+ "shipping_zip": self.customer_shipping_address.address_zip,
+ "contact_phone": self.customer_shipping_address.address_phone,
},
)
diff --git a/shop/tests/api/test_shop_models.py b/shop/tests/api/test_shop_models.py
index 7f91ddd..9d6c22d 100644
--- a/shop/tests/api/test_shop_models.py
+++ b/shop/tests/api/test_shop_models.py
@@ -1,10 +1,13 @@
from decimal import Decimal
+from django.contrib.auth import get_user_model
from rest_framework.test import APITestCase as TestCase
-from shop.models import Customer, Product, ProductPrice, Tax
+from shop.models import Customer, Product, ProductPrice, Tax, CustomerAddress
from shop.utils import create_order, create_order_line_for_product
+User = get_user_model()
+
class ShopModelsTest(TestCase):
def setUp(self) -> None:
@@ -12,6 +15,33 @@ class ShopModelsTest(TestCase):
code="IVA",
value=21,
)
+ self.customer = User.objects.create_user(
+ username="11111111H",
+ first_name="Darth",
+ last_name="Maull",
+ email="darth@maul.com",
+ password="dathomir",
+ )
+
+ self.customer_shipping_address = CustomerAddress.objects.create(
+ user=self.customer,
+ address="Dathomir",
+ address_town="Dathomir",
+ address_zip="00001",
+ address_state="Dathomir",
+ address_phone="900000000",
+ address_type=CustomerAddress.Types.SHIPPING,
+ )
+
+ self.customer_billing_address = CustomerAddress.objects.create(
+ user=self.customer,
+ address="Dathomir",
+ address_town="Dathomir",
+ address_zip="00001",
+ address_state="Dathomir",
+ address_phone="900000000",
+ address_type=CustomerAddress.Types.BILLING,
+ )
self.create_products()
def create_products(self):
@@ -42,24 +72,13 @@ class ShopModelsTest(TestCase):
)
def test_create_order(self):
- self.customer = Customer.objects.create(
- first_name="Luke",
- last_name="Skywalker",
- vat_id="11111111H",
- address="Farm Skywalker",
- city="Desert",
- state="Mos-Eisley",
- zip="00001",
- country="Tatooine",
- )
-
order = create_order(
customer=self.customer,
- billing_address=self.customer.address,
- billing_city=self.customer.city,
- billing_state=self.customer.state,
- billing_zip=self.customer.zip,
- billing_country=self.customer.country,
+ billing_address=self.customer_billing_address.address,
+ billing_city=self.customer_billing_address.address_town,
+ billing_state=self.customer_billing_address.address_state,
+ billing_zip=self.customer_billing_address.address_zip,
+ billing_country=self.customer_billing_address.address_country,
)
l1 = create_order_line_for_product(
diff --git a/shop/utils.py b/shop/utils.py
index edbb38b..9886507 100644
--- a/shop/utils.py
+++ b/shop/utils.py
@@ -1,6 +1,9 @@
from decimal import Decimal
from shop.models import Customer, Order, OrderLine, Product, ProductBatch
+from django.contrib.auth import get_user_model
+
+User = get_user_model()
def create_order_line_for_product(product: Product, quantity: Decimal, order: Order):
@@ -22,7 +25,7 @@ def create_order_line_for_product(product: Product, quantity: Decimal, order: Or
def create_order(
- customer: Customer,
+ customer: User,
billing_address: str,
billing_city: str,
billing_state: str,
@@ -47,7 +50,7 @@ def create_order(
shipping_zip = shipping_zip if shipping_zip else billing_zip
order = Order.objects.create(
- customer=customer,
+ user=customer,
billing_address=billing_address,
billing_city=billing_city,
billing_state=billing_state,
diff --git a/web/templates/components/cart/cart.html b/web/templates/components/cart/cart.html
index 475566e..55ff8dc 100644
--- a/web/templates/components/cart/cart.html
+++ b/web/templates/components/cart/cart.html
@@ -1,5 +1,5 @@
{% load i18n %}
-
+
{% translate 'Carrito' %}
@@ -75,12 +75,12 @@
- {% translate 'Base imponible' %}
- - {{ base_total }}
+ - {{ base_total }} €
- {% translate 'Descuentos' %}
- - -{{ savings }}
+ - -{{ savings }} €
@@ -91,13 +91,13 @@
- {% translate 'Impuestos' %}
- - {{ tax_total }}
+ - {{ tax_total }} €
- {% translate 'Total' %}
- - {{ total }}
+ - {{ total }} €
diff --git a/web/templates/components/cart/cart_navbar.html b/web/templates/components/cart/cart_navbar.html
index 59f903b..bdafb66 100644
--- a/web/templates/components/cart/cart_navbar.html
+++ b/web/templates/components/cart/cart_navbar.html
@@ -34,7 +34,6 @@
{{ cart_item.product.price.price_with_tax }}€
-