This commit is contained in:
2026-05-22 06:08:51 +00:00
parent c078a257e9
commit bafec754d1
131 changed files with 2346 additions and 893 deletions

View File

@@ -1,5 +1,7 @@
from django.utils import timezone # Potrebno za kreiranje vremena polaska
from django.db import transaction # Potrebno za zaključavanje baze i sprječavanje dupliranja brojeva
from rest_framework import serializers
from .models import RadniNalog, RadniNalogSlika
from .models import RadniNalog, RadniNalogSlika, PutniNalog
from kupci.serializers import KupacListaSerializer
from fleet.serializers import VoziloListaSerializer, StrojSerializer
@@ -9,6 +11,12 @@ class RadniNalogSlikaSerializer(serializers.ModelSerializer):
model = RadniNalogSlika
fields = ['id', 'slika', 'opis']
# --- POMOĆNI SERIALIZER ZA PRIKAZ VEZANOG PUTNOG NALOGA ---
class PutniNalogMinimalSerializer(serializers.ModelSerializer):
class Meta:
model = PutniNalog
fields = ['id', 'broj_naloga', 'status', 'pocetna_km']
# --- 1. LISTA SERIALIZER ---
class RadniNalogListaSerializer(serializers.ModelSerializer):
klijent_naziv = serializers.CharField(source='klijent.naziv', read_only=True)
@@ -33,6 +41,8 @@ class RadniNalogDetaljiSerializer(serializers.ModelSerializer):
stroj = StrojSerializer(read_only=True)
slike = RadniNalogSlikaSerializer(many=True, read_only=True)
putni_nalog = PutniNalogMinimalSerializer(read_only=True)
# VOZILO dohvaćamo preko putnog naloga
vozilo = serializers.SerializerMethodField()
@@ -50,19 +60,18 @@ class RadniNalogDetaljiSerializer(serializers.ModelSerializer):
read_only_fields = ['datum_kreiranja', 'datum_azuriranja']
def get_vozilo(self, obj):
# Ako je radni nalog vezan za putni nalog, vrati podatke o vozilu
if obj.putni_nalog and obj.putni_nalog.vozilo:
return {
"id": obj.putni_nalog.vozilo.id,
"naziv": obj.putni_nalog.vozilo.naziv,
"registracija": obj.putni_nalog.vozilo.registracija,
"trenutni_kilometri": obj.putni_nalog.vozilo.trenutni_kilometri
"trenutni_kilometri": obj.putni_nalog.vozilo.trenutni_kilometri,
"status_prikaz": obj.putni_nalog.vozilo.status
}
return None
# --- 3. DEFAULT SERIALIZER ---
class RadniNalogSerializer(serializers.ModelSerializer):
# Dozvoljavamo unos, ali nije obavezan ako ga backend generira
broj_naloga = serializers.CharField(required=False, read_only=True)
class Meta:
@@ -70,17 +79,81 @@ class RadniNalogSerializer(serializers.ModelSerializer):
exclude = []
def validate_broj_naloga(self, value):
# Provjera jedinstvenosti prije nego što dođe do baze
if RadniNalog.objects.filter(broj_naloga=value).exists():
raise serializers.ValidationError("Radni nalog s ovim brojem već postoji.")
return value
def validate(self, data):
# Tvoja postojeća validacija klijenta i stroja
stroj = data.get('stroj')
klijent = data.get('klijent')
if stroj and klijent and stroj.vlasnik != klijent:
raise serializers.ValidationError(
{"stroj": "Odabrani stroj ne pripada odabranom klijentu."}
)
return data
return data
# --- 4. KREIRANJE PUTNOG NALOGA SERIALIZER (AUTOMATSKO PROŠIRENJE SEKVENCI) ---
class KreirajPutniNalogSerializer(serializers.ModelSerializer):
radni_nalog_id = serializers.IntegerField(write_only=True)
class Meta:
model = PutniNalog
fields = ['id', 'radni_nalog_id', 'broj_naloga', 'vozilo', 'korisnik', 'relacija', 'mjesto_odredista', 'pocetna_km', 'status']
read_only_fields = ['id', 'broj_naloga', 'korisnik', 'relacija', 'mjesto_odredista', 'pocetna_km', 'status']
def validate_radni_nalog_id(self, value):
try:
nalog = RadniNalog.objects.get(id=value)
except RadniNalog.DoesNotExist:
raise serializers.ValidationError("Radni nalog s ovim ID-jem ne postoji.")
if nalog.putni_nalog is not None:
raise serializers.ValidationError("Za ovaj radni nalog već je izrađen putni nalog.")
if not nalog.izvrsitelj:
raise serializers.ValidationError("Radni nalog mora imati dodijeljenog izvršitelja da bi se kreirao putni nalog.")
return value
def create(self, validated_data):
radni_nalog = RadniNalog.objects.get(id=validated_data['radni_nalog_id'])
vozilo = validated_data.get('vozilo')
godina = timezone.now().year
prefix = f"PN-{godina}-"
# Koristimo atomsku transakciju i select_for_update da spriječimo trke podataka
with transaction.atomic():
# Pronalazimo zadnji kreirani putni nalog za tekuću godinu
zadnji_pn = PutniNalog.objects.select_for_update().filter(
broj_naloga__startswith=prefix
).order_by('-broj_naloga').first()
if zadnji_pn:
try:
# PN-2026-0002 -> uzimamo zadnji segment "0002" i uvećavamo ga
zadnji_broj_str = zadnji_pn.broj_naloga.split('-')[-1]
novi_broj = int(zadnji_broj_str) + 1
except (ValueError, IndexError):
novi_broj = 1
else:
novi_broj = 1
# Sklapanje jedinstvenog broja putnog naloga u formatu PN-2026-XXXX
broj_pn = f"{prefix}{novi_broj:04d}"
# Siguran upis u bazu podataka
putni_nalog = PutniNalog.objects.create(
broj_naloga=broj_pn,
vozilo=vozilo,
korisnik=radni_nalog.izvrsitelj,
relacija=f"Zagreb - {radni_nalog.klijent.grad} - Zagreb",
mjesto_odredista=radni_nalog.klijent.grad,
vrijeme_polaska=timezone.now()
)
# Povezujemo radni nalog na novokreirani putni nalog
radni_nalog.putni_nalog = putni_nalog
radni_nalog.save()
return putni_nalog