Refactor order creation and add configuration endpoints

Refactored order creation logic to use new serializers and transaction handling, improving validation and modularity. Introduced admin and public endpoints for shop configuration with sensitive fields protected. Enhanced Zásilkovna (Packeta) integration, including packet widget template, new API fields, and improved error handling. Added django-silk for profiling, updated requirements and settings, and improved frontend Orval config for API client generation.
This commit is contained in:
David Bruno Vontor
2025-12-08 18:19:20 +01:00
parent 5b066e2770
commit 946f86db7e
18 changed files with 606 additions and 309 deletions

View File

@@ -22,7 +22,11 @@ class ShopConfiguration(models.Model):
#zasilkovna settings
zasilkovna_shipping_price = models.DecimalField(max_digits=10, decimal_places=2, default=50)
zasilkovna_address_id = models.CharField(max_length=100, blank=True, null=True, help_text="ID výdejního místa Zásilkovny pro odesílání zásilek")
#FIXME: není implementováno ↓↓↓
zasilkovna_api_key = models.CharField(max_length=255, blank=True, null=True, help_text="API klíč pro přístup k Zásilkovna API (zatím není využito)")
#FIXME: není implementováno ↓↓↓
zasilkovna_api_password = models.CharField(max_length=255, blank=True, null=True, help_text="API heslo pro přístup k Zásilkovna API (zatím není využito)")
#FIXME: není implementováno ↓↓↓
free_shipping_over = models.DecimalField(max_digits=10, decimal_places=2, default=2000)
#coupon settings

View File

@@ -0,0 +1,54 @@
from rest_framework import serializers
from .models import ShopConfiguration
class ShopConfigurationAdminSerializer(serializers.ModelSerializer):
class Meta:
model = ShopConfiguration
fields = [
"id",
"name",
"logo",
"favicon",
"contact_email",
"contact_phone",
"contact_address",
"opening_hours",
"facebook_url",
"instagram_url",
"youtube_url",
"tiktok_url",
"whatsapp_number",
"zasilkovna_shipping_price",
"zasilkovna_api_key",
"zasilkovna_api_password",
"free_shipping_over",
"multiplying_coupons",
"addition_of_coupons_amount",
"currency",
]
class ShopConfigurationPublicSerializer(serializers.ModelSerializer):
class Meta:
model = ShopConfiguration
# Expose only non-sensitive fields
fields = [
"id",
"name",
"logo",
"favicon",
"contact_email",
"contact_phone",
"contact_address",
"opening_hours",
"facebook_url",
"instagram_url",
"youtube_url",
"tiktok_url",
# Exclude API keys/passwords
"zasilkovna_shipping_price",
"free_shipping_over",
"currency",
]

View File

@@ -0,0 +1,8 @@
from rest_framework.routers import DefaultRouter
from .views import ShopConfigurationAdminViewSet, ShopConfigurationPublicViewSet
router = DefaultRouter()
router.register(r"admin/shop-configuration", ShopConfigurationAdminViewSet, basename="shop-config-admin")
router.register(r"public/shop-configuration", ShopConfigurationPublicViewSet, basename="shop-config-public")
urlpatterns = router.urls

View File

@@ -1,6 +1,25 @@
from django.shortcuts import render
from rest_framework import viewsets, mixins
from rest_framework.permissions import IsAdminUser, AllowAny
from .models import ShopConfiguration
from .serializers import (
ShopConfigurationAdminSerializer,
ShopConfigurationPublicSerializer,
)
# Create your views here.
#TODO: dej public tag pro view
# rozdělit fieldy podle práv aby se třeba neexposelo citlivé údaje
class _SingletonQuerysetMixin:
def get_queryset(self):
return ShopConfiguration.objects.filter(pk=1)
def get_object(self):
return ShopConfiguration.get_solo()
class ShopConfigurationAdminViewSet(_SingletonQuerysetMixin, viewsets.ModelViewSet):
permission_classes = [IsAdminUser]
serializer_class = ShopConfigurationAdminSerializer
class ShopConfigurationPublicViewSet(_SingletonQuerysetMixin, viewsets.ReadOnlyModelViewSet):
permission_classes = [AllowAny]
serializer_class = ShopConfigurationPublicSerializer