Files
diario_coversazioni/diario/models.py
automationkriz d296353dcb Initial commit: Diario Conversazioni Olimpic Nastri
- Django 5.2 + PostgreSQL + Gunicorn
- Conversazioni, Obiettivi, Documenti PDF, Persone
- Commenti e aggiornamenti con modifica/eliminazione
- Agenda, ricerca live, giorni rimanenti scadenze
- Bootstrap 5 + HTMX + toast notifications
- Deploy: Nginx + Gunicorn + SSL
2026-04-05 14:48:22 +00:00

140 lines
4.6 KiB
Python

from django.db import models
from django.contrib.auth.models import User
from django.core.validators import FileExtensionValidator
from django.utils import timezone
def validate_file_size(value):
limit = 10 * 1024 * 1024 # 10 MB
if value.size > limit:
from django.core.exceptions import ValidationError
raise ValidationError('Il file non può superare i 10 MB.')
class Conversazione(models.Model):
titolo = models.CharField(max_length=200)
data = models.DateTimeField()
partecipanti = models.ManyToManyField(User, related_name='conversazioni_partecipate', blank=True)
contenuto = models.TextField()
registrato_da = models.ForeignKey(
User, on_delete=models.SET_NULL, null=True, related_name='conversazioni_registrate'
)
class Meta:
ordering = ['-data']
verbose_name = 'Conversazione'
verbose_name_plural = 'Conversazioni'
def __str__(self):
return f"{self.titolo} ({self.data.strftime('%d/%m/%Y')})"
class Obiettivo(models.Model):
TIPO_CHOICES = [
('collettivo', 'Collettivo'),
('individuale', 'Individuale'),
]
STATO_CHOICES = [
('aperto', 'Aperto'),
('in_corso', 'In corso'),
('completato', 'Completato'),
('sospeso', 'Sospeso'),
]
titolo = models.CharField(max_length=200)
descrizione = models.TextField(blank=True)
avanzamento = models.PositiveSmallIntegerField(default=0) # 0-100
tipo = models.CharField(max_length=20, choices=TIPO_CHOICES, default='collettivo')
assegnato_a = models.ManyToManyField(
User, blank=True,
related_name='obiettivi_assegnati'
)
stato = models.CharField(max_length=20, choices=STATO_CHOICES, default='aperto')
data_scadenza = models.DateField(null=True, blank=True)
creato_da = models.ForeignKey(
User, on_delete=models.SET_NULL, null=True, related_name='obiettivi_creati'
)
data_creazione = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-data_creazione']
verbose_name = 'Obiettivo'
verbose_name_plural = 'Obiettivi'
def __str__(self):
return self.titolo
@property
def giorni_rimanenti(self):
"""Restituisce i giorni rimanenti alla scadenza (None se non impostata)."""
if not self.data_scadenza:
return None
delta = self.data_scadenza - timezone.now().date()
return delta.days
class AggiornamentoObiettivo(models.Model):
obiettivo = models.ForeignKey(Obiettivo, on_delete=models.CASCADE, related_name='aggiornamenti')
testo = models.TextField()
autore = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name='aggiornamenti')
data = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-data']
verbose_name = 'Aggiornamento'
verbose_name_plural = 'Aggiornamenti'
def __str__(self):
return f"Aggiornamento su '{self.obiettivo}' del {self.data.strftime('%d/%m/%Y')}"
class CommentoConversazione(models.Model):
conversazione = models.ForeignKey(Conversazione, on_delete=models.CASCADE, related_name='commenti')
testo = models.TextField()
autore = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name='commenti_conversazione')
data = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-data']
verbose_name = 'Commento'
verbose_name_plural = 'Commenti'
def __str__(self):
return f"Commento su '{self.conversazione}' del {self.data.strftime('%d/%m/%Y')}"
class Documento(models.Model):
file = models.FileField(
upload_to='documenti/%Y/%m/',
validators=[
FileExtensionValidator(allowed_extensions=['pdf']),
validate_file_size,
],
)
titolo = models.CharField(max_length=200)
descrizione = models.TextField(blank=True)
caricato_da = models.ForeignKey(
User, on_delete=models.SET_NULL, null=True, related_name='documenti_caricati'
)
data_caricamento = models.DateTimeField(auto_now_add=True)
conversazione = models.ForeignKey(
'Conversazione', on_delete=models.SET_NULL, null=True, blank=True, related_name='documenti'
)
obiettivo = models.ForeignKey(
'Obiettivo', on_delete=models.SET_NULL, null=True, blank=True, related_name='documenti'
)
class Meta:
ordering = ['-data_caricamento']
verbose_name = 'Documento'
verbose_name_plural = 'Documenti'
def __str__(self):
return self.titolo
@property
def filename(self):
import os
return os.path.basename(self.file.name)