feat: added lots of tests
This commit is contained in:
@@ -9,7 +9,7 @@ urlpatterns = [
|
||||
"swagger/", SpectacularSwaggerView.as_view(url_name="schema"), name="swagger-ui"
|
||||
),
|
||||
path("redoc/", SpectacularRedocView.as_view(url_name="schema"), name="redoc"),
|
||||
path("shop/", include("shop.api.v1.routers")),
|
||||
path("files/", include("files.api.v1.urls")),
|
||||
path("auth/", include("users.api.v1.urls")),
|
||||
path("shop/", include("shop.api.v1.routers", namespace="shop")),
|
||||
path("files/", include("files.api.v1.urls", namespace="files")),
|
||||
path("auth/", include("users.api.v1.urls", namespace="auth")),
|
||||
]
|
||||
|
||||
@@ -2,6 +2,10 @@ from rest_framework.routers import DefaultRouter
|
||||
|
||||
from files.api.v1.views import FileUploadViewSet
|
||||
|
||||
|
||||
app_name = "files"
|
||||
|
||||
|
||||
router = DefaultRouter(trailing_slash=True)
|
||||
router.register("", FileUploadViewSet)
|
||||
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
[pytest]
|
||||
DJANGO_SETTINGS_MODULE = config.settings.develop
|
||||
DJANGO_SETTINGS_MODULE = config.settings.base
|
||||
addopts = --ignore=src
|
||||
|
||||
@@ -11,13 +11,16 @@ from shop.api.v1.viewsets import (
|
||||
)
|
||||
|
||||
|
||||
app_name = "shop"
|
||||
|
||||
|
||||
router = DefaultRouter()
|
||||
|
||||
router.register("taxes", TaxViewSet)
|
||||
router.register("customers", CustomerViewSet)
|
||||
router.register("providers", ProviderViewSet)
|
||||
router.register("products", ProductViewSet)
|
||||
router.register("product-prices", ProductPriceViewSet)
|
||||
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)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from django.utils import timezone
|
||||
from rest_framework import serializers
|
||||
|
||||
from files.api.v1.serializers import FileUploadSerializer
|
||||
@@ -17,6 +18,7 @@ class TaxSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Tax
|
||||
fields = (
|
||||
"id",
|
||||
"code",
|
||||
"value",
|
||||
)
|
||||
@@ -35,15 +37,20 @@ class ProductPriceSerializer(serializers.ModelSerializer):
|
||||
)
|
||||
|
||||
|
||||
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()
|
||||
|
||||
def get_price(self, product):
|
||||
last_price = product.prices.last()
|
||||
|
||||
return ProductPriceSerializer(last_price).data
|
||||
|
||||
class Meta:
|
||||
model = Product
|
||||
fields = (
|
||||
@@ -56,10 +63,49 @@ class ProductSerializer(serializers.ModelSerializer):
|
||||
)
|
||||
|
||||
|
||||
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(
|
||||
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"),
|
||||
)
|
||||
ProductPrice.objects.create(
|
||||
product=instance,
|
||||
date=timezone.now(),
|
||||
price=validated_data.get("price"),
|
||||
tax=validated_data.get("tax"),
|
||||
)
|
||||
return instance
|
||||
|
||||
class Meta:
|
||||
model = Product
|
||||
fields = (
|
||||
"id",
|
||||
"name",
|
||||
"description",
|
||||
"stock",
|
||||
"is_digital_asset",
|
||||
"url",
|
||||
"price",
|
||||
"tax",
|
||||
)
|
||||
|
||||
|
||||
class ProductBatchSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = ProductBatch
|
||||
fields = (
|
||||
"id",
|
||||
"code",
|
||||
"product",
|
||||
"quantity",
|
||||
@@ -72,6 +118,7 @@ class CustomerSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Customer
|
||||
fields = (
|
||||
"id",
|
||||
"vat_id",
|
||||
"first_name",
|
||||
"last_name",
|
||||
@@ -88,6 +135,7 @@ class ProviderSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Provider
|
||||
fields = (
|
||||
"id",
|
||||
"vat_id",
|
||||
"name",
|
||||
"email",
|
||||
|
||||
+40
-1
@@ -1,4 +1,9 @@
|
||||
from django.db.models.deletion import ProtectedError
|
||||
from django.utils.text import gettext_lazy as _
|
||||
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
from rest_framework.exceptions import ValidationError
|
||||
from rest_framework.permissions import IsAdminUser
|
||||
|
||||
from shop.api.v1.serializers import (
|
||||
ProductSerializer,
|
||||
@@ -9,6 +14,8 @@ from shop.api.v1.serializers import (
|
||||
OrderLineSerializer,
|
||||
ProviderSerializer,
|
||||
ProductBatchSerializer,
|
||||
CreateProductSerializer,
|
||||
CreateProductPriceSerializer,
|
||||
)
|
||||
from shop.models import (
|
||||
Product,
|
||||
@@ -21,15 +28,47 @@ from shop.models import (
|
||||
ProductBatch,
|
||||
)
|
||||
|
||||
from shop.api.v1.permissions import ProductPermissions, ProductPricePermissions
|
||||
|
||||
|
||||
class ProductViewSet(ModelViewSet):
|
||||
serializer_class = ProductSerializer
|
||||
queryset = Product.objects.all()
|
||||
queryset = Product.objects.prefetch_related("prices").all()
|
||||
permission_classes = (
|
||||
IsAdminUser,
|
||||
ProductPermissions,
|
||||
)
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.action == "create":
|
||||
return CreateProductSerializer
|
||||
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):
|
||||
serializer.save(product_id=self.kwargs.get("product_id"))
|
||||
|
||||
|
||||
class ProductBatchViewSet(ModelViewSet):
|
||||
|
||||
@@ -34,6 +34,10 @@ class Product(models.Model):
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
@property
|
||||
def price(self):
|
||||
return self.prices.last()
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Producto")
|
||||
verbose_name_plural = _("Productos")
|
||||
|
||||
@@ -7,6 +7,10 @@ from rest_framework_simplejwt.views import (
|
||||
token_verify,
|
||||
)
|
||||
|
||||
|
||||
app_name = "auth"
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path("login/", token_obtain_pair, name="login"),
|
||||
path("refresh/", token_refresh, name="refresh_jwt"),
|
||||
|
||||
Reference in New Issue
Block a user