backend_users_equipment_interventions

This commit is contained in:
2026-08-18 16:14:45 +03:00
parent 3715c7e296
commit 75bcef3095
30 changed files with 1401 additions and 38 deletions
View File
+110
View File
@@ -0,0 +1,110 @@
from django.contrib import admin
from simple_history.admin import SimpleHistoryAdmin
from .models import (
Computer,
Monitor,
Peripheral,
DigitalCertificate,
MaintenanceRecord,
DecommissionRecord,
)
# --- Inlines for Computer ---
class MaintenanceInlineComputer(admin.TabularInline):
model = MaintenanceRecord
fk_name = "computer"
extra = 0
class DecommissionInlineComputer(admin.StackedInline):
model = DecommissionRecord
fk_name = "computer"
extra = 0
max_num = 1
# --- Inlines for Monitor ---
class MaintenanceInlineMonitor(admin.TabularInline):
model = MaintenanceRecord
fk_name = "monitor"
extra = 0
class DecommissionInlineMonitor(admin.StackedInline):
model = DecommissionRecord
fk_name = "monitor"
extra = 0
max_num = 1
# --- Inlines for Peripheral ---
class MaintenanceInlinePeripheral(admin.TabularInline):
model = MaintenanceRecord
fk_name = "peripheral"
extra = 0
class DecommissionInlinePeripheral(admin.StackedInline):
model = DecommissionRecord
fk_name = "peripheral"
extra = 0
max_num = 1
@admin.register(Computer)
class ComputerAdmin(SimpleHistoryAdmin):
list_display = ("equipment_code", "oem_name", "status", "assigned_to", "entry_date")
list_filter = ("status", "entry_date", "assigned_to")
search_fields = ("equipment_code", "oem_name", "mac_address", "observations")
inlines = [MaintenanceInlineComputer, DecommissionInlineComputer]
@admin.register(Monitor)
class MonitorAdmin(SimpleHistoryAdmin):
list_display = ("equipment_code", "name", "status", "assigned_to", "entry_date")
list_filter = ("status", "entry_date", "assigned_to")
search_fields = ("equipment_code", "name", "serial_number")
inlines = [MaintenanceInlineMonitor, DecommissionInlineMonitor]
@admin.register(Peripheral)
class PeripheralAdmin(SimpleHistoryAdmin):
list_display = (
"equipment_code",
"name",
"peripheral_type",
"status",
"assigned_to",
)
list_filter = ("status", "peripheral_type", "entry_date", "assigned_to")
search_fields = ("equipment_code", "name", "serial_number")
inlines = [MaintenanceInlinePeripheral, DecommissionInlinePeripheral]
@admin.register(DigitalCertificate)
class DigitalCertificateAdmin(SimpleHistoryAdmin):
list_display = (
"get_certificate_type_display",
"assigned_to",
"issue_date",
"expiration_date",
"is_canceled",
)
list_filter = ("certificate_type", "is_canceled", "issue_date")
search_fields = ("assigned_to__name", "assigned_to__username")
# Optionally register the records independently so they can be searched globally
@admin.register(MaintenanceRecord)
class MaintenanceRecordAdmin(SimpleHistoryAdmin):
list_display = ("date", "operation_type", "performed_by")
list_filter = ("date", "operation_type")
search_fields = ("description", "performed_by")
@admin.register(DecommissionRecord)
class DecommissionRecordAdmin(SimpleHistoryAdmin):
list_display = ("document_number", "date", "reason")
list_filter = ("date",)
search_fields = ("document_number", "reason")
+5
View File
@@ -0,0 +1,5 @@
from django.apps import AppConfig
class EquipmentConfig(AppConfig):
name = 'equipment'
+196
View File
@@ -0,0 +1,196 @@
# Generated by Django 6.1 on 2026-08-18 12:20
import datetime
import django.db.models.deletion
import simple_history.models
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('users', '0002_historicalcompartiment_historicaldirectie_and_more'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Computer',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('equipment_code', models.CharField(blank=True, max_length=50, unique=True, verbose_name='Cod Echipament')),
('entry_date', models.DateField(default=datetime.date.today, verbose_name='Data intrării')),
('oem_name', models.CharField(max_length=255, 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(blank=True, max_length=100, null=True, verbose_name='Unitate optică')),
('gpu', models.CharField(max_length=255, verbose_name='Placă video (GPU)')),
('mac_address', models.CharField(max_length=50, verbose_name='Adresă MAC')),
('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')),
('assigned_to', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='computers', to='users.employee', verbose_name='Atribuit către')),
],
options={
'verbose_name': 'Computer / Laptop',
'verbose_name_plural': 'Computere / Laptopuri',
},
),
migrations.CreateModel(
name='DigitalCertificate',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('certificate_type', models.CharField(choices=[('cloud', 'Cloud'), ('usb', 'USB Token')], max_length=50, 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?')),
('assigned_to', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='digital_certificates', to='users.employee', verbose_name='Titular Certificat')),
],
options={
'verbose_name': 'Certificat Digital',
'verbose_name_plural': 'Certificate Digitale',
},
),
migrations.CreateModel(
name='HistoricalComputer',
fields=[
('id', models.BigIntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')),
('equipment_code', models.CharField(blank=True, db_index=True, max_length=50, verbose_name='Cod Echipament')),
('entry_date', models.DateField(default=datetime.date.today, verbose_name='Data intrării')),
('oem_name', models.CharField(max_length=255, 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(blank=True, max_length=100, null=True, verbose_name='Unitate optică')),
('gpu', models.CharField(max_length=255, verbose_name='Placă video (GPU)')),
('mac_address', models.CharField(max_length=50, verbose_name='Adresă MAC')),
('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')),
('history_id', models.AutoField(primary_key=True, serialize=False)),
('history_date', models.DateTimeField(db_index=True)),
('history_change_reason', models.CharField(max_length=100, null=True)),
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
('assigned_to', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='users.employee', verbose_name='Atribuit către')),
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'historical Computer / Laptop',
'verbose_name_plural': 'historical Computere / Laptopuri',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': ('history_date', 'history_id'),
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
migrations.CreateModel(
name='HistoricalDigitalCertificate',
fields=[
('id', models.BigIntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')),
('certificate_type', models.CharField(choices=[('cloud', 'Cloud'), ('usb', 'USB Token')], max_length=50, 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?')),
('history_id', models.AutoField(primary_key=True, serialize=False)),
('history_date', models.DateTimeField(db_index=True)),
('history_change_reason', models.CharField(max_length=100, null=True)),
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
('assigned_to', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='users.employee', verbose_name='Titular Certificat')),
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'historical Certificat Digital',
'verbose_name_plural': 'historical Certificate Digitale',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': ('history_date', 'history_id'),
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
migrations.CreateModel(
name='HistoricalMonitor',
fields=[
('id', models.BigIntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')),
('equipment_code', models.CharField(blank=True, db_index=True, max_length=50, verbose_name='Cod Echipament')),
('entry_date', models.DateField(default=datetime.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')),
('history_id', models.AutoField(primary_key=True, serialize=False)),
('history_date', models.DateTimeField(db_index=True)),
('history_change_reason', models.CharField(max_length=100, null=True)),
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
('assigned_to', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='users.employee', verbose_name='Atribuit către')),
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'historical Monitor',
'verbose_name_plural': 'historical Monitoare',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': ('history_date', 'history_id'),
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
migrations.CreateModel(
name='HistoricalPeripheral',
fields=[
('id', models.BigIntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')),
('equipment_code', models.CharField(blank=True, db_index=True, max_length=50, verbose_name='Cod Echipament')),
('entry_date', models.DateField(default=datetime.date.today, verbose_name='Data intrării')),
('peripheral_type', models.CharField(choices=[('printer', 'Imprimantă'), ('ups', 'UPS'), ('scanner', 'Scanner'), ('copier', 'Copiator'), ('ethernet', 'Adaptor Ethernet'), ('audio', 'Boxe Audio'), ('hdd_ext', 'HDD Extern'), ('webcam', 'Cameră Web'), ('other', 'Altul')], max_length=50, 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')),
('history_id', models.AutoField(primary_key=True, serialize=False)),
('history_date', models.DateTimeField(db_index=True)),
('history_change_reason', models.CharField(max_length=100, null=True)),
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
('assigned_to', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='users.employee', verbose_name='Atribuit către')),
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'historical Periferic',
'verbose_name_plural': 'historical Periferice',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': ('history_date', 'history_id'),
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
migrations.CreateModel(
name='Monitor',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('equipment_code', models.CharField(blank=True, max_length=50, unique=True, verbose_name='Cod Echipament')),
('entry_date', models.DateField(default=datetime.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(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='monitors', to='users.employee', verbose_name='Atribuit către')),
],
options={
'verbose_name': 'Monitor',
'verbose_name_plural': 'Monitoare',
},
),
migrations.CreateModel(
name='Peripheral',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('equipment_code', models.CharField(blank=True, max_length=50, unique=True, verbose_name='Cod Echipament')),
('entry_date', models.DateField(default=datetime.date.today, verbose_name='Data intrării')),
('peripheral_type', models.CharField(choices=[('printer', 'Imprimantă'), ('ups', 'UPS'), ('scanner', 'Scanner'), ('copier', 'Copiator'), ('ethernet', 'Adaptor Ethernet'), ('audio', 'Boxe Audio'), ('hdd_ext', 'HDD Extern'), ('webcam', 'Cameră Web'), ('other', 'Altul')], max_length=50, 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(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='peripherals', to='users.employee', verbose_name='Atribuit către')),
],
options={
'verbose_name': 'Periferic',
'verbose_name_plural': 'Periferice',
},
),
]
@@ -0,0 +1,63 @@
# Generated by Django 6.1 on 2026-08-18 12:45
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('equipment', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='computer',
name='equipment_code',
field=models.CharField(max_length=50, unique=True, verbose_name='Cod Echipament'),
),
migrations.AlterField(
model_name='computer',
name='gpu',
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='Placă video (GPU)'),
),
migrations.AlterField(
model_name='computer',
name='oem_name',
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='Producător (OEM)'),
),
migrations.AlterField(
model_name='historicalcomputer',
name='equipment_code',
field=models.CharField(db_index=True, max_length=50, verbose_name='Cod Echipament'),
),
migrations.AlterField(
model_name='historicalcomputer',
name='gpu',
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='Placă video (GPU)'),
),
migrations.AlterField(
model_name='historicalcomputer',
name='oem_name',
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='Producător (OEM)'),
),
migrations.AlterField(
model_name='historicalmonitor',
name='equipment_code',
field=models.CharField(db_index=True, max_length=50, verbose_name='Cod Echipament'),
),
migrations.AlterField(
model_name='historicalperipheral',
name='equipment_code',
field=models.CharField(db_index=True, max_length=50, verbose_name='Cod Echipament'),
),
migrations.AlterField(
model_name='monitor',
name='equipment_code',
field=models.CharField(max_length=50, unique=True, verbose_name='Cod Echipament'),
),
migrations.AlterField(
model_name='peripheral',
name='equipment_code',
field=models.CharField(max_length=50, unique=True, verbose_name='Cod Echipament'),
),
]
@@ -0,0 +1,130 @@
# Generated by Django 6.1 on 2026-08-18 12:55
import datetime
import django.db.models.deletion
import simple_history.models
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('equipment', '0002_alter_computer_equipment_code_alter_computer_gpu_and_more'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.AddField(
model_name='computer',
name='status',
field=models.CharField(choices=[('activ', 'Activ'), ('casat', 'Casat (Decommissioned)')], default='activ', max_length=20, verbose_name='Stare'),
),
migrations.AddField(
model_name='historicalcomputer',
name='status',
field=models.CharField(choices=[('activ', 'Activ'), ('casat', 'Casat (Decommissioned)')], default='activ', max_length=20, verbose_name='Stare'),
),
migrations.AddField(
model_name='historicalmonitor',
name='status',
field=models.CharField(choices=[('activ', 'Activ'), ('casat', 'Casat (Decommissioned)')], default='activ', max_length=20, verbose_name='Stare'),
),
migrations.AddField(
model_name='historicalperipheral',
name='status',
field=models.CharField(choices=[('activ', 'Activ'), ('casat', 'Casat (Decommissioned)')], default='activ', max_length=20, verbose_name='Stare'),
),
migrations.AddField(
model_name='monitor',
name='status',
field=models.CharField(choices=[('activ', 'Activ'), ('casat', 'Casat (Decommissioned)')], default='activ', max_length=20, verbose_name='Stare'),
),
migrations.AddField(
model_name='peripheral',
name='status',
field=models.CharField(choices=[('activ', 'Activ'), ('casat', 'Casat (Decommissioned)')], default='activ', max_length=20, verbose_name='Stare'),
),
migrations.CreateModel(
name='DecommissionRecord',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateField(default=datetime.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.)')),
('computer', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='decommission_log', to='equipment.computer')),
('monitor', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='decommission_log', to='equipment.monitor')),
('peripheral', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='decommission_log', to='equipment.peripheral')),
],
options={
'verbose_name': 'Înregistrare Casare',
'verbose_name_plural': 'Înregistrări Casare',
},
),
migrations.CreateModel(
name='HistoricalDecommissionRecord',
fields=[
('id', models.BigIntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')),
('date', models.DateField(default=datetime.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.)')),
('history_id', models.AutoField(primary_key=True, serialize=False)),
('history_date', models.DateTimeField(db_index=True)),
('history_change_reason', models.CharField(max_length=100, null=True)),
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
('computer', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='equipment.computer')),
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
('monitor', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='equipment.monitor')),
('peripheral', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='equipment.peripheral')),
],
options={
'verbose_name': 'historical Înregistrare Casare',
'verbose_name_plural': 'historical Înregistrări Casare',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': ('history_date', 'history_id'),
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
migrations.CreateModel(
name='HistoricalMaintenanceRecord',
fields=[
('id', models.BigIntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')),
('date', models.DateField(default=datetime.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')),
('history_id', models.AutoField(primary_key=True, serialize=False)),
('history_date', models.DateTimeField(db_index=True)),
('history_change_reason', models.CharField(max_length=100, null=True)),
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
('computer', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='equipment.computer')),
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
('monitor', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='equipment.monitor')),
('peripheral', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='equipment.peripheral')),
],
options={
'verbose_name': 'historical Foaie de Mentenanță',
'verbose_name_plural': 'historical Foi de Mentenanță',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': ('history_date', 'history_id'),
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
migrations.CreateModel(
name='MaintenanceRecord',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateField(default=datetime.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')),
('computer', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='maintenance_logs', to='equipment.computer')),
('monitor', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='maintenance_logs', to='equipment.monitor')),
('peripheral', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='maintenance_logs', to='equipment.peripheral')),
],
options={
'verbose_name': 'Foaie de Mentenanță',
'verbose_name_plural': 'Foi de Mentenanță',
},
),
]
View File
+291
View File
@@ -0,0 +1,291 @@
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"
+3
View File
@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.
+3
View File
@@ -0,0 +1,3 @@
from django.shortcuts import render
# Create your views here.