Files
003-fleet-management/001.BACKEND/operations/serializers.py
2026-05-22 06:08:51 +00:00

159 lines
6.4 KiB
Python

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, PutniNalog
from kupci.serializers import KupacListaSerializer
from fleet.serializers import VoziloListaSerializer, StrojSerializer
# --- POMOĆNI SERIALIZER ZA SLIKE ---
class RadniNalogSlikaSerializer(serializers.ModelSerializer):
class Meta:
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)
stroj_naziv = serializers.CharField(source='stroj.naziv', read_only=True)
izvrsitelj_ime = serializers.CharField(source='izvrsitelj.get_full_name', read_only=True)
class Meta:
model = RadniNalog
fields = [
'id',
'broj_naloga',
'klijent_naziv',
'stroj_naziv',
'status',
'izvrsitelj_ime',
'datum_kreiranja'
]
# --- 2. DETALJI SERIALIZER ---
class RadniNalogDetaljiSerializer(serializers.ModelSerializer):
klijent = KupacListaSerializer(read_only=True)
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()
status_display = serializers.CharField(source='get_status_display', read_only=True)
izvrsitelj_ime = serializers.CharField(source='izvrsitelj.get_full_name', read_only=True)
class Meta:
model = RadniNalog
fields = [
'id', 'broj_naloga', 'klijent', 'stroj', 'putni_nalog', 'vozilo', 'opis_kvara',
'izvrsitelj', 'izvrsitelj_ime', 'status', 'status_display',
'datum_kreiranja', 'datum_azuriranja', 'slika_kvara',
'potpis_klijenta', 'slike'
]
read_only_fields = ['datum_kreiranja', 'datum_azuriranja']
def get_vozilo(self, obj):
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,
"status_prikaz": obj.putni_nalog.vozilo.status
}
return None
# --- 3. DEFAULT SERIALIZER ---
class RadniNalogSerializer(serializers.ModelSerializer):
broj_naloga = serializers.CharField(required=False, read_only=True)
class Meta:
model = RadniNalog
exclude = []
def validate_broj_naloga(self, value):
if RadniNalog.objects.filter(broj_naloga=value).exists():
raise serializers.ValidationError("Radni nalog s ovim brojem već postoji.")
return value
def validate(self, data):
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
# --- 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