from django.db import models from datetime import date from simple_history.models import HistoricalRecords from users.models import Employee from django.core.exceptions import ValidationError EQUIPMENT_STATUS = [ ("activ", "Activ"), ("casat", "Casat (Decommissioned)"), ] class Computer(models.Model): # Unique ID and Entry equipment_code = models.CharField( max_length=50, unique=True, verbose_name="Cod Echipament" ) entry_date = models.DateField(default=date.today, verbose_name="Data intrării") # Hardware Specs oem_name = models.CharField( max_length=255, null=True, blank=True, verbose_name="Producător (OEM)" ) motherboard = models.CharField(max_length=255, verbose_name="Placă de bază") cpu = models.CharField(max_length=255, verbose_name="Procesor (CPU)") ram = models.CharField(max_length=100, verbose_name="Memorie RAM") storage = models.CharField(max_length=100, verbose_name="Stocare (HDD/SSD)") optical_drive = models.CharField( max_length=100, blank=True, null=True, verbose_name="Unitate optică" ) gpu = models.CharField( max_length=255, null=True, blank=True, verbose_name="Placă video (GPU)" ) mac_address = models.CharField(max_length=50, verbose_name="Adresă MAC") # Software & Misc os_license = models.CharField(max_length=255, verbose_name="Licență OS") additional_licenses = models.TextField( blank=True, null=True, verbose_name="Licențe adiționale" ) observations = models.TextField(blank=True, null=True, verbose_name="Observații") # Custody Assignment assigned_to = models.ForeignKey( Employee, on_delete=models.SET_NULL, null=True, blank=True, related_name="computers", verbose_name="Atribuit către", ) status = models.CharField( max_length=20, choices=EQUIPMENT_STATUS, default="activ", verbose_name="Stare" ) history = HistoricalRecords() def __str__(self): return f"{self.equipment_code} - {self.oem_name or 'Sistem Asamblat'}" class Meta: verbose_name = "Computer / Laptop" verbose_name_plural = "Computere / Laptopuri" class Monitor(models.Model): equipment_code = models.CharField( max_length=50, unique=True, verbose_name="Cod Echipament" ) entry_date = models.DateField(default=date.today, verbose_name="Data intrării") name = models.CharField(max_length=255, verbose_name="Nume Monitor") serial_number = models.CharField(max_length=100, verbose_name="Număr Serial") screen_diagonal = models.CharField(max_length=50, verbose_name="Diagonală (inch)") observations = models.TextField(blank=True, null=True, verbose_name="Observații") assigned_to = models.ForeignKey( Employee, on_delete=models.SET_NULL, null=True, blank=True, related_name="monitors", verbose_name="Atribuit către", ) status = models.CharField( max_length=20, choices=EQUIPMENT_STATUS, default="activ", verbose_name="Stare" ) history = HistoricalRecords() def __str__(self): return f"{self.equipment_code} - {self.name}" class Meta: verbose_name = "Monitor" verbose_name_plural = "Monitoare" class Peripheral(models.Model): PERIPHERAL_TYPES = [ ("printer", "Imprimantă"), ("ups", "UPS"), ("scanner", "Scanner"), ("copier", "Copiator"), ("ethernet", "Adaptor Ethernet"), ("audio", "Boxe Audio"), ("hdd_ext", "HDD Extern"), ("webcam", "Cameră Web"), ("other", "Altul"), ] equipment_code = models.CharField( max_length=50, unique=True, verbose_name="Cod Echipament" ) entry_date = models.DateField(default=date.today, verbose_name="Data intrării") peripheral_type = models.CharField( max_length=50, choices=PERIPHERAL_TYPES, verbose_name="Tip Periferic" ) name = models.CharField(max_length=255, verbose_name="Nume Echipament") serial_number = models.CharField(max_length=100, verbose_name="Număr Serial") assigned_to = models.ForeignKey( Employee, on_delete=models.SET_NULL, null=True, blank=True, related_name="peripherals", verbose_name="Atribuit către", ) status = models.CharField( max_length=20, choices=EQUIPMENT_STATUS, default="activ", verbose_name="Stare" ) history = HistoricalRecords() def __str__(self): return f"{self.equipment_code} - {self.name} ({self.get_peripheral_type_display()})" class Meta: verbose_name = "Periferic" verbose_name_plural = "Periferice" class DigitalCertificate(models.Model): CERT_TYPES = [ ("cloud", "Cloud"), ("usb", "USB Token"), ] certificate_type = models.CharField( max_length=50, choices=CERT_TYPES, verbose_name="Tip Certificat" ) issue_date = models.DateField(verbose_name="Data emiterii") expiration_date = models.DateField(verbose_name="Data expirării") is_canceled = models.BooleanField(default=False, verbose_name="Anulat?") # Links directly to the employee assigned_to = models.ForeignKey( Employee, on_delete=models.CASCADE, related_name="digital_certificates", verbose_name="Titular Certificat", ) history = HistoricalRecords() def __str__(self): return f"Certificat {self.get_certificate_type_display()} - {self.assigned_to.name}" class Meta: verbose_name = "Certificat Digital" verbose_name_plural = "Certificate Digitale" class MaintenanceRecord(models.Model): date = models.DateField(default=date.today, verbose_name="Data intervenției") operation_type = models.CharField( max_length=150, verbose_name="Tip operațiune (Curățare, Upgrade, etc.)" ) description = models.TextField(verbose_name="Descriere detaliată") performed_by = models.CharField(max_length=100, verbose_name="Efectuat de") # Links to equipment (only one should be populated) computer = models.ForeignKey( Computer, on_delete=models.CASCADE, null=True, blank=True, related_name="maintenance_logs", ) monitor = models.ForeignKey( Monitor, on_delete=models.CASCADE, null=True, blank=True, related_name="maintenance_logs", ) peripheral = models.ForeignKey( Peripheral, on_delete=models.CASCADE, null=True, blank=True, related_name="maintenance_logs", ) history = HistoricalRecords() def clean(self): equipment_count = sum( [bool(self.computer), bool(self.monitor), bool(self.peripheral)] ) if equipment_count != 1: raise ValidationError( "O înregistrare de mentenanță trebuie să fie legată de exact un singur echipament." ) def save(self, *args, **kwargs): self.clean() super().save(*args, **kwargs) def __str__(self): return f"{self.date} - {self.operation_type}" class Meta: verbose_name = "Foaie de Mentenanță" verbose_name_plural = "Foi de Mentenanță" 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)" ) 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", ) monitor = models.OneToOneField( Monitor, on_delete=models.CASCADE, null=True, blank=True, related_name="decommission_log", ) peripheral = models.OneToOneField( Peripheral, on_delete=models.CASCADE, null=True, blank=True, related_name="decommission_log", ) 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() def __str__(self): return f"Casare {self.document_number} din {self.date}" class Meta: verbose_name = "Înregistrare Casare" verbose_name_plural = "Înregistrări Casare"