docbow/docbow_project/docbow/models.py

306 lines
10 KiB
Python

import os
import datetime as dt
import random
import hashlib
from django.db.models import Model, ForeignKey, \
DateTimeField, CharField, FileField, ManyToManyField, \
TextField, Manager, BooleanField, OneToOneField
from django.contrib.auth.models import User, Group
from django.template.defaultfilters import slugify
from django.utils.translation import ugettext_lazy as _
from django.forms import ValidationError
DOCBOW_APP = _('docbow')
DOCBOW_APP = _('Docbow_App')
DOCBOW_APP2 = _('Docbow_app')
class GetByNameManager(Manager):
def get_by_natural_key(self, name):
return self.get(name=name)
class ContentManager(Manager):
def get_by_natural_key(self, description):
return self.get(description=description)
class NameNaturalKey(object):
def natural_key(self):
return (self.name,)
class FileType(NameNaturalKey, Model):
'''
A type of file that can be sent inside the application.
'''
objects = GetByNameManager()
name = CharField(max_length=128, unique=True)
def __unicode__(self):
return self.name
class Meta:
ordering = ['name']
verbose_name = _('File type')
verbose_name_plural = _('File types')
class Content(Model):
'''Predefined content type'''
objects = ContentManager()
description = CharField(max_length=128, unique=True)
def __unicode__(self):
return self.description
class Meta:
ordering = ['description']
verbose_name = _('Content')
verbose_name_plural = _('Contents')
def username(user):
return user.get_full_name() or user.username
def generate_filename(instance, filename):
now = dt.date.today()
# Keep all underscores and points
parts = filename.split('.')
parts = map(slugify, parts)
filename = '.'.join(parts)
return os.path.join('files', now.isoformat(), '%d_%s' % (random.randint(0,10000000), filename))
class Document(Model):
'''
Represent a file sent between a user and some targets, user or groups.
'''
class Meta:
ordering = ['-date']
verbose_name = _('Document')
verbose_name_plural = _('Documents')
sender = ForeignKey(User, verbose_name=_('Sender'),
related_name='documents_sent')
date = DateTimeField(default=dt.datetime.now,
verbose_name=_("Date d'envoi"))
to_user = ManyToManyField(User, related_name='directly_received_documents',
blank=True, null=True, verbose_name=_('Users to send to'))
to_list = ManyToManyField('MailingList', blank=True, null=True,
verbose_name=_('Groups to send to'))
filetype = ForeignKey(FileType, verbose_name=_('Document type'))
comment = TextField(blank=True, verbose_name=_('Comments'))
def __unicode__(self):
ctx = {
'sender': username(self.sender),
'date': self.date.date().isoformat(),
'filename': self.filenames(),
'filetype': self.filetype,
'comment': self.comment }
return _('%(comment)s; %(filetype)s, %(filename)s de %(sender)s le %(date)s') % ctx
def filenames(self):
files = [ attached_file for attached_file in self.attached_files.all() ]
return ', '.join([f.filename() for f in files])
filenames.short_description = _('Attached files')
def filename_links(self):
links = []
for attached_file in self.attached_files.all():
name = attached_file.filename()
url = attached_file.link()
links.append(u'<a href="%s">%s</a>' % (url, name))
return ', '.join(links)
filename_links.short_description = _('Attached files')
filename_links.allow_tags = True
def user_human_to(self):
return sorted(map(username, self.to_user.all()))
def group_human_to(self):
return sorted(map(unicode, self.to_list.all()))
def human_to(self):
return sorted(map(username, self.to_user.all()) + \
map(unicode, self.to_list.all()))
def recipients(self):
return ', '.join(self.human_to())
recipients.short_description = _('Recipients')
def to(self):
q = self.to_user.all() | \
User.objects.filter(mailing_lists__in=self.to_list.all())
return q.distinct()
def post(self):
to = self.to()
for user in to:
if user.is_active:
Mailbox.objects.get_or_create(owner=user,document=self)
# Add to outbox
Mailbox.objects.get_or_create(owner=self.sender, outbox=True, document=self)
return to.count()
def timestamp_blob(self):
blob = {}
blob['from'] = username(self.sender)
blob['date'] = self.date.isoformat()
blob['to'] = self.recipients()
blob['filetype'] = unicode(self.filetype)
blob['comment'] = self.comment
blob['files'] = []
for f in self.attached_files.all():
d = dict(name=f.filename(), size=f.content.size,
digest=hashlib.sha1(f.content.read()).hexdigest())
blob['files'].append(d)
return blob
class DocumentForwarded(Model):
'''Model to store tags applied to models.
First use will be to mark message as having been forwarded.
'''
from_document = ForeignKey(Document, related_name='document_forwarded_to')
to_document = ForeignKey(Document, related_name='document_forwarded_from')
date = DateTimeField(auto_now=True,
auto_now_add=True)
automatic = BooleanField(default=False)
def list_to_csv(l, mapping_func=None):
if mapping_func:
l = map(mapping_func, l)
return u', '.join(map(unicode, l))
class AutomaticForwarding(Model):
'''
Choice of sender and filetype to transfer mail automatically to a list
of recipients.
'''
filetypes = ManyToManyField(FileType, related_name='forwarding_rules',
verbose_name=_('filetype'))
originaly_to_user = ManyToManyField(User, related_name='as_original_recipient_forwarding_rules',
blank=True, null=True, verbose_name=_('Original recipients'),
help_text=_('At least one recipient must match for the rule to '
'apply.'))
forward_to_user = ManyToManyField(User, related_name='as_recipient_forwarding_rules',
blank=True, null=True, verbose_name=_('Users to forward to'))
forward_to_list = ManyToManyField('MailingList', blank=True, null=True,
verbose_name=_('Groups to forward to'), related_name='as_recipient_forwarding_rules')
def __unicode__(self):
ctx = {
'filetypes': list_to_csv(self.filetypes.all()),
'to': list_to_csv(map(username, self.forward_to_user.all())
+ list(self.forward_to_list.all())) }
return _('Forward documents of type %(filetypes)s automatically to %(to)s') % ctx
class Meta:
verbose_name = _('Automatic forwarding rule')
verbose_name_plural = _('Automatic forwarding rules')
class AttachedFile(Model):
name = CharField(max_length=128, verbose_name=_('Name'))
content = FileField(upload_to=generate_filename, verbose_name=_('File'))
document = ForeignKey(Document, verbose_name=_('Attached to'),
related_name='attached_files')
def filename(self):
filename = os.path.basename(self.content.name)
try:
prefix, true_filename = filename.split('_', 1)
if prefix.isdigit():
return true_filename
except:
pass
return filename
def link(self):
return '/admin/docbow/attachedfile/%s/download/' % self.id
def __unicode__(self):
return '<AttachedFile pk: %s>' % self.pk
class Delegation(Model):
'''
Delegate account, managable by user themselves.
'''
class Meta:
ordering = [ 'by' ]
verbose_name = _('Account delegation')
verbose_name_plural = _('Account delegations')
app_label = 'auth'
by = ForeignKey(User, related_name='delegations_to')
to = ForeignKey(User, related_name='delegations_by')
guest_delegate = BooleanField(blank=True)
class MailingList(NameNaturalKey, Model):
class Meta:
ordering = [ 'name' ]
verbose_name = _('Mailing list')
verbose_name_plural = _('Mailing lists')
name = CharField(max_length=128, verbose_name=_('Name'))
members = ManyToManyField(User, verbose_name=_('Members'), blank=True,
null=True, related_name='mailing_lists')
objects = GetByNameManager()
def __unicode__(self):
return self.name
class Mailbox(Model):
'''List of document received by a user'''
owner = ForeignKey(User, verbose_name=_('Mailbox owner'),
related_name='documents')
document = ForeignKey(Document, verbose_name=('Document'),
related_name='mailboxes')
seen = BooleanField(verbose_name=_('Seen'), blank=True)
deleted = BooleanField(verbose_name=_('Deleted'), blank=True)
outbox = BooleanField(verbose_name=_('Outbox message'), blank=True,
default=False)
date = DateTimeField(auto_now=True,
auto_now_add=True)
class Meta:
ordering = [ '-date' ]
verbose_name = _('Mailbox')
verbose_name_plural = _('Mailboxes')
class DocbowUser(User):
class Meta:
verbose_name = _('Docbow admin user')
proxy = True
app_label = 'auth'
class DocbowGroup(Group):
class Meta:
verbose_name = _('Docbow admin group')
app_label = 'auth'
proxy = True
class Inbox(Mailbox):
class Meta:
proxy = True
verbose_name = _('Inbox')
verbose_name_plural = _('Inboxes')
class Outbox(Mailbox):
class Meta:
proxy = True
verbose_name = _('Outbox')
verbose_name_plural = _('Outboxes')
class SendingLimitation(Model):
mailing_list = OneToOneField(MailingList, unique=True,
verbose_name=MailingList._meta.verbose_name)
filetypes = ManyToManyField(FileType, blank=True,
related_name='filetype_limitation',
verbose_name=_('Limitation des types de fichier'))
lists = ManyToManyField(MailingList, related_name='lists_limitation',
verbose_name=_('Limitation des destinataires'))
class Meta:
verbose_name = _('Limitation par liste de destinataires')
verbose_name = _('Limitation par liste de destinataires')
verbose_name_plural = verbose_name