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
+38
View File
@@ -0,0 +1,38 @@
from django.contrib import admin
from simple_history.admin import SimpleHistoryAdmin
from .models import Directie, Serviciu, Compartiment, Employee
@admin.register(Directie)
class DirectieAdmin(SimpleHistoryAdmin):
list_display = ("name",)
search_fields = ("name",)
@admin.register(Serviciu)
class ServiciuAdmin(SimpleHistoryAdmin):
list_display = ("name", "directie")
list_filter = ("directie",)
search_fields = ("name",)
@admin.register(Compartiment)
class CompartimentAdmin(SimpleHistoryAdmin):
list_display = ("name", "directie", "serviciu")
list_filter = ("directie", "serviciu")
search_fields = ("name",)
@admin.register(Employee)
class EmployeeAdmin(SimpleHistoryAdmin):
list_display = (
"name",
"username",
"role",
"email",
"directie",
"serviciu",
"compartiment",
)
list_filter = ("directie", "serviciu", "compartiment")
search_fields = ("name", "username", "email")
+5
View File
@@ -0,0 +1,5 @@
from django.apps import AppConfig
class UsersConfig(AppConfig):
name = 'users'
+74
View File
@@ -0,0 +1,74 @@
# Generated by Django 6.1 on 2026-08-18 11:35
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Directie',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, verbose_name='Nume Direcție')),
],
options={
'verbose_name': 'Direcție',
'verbose_name_plural': 'Direcții',
},
),
migrations.CreateModel(
name='Compartiment',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, verbose_name='Nume Compartiment')),
('directie', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='compartimente_directe', to='users.directie', verbose_name='Direcție (Direct)')),
],
options={
'verbose_name': 'Compartiment',
'verbose_name_plural': 'Compartimente',
},
),
migrations.CreateModel(
name='Serviciu',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, verbose_name='Nume Serviciu')),
('directie', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='servicii', to='users.directie', verbose_name='Direcție')),
],
options={
'verbose_name': 'Serviciu',
'verbose_name_plural': 'Servicii',
},
),
migrations.CreateModel(
name='Employee',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, verbose_name='Name')),
('username', models.CharField(max_length=150, unique=True, verbose_name='User name')),
('role', models.CharField(max_length=255, verbose_name='Function/role')),
('office_number', models.CharField(max_length=50, verbose_name='Office number')),
('email', models.EmailField(max_length=254, verbose_name='Email address')),
('observations', models.TextField(blank=True, null=True, verbose_name='Observations')),
('compartiment', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='employees', to='users.compartiment', verbose_name='Compartiment')),
('directie', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='employees', to='users.directie', verbose_name='Direcție')),
('serviciu', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='employees', to='users.serviciu', verbose_name='Serviciu')),
],
options={
'verbose_name': 'Angajat / Utilizator',
'verbose_name_plural': 'Angajați / Utilizatori',
},
),
migrations.AddField(
model_name='compartiment',
name='serviciu',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='compartimente_subordonate', to='users.serviciu', verbose_name='Serviciu'),
),
]
@@ -0,0 +1,104 @@
# Generated by Django 6.1 on 2026-08-18 11:43
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 = [
('users', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='HistoricalCompartiment',
fields=[
('id', models.BigIntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')),
('name', models.CharField(max_length=255, verbose_name='Nume Compartiment')),
('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)),
('directie', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='users.directie', verbose_name='Direcție (Direct)')),
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
('serviciu', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='users.serviciu', verbose_name='Serviciu')),
],
options={
'verbose_name': 'historical Compartiment',
'verbose_name_plural': 'historical Compartimente',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': ('history_date', 'history_id'),
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
migrations.CreateModel(
name='HistoricalDirectie',
fields=[
('id', models.BigIntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')),
('name', models.CharField(max_length=255, verbose_name='Nume Direcție')),
('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)),
('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 Direcție',
'verbose_name_plural': 'historical Direcții',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': ('history_date', 'history_id'),
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
migrations.CreateModel(
name='HistoricalEmployee',
fields=[
('id', models.BigIntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')),
('name', models.CharField(max_length=255, verbose_name='Name')),
('username', models.CharField(db_index=True, max_length=150, verbose_name='User name')),
('role', models.CharField(max_length=255, verbose_name='Function/role')),
('office_number', models.CharField(max_length=50, verbose_name='Office number')),
('email', models.EmailField(max_length=254, verbose_name='Email address')),
('observations', models.TextField(blank=True, null=True, verbose_name='Observations')),
('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)),
('compartiment', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='users.compartiment', verbose_name='Compartiment')),
('directie', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='users.directie', verbose_name='Direcție')),
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
('serviciu', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='users.serviciu', verbose_name='Serviciu')),
],
options={
'verbose_name': 'historical Angajat / Utilizator',
'verbose_name_plural': 'historical Angajați / Utilizatori',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': ('history_date', 'history_id'),
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
migrations.CreateModel(
name='HistoricalServiciu',
fields=[
('id', models.BigIntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')),
('name', models.CharField(max_length=255, verbose_name='Nume Serviciu')),
('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)),
('directie', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='users.directie', verbose_name='Direcție')),
('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 Serviciu',
'verbose_name_plural': 'historical Servicii',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': ('history_date', 'history_id'),
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
]
View File
+126
View File
@@ -0,0 +1,126 @@
from django.db import models
from django.core.exceptions import ValidationError
from simple_history.models import HistoricalRecords
class Directie(models.Model):
name = models.CharField(max_length=255, verbose_name="Nume Direcție")
history = HistoricalRecords()
def __str__(self):
return self.name
class Meta:
verbose_name = "Direcție"
verbose_name_plural = "Direcții"
class Serviciu(models.Model):
name = models.CharField(max_length=255, verbose_name="Nume Serviciu")
# A Serviciu is directly assigned to a Direcție
directie = models.ForeignKey(
Directie,
on_delete=models.CASCADE,
related_name="servicii",
verbose_name="Direcție",
)
history = HistoricalRecords()
def __str__(self):
return self.name
class Meta:
verbose_name = "Serviciu"
verbose_name_plural = "Servicii"
class Compartiment(models.Model):
name = models.CharField(max_length=255, verbose_name="Nume Compartiment")
# A Compartiment can be part of a Serviciu or directly included in a Direcție
directie = models.ForeignKey(
Directie,
on_delete=models.CASCADE,
null=True,
blank=True,
related_name="compartimente_directe",
verbose_name="Direcție (Direct)",
)
serviciu = models.ForeignKey(
Serviciu,
on_delete=models.CASCADE,
null=True,
blank=True,
related_name="compartimente_subordonate",
verbose_name="Serviciu",
)
history = HistoricalRecords()
def clean(self):
# Validation to ensure the Compartiment belongs to either a Direcție OR a Serviciu, but not both or neither.
if not self.directie and not self.serviciu:
raise ValidationError(
"Un compartiment trebuie să aparțină de o Direcție sau de un Serviciu."
)
if self.directie and self.serviciu:
raise ValidationError(
"Un compartiment nu poate aparține simultan și de o Direcție și de un Serviciu."
)
def save(self, *args, **kwargs):
self.clean()
super().save(*args, **kwargs)
def __str__(self):
return self.name
class Meta:
verbose_name = "Compartiment"
verbose_name_plural = "Compartimente"
class Employee(models.Model):
"""
Represents the 'Users' from the project specification who will hold equipment.
Named 'Employee' to avoid conflicts with Django's built-in auth.User model.
"""
name = models.CharField(max_length=255, verbose_name="Name")
username = models.CharField(max_length=150, unique=True, verbose_name="User name")
role = models.CharField(max_length=255, verbose_name="Function/role")
office_number = models.CharField(max_length=50, verbose_name="Office number")
email = models.EmailField(verbose_name="Email address")
observations = models.TextField(null=True, blank=True, verbose_name="Observations")
# Organizational Placement - Employees can be placed at any of the three levels
directie = models.ForeignKey(
Directie,
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="employees",
verbose_name="Direcție",
)
serviciu = models.ForeignKey(
Serviciu,
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="employees",
verbose_name="Serviciu",
)
compartiment = models.ForeignKey(
Compartiment,
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="employees",
verbose_name="Compartiment",
)
history = HistoricalRecords()
def __str__(self):
return f"{self.name} ({self.username})"
class Meta:
verbose_name = "Angajat / Utilizator"
verbose_name_plural = "Angajați / Utilizatori"
+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.