Versiunea funcțională EUMI
This commit is contained in:
+108
-48
@@ -3,12 +3,21 @@ from datetime import date
|
||||
from simple_history.models import HistoricalRecords
|
||||
from users.models import Employee
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db.models import Max
|
||||
|
||||
EQUIPMENT_STATUS = [
|
||||
("activ", "Activ"),
|
||||
("casat", "Casat (Decommissioned)"),
|
||||
]
|
||||
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
|
||||
def validate_file_size(value):
|
||||
limit_mb = 3
|
||||
if value.size > limit_mb * 1024 * 1024:
|
||||
raise ValidationError(f"Dimensiunea maximă permisă este de {limit_mb} MB.")
|
||||
|
||||
|
||||
class Computer(models.Model):
|
||||
# Unique ID and Entry
|
||||
@@ -56,7 +65,8 @@ class Computer(models.Model):
|
||||
history = HistoricalRecords()
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.equipment_code} - {self.oem_name or 'Sistem Asamblat'}"
|
||||
# Format: Cod Echipament | CPU | RAM | Placă de bază
|
||||
return f"{self.equipment_code} | {self.cpu} | {self.ram} | {self.motherboard}"
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Computer / Laptop"
|
||||
@@ -89,7 +99,8 @@ class Monitor(models.Model):
|
||||
history = HistoricalRecords()
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.equipment_code} - {self.name}"
|
||||
# Format: Cod Echipament | Model
|
||||
return f"{self.equipment_code} | {self.name}"
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Monitor"
|
||||
@@ -119,6 +130,7 @@ class Peripheral(models.Model):
|
||||
)
|
||||
name = models.CharField(max_length=255, verbose_name="Nume Echipament")
|
||||
serial_number = models.CharField(max_length=100, verbose_name="Număr Serial")
|
||||
observations = models.TextField(blank=True, null=True, verbose_name="Observații")
|
||||
|
||||
assigned_to = models.ForeignKey(
|
||||
Employee,
|
||||
@@ -135,7 +147,8 @@ class Peripheral(models.Model):
|
||||
history = HistoricalRecords()
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.equipment_code} - {self.name} ({self.get_peripheral_type_display()})"
|
||||
# Format: Cod Echipament | Tip | Model
|
||||
return f"{self.equipment_code} | {self.get_peripheral_type_display()} | {self.name}"
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Periferic"
|
||||
@@ -153,6 +166,7 @@ class DigitalCertificate(models.Model):
|
||||
)
|
||||
issue_date = models.DateField(verbose_name="Data emiterii")
|
||||
expiration_date = models.DateField(verbose_name="Data expirării")
|
||||
observations = models.TextField(blank=True, null=True, verbose_name="Observații")
|
||||
is_canceled = models.BooleanField(default=False, verbose_name="Anulat?")
|
||||
|
||||
# Links directly to the employee
|
||||
@@ -180,6 +194,9 @@ class MaintenanceRecord(models.Model):
|
||||
)
|
||||
description = models.TextField(verbose_name="Descriere detaliată")
|
||||
performed_by = models.CharField(max_length=100, verbose_name="Efectuat de")
|
||||
next_maintenance_date = models.DateField(
|
||||
null=True, blank=True, verbose_name="Următoarea mentenanță planificată"
|
||||
)
|
||||
|
||||
# Links to equipment (only one should be populated)
|
||||
computer = models.ForeignKey(
|
||||
@@ -230,62 +247,105 @@ class MaintenanceRecord(models.Model):
|
||||
class DecommissionRecord(models.Model):
|
||||
date = models.DateField(default=date.today, verbose_name="Data casării")
|
||||
document_number = models.CharField(
|
||||
max_length=100, verbose_name="Număr document (Proces Verbal)"
|
||||
max_length=100, verbose_name="Număr Proces Verbal"
|
||||
)
|
||||
reason = models.TextField(verbose_name="Motivul casării (Defect, Uzat moral, etc.)")
|
||||
|
||||
# Links to equipment
|
||||
computer = models.OneToOneField(
|
||||
Computer,
|
||||
on_delete=models.CASCADE,
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name="decommission_log",
|
||||
# Am transformat relațiile în ManyToMany pentru a permite liste de echipamente
|
||||
computers = models.ManyToManyField(
|
||||
Computer, blank=True, verbose_name="Computere casate"
|
||||
)
|
||||
monitor = models.OneToOneField(
|
||||
Monitor,
|
||||
on_delete=models.CASCADE,
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name="decommission_log",
|
||||
monitors = models.ManyToManyField(
|
||||
Monitor, blank=True, verbose_name="Monitoare casate"
|
||||
)
|
||||
peripheral = models.OneToOneField(
|
||||
Peripheral,
|
||||
on_delete=models.CASCADE,
|
||||
null=True,
|
||||
peripherals = models.ManyToManyField(
|
||||
Peripheral, blank=True, verbose_name="Periferice casate"
|
||||
)
|
||||
|
||||
# Comisia de casare (opțional, dar util pentru PDF)
|
||||
committee_members = models.TextField(
|
||||
blank=True,
|
||||
related_name="decommission_log",
|
||||
null=True,
|
||||
verbose_name="Membrii comisiei de casare (nume și funcție)",
|
||||
)
|
||||
|
||||
history = HistoricalRecords()
|
||||
|
||||
def clean(self):
|
||||
equipment_count = sum(
|
||||
[bool(self.computer), bool(self.monitor), bool(self.peripheral)]
|
||||
)
|
||||
if equipment_count != 1:
|
||||
raise ValidationError(
|
||||
"Un proces verbal de casare trebuie să fie legat de exact un singur echipament."
|
||||
)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
self.clean()
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
# Automatically update the status of the linked equipment to 'casat'
|
||||
if self.computer:
|
||||
self.computer.status = "casat"
|
||||
self.computer.save()
|
||||
elif self.monitor:
|
||||
self.monitor.status = "casat"
|
||||
self.monitor.save()
|
||||
elif self.peripheral:
|
||||
self.peripheral.status = "casat"
|
||||
self.peripheral.save()
|
||||
# Eliminăm vechea funcție clean() care forța un singur echipament
|
||||
# Eliminăm vechea funcție save() - vom face actualizarea statusului direct din View (ca la predare)
|
||||
|
||||
def __str__(self):
|
||||
return f"Casare {self.document_number} din {self.date}"
|
||||
return f"PV Casare nr. {self.document_number} din {self.date}"
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Înregistrare Casare"
|
||||
verbose_name_plural = "Înregistrări Casare"
|
||||
verbose_name = "Proces Verbal de Casare"
|
||||
verbose_name_plural = "Procese Verbale de Casare"
|
||||
|
||||
|
||||
class HandoverProtocol(models.Model):
|
||||
date = models.DateField(default=date.today, verbose_name="Data documentului")
|
||||
document_number = models.IntegerField(
|
||||
unique=True, blank=True, verbose_name="Număr Proces Verbal"
|
||||
)
|
||||
|
||||
previous_holder = models.ForeignKey(
|
||||
Employee,
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name="equipment_handed_over",
|
||||
verbose_name="Predat de (Predător)",
|
||||
)
|
||||
new_holder = models.ForeignKey(
|
||||
Employee,
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name="equipment_received",
|
||||
verbose_name="Primit de (Primitor)",
|
||||
)
|
||||
|
||||
# We will populate this automatically in the admin
|
||||
it_validator = models.CharField(
|
||||
max_length=255, blank=True, verbose_name="Întocmit de (IT)"
|
||||
)
|
||||
|
||||
computers = models.ManyToManyField(
|
||||
Computer, blank=True, verbose_name="Computere transferate"
|
||||
)
|
||||
monitors = models.ManyToManyField(
|
||||
Monitor, blank=True, verbose_name="Monitoare transferate"
|
||||
)
|
||||
peripherals = models.ManyToManyField(
|
||||
Peripheral, blank=True, verbose_name="Periferice transferate"
|
||||
)
|
||||
|
||||
notes = models.TextField(blank=True, null=True, verbose_name="Observații")
|
||||
|
||||
# Field to attach the signed document
|
||||
scanned_document = models.FileField(
|
||||
upload_to="handover_protocols/",
|
||||
blank=True,
|
||||
null=True,
|
||||
validators=[validate_file_size],
|
||||
verbose_name="Document scanat (semnat)",
|
||||
)
|
||||
|
||||
history = HistoricalRecords()
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.document_number:
|
||||
max_num = HandoverProtocol.objects.aggregate(Max("document_number"))[
|
||||
"document_number__max"
|
||||
]
|
||||
self.document_number = (
|
||||
(max_num + 1) if (max_num and max_num >= 1000) else 1000
|
||||
)
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
def __str__(self):
|
||||
return f"PV Predare-Primire nr. {self.document_number} din {self.date}"
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Proces Verbal Predare-Primire"
|
||||
verbose_name_plural = "Procese Verbale Predare-Primire"
|
||||
|
||||
Reference in New Issue
Block a user