174 lines
7.1 KiB
Python
174 lines
7.1 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']
|
|
|
|
# --- NOVI STANDARDNI PUTNI NALOG SERIALIZER (Za rješavanje ImportError-a) ---
|
|
class PutniNalogSerializer(serializers.ModelSerializer):
|
|
vozilo_detalji = VoziloListaSerializer(source='vozilo', read_only=True)
|
|
korisnik_ime = serializers.CharField(source='korisnik.get_full_name', read_only=True)
|
|
status_display = serializers.CharField(source='get_status_display', read_only=True)
|
|
|
|
class Meta:
|
|
model = PutniNalog
|
|
fields = [
|
|
'id', 'broj_naloga', 'vozilo', 'vozilo_detalji', 'korisnik', 'korisnik_ime',
|
|
'relacija', 'mjesto_odredista', 'pocetna_km', 'zavrsna_km', 'status',
|
|
'status_display', 'vrijeme_polaska', 'vrijeme_povratka'
|
|
]
|
|
read_only_fields = ['id', 'broj_naloga', 'vrijeme_polaska']
|
|
|
|
# --- 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 |