Pregatire pentru productie si adaugare whitenoise
This commit is contained in:
@@ -46,3 +46,7 @@ docker compose exec web python manage.py migrate
|
|||||||
docker compose exec web python manage.py makemigrations equipment
|
docker compose exec web python manage.py makemigrations equipment
|
||||||
docker compose exec web python manage.py migrate
|
docker compose exec web python manage.py migrate
|
||||||
|
|
||||||
|
|
||||||
|
docker compose exec web python manage.py import_access
|
||||||
|
|
||||||
|
docker compose exec web python manage.py clear_database
|
||||||
|
|||||||
+7
-7
@@ -4,15 +4,15 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- postgres_data:/var/lib/postgresql/data
|
- postgres_data:/var/lib/postgresql/data
|
||||||
environment:
|
environment:
|
||||||
- POSTGRES_DB=djangodb
|
- POSTGRES_DB=eumi-db
|
||||||
- POSTGRES_USER=djangouser
|
- POSTGRES_USER=eumi-user
|
||||||
- POSTGRES_PASSWORD=djangopass
|
- POSTGRES_PASSWORD=kBGedy4ScgI7g
|
||||||
|
|
||||||
pgadmin:
|
pgadmin:
|
||||||
image: dpage/pgadmin4
|
image: dpage/pgadmin4
|
||||||
environment:
|
environment:
|
||||||
- PGADMIN_DEFAULT_EMAIL=catalin@x3c.ro
|
- PGADMIN_DEFAULT_EMAIL=catalin@x3c.ro
|
||||||
- PGADMIN_DEFAULT_PASSWORD=Parola123
|
- PGADMIN_DEFAULT_PASSWORD=CFratxlTiJ0TB
|
||||||
ports:
|
ports:
|
||||||
- "5050:80"
|
- "5050:80"
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -26,9 +26,9 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- "8000:8000"
|
- "8000:8000"
|
||||||
environment:
|
environment:
|
||||||
- DB_NAME=djangodb
|
- DB_NAME=eumi-db
|
||||||
- DB_USER=djangouser
|
- DB_USER=eumi-user
|
||||||
- DB_PASSWORD=djangopass
|
- DB_PASSWORD=kBGedy4ScgI7g
|
||||||
- DB_HOST=db
|
- DB_HOST=db
|
||||||
- DB_PORT=5432
|
- DB_PORT=5432
|
||||||
depends_on:
|
depends_on:
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
# management/commands/clear_database.py
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from django.db import connection
|
||||||
|
from users.models import Employee
|
||||||
|
from equipment.models import Computer, Monitor, Peripheral
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = "Clear all data from equipment and users tables"
|
||||||
|
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument(
|
||||||
|
"--force",
|
||||||
|
action="store_true",
|
||||||
|
help="Skip confirmation prompt",
|
||||||
|
)
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
if not options.get("force"):
|
||||||
|
confirm = input(
|
||||||
|
"This will DELETE ALL data from Employee, Computer, Monitor, and Peripheral tables. Are you sure? (y/n): "
|
||||||
|
)
|
||||||
|
if confirm.lower() != "y":
|
||||||
|
self.stdout.write("Operation cancelled.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Option A: Using Django's delete() - slower but triggers signals
|
||||||
|
Employee.objects.all().delete()
|
||||||
|
Computer.objects.all().delete()
|
||||||
|
Monitor.objects.all().delete()
|
||||||
|
Peripheral.objects.all().delete()
|
||||||
|
|
||||||
|
# Option B: Using raw SQL TRUNCATE - faster, resets sequences
|
||||||
|
with connection.cursor() as cursor:
|
||||||
|
# Truncate in correct order to respect foreign key constraints
|
||||||
|
cursor.execute("TRUNCATE TABLE equipment_peripheral CASCADE;")
|
||||||
|
cursor.execute("TRUNCATE TABLE equipment_monitor CASCADE;")
|
||||||
|
cursor.execute("TRUNCATE TABLE equipment_computer CASCADE;")
|
||||||
|
cursor.execute("TRUNCATE TABLE users_employee CASCADE;")
|
||||||
|
|
||||||
|
# Reset auto-increment sequences (if using serial/identity columns)
|
||||||
|
cursor.execute("ALTER SEQUENCE users_employee_id_seq RESTART WITH 1;")
|
||||||
|
cursor.execute("ALTER SEQUENCE equipment_computer_id_seq RESTART WITH 1;")
|
||||||
|
cursor.execute("ALTER SEQUENCE equipment_monitor_id_seq RESTART WITH 1;")
|
||||||
|
cursor.execute("ALTER SEQUENCE equipment_peripheral_id_seq RESTART WITH 1;")
|
||||||
|
|
||||||
|
self.stdout.write(self.style.SUCCESS("Database cleared successfully!"))
|
||||||
@@ -18,6 +18,31 @@ class Command(BaseCommand):
|
|||||||
|
|
||||||
# Funcție ajutătoare pentru a evita erorile la date calendaristice goale
|
# Funcție ajutătoare pentru a evita erorile la date calendaristice goale
|
||||||
# Funcție ajutătoare pentru conversia datelor din DD-MM-YYYY în YYYY-MM-DD
|
# Funcție ajutătoare pentru conversia datelor din DD-MM-YYYY în YYYY-MM-DD
|
||||||
|
# def parse_date(date_str):
|
||||||
|
# # Definim data de rezervă dacă rubrică e goală
|
||||||
|
# fallback_date = "2000-01-01"
|
||||||
|
|
||||||
|
# if not date_str or str(date_str).strip() == "":
|
||||||
|
# return fallback_date
|
||||||
|
|
||||||
|
# clean_str = str(date_str).strip()
|
||||||
|
|
||||||
|
# try:
|
||||||
|
# parsed = datetime.strptime(clean_str, "%d-%m-%Y")
|
||||||
|
# return parsed.strftime("%Y-%m-%d")
|
||||||
|
# except ValueError:
|
||||||
|
# try:
|
||||||
|
# parsed = datetime.strptime(clean_str, "%d/%m/%Y")
|
||||||
|
# return parsed.strftime("%Y-%m-%d")
|
||||||
|
# except ValueError:
|
||||||
|
# # Dacă data există dar formatul e complet invalid, punem tot fallback
|
||||||
|
# self.stdout.write(
|
||||||
|
# self.style.WARNING(
|
||||||
|
# f"Atenție: Data '{clean_str}' e invalidă. Folosim data de azi."
|
||||||
|
# )
|
||||||
|
# )
|
||||||
|
# return fallback_date
|
||||||
|
|
||||||
def parse_date(date_str):
|
def parse_date(date_str):
|
||||||
# Definim data de rezervă dacă rubrică e goală
|
# Definim data de rezervă dacă rubrică e goală
|
||||||
fallback_date = "2000-01-01"
|
fallback_date = "2000-01-01"
|
||||||
@@ -27,21 +52,55 @@ class Command(BaseCommand):
|
|||||||
|
|
||||||
clean_str = str(date_str).strip()
|
clean_str = str(date_str).strip()
|
||||||
|
|
||||||
|
# Elimină partea de timp (0:00:00) dacă există
|
||||||
|
if " " in clean_str:
|
||||||
|
clean_str = clean_str.split(" ")[0]
|
||||||
|
|
||||||
|
# Încearcă să parseze formatul DD-M-YYYY (cu sau fără leading zeros)
|
||||||
try:
|
try:
|
||||||
parsed = datetime.strptime(clean_str, "%d-%m-%Y")
|
# Split după '-'
|
||||||
return parsed.strftime("%Y-%m-%d")
|
parts = clean_str.split("-")
|
||||||
except ValueError:
|
if len(parts) == 3:
|
||||||
try:
|
day = parts[0].zfill(2) # Adaugă zero în față dacă e necesar
|
||||||
|
month = parts[1].zfill(2) # Adaugă zero în față dacă e necesar
|
||||||
|
year = parts[2]
|
||||||
|
|
||||||
|
# Verifică dacă anul are 4 cifre
|
||||||
|
if len(year) == 2:
|
||||||
|
year = "20" + year
|
||||||
|
|
||||||
|
clean_str = f"{day}-{month}-{year}"
|
||||||
|
|
||||||
|
parsed = datetime.strptime(clean_str, "%d-%m-%Y")
|
||||||
|
return parsed.strftime("%Y-%m-%d")
|
||||||
|
except (ValueError, IndexError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Încearcă și cu slash ca separator
|
||||||
|
try:
|
||||||
|
parts = clean_str.split("/")
|
||||||
|
if len(parts) == 3:
|
||||||
|
day = parts[0].zfill(2)
|
||||||
|
month = parts[1].zfill(2)
|
||||||
|
year = parts[2]
|
||||||
|
|
||||||
|
if len(year) == 2:
|
||||||
|
year = "20" + year
|
||||||
|
|
||||||
|
clean_str = f"{day}/{month}/{year}"
|
||||||
|
|
||||||
parsed = datetime.strptime(clean_str, "%d/%m/%Y")
|
parsed = datetime.strptime(clean_str, "%d/%m/%Y")
|
||||||
return parsed.strftime("%Y-%m-%d")
|
return parsed.strftime("%Y-%m-%d")
|
||||||
except ValueError:
|
except (ValueError, IndexError):
|
||||||
# Dacă data există dar formatul e complet invalid, punem tot fallback
|
pass
|
||||||
self.stdout.write(
|
|
||||||
self.style.WARNING(
|
# Dacă data există dar formatul e complet invalid, punem fallback
|
||||||
f"Atenție: Data '{clean_str}' e invalidă. Folosim data de azi."
|
self.stdout.write(
|
||||||
)
|
self.style.WARNING(
|
||||||
)
|
f"Atenție: Data '{date_str}' e invalidă. Folosim {fallback_date}."
|
||||||
return fallback_date
|
)
|
||||||
|
)
|
||||||
|
return fallback_date
|
||||||
|
|
||||||
# 1. IMPORTUL ANGAJAȚILOR
|
# 1. IMPORTUL ANGAJAȚILOR
|
||||||
self.stdout.write("Începe importul angajaților...")
|
self.stdout.write("Începe importul angajaților...")
|
||||||
|
|||||||
@@ -17,7 +17,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- Am adăugat înălțime fixă (max-height) și overflow-y pentru scroll -->
|
<!-- Am adăugat înălțime fixă (max-height) și overflow-y pentru scroll -->
|
||||||
<div class="card-body" style="max-height: 450px; overflow-y: auto;">
|
<div class="card-body" style="max-height: 450px; overflow-y: auto;">
|
||||||
<p class="mb-2">Total Calculatoare: <strong>{{ total_computers }}</strong></p>
|
<p class="mb-1">Total Calculatoare: <strong>{{ total_computers }}</strong></p>
|
||||||
|
<p class="mb-1">Total Monitoare: <strong>{{ total_monitors }}</strong></p>
|
||||||
|
<p class="mb-0">Total Periferice: <strong>{{ total_peripherals }}</strong></p>
|
||||||
<hr>
|
<hr>
|
||||||
<h6 class="fw-bold text-danger mt-3">Calculatoare Neasignate:</h6>
|
<h6 class="fw-bold text-danger mt-3">Calculatoare Neasignate:</h6>
|
||||||
<ul class="list-unstyled mb-3">
|
<ul class="list-unstyled mb-3">
|
||||||
|
|||||||
@@ -557,6 +557,9 @@ def handover_protocol_form(request, pk=None):
|
|||||||
def dashboard_view(request):
|
def dashboard_view(request):
|
||||||
# --- Coloana 1: Sumar Inventar (Înlocuitor temporar pt. Tichete) ---
|
# --- Coloana 1: Sumar Inventar (Înlocuitor temporar pt. Tichete) ---
|
||||||
total_computers = Computer.objects.count()
|
total_computers = Computer.objects.count()
|
||||||
|
total_monitors = Monitor.objects.count()
|
||||||
|
total_peripherals = Peripheral.objects.count()
|
||||||
|
|
||||||
unassigned_computers = Computer.objects.filter(assigned_to__isnull=True)
|
unassigned_computers = Computer.objects.filter(assigned_to__isnull=True)
|
||||||
unassigned_monitors = Monitor.objects.filter(assigned_to__isnull=True)
|
unassigned_monitors = Monitor.objects.filter(assigned_to__isnull=True)
|
||||||
|
|
||||||
@@ -578,6 +581,8 @@ def dashboard_view(request):
|
|||||||
|
|
||||||
context = {
|
context = {
|
||||||
"total_computers": total_computers,
|
"total_computers": total_computers,
|
||||||
|
"total_monitors": total_monitors,
|
||||||
|
"total_peripherals": total_peripherals,
|
||||||
"unassigned_computers": unassigned_computers,
|
"unassigned_computers": unassigned_computers,
|
||||||
"unassigned_monitors": unassigned_monitors,
|
"unassigned_monitors": unassigned_monitors,
|
||||||
"activity_log": activity_log,
|
"activity_log": activity_log,
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ BASE_DIR = Path(__file__).resolve().parent.parent
|
|||||||
SECRET_KEY = "django-insecure-z(p$%wh6x^_9!1cgt%!s$w8k39(fox-^!iujxai42_wncja4%s"
|
SECRET_KEY = "django-insecure-z(p$%wh6x^_9!1cgt%!s$w8k39(fox-^!iujxai42_wncja4%s"
|
||||||
|
|
||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
DEBUG = True
|
DEBUG = False
|
||||||
|
|
||||||
ALLOWED_HOSTS = ["localhost", "127.0.0.1", "0.0.0.0"]
|
ALLOWED_HOSTS = ["192.168.100.142", "eumi.local", "localhost", "127.0.0.1", "0.0.0.0"]
|
||||||
|
|
||||||
|
|
||||||
# Application definition
|
# Application definition
|
||||||
@@ -48,6 +48,7 @@ INSTALLED_APPS = [
|
|||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
"django.middleware.security.SecurityMiddleware",
|
"django.middleware.security.SecurityMiddleware",
|
||||||
|
"whitenoise.middleware.WhiteNoiseMiddleware",
|
||||||
"django.contrib.sessions.middleware.SessionMiddleware",
|
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||||
"django.middleware.common.CommonMiddleware",
|
"django.middleware.common.CommonMiddleware",
|
||||||
"django.middleware.csrf.CsrfViewMiddleware",
|
"django.middleware.csrf.CsrfViewMiddleware",
|
||||||
@@ -128,9 +129,7 @@ USE_TZ = True
|
|||||||
# https://docs.djangoproject.com/en/6.1/howto/static-files/
|
# https://docs.djangoproject.com/en/6.1/howto/static-files/
|
||||||
|
|
||||||
STATIC_URL = "static/"
|
STATIC_URL = "static/"
|
||||||
STATICFILES_DIRS = [
|
STATIC_ROOT = BASE_DIR / "staticfiles"
|
||||||
BASE_DIR / "static",
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
# Email
|
# Email
|
||||||
|
|||||||
@@ -4,3 +4,4 @@ psycopg2-binary==2.9.12
|
|||||||
sqlparse==0.6.0
|
sqlparse==0.6.0
|
||||||
django-simple-history
|
django-simple-history
|
||||||
xhtml2pdf>=0.2.11
|
xhtml2pdf>=0.2.11
|
||||||
|
whitenoise
|
||||||
|
|||||||
Reference in New Issue
Block a user