feat: added product variants

This commit is contained in:
2026-07-23 11:37:37 +02:00
parent 5786c07077
commit 87405f31fa
22 changed files with 818 additions and 315 deletions
+59
View File
@@ -166,3 +166,62 @@ class TestCart(TestCase, CreateProductsMixin):
self.client.force_login(self.user)
response = self.client.get(reverse('web:cart'))
assert response.status_code == 200
def test_add_product_variant_to_cart(self):
size_m = self.create_attribute_value('Talla', 'M')
variant = self.create_product_variant(self.product, sku='V1', attribute_values=[size_m])
quantity = 2
response = self.client.post(
reverse('web:add_cart_item'),
{'product': self.product.pk, 'variant': variant.pk, 'quantity': quantity},
)
assert response.status_code == 201
cart_item = CartItem.objects.filter(cart__uuid=response.cookies.get(ANONYMOUS_CART_ID_COOKIE_NAME).value).first()
assert cart_item is not None
assert cart_item.variant == variant
assert cart_item.quantity == quantity
def test_add_product_with_variants_without_selecting_one_fails(self):
size_m = self.create_attribute_value('Talla', 'M')
self.create_product_variant(self.product, sku='V1', attribute_values=[size_m])
response = self.client.post(reverse('web:add_cart_item'), {'product': self.product.pk, 'quantity': 1})
assert response.status_code == 404
assert CartItem.objects.count() == 0
def test_add_same_product_different_variants_creates_separate_lines(self):
size_m = self.create_attribute_value('Talla', 'M')
size_l = self.create_attribute_value('Talla', 'L')
variant_m = self.create_product_variant(self.product, sku='V1', attribute_values=[size_m])
variant_l = self.create_product_variant(self.product, sku='V2', attribute_values=[size_l])
self.client.force_login(self.user)
response = self.client.post(
reverse('web:add_cart_item'), {'product': self.product.pk, 'variant': variant_m.pk, 'quantity': 1}
)
assert response.status_code == 201
response = self.client.post(
reverse('web:add_cart_item'), {'product': self.product.pk, 'variant': variant_l.pk, 'quantity': 1}
)
assert response.status_code == 201
cart = Cart.objects.get(user=self.user)
assert CartItem.objects.filter(cart=cart).count() == 2
def test_add_same_product_and_variant_multiple_times_sums_quantity(self):
size_m = self.create_attribute_value('Talla', 'M')
variant = self.create_product_variant(self.product, sku='V1', attribute_values=[size_m])
self.client.force_login(self.user)
self.client.post(
reverse('web:add_cart_item'), {'product': self.product.pk, 'variant': variant.pk, 'quantity': 1}
)
self.client.post(
reverse('web:add_cart_item'), {'product': self.product.pk, 'variant': variant.pk, 'quantity': 1}
)
cart = Cart.objects.get(user=self.user)
assert CartItem.objects.filter(cart=cart).count() == 1
assert CartItem.objects.get(cart=cart).quantity == 2
+35 -1
View File
@@ -4,7 +4,7 @@ from django.contrib.auth.models import User
from django.test import TestCase
from django.urls import reverse
from shop.models import Cart, CartItem, CustomerAddress, Order, ShippingMethod, ShopSettings
from shop.models import Cart, CartItem, CustomerAddress, Order, OrderLine, ShippingMethod, ShopSettings
from shop.tests.mixins import CreateProductsMixin
@@ -111,3 +111,37 @@ class TestOrders(TestCase, CreateProductsMixin):
assert response.status_code == 200
assert not Order.objects.filter(user=self.user).exists()
def test_order_from_cart_with_variant_uses_variant_price(self):
size_m = self.create_attribute_value('Talla', 'M')
variant = self.create_product_variant(self.product, sku='V1', price=Decimal('25.00'), attribute_values=[size_m])
CartItem.objects.create(cart=self.cart_for_user, product=self.product, variant=variant, quantity=1)
self.client.force_login(self.user)
data = {
'email': self.user.email,
'shipping_address_full_name': self.address.full_name,
'shipping_address': self.address.address,
'shipping_address_town': self.address.address_town,
'shipping_address_zip': self.address.address_zip,
'shipping_address_state': self.address.address_state,
'shipping_address_country': self.address.address_country,
'shipping_address_phone': self.address.address_phone,
'same_as_shipping': True,
'billing_address_full_name': self.address.full_name,
'billing_address': self.address.address,
'billing_address_town': self.address.address_town,
'billing_address_zip': self.address.address_zip,
'billing_address_state': self.address.address_state,
'billing_address_country': self.address.address_country,
'billing_address_phone': self.address.address_phone,
'shipping_method': self.shipping_method.pk,
}
response = self.client.post(reverse('web:cart_detail'), data)
assert response.status_code == 302
order = Order.objects.get(user=self.user)
variant_line = OrderLine.objects.get(order=order, variant=variant)
assert variant_line.price == Decimal('25.00')