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 }}€

-
diff --git a/web/templates/components/users/user_dropdown.html b/web/templates/components/users/user_dropdown.html index 5d8ff89..7e8d53e 100644 --- a/web/templates/components/users/user_dropdown.html +++ b/web/templates/components/users/user_dropdown.html @@ -1,7 +1,7 @@ {% load i18n %}
  • - {% translate 'Mi cuenta' %} diff --git a/web/templates/users/user_details.html b/web/templates/users/user_details.html new file mode 100644 index 0000000..a658b4c --- /dev/null +++ b/web/templates/users/user_details.html @@ -0,0 +1,436 @@ +{% extends 'theme/base.html' %} +{% load i18n %} +{% block main %} + {% include 'components/generic/navbar.html' %} +
    +
    +

    {% translate 'Mi cuenta' %}

    + +
    +
    +
    +
    +
    +

    Helene Engels

    +
    +
    +
    +
    Email Address
    +
    helene@example.com
    +
    +
    +
    Home Address
    +
    + + 2 Miles Drive, NJ 071, New York, United States of America +
    +
    +
    +
    Delivery Address
    +
    + + 9th St. PATH Station, New York, United States of America +
    +
    +
    +
    +
    +
    Phone Number
    +
    +1234 567 890 / +12 345 678
    +
    +
    +
    Favorite pick-up point
    +
    + + Herald Square, 2, New York, United States of America +
    +
    +
    +
    My Companies
    +
    FLOWBITE LLC, Fiscal code: 18673557
    +
    +
    +
    Payment Methods
    +
    +
    + + +
    +
    +
    +

    Visa ending in 7658

    +

    Expiry 10/2024

    +
    +
    +
    +
    +
    +
    + +
    +
    + + + + +
    +{% endblock %} \ No newline at end of file diff --git a/web/urls.py b/web/urls.py index 702c4a1..0938823 100644 --- a/web/urls.py +++ b/web/urls.py @@ -1,7 +1,7 @@ from django.urls import path from web.views.components import cart, cart_dropdown, list_products -from web.views.users import login, logout, register, reset_password +from web.views.users import login, logout, my_account, register, reset_password from web.views.web import ( add_cart_item, cart_detail, @@ -22,6 +22,7 @@ urlpatterns = [ path("logout/", logout, name="logout"), path("register/", register, name="register"), path("reset-password/", reset_password, name="reset-password"), + path("my-account/", my_account, name="my_account"), # components path("web/components/products/", list_products, name="list_products"), path("web/components/cart-dropdown/", cart_dropdown, name="cart_dropdown"), diff --git a/web/views/users.py b/web/views/users.py index 6cc8576..e49d4d3 100644 --- a/web/views/users.py +++ b/web/views/users.py @@ -74,7 +74,13 @@ class ResetPasswordView(TemplateView): template_name = "web/reset-password.html" +class MyAccountView(TemplateView): + template_name = "users/user_details.html" + + login = LoginView.as_view() logout = LogoutView.as_view() register = RegisterView.as_view() reset_password = ResetPasswordView.as_view() + +my_account = MyAccountView.as_view()