v004
This commit is contained in:
@@ -7,16 +7,31 @@ from django.utils import timezone
|
||||
from django.core.files.base import ContentFile
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
class BrojacSekvence(models.Model):
|
||||
"""
|
||||
Tablica koja pamti isključivo zadnji iskorišteni broj za bilo koji entitet.
|
||||
Broj se ovdje samo povećava i nikada se ne briše.
|
||||
"""
|
||||
naziv_sekvence = models.CharField(max_length=50, unique=True) # npr. 'radni_nalog_2026'
|
||||
zadnji_broj = models.PositiveIntegerField(default=0)
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Brojač sekvence"
|
||||
verbose_name_plural = "Brojači sekvenci"
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.naziv_sekvence}: {self.zadnji_broj}"
|
||||
|
||||
# --- FUNKCIJE ZA DINAMIČKE PUTANJE ---
|
||||
|
||||
def putanja_slike_naloga(instance, filename):
|
||||
# Kreira putanju: radni-nalozi/broj_naloga/originalni_naziv.ekstenzija
|
||||
return f'radni-nalozi/{instance.broj_naloga}/{filename}'
|
||||
# Čistimo broj naloga od duplih oznaka za putanju direktorija
|
||||
broj = instance.broj_naloga.replace('RN-', '') if instance.broj_naloga else 'nepoznato'
|
||||
return f'radni-nalozi/RN-{broj}/{filename}'
|
||||
|
||||
def putanja_galerije_naloga(instance, filename):
|
||||
# instance je objekt RadniNalogSlika koji ima ForeignKey na radni_nalog
|
||||
# Sprema u isti folder gdje je i glavna slika kvara
|
||||
return f'radni-nalozi/{instance.radni_nalog.broj_naloga}/galerija/{filename}'
|
||||
broj = instance.radni_nalog.broj_naloga.replace('RN-', '') if instance.radni_nalog.broj_naloga else 'nepoznato'
|
||||
return f'radni-nalozi/RN-{broj}/galerija/{filename}'
|
||||
|
||||
|
||||
class PutniNalog(models.Model):
|
||||
@@ -93,7 +108,7 @@ class RadniNalog(models.Model):
|
||||
class StatusRadaChoices(models.TextChoices):
|
||||
PLANIRANO = 'PLANIRANO', 'Planirano'
|
||||
U_RADU = 'U_RADU', 'U radu'
|
||||
ZAVRSENO = 'ZAVRSENO', 'Završeno'
|
||||
ZAVRSENO = 'ZAVRSENO', 'Završen'
|
||||
|
||||
broj_naloga = models.CharField(max_length=20, unique=True, blank=True)
|
||||
|
||||
@@ -137,29 +152,41 @@ class RadniNalog(models.Model):
|
||||
potpis_klijenta = models.ImageField(upload_to='potpisi/%Y/%m/', null=True, blank=True)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
# 1. AUTOMATSKO GENERIRANJE BROJA NALOGA
|
||||
if self.broj_naloga == "":
|
||||
self.broj_naloga = None
|
||||
|
||||
# 1. AUTOMATSKO GENERIRANJE BROJA NALOGA KROZ SEKVENCIJSKU TABLICU
|
||||
if not self.broj_naloga:
|
||||
godina = timezone.now().year
|
||||
kljuc_sekvence = f"radni_nalog_{godina}"
|
||||
prefix = f"RN-{godina}-"
|
||||
|
||||
# Koristimo atomsku transakciju i select_for_update da spriječimo
|
||||
# da dva korisnika dobiju isti broj u istoj milisekundi
|
||||
# Atomska transakcija zaključava samo brojač, sprječavajući dupliranje
|
||||
with transaction.atomic():
|
||||
zadnji_nalog = RadniNalog.objects.select_for_update().filter(
|
||||
broj_naloga__startswith=prefix
|
||||
).order_by('-broj_naloga').first()
|
||||
# Dohvati ili kreiraj brojač za tekuću godinu i zaključaj redak za ažuriranje
|
||||
brojac, created = BrojacSekvence.objects.select_for_update().get_or_create(
|
||||
naziv_sekvence=kljuc_sekvence
|
||||
)
|
||||
|
||||
# Ako je brojač tek kreiran, a u bazi već imaš povijest (npr. stigao si do 25),
|
||||
# radimo automatsku sinkronizaciju da ne krene od 1 ako tablica nije prazna
|
||||
if created:
|
||||
zadnji_u_bazi = RadniNalog.objects.filter(broj_naloga__startswith=prefix).order_by('-broj_naloga').first()
|
||||
if zadnji_u_bazi:
|
||||
try:
|
||||
brojac.zadnji_broj = int(zadnji_u_bazi.broj_naloga.split('-')[-1])
|
||||
except (ValueError, IndexError):
|
||||
brojac.zadnji_broj = 0
|
||||
|
||||
if zadnji_nalog:
|
||||
try:
|
||||
# RN-2026-0001 -> uzimamo "0001"
|
||||
zadnji_broj_str = zadnji_nalog.broj_naloga.split('-')[-1]
|
||||
novi_broj = int(zadnji_broj_str) + 1
|
||||
except (ValueError, IndexError):
|
||||
novi_broj = 1
|
||||
else:
|
||||
novi_broj = 1
|
||||
# Uvećaj sekvencu za 1 (Čak i ako se nalozi obrišu, ovaj broj samo raste!)
|
||||
brojac.zadnji_broj += 1
|
||||
brojac.save()
|
||||
|
||||
self.broj_naloga = f"{prefix}{novi_broj:04d}"
|
||||
# Dodijeli savršeno formatiran broj
|
||||
self.broj_naloga = f"{prefix}{brojac.zadnji_broj:04d}"
|
||||
else:
|
||||
if self.broj_naloga.startswith("RN-RN-"):
|
||||
self.broj_naloga = self.broj_naloga.replace("RN-RN-", "RN-")
|
||||
|
||||
# 2. OBRADA SLIKE
|
||||
if self.slika_kvara:
|
||||
@@ -174,9 +201,8 @@ class RadniNalog(models.Model):
|
||||
# 4. LOGIKA ZA PUTNI NALOG
|
||||
if self.putni_nalog and self.status == self.StatusRadaChoices.ZAVRSENO:
|
||||
pn = self.putni_nalog
|
||||
# Provjeravamo ima li nalog još uvijek otvorenih radnih naloga
|
||||
ostali_otvoreni = pn.radni_nalozi.exclude(
|
||||
id=self.id, # Isključujemo trenutni nalog jer je on upravo završen
|
||||
id=self.id,
|
||||
status=self.StatusRadaChoices.ZAVRSENO
|
||||
).exists()
|
||||
|
||||
@@ -200,7 +226,10 @@ class RadniNalog(models.Model):
|
||||
verbose_name_plural = "Radni nalozi"
|
||||
|
||||
def __str__(self):
|
||||
return f"RN-{self.broj_naloga} | {self.stroj.naziv}"
|
||||
# POPRAVLJENO: Budući da polje broj_naloga već u bazi sadrži "RN-2026-0004",
|
||||
# ovdje izbacujemo fiksni prefiks "RN-" kako se ne bi duplirao pri pretvaranju objekta u string!
|
||||
return f"{self.broj_naloga} | {self.stroj.naziv}"
|
||||
|
||||
|
||||
class RadniNalogSlika(models.Model):
|
||||
radni_nalog = models.ForeignKey(
|
||||
@@ -208,7 +237,6 @@ class RadniNalogSlika(models.Model):
|
||||
related_name='slike',
|
||||
on_delete=models.CASCADE
|
||||
)
|
||||
# POPRAVLJENO: uklonjeni navodnici oko funkcije
|
||||
slika = models.ImageField(upload_to=putanja_galerije_naloga, verbose_name="Slika")
|
||||
opis = models.CharField(max_length=100, blank=True, verbose_name="Kratki opis slike")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user