feat: lots of stuff
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# Generated by Django 5.0.3 on 2024-03-24 12:51
|
||||
# Generated by Django 5.0.3 on 2024-03-24 18:23
|
||||
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
@@ -13,6 +13,43 @@ class Migration(migrations.Migration):
|
||||
dependencies = []
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="Customer",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"vat_id",
|
||||
models.CharField(
|
||||
max_length=32,
|
||||
unique=True,
|
||||
verbose_name="Documento de identidad",
|
||||
),
|
||||
),
|
||||
("first_name", models.CharField(max_length=64, verbose_name="Nombre")),
|
||||
(
|
||||
"last_name",
|
||||
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")),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "Cliente",
|
||||
"verbose_name_plural": "Clientes",
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="OrderLine",
|
||||
fields=[
|
||||
@@ -189,6 +226,68 @@ class Migration(migrations.Migration):
|
||||
verbose_name="Total",
|
||||
),
|
||||
),
|
||||
(
|
||||
"billing_address",
|
||||
models.CharField(
|
||||
max_length=255, verbose_name="Dirección de facturación"
|
||||
),
|
||||
),
|
||||
(
|
||||
"billing_city",
|
||||
models.CharField(
|
||||
max_length=64, verbose_name="Ciudad de facturación"
|
||||
),
|
||||
),
|
||||
(
|
||||
"billing_state",
|
||||
models.CharField(
|
||||
max_length=64, verbose_name="Región de facturación"
|
||||
),
|
||||
),
|
||||
(
|
||||
"billing_country",
|
||||
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"
|
||||
),
|
||||
),
|
||||
(
|
||||
"shipping_address",
|
||||
models.CharField(max_length=255, verbose_name="Dirección"),
|
||||
),
|
||||
(
|
||||
"shipping_city",
|
||||
models.CharField(max_length=64, verbose_name="Ciudad"),
|
||||
),
|
||||
(
|
||||
"shipping_state",
|
||||
models.CharField(max_length=64, verbose_name="Región"),
|
||||
),
|
||||
(
|
||||
"shipping_country",
|
||||
models.CharField(max_length=64, verbose_name="País"),
|
||||
),
|
||||
(
|
||||
"shipping_zip",
|
||||
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"
|
||||
),
|
||||
),
|
||||
(
|
||||
"customer",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to="shop.customer",
|
||||
verbose_name="Cliente",
|
||||
),
|
||||
),
|
||||
(
|
||||
"lines",
|
||||
models.ManyToManyField(to="shop.orderline", verbose_name="Líneas"),
|
||||
|
||||
@@ -80,6 +80,33 @@ class Tax(models.Model):
|
||||
verbose_name_plural = _("Impuestos")
|
||||
|
||||
|
||||
class Customer(models.Model):
|
||||
vat_id = models.CharField(
|
||||
max_length=32,
|
||||
blank=False,
|
||||
unique=True,
|
||||
verbose_name=_("Documento de identidad"),
|
||||
)
|
||||
first_name = models.CharField(max_length=64, blank=False, verbose_name=_("Nombre"))
|
||||
last_name = models.CharField(
|
||||
max_length=64, blank=False, verbose_name=_("Apellidos")
|
||||
)
|
||||
email = models.EmailField(blank=False, verbose_name=_("E-mail"))
|
||||
|
||||
address = models.CharField(max_length=255, blank=False, verbose_name=_("Dirección"))
|
||||
city = models.CharField(max_length=64, blank=False, verbose_name=_("Ciudad"))
|
||||
state = models.CharField(max_length=64, blank=False, verbose_name=_("Región"))
|
||||
country = models.CharField(max_length=64, blank=False, verbose_name=_("País"))
|
||||
zip = models.CharField(max_length=32, blank=False, verbose_name=_("Código postal"))
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.vat_id} - {self.first_name} {self.last_name}"
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Cliente")
|
||||
verbose_name_plural = _("Clientes")
|
||||
|
||||
|
||||
class OrderLine(models.Model):
|
||||
product = models.ForeignKey(
|
||||
"shop.Product",
|
||||
@@ -154,6 +181,48 @@ class Order(models.Model):
|
||||
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")
|
||||
)
|
||||
|
||||
# Billing information
|
||||
billing_address = models.CharField(
|
||||
max_length=255, blank=False, verbose_name=_("Dirección de facturación")
|
||||
)
|
||||
billing_city = models.CharField(
|
||||
max_length=64, blank=False, verbose_name=_("Ciudad de facturación")
|
||||
)
|
||||
billing_state = models.CharField(
|
||||
max_length=64, blank=False, verbose_name=_("Región de facturación")
|
||||
)
|
||||
billing_country = models.CharField(
|
||||
max_length=64, blank=False, verbose_name=_("País de facturación")
|
||||
)
|
||||
billing_zip = models.CharField(
|
||||
max_length=32, blank=False, verbose_name=_("Código postal de facturación")
|
||||
)
|
||||
|
||||
# Shipping information
|
||||
shipping_address = models.CharField(
|
||||
max_length=255, blank=False, verbose_name=_("Dirección")
|
||||
)
|
||||
shipping_city = models.CharField(
|
||||
max_length=64, blank=False, verbose_name=_("Ciudad")
|
||||
)
|
||||
shipping_state = models.CharField(
|
||||
max_length=64, blank=False, verbose_name=_("Región")
|
||||
)
|
||||
shipping_country = models.CharField(
|
||||
max_length=64, blank=False, verbose_name=_("País")
|
||||
)
|
||||
shipping_zip = models.CharField(
|
||||
max_length=32, blank=False, verbose_name=_("Código postal")
|
||||
)
|
||||
contact_phone = models.CharField(
|
||||
max_length=32, blank=True, verbose_name=_("Teléfono de contacto")
|
||||
)
|
||||
|
||||
def calculate_total_from_lines(self):
|
||||
self.base_total = self.lines.aggregate(base_total=models.Sum("base_total")).get(
|
||||
"base_total"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from decimal import Decimal
|
||||
from rest_framework.test import APITestCase as TestCase
|
||||
from shop.models import Product, ProductPrice, OrderLine, Tax
|
||||
from shop.models import Product, ProductPrice, OrderLine, Tax, Customer
|
||||
from shop.utils import create_order_line_for_product, create_order
|
||||
|
||||
|
||||
@@ -34,6 +34,17 @@ class ShopModelsTest(TestCase):
|
||||
ProductPrice.objects.create(product=self.usb_c, price=Decimal("9.95"))
|
||||
|
||||
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',
|
||||
)
|
||||
|
||||
l1 = create_order_line_for_product(
|
||||
self.potatoes,
|
||||
quantity=Decimal("1.5"),
|
||||
@@ -50,7 +61,15 @@ class ShopModelsTest(TestCase):
|
||||
tax=self.tax,
|
||||
)
|
||||
|
||||
order = create_order(OrderLine.objects.all())
|
||||
order = create_order(
|
||||
customer=self.customer,
|
||||
lines=OrderLine.objects.all(),
|
||||
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,
|
||||
)
|
||||
|
||||
assert order.total == l1.total + l2.total + l3.total
|
||||
assert order.base_total == l1.base_total + l2.base_total + l3.base_total
|
||||
|
||||
+47
-4
@@ -1,5 +1,7 @@
|
||||
from decimal import Decimal
|
||||
from shop.models import OrderLine, Tax, Product, Order
|
||||
from typing import Iterable
|
||||
|
||||
from shop.models import OrderLine, Tax, Product, Order, Customer
|
||||
from django.db.models import QuerySet
|
||||
|
||||
|
||||
@@ -19,10 +21,51 @@ def create_order_line_for_product(product: Product, quantity: Decimal, tax: Tax)
|
||||
)
|
||||
|
||||
|
||||
def create_order(lines: QuerySet):
|
||||
order = Order.objects.create()
|
||||
def create_order(
|
||||
customer: Customer,
|
||||
lines: Iterable,
|
||||
|
||||
for line in lines.all():
|
||||
billing_address: str,
|
||||
billing_city: str,
|
||||
billing_state: str,
|
||||
billing_country: str,
|
||||
billing_zip: str,
|
||||
|
||||
shipping_address: str = '',
|
||||
shipping_city: str = '',
|
||||
shipping_state: str = '',
|
||||
shipping_country: str = '',
|
||||
shipping_zip: str = '',
|
||||
) -> Order:
|
||||
billing_address = billing_address if billing_address else customer.address
|
||||
billing_city = billing_city if billing_city else customer.city
|
||||
billing_state = billing_state if billing_state else customer.state
|
||||
billing_country = billing_country if billing_country else customer.country
|
||||
billing_zip = billing_zip if billing_zip else customer.zip
|
||||
|
||||
shipping_address = shipping_address if shipping_address else billing_address
|
||||
shipping_city = shipping_city if shipping_city else billing_city
|
||||
shipping_state = shipping_state if shipping_state else billing_state
|
||||
shipping_country = shipping_country if shipping_country else billing_country
|
||||
shipping_zip = shipping_zip if shipping_zip else billing_zip
|
||||
|
||||
order = Order.objects.create(
|
||||
customer=customer,
|
||||
|
||||
billing_address=billing_address,
|
||||
billing_city=billing_city,
|
||||
billing_state=billing_state,
|
||||
billing_country=billing_country,
|
||||
billing_zip=billing_zip,
|
||||
|
||||
shipping_address=shipping_address,
|
||||
shipping_city=shipping_city,
|
||||
shipping_state=shipping_state,
|
||||
shipping_country=shipping_country,
|
||||
shipping_zip=shipping_zip,
|
||||
)
|
||||
|
||||
for line in lines:
|
||||
order.lines.add(line)
|
||||
|
||||
order.calculate_total_from_lines()
|
||||
|
||||
Reference in New Issue
Block a user