diff --git a/shop/migrations/0005_alter_order_options_order_amount_paid_and_more.py b/shop/migrations/0005_alter_order_options_order_amount_paid_and_more.py
new file mode 100644
index 0000000..61b291f
--- /dev/null
+++ b/shop/migrations/0005_alter_order_options_order_amount_paid_and_more.py
@@ -0,0 +1,44 @@
+# Generated by Django 5.1.4 on 2025-01-16 17:00
+
+import django.db.models.deletion
+from decimal import Decimal
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("shop", "0004_shopsettings_tpv_domain"),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name="order",
+ options={
+ "ordering": ("creation_date",),
+ "verbose_name": "pedido",
+ "verbose_name_plural": "pedidos",
+ },
+ ),
+ migrations.AddField(
+ model_name="order",
+ name="amount_paid",
+ field=models.DecimalField(
+ decimal_places=2,
+ default=Decimal("0.00"),
+ max_digits=11,
+ verbose_name="cantidad pagada",
+ ),
+ ),
+ migrations.AddField(
+ model_name="order",
+ name="from_cart",
+ field=models.ForeignKey(
+ blank=True,
+ null=True,
+ on_delete=django.db.models.deletion.SET_NULL,
+ to="shop.cart",
+ verbose_name="carrito de origen de pedido",
+ ),
+ ),
+ ]
diff --git a/shop/models.py b/shop/models.py
index dd2b953..c673be9 100644
--- a/shop/models.py
+++ b/shop/models.py
@@ -429,6 +429,13 @@ class Order(TimestampedModel):
max_length=32, blank=True, verbose_name=_("teléfono de contacto")
)
+ amount_paid = models.DecimalField(
+ default=Decimal("0.00"),
+ max_digits=11,
+ decimal_places=2,
+ verbose_name=_("cantidad pagada"),
+ )
+
shipping_method = models.ForeignKey(
"shop.ShippingMethod",
blank=True,
@@ -437,6 +444,14 @@ class Order(TimestampedModel):
verbose_name=_("método de envío"),
)
+ from_cart = models.ForeignKey(
+ "shop.Cart",
+ on_delete=models.SET_NULL,
+ blank=True,
+ null=True,
+ verbose_name=_("carrito de origen de pedido"),
+ )
+
def calculate_total_from_lines(self):
self.base_total = self.lines.aggregate(base_total=models.Sum("base_total")).get(
"base_total"
diff --git a/shop/utils.py b/shop/utils.py
index ab97de2..13bea48 100644
--- a/shop/utils.py
+++ b/shop/utils.py
@@ -7,6 +7,7 @@ from decimal import Decimal
import pyDes
from django.contrib.auth import get_user_model
from django.db import transaction
+from django.db.models import Sum
from django.utils import timezone
from django.utils.text import gettext_lazy as _
@@ -20,8 +21,10 @@ from shop.models import (
ProductBatch,
ProductPrice,
ShippingMethod,
+ CartItem,
)
from shop.settings import ERROR_CODES
+from shop.signals import clear_cart
User = get_user_model()
@@ -114,6 +117,7 @@ def create_order_from_cart(
shipping_method=shipping_method,
user=cart.user,
email=email,
+ from_cart=cart,
)
for item in cart.items.all():
@@ -261,15 +265,34 @@ def validate_expiry_date(expiry_date: str):
return True
-def pay_order(order: Order, amount_paid: Decimal):
- with transaction.atomic() as tx:
+def update_order_payment_status(order: Order):
+ if order.amount_paid >= order.total:
+ order.status = Order.Statuses.STATUS_PAID
+ elif order.status == Order.Statuses.STATUS_PAID and order.amount_paid == Decimal(
+ "0.00"
+ ):
+ order.status = Order.Statuses.STATUS_RETURNED
+ else:
+ order.status = Order.Statuses.STATUS_PENDING
+
+ order.save()
+
+
+def delete_cart_items_from_order(order):
+ if order.status == Order.Statuses.STATUS_PAID and order.from_cart:
+ CartItem.objects.filter(cart=order.from_cart).delete()
+
+
+def add_payment_to_order(order: Order, amount):
+ with transaction.atomic():
payment = Payment.objects.create(
- amount=amount_paid,
+ amount=amount,
order=order,
user=order.user,
method=Payment.MethodChoices.REDSYS,
)
+ order.amount_paid += payment.amount
- if amount_paid >= order.total:
- order.status = Order.Statuses.STATUS_PAID
- order.save()
+ update_order_payment_status(order)
+
+ delete_cart_items_from_order(order)
diff --git a/shop/views.py b/shop/views.py
index 76c2158..b48ecf8 100644
--- a/shop/views.py
+++ b/shop/views.py
@@ -3,7 +3,7 @@ from django.shortcuts import get_object_or_404
from django.views.decorators.csrf import csrf_exempt
from shop.models import Order
-from shop.utils import pay_order, validate_payment_for_order
+from shop.utils import validate_payment_for_order, add_payment_to_order
@csrf_exempt
@@ -12,7 +12,7 @@ def webhook(request, uuid):
try:
amount_paid = validate_payment_for_order(request, order)
- pay_order(order, amount_paid)
+ add_payment_to_order(order, amount_paid)
return HttpResponse(status=200)
except Exception as e:
diff --git a/web/forms.py b/web/forms.py
index ee9ba4f..66cc568 100644
--- a/web/forms.py
+++ b/web/forms.py
@@ -8,6 +8,7 @@ class CartItemForm(forms.Form):
"""
+
product = forms.IntegerField(widget=widgets.HiddenInput)
quantity = forms.IntegerField()
diff --git a/web/tests/test_manifest.py b/web/tests/test_manifest.py
index 93db4a5..b7bf3cb 100644
--- a/web/tests/test_manifest.py
+++ b/web/tests/test_manifest.py
@@ -11,10 +11,13 @@ class TestManifest(TestCase):
def setUp(self):
self.settings = WebSettings.load()
- with open(os.path.join(settings.BASE_DIR, 'web', 'tests', 'images', 'trolley.png'), 'rb') as f:
- file_128 = SimpleUploadedFile('logo_128.png', f.read())
+ with open(
+ os.path.join(settings.BASE_DIR, "web", "tests", "images", "trolley.png"),
+ "rb",
+ ) as f:
+ file_128 = SimpleUploadedFile("logo_128.png", f.read())
self.settings.logo_128 = file_128
- file_240 = SimpleUploadedFile('logo_240.png', f.read())
+ file_240 = SimpleUploadedFile("logo_240.png", f.read())
self.settings.logo_240 = file_240
self.settings.logo = file_240
self.settings.save()
diff --git a/web/tests/test_orders.py b/web/tests/test_orders.py
index e23a008..adbeca3 100644
--- a/web/tests/test_orders.py
+++ b/web/tests/test_orders.py
@@ -4,14 +4,23 @@ from django.contrib.auth.models import User
from django.test import TestCase
from django.urls import reverse
-from shop.models import Cart, CartItem, Order, CustomerAddress, ShippingMethod, ShopSettings
+from shop.models import (
+ Cart,
+ CartItem,
+ Order,
+ CustomerAddress,
+ ShippingMethod,
+ ShopSettings,
+)
from shop.tests.mixins import CreateProductsMixin
class TestOrders(TestCase, CreateProductsMixin):
def setUp(self):
self.product = self.create_product()
- self.user = User.objects.create_user("anakin", "anakin@skywalker.com", "ihatesand")
+ self.user = User.objects.create_user(
+ "anakin", "anakin@skywalker.com", "ihatesand"
+ )
self.cart_for_user = self.create_cart(user=self.user)
self.anonymous_cart = self.create_cart()
self.address = CustomerAddress.objects.create(