feat: removed entire API

This commit is contained in:
2025-01-19 14:13:50 +01:00
parent 53bdf739b0
commit 97d0d27c97
31 changed files with 0 additions and 1880 deletions
View File
View File
-17
View File
@@ -1,17 +0,0 @@
from rest_framework.permissions import BasePermission
from config.api.v1.mixins import CRUDPermissionsMixin
class ProductPermissions(CRUDPermissionsMixin, BasePermission):
view_permission_codes = ("shop.view_product",)
create_permission_codes = ("shop.add_product",)
destroy_permission_codes = ("shop.delete_product",)
update_permission_codes = ("shop.change_product",)
class ProductPricePermissions(CRUDPermissionsMixin, BasePermission):
view_permission_codes = ("shop.view_productprice",)
create_permission_codes = ("shop.add_productprice",)
destroy_permission_codes = ("shop.delete_productprice",)
update_permission_codes = ("shop.change_productprice",)
-31
View File
@@ -1,31 +0,0 @@
from rest_framework.routers import DefaultRouter
from shop.api.v1.viewsets import (
BrandViewSet,
OrderLineViewSet,
OrderViewSet,
ProductBatchViewSet,
ProductPriceViewSet,
ProductViewSet,
ProviderViewSet,
TagViewSet,
TaxViewSet,
)
app_name = "shop"
router = DefaultRouter()
router.register("taxes", TaxViewSet)
router.register("tags", TagViewSet)
router.register("brands", BrandViewSet)
router.register("providers", ProviderViewSet)
router.register("products", ProductViewSet)
router.register("products/(?P<product_id>[^/.]+)/prices", ProductPriceViewSet)
router.register("product-batches", ProductBatchViewSet)
router.register("orders", OrderViewSet)
router.register("orders/(?P<order_id>[^/.]+)/lines", OrderLineViewSet)
urlpatterns = router.urls
-252
View File
@@ -1,252 +0,0 @@
from django.utils import timezone
from rest_framework import serializers
from files.api.v1.serializers import FileUploadSerializer, NoIDFileUploadSerializer
from shop.models import (
Brand,
Order,
OrderLine,
Product,
ProductBatch,
ProductPrice,
Provider,
Tag,
Tax,
)
class TaxSerializer(serializers.ModelSerializer):
class Meta:
model = Tax
fields = (
"id",
"code",
"value",
)
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
fields = (
"id",
"name",
)
class ProductPriceSerializer(serializers.ModelSerializer):
tax = TaxSerializer()
class Meta:
model = ProductPrice
fields = (
"price",
"current",
"date",
"tax",
"price_with_tax",
)
class CreateProductPriceSerializer(serializers.ModelSerializer):
class Meta:
model = ProductPrice
fields = (
"id",
"price",
"tax",
)
class ProductSerializer(serializers.ModelSerializer):
images = FileUploadSerializer(many=True, read_only=True)
price = ProductPriceSerializer()
class Meta:
model = Product
fields = (
"id",
"sku",
"name",
"description",
"stock",
"is_digital_asset",
"images",
"price",
"tags",
)
class ListProductSerializer(serializers.ModelSerializer):
price = ProductPriceSerializer()
tags = TagSerializer(many=True)
images = NoIDFileUploadSerializer(many=True, read_only=True)
class Meta:
model = Product
fields = (
"id",
"sku",
"name",
"description",
"stock",
"is_digital_asset",
"price",
"tags",
"images",
)
class CreateProductSerializer(serializers.ModelSerializer):
price = serializers.DecimalField(
max_digits=13, decimal_places=4, required=False, write_only=True
)
tax = serializers.PrimaryKeyRelatedField(
queryset=Tax.objects.all(), write_only=True
)
def create(self, validated_data):
instance = Product.objects.create(
sku=validated_data.get("sku"),
name=validated_data.get("name"),
description=validated_data.get("description"),
stock=validated_data.get("stock"),
is_digital_asset=validated_data.get("is_digital_asset"),
url=validated_data.get("url"),
)
tags = validated_data.get("tags")
for tag in tags:
instance.tags.add(tag)
ProductPrice.objects.create(
product=instance,
date=timezone.now(),
price=validated_data.get("price"),
tax=validated_data.get("tax"),
current=True,
)
return instance
class Meta:
model = Product
fields = (
"id",
"sku",
"name",
"description",
"stock",
"is_digital_asset",
"url",
"price",
"tax",
"tags",
"images",
)
class UpdateProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = (
"id",
"sku",
"name",
"description",
"stock",
"is_digital_asset",
"url",
"tags",
"images",
)
class ProductBatchSerializer(serializers.ModelSerializer):
class Meta:
model = ProductBatch
fields = (
"id",
"code",
"product",
"quantity",
"creation_date",
"expiration_date",
)
class ProviderSerializer(serializers.ModelSerializer):
class Meta:
model = Provider
fields = (
"id",
"vat_id",
"name",
"email",
"phone",
"address",
"city",
"state",
"country",
"zip",
)
class BrandSerializer(serializers.ModelSerializer):
class Meta:
model = Brand
fields = (
"id",
"name",
)
class OrderSerializer(serializers.ModelSerializer):
class Meta:
model = Order
fields = (
"uuid",
"creation_date",
"last_modification_date",
"base_total",
"total",
"user",
"billing_address",
"billing_city",
"billing_state",
"billing_country",
"billing_zip",
"shipping_address",
"shipping_city",
"shipping_state",
"shipping_country",
"shipping_zip",
"contact_phone",
)
read_only_fields = (
"uuid",
"base_total",
"total",
)
class OrderLineSerializer(serializers.ModelSerializer):
class Meta:
model = OrderLine
fields = (
"id",
"product",
"quantity",
"price",
"base_total",
"total",
"taxes",
"tax_value",
)
read_only_fields = (
"price",
"base_total",
"total",
"taxes",
"tax_value",
)
-194
View File
@@ -1,194 +0,0 @@
from decimal import Decimal
from django.db import transaction
from django.db.models.deletion import ProtectedError
from django.shortcuts import get_object_or_404
from django.utils.text import gettext_lazy as _
from rest_framework.exceptions import ValidationError
from rest_framework.permissions import IsAdminUser
from rest_framework.viewsets import ModelViewSet
from shop.api.v1.permissions import ProductPermissions, ProductPricePermissions
from shop.api.v1.serializers import (
BrandSerializer,
CreateProductPriceSerializer,
CreateProductSerializer,
ListProductSerializer,
OrderLineSerializer,
OrderSerializer,
ProductBatchSerializer,
ProductPriceSerializer,
ProductSerializer,
ProviderSerializer,
TagSerializer,
TaxSerializer,
UpdateProductSerializer,
)
from shop.filters import ProductFilter
from shop.models import (
Brand,
Order,
OrderLine,
Product,
ProductBatch,
ProductPrice,
Provider,
Tag,
Tax,
)
from shop.utils import delete_product_batch
class ProductViewSet(ModelViewSet):
serializer_class = ProductSerializer
queryset = (
Product.objects.prefetch_related("prices")
.prefetch_related("tags")
.prefetch_related("images")
.all()
)
permission_classes = (
IsAdminUser,
ProductPermissions,
)
search_fields = ("name",)
filterset_class = ProductFilter
def get_serializer_class(self):
if self.action == "create":
return CreateProductSerializer
elif self.action == "list":
return ListProductSerializer
elif self.action in ("update", "partial_update"):
return UpdateProductSerializer
return self.serializer_class
def perform_destroy(self, instance):
try:
super().perform_destroy(instance)
except ProtectedError:
raise ValidationError(_("No se puede borrar el producto"))
class ProductPriceViewSet(ModelViewSet):
serializer_class = ProductPriceSerializer
queryset = ProductPrice.objects.all()
permission_classes = (
IsAdminUser,
ProductPricePermissions,
)
def get_queryset(self):
return super().get_queryset().filter(product_id=self.kwargs.get("product_id"))
def get_serializer_class(self):
if self.action == "create":
return CreateProductPriceSerializer
return self.serializer_class
def perform_create(self, serializer):
product = get_object_or_404(Product, pk=self.kwargs.get("product_id"))
product.prices.all().update(current=False)
serializer.save(product=product, current=True)
class ProductBatchViewSet(ModelViewSet):
serializer_class = ProductBatchSerializer
queryset = ProductBatch.objects.all()
permission_classes = (IsAdminUser,)
def perform_create(self, serializer):
instance = serializer.save()
product = instance.product
product.stock += instance.quantity
product.save()
def perform_destroy(self, instance):
delete_product_batch(instance)
def perform_update(self, serializer):
instance = self.get_object()
product = instance.product
product.stock -= instance.quantity
updated_batch = serializer.save()
product.stock += updated_batch.quantity
product.save()
class ProviderViewSet(ModelViewSet):
serializer_class = ProviderSerializer
queryset = Provider.objects.all()
permission_classes = (IsAdminUser,)
class TaxViewSet(ModelViewSet):
serializer_class = TaxSerializer
queryset = Tax.objects.all()
permission_classes = (IsAdminUser,)
search_fields = ("code",)
class OrderViewSet(ModelViewSet):
serializer_class = OrderSerializer
queryset = Order.objects.all()
lookup_field = "uuid"
class OrderLineViewSet(ModelViewSet):
serializer_class = OrderLineSerializer
queryset = OrderLine.objects.all()
def perform_create(self, serializer):
with transaction.atomic():
order = get_object_or_404(Order, uuid=self.kwargs.get("order_id"))
product = serializer.validated_data.get("product")
price = product.prices.last()
tax = price.tax.value
quantity = serializer.validated_data.get("quantity")
base_total = quantity * price.price
taxes = base_total * (tax / Decimal("100"))
total = base_total + taxes
instance = serializer.save(
order=order,
price=price.price,
base_total=base_total,
tax_value=tax,
taxes=taxes,
total=total,
)
order.base_total += instance.base_total
order.total += instance.total
order.save()
def perform_destroy(self, instance):
order = instance.order
with transaction.atomic():
order.base_total -= instance.base_total
order.total -= instance.total
instance.delete()
order.save()
def get_queryset(self):
return (
super()
.get_queryset()
.select_related("order")
.filter(order__uuid=self.kwargs.get("order_id"))
)
class TagViewSet(ModelViewSet):
serializer_class = TagSerializer
queryset = Tag.objects.all()
permission_classes = (IsAdminUser,)
class BrandViewSet(ModelViewSet):
serializer_class = BrandSerializer
queryset = Brand.objects.all()
permission_classes = (IsAdminUser,)
search_fields = ("name",)
View File
-50
View File
@@ -1,50 +0,0 @@
from rest_framework import status
from rest_framework.test import APITestCase
from config.tests.mixins import TestUserAuthenticationMixin
from shop.models import Brand
class TestBrandsAPI(APITestCase, TestUserAuthenticationMixin):
model_name = "brand"
def setUp(self):
self.create_user()
def create_brands(self):
Brand.objects.create(
name="Marca",
)
def test_fetch_brands(self):
self.create_brands()
self.login()
response = self.client.get("/api/v1/shop/brands/")
assert response.status_code == status.HTTP_200_OK
assert len(response.data.get("results")) == 1
def test_create_retrieve_brand(self):
self.login()
response = self.client.post("/api/v1/shop/brands/", {"name": "Marca 1"})
assert response.status_code == status.HTTP_201_CREATED
pk = response.data.get("id")
response = self.client.get(f"/api/v1/shop/brands/{pk}/")
assert response.status_code == status.HTTP_200_OK
def test_create_update_brand(self):
self.login()
response = self.client.post("/api/v1/shop/brands/", {"name": "Marca 1"})
assert response.status_code == status.HTTP_201_CREATED
pk = response.data.get("id")
response = self.client.get(f"/api/v1/shop/brands/{pk}/")
assert response.status_code == status.HTTP_200_OK
response = self.client.patch(f"/api/v1/shop/brands/{pk}/", {"name": "Marca 2"})
assert response.status_code == status.HTTP_200_OK
response = self.client.get(f"/api/v1/shop/brands/{pk}/")
assert response.status_code == status.HTTP_200_OK
assert response.data.get("name") == "Marca 2"
-206
View File
@@ -1,206 +0,0 @@
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 CustomerAddress, Product, ProductPrice, Tax
User = get_user_model()
class TestOrdersAPI(APITestCase, TestUserAuthenticationMixin):
model_name = "productprice"
def setUp(self):
self.create_user()
self.tax = Tax.objects.create(
code="IVA",
value=21,
)
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",
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):
self.product = Product.objects.create(
name="Papafritas",
description="Las mejores papafritas",
is_digital_asset=False,
url="",
)
ProductPrice.objects.create(
product=self.product,
price=Decimal("1.20"),
tax=self.tax,
)
def test_create_retrieve_order(self):
self.login()
response = self.client.post(
f"/api/v1/shop/orders/",
{
"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,
},
)
assert response.status_code == status.HTTP_201_CREATED
pk = response.data.get("uuid")
response = self.client.get(f"/api/v1/shop/orders/{pk}/")
assert response.status_code == status.HTTP_200_OK
def test_create_retrieve_order_with_lines(self):
self.login()
response = self.client.post(
f"/api/v1/shop/orders/",
{
"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,
},
)
assert response.status_code == status.HTTP_201_CREATED
pk = response.data.get("uuid")
response = self.client.get(f"/api/v1/shop/orders/{pk}/")
assert response.status_code == status.HTTP_200_OK
assert Decimal(response.data.get("base_total")) == Decimal("0.00")
assert Decimal(response.data.get("total")) == Decimal("0.00")
response = self.client.post(
f"/api/v1/shop/orders/{pk}/lines/",
{
"product": self.product.pk,
"quantity": "5",
},
)
assert response.status_code == status.HTTP_201_CREATED
response = self.client.get(f"/api/v1/shop/orders/{pk}/lines/")
assert len(response.data.get("results")) == 1
response = self.client.get(f"/api/v1/shop/orders/{pk}/")
assert response.status_code == status.HTTP_200_OK
assert Decimal(response.data.get("base_total")) == Decimal("6.00")
assert Decimal(response.data.get("total")) == Decimal("6.00") + (
Decimal("6.00") * Decimal("0.21")
)
def test_create_delete_order_with_lines(self):
self.login()
# Create order
response = self.client.post(
f"/api/v1/shop/orders/",
{
"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,
},
)
assert response.status_code == status.HTTP_201_CREATED
pk = response.data.get("uuid")
response = self.client.get(f"/api/v1/shop/orders/{pk}/")
assert response.status_code == status.HTTP_200_OK
# Assert order is created with 0.00€
assert Decimal(response.data.get("base_total")) == Decimal("0.00")
assert Decimal(response.data.get("total")) == Decimal("0.00")
# Create order line
response = self.client.post(
f"/api/v1/shop/orders/{pk}/lines/",
{
"product": self.product.pk,
"quantity": "5",
},
)
line_pk = response.data.get("id")
assert response.status_code == status.HTTP_201_CREATED
response = self.client.get(f"/api/v1/shop/orders/{pk}/lines/")
assert len(response.data.get("results")) == 1
response = self.client.get(f"/api/v1/shop/orders/{pk}/")
assert response.status_code == status.HTTP_200_OK
# Assert order totals are set
assert Decimal(response.data.get("base_total")) == Decimal("6.00")
assert Decimal(response.data.get("total")) == Decimal("6.00") + (
Decimal("6.00") * Decimal("0.21")
)
# Delete line
response = self.client.delete(f"/api/v1/shop/orders/{pk}/lines/{line_pk}/")
assert response.status_code == status.HTTP_204_NO_CONTENT
response = self.client.get(f"/api/v1/shop/orders/{pk}/")
assert response.status_code == status.HTTP_200_OK
# Assert order totals are 0.00
assert Decimal(response.data.get("base_total")) == Decimal("0.00")
assert Decimal(response.data.get("total")) == Decimal("0.00")
-120
View File
@@ -1,120 +0,0 @@
from decimal import Decimal
from rest_framework import status
from rest_framework.test import APITestCase
from config.tests.mixins import TestUserAuthenticationMixin
from shop.models import Product, Provider
class TestProductBatchesAPI(APITestCase, TestUserAuthenticationMixin):
model_name = "productbatch"
def setUp(self):
self.create_user()
def create_provider(self):
return Provider.objects.create(
vat_id="11111111H",
name="Mandalorians",
email="din@djarin.com",
phone="612345678",
address="Mandalore",
city="Mandalore",
state="Mandalore",
country="Mandalore",
zip="12345",
)
def create_product(self):
self.product = Product.objects.create(
name="Papafritas",
description="Las mejores papafritas",
is_digital_asset=False,
url="",
)
def test_create_retrieve_product_batch(self):
self.login()
self.create_product()
provider = self.create_provider()
response = self.client.post(
"/api/v1/shop/product-batches/",
{
"code": "B00001",
"product": self.product.pk,
"quantity": "5",
"provider": provider.pk,
},
)
assert response.status_code == status.HTTP_201_CREATED
pk = response.data.get("id")
response = self.client.get(f"/api/v1/shop/product-batches/{pk}/")
self.product.refresh_from_db()
assert self.product.stock == Decimal("5")
assert response.status_code == status.HTTP_200_OK
def test_create_update_product_batch(self):
self.login()
self.create_product()
provider = self.create_provider()
response = self.client.post(
"/api/v1/shop/product-batches/",
{
"code": "B00001",
"product": self.product.pk,
"quantity": "5",
"provider": provider.pk,
},
)
assert response.status_code == status.HTTP_201_CREATED
pk = response.data.get("id")
response = self.client.get(f"/api/v1/shop/product-batches/{pk}/")
assert response.status_code == status.HTTP_200_OK
self.product.refresh_from_db()
assert self.product.stock == Decimal("5")
response = self.client.patch(
f"/api/v1/shop/product-batches/{pk}/",
{
"quantity": "10",
},
)
assert response.status_code == status.HTTP_200_OK
self.product.refresh_from_db()
assert self.product.stock == Decimal("10")
response = self.client.get(f"/api/v1/shop/product-batches/{pk}/")
assert response.status_code == status.HTTP_200_OK
assert Decimal(response.data.get("quantity")) == Decimal("10")
def test_create_delete_product_batch(self):
self.login()
self.create_product()
provider = self.create_provider()
response = self.client.post(
"/api/v1/shop/product-batches/",
{
"code": "B00001",
"product": self.product.pk,
"quantity": "5",
"provider": provider.pk,
},
)
assert response.status_code == status.HTTP_201_CREATED
pk = response.data.get("id")
response = self.client.get(f"/api/v1/shop/product-batches/{pk}/")
assert response.status_code == status.HTTP_200_OK
self.product.refresh_from_db()
assert self.product.stock == Decimal("5")
response = self.client.delete(f"/api/v1/shop/product-batches/{pk}/")
assert response.status_code == status.HTTP_204_NO_CONTENT
-116
View File
@@ -1,116 +0,0 @@
from decimal import Decimal
from rest_framework import status
from rest_framework.test import APITestCase
from config.tests.mixins import TestUserAuthenticationMixin
from shop.models import Product, ProductPrice, Tax
class TestProductPricessAPI(APITestCase, TestUserAuthenticationMixin):
model_name = "productprice"
def setUp(self):
self.create_user()
self.tax = Tax.objects.create(
code="IVA",
value=21,
)
def create_products(self):
self.product = Product.objects.create(
name="Papafritas",
description="Las mejores papafritas",
is_digital_asset=False,
url="",
)
ProductPrice.objects.create(
product=self.product,
price=Decimal("1.20"),
tax=self.tax,
)
def test_fetch_product_prices(self):
self.login()
self.create_products()
response = self.client.get(f"/api/v1/shop/products/{self.product.pk}/prices/")
assert response.status_code == status.HTTP_200_OK
assert len(response.data.get("results")) == 1
def test_create_product_prices(self):
self.login()
product = Product.objects.create(
name="Papafritas",
description="Las mejores papafritas",
is_digital_asset=False,
url="",
)
response = self.client.post(
f"/api/v1/shop/products/{product.pk}/prices/",
{
"price": "1.20",
"tax": self.tax.pk,
},
)
assert response.status_code == status.HTTP_201_CREATED
response = self.client.get(f"/api/v1/shop/products/{product.pk}/prices/")
assert response.status_code == status.HTTP_200_OK
assert len(response.data.get("results")) == 1
def test_create_update_product_prices(self):
self.login()
product = Product.objects.create(
name="Papafritas",
description="Las mejores papafritas",
is_digital_asset=False,
url="",
)
response = self.client.post(
f"/api/v1/shop/products/{product.pk}/prices/",
{
"price": "1.20",
"tax": self.tax.pk,
},
)
assert response.status_code == status.HTTP_201_CREATED
pk = response.data.get("id")
response = self.client.patch(
f"/api/v1/shop/products/{product.pk}/prices/{pk}/",
{
"price": "1.10",
},
)
assert response.status_code == status.HTTP_200_OK
response = self.client.get(f"/api/v1/shop/products/{product.pk}/prices/{pk}/")
assert response.data.get("price") == "1.10"
def test_create_delete_product_prices(self):
self.login()
product = Product.objects.create(
name="Papafritas",
description="Las mejores papafritas",
is_digital_asset=False,
url="",
)
response = self.client.post(
f"/api/v1/shop/products/{product.pk}/prices/",
{
"price": "1.20",
"tax": self.tax.pk,
},
)
assert response.status_code == status.HTTP_201_CREATED
pk = response.data.get("id")
response = self.client.delete(
f"/api/v1/shop/products/{product.pk}/prices/{pk}/"
)
assert response.status_code == status.HTTP_204_NO_CONTENT
response = self.client.get(f"/api/v1/shop/products/{product.pk}/prices/{pk}/")
assert response.status_code == status.HTTP_404_NOT_FOUND
-176
View File
@@ -1,176 +0,0 @@
import random
import string
from decimal import Decimal
from django.utils import timezone
from rest_framework import status
from rest_framework.test import APITestCase
from config.tests.mixins import TestUserAuthenticationMixin
from shop.models import Product, ProductBatch, ProductPrice, Tag, Tax
class TestProductsAPI(APITestCase, TestUserAuthenticationMixin):
model_name = "product"
def setUp(self):
self.create_user()
self.tax = Tax.objects.create(
code="IVA",
value=21,
)
self.tag = Tag.objects.create(name="Alimentos")
def get_random_sku(self):
return "".join(random.choices(string.ascii_uppercase, k=16))
def create_products(self):
self.product = Product.objects.create(
sku=self.get_random_sku(),
name="Papafritas",
description="Las mejores papafritas",
is_digital_asset=False,
url="",
)
self.product_price = ProductPrice.objects.create(
product=self.product,
price=Decimal("1.20"),
tax=self.tax,
date=timezone.now(),
)
self.batch = ProductBatch.objects.create(
code="B0001",
product=self.product,
quantity=Decimal("10"),
)
def test_fetch_products(self):
self.login()
self.create_products()
response = self.client.get("/api/v1/shop/products/")
assert response.status_code == status.HTTP_200_OK
assert len(response.data.get("results")) == 1
def test_create_product(self):
self.login()
response = self.client.post(
"/api/v1/shop/products/",
{
"sku": self.get_random_sku(),
"name": "Papafritas",
"description": "Las mejores papafritas",
"is_digital_asset": False,
"url": "",
"price": "1.20",
"stock": "100",
"tax": self.tax.pk,
"tags": [self.tag.pk],
},
)
assert response.status_code == status.HTTP_201_CREATED
pk = response.data.get("id")
response = self.client.get(f"/api/v1/shop/products/{pk}/")
assert response.status_code == status.HTTP_200_OK
def test_create_update_product(self):
self.login()
response = self.client.post(
"/api/v1/shop/products/",
{
"sku": self.get_random_sku(),
"name": "Papafritas",
"description": "Las mejores papafritas",
"is_digital_asset": False,
"url": "",
"price": "1.20",
"stock": "100",
"tax": self.tax.pk,
"tags": [
self.tag.pk,
],
},
)
assert response.status_code == status.HTTP_201_CREATED
pk = response.data.get("id")
response = self.client.get(f"/api/v1/shop/products/{pk}/")
assert response.status_code == status.HTTP_200_OK
response = self.client.patch(
f"/api/v1/shop/products/{pk}/", {"name": "Papafritas pafritas"}
)
assert response.status_code == status.HTTP_200_OK
response = self.client.get(f"/api/v1/shop/products/{pk}/")
assert response.data.get("name") == "Papafritas pafritas"
def test_create_delete_product(self):
self.login()
response = self.client.post(
"/api/v1/shop/products/",
{
"sku": self.get_random_sku(),
"name": "Papafritas",
"description": "Las mejores papafritas",
"is_digital_asset": False,
"url": "",
"price": "1.20",
"stock": "100",
"tax": self.tax.pk,
"tags": [
self.tag.pk,
],
},
)
assert response.status_code == status.HTTP_201_CREATED
pk = response.data.get("id")
response = self.client.get(f"/api/v1/shop/products/{pk}/")
assert response.status_code == status.HTTP_200_OK
response = self.client.delete(f"/api/v1/shop/products/{pk}/")
assert response.status_code == status.HTTP_204_NO_CONTENT
response = self.client.get(f"/api/v1/shop/products/{pk}/")
assert response.status_code == status.HTTP_404_NOT_FOUND
def test_create_cannot_delete_product_with_a_batch(self):
self.login()
self.create_products()
response = self.client.get(f"/api/v1/shop/products/{self.product.pk}/")
assert response.status_code == status.HTTP_200_OK
response = self.client.delete(f"/api/v1/shop/products/{self.product.pk}/")
assert response.status_code == status.HTTP_400_BAD_REQUEST
def test_create_update_product_tags(self):
self.login()
tag = Tag.objects.create(name="Alimentación")
response = self.client.post(
"/api/v1/shop/products/",
{
"sku": self.get_random_sku(),
"name": "Papafritas",
"description": "Las mejores papafritas",
"is_digital_asset": False,
"url": "",
"price": "1.20",
"stock": "100",
"tax": self.tax.pk,
"tags": [
self.tag.pk,
],
},
)
assert response.status_code == status.HTTP_201_CREATED
pk = response.data.get("id")
response = self.client.get(f"/api/v1/shop/products/{pk}/")
assert response.status_code == status.HTTP_200_OK
response = self.client.patch(f"/api/v1/shop/products/{pk}/", {"tags": [tag.pk]})
assert response.status_code == status.HTTP_200_OK
response = self.client.get(f"/api/v1/shop/products/{pk}/")
assert response.data.get("tags", [])[0] == tag.pk
-66
View File
@@ -1,66 +0,0 @@
from rest_framework import status
from rest_framework.test import APITestCase
from config.tests.mixins import TestUserAuthenticationMixin
class TestProvidersAPI(APITestCase, TestUserAuthenticationMixin):
model_name = "provider"
def setUp(self):
self.create_user()
def test_create_retrieve_provider(self):
self.login()
response = self.client.post(
f"/api/v1/shop/providers/",
{
"vat_id": "11111111H",
"name": "Darth Maul",
"email": "darth@maul.com",
"address": "Dathomir",
"city": "Dathomir",
"state": "Dathomir",
"country": "Dathomir",
"zip": "00001",
},
)
assert response.status_code == status.HTTP_201_CREATED
pk = response.data.get("id")
response = self.client.get(f"/api/v1/shop/providers/{pk}/")
assert response.status_code == status.HTTP_200_OK
def test_create_update_provider(self):
self.login()
response = self.client.post(
f"/api/v1/shop/providers/",
{
"vat_id": "11111111H",
"name": "Darth Maul",
"email": "darth@maul.com",
"address": "Dathomir",
"city": "Dathomir",
"state": "Dathomir",
"country": "Dathomir",
"zip": "00001",
},
)
assert response.status_code == status.HTTP_201_CREATED
pk = response.data.get("id")
response = self.client.get(f"/api/v1/shop/providers/{pk}/")
assert response.status_code == status.HTTP_200_OK
response = self.client.patch(
f"/api/v1/shop/providers/{pk}/",
{
"address": "Mandalore",
},
)
assert response.status_code == status.HTTP_200_OK
response = self.client.get(f"/api/v1/shop/providers/{pk}/")
assert response.status_code == status.HTTP_200_OK
assert response.data.get("address") == "Mandalore"
-50
View File
@@ -1,50 +0,0 @@
from rest_framework import status
from rest_framework.test import APITestCase
from config.tests.mixins import TestUserAuthenticationMixin
from shop.models import Tag
class TestTagsAPI(APITestCase, TestUserAuthenticationMixin):
model_name = "tag"
def setUp(self):
self.create_user()
def create_tags(self):
Tag.objects.create(name="Deportes")
def test_fetch_taxes(self):
self.create_tags()
self.login()
response = self.client.get("/api/v1/shop/tags/")
assert response.status_code == status.HTTP_200_OK
assert len(response.data.get("results")) == 1
def test_create_retrieve_tax(self):
self.login()
response = self.client.post("/api/v1/shop/tags/", {"name": "Videojuegos"})
assert response.status_code == status.HTTP_201_CREATED
pk = response.data.get("id")
response = self.client.get(f"/api/v1/shop/tags/{pk}/")
assert response.status_code == status.HTTP_200_OK
def test_create_update_tax(self):
self.login()
response = self.client.post("/api/v1/shop/tags/", {"name": "Videojuegos"})
assert response.status_code == status.HTTP_201_CREATED
pk = response.data.get("id")
response = self.client.get(f"/api/v1/shop/tags/{pk}/")
assert response.status_code == status.HTTP_200_OK
response = self.client.patch(
f"/api/v1/shop/tags/{pk}/", {"name": "Juegos de mesa"}
)
assert response.status_code == status.HTTP_200_OK
response = self.client.get(f"/api/v1/shop/tags/{pk}/")
assert response.status_code == status.HTTP_200_OK
assert response.data.get("name") == "Juegos de mesa"
-54
View File
@@ -1,54 +0,0 @@
from rest_framework import status
from rest_framework.test import APITestCase
from config.tests.mixins import TestUserAuthenticationMixin
from shop.models import Tax
class TestTaxesAPI(APITestCase, TestUserAuthenticationMixin):
model_name = "tax"
def setUp(self):
self.create_user()
def create_taxes(self):
Tax.objects.create(
code="IVA",
value=21,
)
def test_fetch_taxes(self):
self.create_taxes()
self.login()
response = self.client.get("/api/v1/shop/taxes/")
assert response.status_code == status.HTTP_200_OK
assert len(response.data.get("results")) == 1
def test_create_retrieve_tax(self):
self.login()
response = self.client.post("/api/v1/shop/taxes/", {"code": "IVA5", "value": 5})
assert response.status_code == status.HTTP_201_CREATED
pk = response.data.get("id")
response = self.client.get(f"/api/v1/shop/taxes/{pk}/")
assert response.status_code == status.HTTP_200_OK
def test_create_update_tax(self):
self.login()
response = self.client.post("/api/v1/shop/taxes/", {"code": "IVA5", "value": 5})
assert response.status_code == status.HTTP_201_CREATED
pk = response.data.get("id")
response = self.client.get(f"/api/v1/shop/taxes/{pk}/")
assert response.status_code == status.HTTP_200_OK
response = self.client.patch(
f"/api/v1/shop/taxes/{pk}/", {"code": "IVA10", "value": 10}
)
assert response.status_code == status.HTTP_200_OK
response = self.client.get(f"/api/v1/shop/taxes/{pk}/")
assert response.status_code == status.HTTP_200_OK
assert response.data.get("code") == "IVA10"
assert response.data.get("value") == 10
-36
View File
@@ -1,36 +0,0 @@
from decimal import Decimal
from django.test import TestCase
from shop.filters import ProductFilter
from shop.models import Product
from shop.tests.mixins import CreateProductsMixin
class TestProductFilter(TestCase, CreateProductsMixin):
def setUp(self):
product_a = self.create_product(
name="producto 1", sku="001", price=Decimal("40.00")
)
product_b = self.create_product(
name="producto 2", sku="002", price=Decimal("70.00")
)
product_c = self.create_product(
name="producto 3", sku="003", price=Decimal("100.00")
)
def test_product_filter_by_price(self):
f = ProductFilter({"price_gt": "40"})
f.is_valid()
qs = f.filter_queryset(Product.objects.all())
assert qs.count() == 3
f = ProductFilter({"price_lt": "40"})
f.is_valid()
qs = f.filter_queryset(Product.objects.all())
assert qs.count() == 0
f = ProductFilter({"price_gt": "100"})
f.is_valid()
qs = f.filter_queryset(Product.objects.all())
assert qs.count() == 1
-102
View File
@@ -1,102 +0,0 @@
from decimal import Decimal
from django.contrib.auth import get_user_model
from rest_framework.test import APITestCase as TestCase
from shop.models import CustomerAddress, Product, ProductPrice, Tax
from shop.utils import create_order, create_order_line_for_product
User = get_user_model()
class ShopModelsTest(TestCase):
def setUp(self) -> None:
self.tax = Tax.objects.create(
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):
self.potatoes = Product.objects.create(
sku="0000001",
name="Patatas",
stock=Decimal("100.00"),
)
self.gasoline = Product.objects.create(
sku="0000002",
name="Gasolina",
stock=Decimal("800.00"),
)
self.usb_c = Product.objects.create(
sku="0000003",
name="Cable USB-C",
stock=Decimal("5.00"),
)
ProductPrice.objects.create(
product=self.potatoes, price=Decimal("0.80"), tax=self.tax
)
ProductPrice.objects.create(
product=self.gasoline, price=Decimal("1.15"), tax=self.tax
)
ProductPrice.objects.create(
product=self.usb_c, price=Decimal("9.95"), tax=self.tax
)
def test_create_order(self):
order = create_order(
customer=self.customer,
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(
self.potatoes,
quantity=Decimal("1.5"),
order=order,
)
l2 = create_order_line_for_product(
self.gasoline,
quantity=Decimal("40"),
order=order,
)
l3 = create_order_line_for_product(
self.usb_c,
quantity=Decimal("1.00"),
order=order,
)
order.calculate_total_from_lines()
assert order.total == l1.total + l2.total + l3.total
assert order.base_total == l1.base_total + l2.base_total + l3.base_total