This commit is contained in:
2025-11-13 02:32:56 +01:00
parent c39467dc7d
commit 5c3a02d282
10 changed files with 113 additions and 32 deletions

View File

@@ -6,7 +6,7 @@ from .serializers import *
from .permissions import *
from .models import CustomUser
from .tokens import *
from .tasks import send_password_reset_email_task
from .tasks import send_password_reset_email_task, send_email_verification_task, send_email_clerk_accepted_task
from django.conf import settings
import logging
logger = logging.getLogger(__name__)

View File

@@ -4,6 +4,8 @@ from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from decimal import Decimal
from thirdparty.zasilkovna.models import PacketaShipment
class Category(models.Model):
name = models.CharField(max_length=100)
@@ -32,19 +34,20 @@ class Category(models.Model):
class Product(models.Model):
name = models.CharField(max_length=200)
description = models.TextField(blank=True)
code = models.CharField(max_length=100, unique=True, blank=True, null=True)
category = models.ForeignKey(Category, related_name='products', on_delete=models.PROTECT)
price = models.DecimalField(max_digits=10, decimal_places=2)
currency = models.CharField(max_length=10, default="czk")
url = models.SlugField(unique=True)
stock = models.PositiveIntegerField(default=0)
is_active = models.BooleanField(default=True)
#limitka
#limitka (volitelné)
limited_to = models.DateTimeField(null=True, blank=True)
default_carrier = models.ForeignKey(
@@ -74,21 +77,36 @@ class ProductImage(models.Model):
return f"{self.product.name} image"
# ------------------ OBJENDÁVKOVÉ MODELY (dole) ------------------
# Dopravci a způsoby dopravy
class Carrier(models.Model):
name = models.CharField(max_length=100) # název dopravce (Zásilkovna, Česká pošta…)
base_price = models.DecimalField(max_digits=10, decimal_places=2, default=0) # základní cena dopravy
delivery_time = models.CharField(max_length=100, blank=True) # např. "23 pracovní dny"
is_active = models.BooleanField(default=True)
# pole pro logo
logo = models.ImageField(upload_to="carriers/", blank=True, null=True)
class Role(models.TextChoices):
ZASILKOVNA = "packeta", "Zásilkovna"
STORE = "store", "Osobní odběr"
# pole pro propojení s externím API (např. ID služby u Zásilkovny)
external_id = models.CharField(max_length=50, blank=True, null=True)
choice = models.CharField(max_length=20, choices=Role.choices, default=Role.STORE)
zasilkovna = models.ForeignKey(
'thirdparty.zasilkovna.Zasilkovna', on_delete=models.DO_NOTHING, null=True, blank=True, related_name="carriers"
)
def __str__(self):
return f"{self.name} ({self.base_price} Kč)"
def save(self, *args, **kwargs):
#zásilkovna instance je vytvořena
if self.choice == self.Role.ZASILKOVNA:
self.packeta = PacketaShipment.objects.create()
elif self.choice == self.Role.STORE:
self.packeta = None
super().save(*args, **kwargs)
@@ -130,20 +148,30 @@ class DiscountCode(models.Model):
return f"{self.code} ({self.percent}% or {self.amount} CZK)"
class Order(models.Model):
class Status(models.TextChoices):
PENDING = "pending", _("Čeká na platbu")
PAID = "paid", _("Zaplaceno")
CANCELLED = "cancelled", _("Zrušeno")
SHIPPED = "shipped", _("Odesláno")
COMPLETED = "completed", _("Dokončeno")
#COMPLETED = "completed", _("Dokončeno")
status = models.CharField(
max_length=20, choices=Status.choices, default=Status.PENDING
)
user = models.ForeignKey(
settings.AUTH_USER_MODEL, related_name="orders", on_delete=models.CASCADE
)
status = models.CharField(
max_length=20, choices=Status.choices, default=Status.PENDING
carrier = models.ForeignKey(
Carrier, on_delete=models.CASCADE, null=True, blank=True, related_name="orders"
)
#itemy
order_items = models.ManyToManyField(
'OrderItem', related_name='orders',
)
# Stored order grand total; recalculated on save
@@ -165,22 +193,33 @@ class Order(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
discount = models.ManyToOneRel("DiscountCode", null=True, blank=True, on_delete=models.PROTECT)
# Oprava: ManyToOneRel není pole. Potřebujeme iterovat přes self.discount.all(), proto ManyToManyField.
discount = models.ManyToManyField("DiscountCode", blank=True, related_name="orders")
def __str__(self):
return f"Order #{self.id} - {self.user.email} ({self.status})"
def calculate_total_price(self):
for discount in self.discount.all():
total = Decimal('0.0')
if self.discount.exists():
for discount in self.discount.all():
total = Decimal('0.0')
# getting all prices from order items (with discount applied if valid)
for item in self.items.all():
total = total + item.get_total_price(discount)
return total
else:
total = Decimal('0.0')
# getting all prices from order items (without discount)
# getting all prices from order items (with discount applied if valid)
for item in self.items.all():
total = total + item.get_total_price(discount)
total = total + (item.product.price * item.quantity)
return total
def save(self, *args, **kwargs):
# Keep total_price always in sync with items and discount
@@ -208,6 +247,10 @@ class OrderItem(models.Model):
else:
raise ValueError("Discount code must have either percent or amount defined.")
elif not discount_object:
return self.quantity * self.product.price
else:
return ValueError("Invalid discount code.")

View File

View File

@@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

6
backend/thirdparty/zasilkovna/apps.py vendored Normal file
View File

@@ -0,0 +1,6 @@
from django.apps import AppConfig
class ZasilkovnaConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'zasilkovna'

View File

18
backend/thirdparty/zasilkovna/models.py vendored Normal file
View File

@@ -0,0 +1,18 @@
from django.db import models
# Create your models here.
class Zasilkovna(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
packet_id = models.CharField(max_length=255, unique=True) # identifikátor od Packety
label_pdf = models.BinaryField(null=True, blank=True) # uložit PDF binárně nebo odkaz
status = models.CharField(max_length=50) # např. „created“, „in_transit“, „delivered“
cancelled = models.BooleanField(default=False)
metadata = models.JSONField(default=dict, blank=True) # pro případná extra data
def save(self, *args, **kwargs):
# případná logika před uložením
super().save(*args, **kwargs)

View File

@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

View File

@@ -0,0 +1,4 @@
from django.shortcuts import render
# Create your views here.