2012-05-09 11:53:11 +02:00
# -*- coding: utf-8 -*-
"""
Request and document
"""
2012-06-14 01:22:04 +02:00
import os . path
2012-05-16 19:31:03 +02:00
import datetime
2012-07-18 12:57:04 +02:00
import decimal
2012-07-25 23:36:36 +02:00
import logging
2012-12-06 17:48:34 +01:00
import re
2012-05-16 19:31:03 +02:00
2013-12-02 15:28:03 +01:00
from django . db import models
2012-07-10 17:35:16 +02:00
from django . utils . translation import ugettext_lazy as _ , string_concat
2012-06-14 01:22:04 +02:00
from django . core import validators
2012-07-03 00:06:56 +02:00
from django . template import Template , Context
from django . core . mail import EmailMessage
2012-07-25 19:06:13 +02:00
from django . utils . timezone import now
2014-01-29 16:55:03 +01:00
from django . core . urlresolvers import reverse
from django . conf import settings
2012-05-09 11:53:11 +02:00
2012-07-03 00:06:56 +02:00
from . . . import utils
2012-07-19 13:00:59 +02:00
from . . import app_settings
2012-07-27 14:31:50 +02:00
from . . import fields
2012-07-19 13:00:59 +02:00
2012-07-18 12:57:04 +02:00
import profile
2012-07-19 13:00:59 +02:00
from user import User # we use a proxy user model to get ldap attribute retrieval
import workflow
2012-05-10 18:11:03 +02:00
2012-06-14 01:22:04 +02:00
TELEPHONE_VALIDATOR = validators . RegexValidator ( regex = r ' [0-9. ]* ' ,
message = _ ( u ' Les numéros de téléphone ne peuvent contenir '
u ' que des chiffres, des points ou des espaces ' ) )
2012-06-06 16:06:19 +02:00
2012-07-25 23:36:36 +02:00
logger = logging . getLogger ( __name__ )
2012-05-14 13:23:35 +02:00
class DocumentUsage ( models . Model ) :
class Meta :
app_label = ' base '
verbose_name = _ ( u " Usage d ' un document " )
verbose_name_plural = _ ( u " Usages d ' un document " )
2012-07-03 00:06:56 +02:00
ordering = ( ' order ' , ' name ' )
2012-05-14 13:23:35 +02:00
def __unicode__ ( self ) :
return self . name
name = models . CharField ( max_length = 64 , verbose_name = _ ( u ' Usage ' ) )
2012-05-16 18:40:20 +02:00
description = models . TextField ( verbose_name = _ ( u ' Description ' ) , blank = True )
url = models . URLField ( max_length = 200 , verbose_name = _ ( u ' URL ' ) , blank = True )
comments = models . TextField ( verbose_name = _ ( u ' Remarques et commentaires ' ) , blank = True )
2012-07-03 00:06:56 +02:00
order = models . IntegerField ( verbose_name = _ ( u ' Ordre ' ) , default = 0 )
2012-11-27 21:48:17 +01:00
no_diffusion = models . BooleanField ( verbose_name = _ ( u ' Ne pas diffuser ' ) ,
help_text = _ ( u ' Si coché, pour les documents ayant cet usage, la diffusion ne sera pas proposée. ' ) ,
default = False , blank = True )
2012-05-14 13:23:35 +02:00
class DocumentLicence ( models . Model ) :
class Meta :
app_label = ' base '
2012-05-15 10:00:01 +02:00
verbose_name = _ ( u " Diffusion d ' un document " )
verbose_name_plural = _ ( u " Diffusions d ' un document " )
2012-07-03 00:06:56 +02:00
ordering = ( ' order ' , ' name ' , )
2012-05-14 13:23:35 +02:00
def __unicode__ ( self ) :
return self . name
2012-05-15 10:00:01 +02:00
name = models . CharField ( max_length = 64 , verbose_name = _ ( u ' Droit de diffusion ' ) )
2012-05-16 18:40:20 +02:00
description = models . TextField ( verbose_name = _ ( u ' Description ' ) , blank = True )
url = models . URLField ( max_length = 200 , verbose_name = _ ( u ' URL ' ) , blank = True )
comments = models . TextField ( verbose_name = _ ( u ' Remarques et commentaires ' ) , blank = True )
2012-07-03 00:06:56 +02:00
order = models . IntegerField ( verbose_name = _ ( u ' Ordre ' ) , default = 0 )
2012-12-05 00:27:33 +01:00
default = models . BooleanField ( verbose_name = _ ( u ' Valeur par défaut ' ) ,
blank = True , default = False )
2012-11-27 15:58:46 +01:00
# Si le document contient des extraits copyrightés, on ne peut pas diffuser le document
only_free_documents = models . BooleanField ( verbose_name = _ ( u ' Réservé aux '
2014-01-29 15:07:45 +01:00
u ' documents libres de droits ' ) , blank = True , default = False )
2012-05-14 13:23:35 +02:00
2012-07-27 14:31:50 +02:00
# pour ajouter un nouveau type de diffusion, l'ajouter ici
2012-11-27 18:17:38 +01:00
DIFFUSION_TAGS = [
2012-07-27 14:31:50 +02:00
( ' oai-pmh ' , _ ( u ' Pousser le document dans le flux OAI-PMH ' ) ) ,
( ' public-url ' , _ ( u ' Le document possède une URL publique ' ) ) ,
2012-11-27 18:17:38 +01:00
]
2012-07-27 14:31:50 +02:00
2012-12-03 10:37:51 +01:00
@classmethod
def add_diffusion_tag ( cls , tag , description ) :
2012-12-03 10:44:20 +01:00
for t , d in cls . DIFFUSION_TAGS :
if t == tag :
return
2012-12-03 10:37:51 +01:00
cls . DIFFUSION_TAGS . append ( ( tag , description ) )
2012-07-27 14:31:50 +02:00
diffusion_tags = fields . MultiSelectField (
verbose_name = _ ( u " Tags de diffusion " ) ,
help_text = _ ( u " Ce sont les options diverses que l ' ont peut "
u " associer à ce type de diffusion " ) ,
blank = True ,
choices = DIFFUSION_TAGS )
2012-05-14 13:23:35 +02:00
class DeliveryPlace ( models . Model ) :
2012-05-14 12:00:16 +02:00
class Meta :
app_label = ' base '
2012-05-14 13:23:35 +02:00
verbose_name = _ ( u " Lieu de livraison " )
verbose_name_plural = _ ( u " Lieux de livraison " )
2012-07-03 00:06:56 +02:00
ordering = ( ' order ' , ' name ' , )
2012-05-14 12:00:16 +02:00
def __unicode__ ( self ) :
return self . name
2012-07-03 00:06:56 +02:00
order = models . IntegerField ( verbose_name = _ ( u ' Ordre ' ) , default = 0 )
2012-05-14 13:23:35 +02:00
name = models . CharField ( max_length = 64 , verbose_name = _ ( u ' Lieu de livraison ' ) )
2012-05-16 18:40:20 +02:00
description = models . TextField ( verbose_name = _ ( u ' Description ' ) , blank = True )
url = models . URLField ( max_length = 200 , verbose_name = _ ( u ' URL ' ) , blank = True )
comments = models . TextField ( verbose_name = _ ( u ' Remarques et commentaires ' ) , blank = True )
2012-05-10 18:11:03 +02:00
2012-06-29 16:23:51 +02:00
def get_default_status ( ) :
''' Retourne le seul et unique status par défaut, sinon une erreur. '''
return workflow . Status . objects . get ( default = True )
2012-05-09 11:53:11 +02:00
2012-07-03 00:06:56 +02:00
def minimum_delivery_timedelta ( ) :
2012-09-05 14:40:20 +02:00
return datetime . timedelta ( days = app_settings . MINIMUM_DELIVERY_DELAY )
2012-07-03 00:06:56 +02:00
2012-07-18 12:57:04 +02:00
class RequestQueryset ( utils . QuerySet ) :
def total_cost ( self ) :
zero = decimal . Decimal ( 0 )
2012-07-19 17:08:29 +02:00
# special case for Postgres so that it is fast in production
if utils . qs_use_postgres ( self ) :
cost_function1 = ' ( {1} .ppp * {0} .nb_pages + {1} .ppd)* {0} .copies ' . format (
Request . _meta . db_table , profile . Profile . _meta . db_table )
cost_function2 = ''' SELECT SUM(( {1} .ppp * {0} .nb_pages + {1} .ppd)* {0} .copies) FROM {1} , {2}
WHERE { 1 } . id = { 2 } . profileoptionchoice_id AND { 2 } . request_id = { 0 } . id ''' .format(
Request . _meta . db_table , profile . ProfileOptionChoice . _meta . db_table ,
Request . _meta . get_field ( ' choices ' ) . rel . through . _meta . db_table )
qs1 = self \
. prefetch_related ( None ) \
. select_related ( depth = 0 ) \
. extra ( select = {
' base_profile_estimated_cost ' : cost_function1 ,
' choices_estimated_cost ' : cost_function2
} )
qs1 . query . join ( ( Request . _meta . db_table , profile . Profile . _meta . db_table ,
Request . _meta . get_field ( ' base_profile ' ) . column ,
profile . Profile . _meta . get_field ( ' id ' ) . column ) )
return sum ( [ r . cost or ( ( r . base_profile_estimated_cost or zero ) + ( r . choices_estimated_cost or zero ) ) for r in qs1 ] )
else :
# generic implementation working everywhere
qs = self . select_related ( depth = 0 ) \
. select_related ( ' base_profile ' ) \
. prefetch_related ( None ) \
. prefetch_related ( ' choices ' ) \
. only ( ' nb_pages ' , ' copies ' , ' base_profile__ppp ' ,
' base_profile__ppd ' , ' choices__ppp ' , ' choices__ppd ' )
total_cost = zero
2013-11-15 15:45:56 +01:00
for r in [ r for r in qs if r . base_profile and ( r . get_copies ( ) > 0 ) ] :
2012-07-19 17:08:29 +02:00
ppp = r . base_profile . ppp
ppd = r . base_profile . ppd
for c in r . choices . all ( ) :
ppp + = c . ppp
ppd + = c . ppd
2013-11-15 15:45:56 +01:00
total_cost + = ( ( r . nb_pages * ppp ) + ppd ) * r . get_copies ( )
2012-07-19 17:08:29 +02:00
return total_cost
2012-07-18 12:57:04 +02:00
2014-01-29 15:05:24 +01:00
class Counter ( models . Model ) :
month = models . DateField ( unique = True )
counter = models . IntegerField ( default = 0 )
class Meta :
app_label = ' base '
2012-05-09 11:53:11 +02:00
class Request ( models . Model ) :
2012-06-29 16:23:51 +02:00
COPYRIGHT_CHOICES = (
( False , _ (
2012-07-03 00:06:56 +02:00
u " Le document ne contient pas d ' extrait d ' oeuvre soumise "
u " au droit d ' auteur " ) ) ,
2012-06-29 16:23:51 +02:00
( True , _ (
u " Le document contient un ou des extrait(s) d ' oeuvres(s) "
u " soumise(s) au droit d ' auteur " ) ) ,
)
2012-05-09 11:53:11 +02:00
2014-01-29 23:38:21 +01:00
NUMBER_RE = re . compile ( r ' ( \ d \ d \ d \ d)-( \ d+)-( \ d+) ' )
FINANCIAL_CODE_RE = re . compile ( r ' \ d { 6,} ' )
2012-05-09 11:53:11 +02:00
class Meta :
app_label = ' base '
2012-05-13 21:20:35 +02:00
verbose_name = _ ( u ' Demande de reprographie ' ) ;
verbose_name_plural = _ ( u ' Demandes de reprographie ' )
2012-07-16 14:35:11 +02:00
ordering = ( ' -creation_date ' , ' -month_order ' )
2012-05-09 11:53:11 +02:00
2012-07-18 12:57:04 +02:00
objects = RequestQueryset . as_manager ( )
2012-05-13 19:56:30 +02:00
user = models . ForeignKey ( User , verbose_name = _ ( u ' Demandeur ' ) )
2012-07-27 14:31:50 +02:00
month_order = models . IntegerField ( verbose_name = _ ( u ' Numéro ' ) , default = - 1 ,
unique_for_month = ' creation_date ' )
2013-11-22 11:35:30 +01:00
name = models . TextField ( verbose_name = _ ( u ' Titre ' ) , blank = True )
2013-12-18 11:19:15 +01:00
uploadfile = models . FileField ( upload_to = ' upload ' , verbose_name = _ ( u ' Fichier ' ) , blank = True , max_length = 512 )
2013-06-11 12:15:23 +02:00
nb_pages = models . PositiveIntegerField ( verbose_name = _ ( u ' Nombre de pages ' ) , blank = True , null = True , default = 0 ,
2012-07-10 17:35:16 +02:00
help_text = _ ( u """ Une information exacte sur le nombre de pages et le titre facilitera la tâche du Service de Reprographie. """ ) )
usage = models . ForeignKey ( DocumentUsage , verbose_name = _ ( u ' Usage du document ' ) , blank = True , null = True , on_delete = models . PROTECT ,
help_text = _ ( u """ L’ usage de votre document sera utile si vous acceptez de l’ envoyer à la Bibliothèque (Etape 6). """ ) )
2012-07-03 00:06:56 +02:00
licence = models . ForeignKey ( DocumentLicence , verbose_name = _ ( u ' Droits de diffusion ' ) , blank = True , null = True , on_delete = models . PROTECT )
2012-06-29 16:08:33 +02:00
copyright = models . NullBooleanField ( verbose_name = _ ( u " Déclaration de présence d ' extraits protégés " ) , choices = COPYRIGHT_CHOICES , blank = True , null = True )
comments = models . TextField ( verbose_name = _ ( u ' Remarques et commentaires ' ) , blank = True )
2012-06-14 01:22:04 +02:00
sponsor = models . CharField ( max_length = 128 , verbose_name = _ ( u ' Commanditaire ' ) , help_text = _ ( u " Complétez cette information si vous faites cette demande pour un tiers. " ) , blank = True )
2012-07-10 17:35:16 +02:00
entity = models . ForeignKey ( ' Entity ' , verbose_name = _ ( u ' Destinataires de ce document ' ) , on_delete = models . PROTECT , blank = True , null = True ,
help_text = _ ( u """ Renseigner le diplôme ou l ' UE concernée permettra un meilleur suivi de votre document. """ ) )
2013-06-11 12:15:23 +02:00
copies = models . PositiveIntegerField ( verbose_name = _ ( u ' Nombre d \' exemplaires ' ) , blank = True , null = True , default = 1 , validators = [ validators . MinValueValidator ( 1 ) ] )
2012-07-10 16:48:20 +02:00
status = models . ForeignKey ( workflow . Status , verbose_name = _ ( u ' Status ' ) , on_delete = models . PROTECT )
2012-11-27 18:46:07 +01:00
base_profile = models . ForeignKey ( ' Profile ' ,
verbose_name = _ ( u ' Profil de reprographie ' ) ,
help_text = _ ( u " Choissez le profil de base, puis complétez si "
u " besoin vos choix dans les options ci-dessous. " ) ,
blank = True , null = True , on_delete = models . PROTECT ,
limit_choices_to = { ' visible ' : True } )
2012-06-07 11:53:11 +02:00
choices = models . ManyToManyField ( ' ProfileOptionChoice ' , verbose_name = _ ( u ' Tous les choix de reprographie ' ) , blank = True )
2012-07-10 17:35:16 +02:00
details = models . TextField ( verbose_name = _ ( u ' Vos observations ou commentaires ' ) , blank = True )
2012-07-03 00:05:45 +02:00
delivery_date = models . DateField ( verbose_name = _ ( u ' Date de livraison souhaitée ' ) ,
blank = True , null = True ,
2012-09-05 14:40:20 +02:00
help_text = string_concat ( _ ( u ' Délai minimum à respecter ' ) , app_settings . MINIMUM_DELIVERY_DELAY , _ ( ' jours. ' ) ) ,
default = lambda : utils . get_next_workable_day ( app_settings . MINIMUM_DELIVERY_DELAY ) )
2012-07-03 00:06:56 +02:00
delivery_place = models . ForeignKey ( DeliveryPlace , verbose_name = _ ( u ' Lieu de livraison ' ) , blank = True , null = True , on_delete = models . PROTECT )
2012-05-16 18:40:20 +02:00
comments = models . TextField ( verbose_name = _ ( u ' Remarques et commentaires ' ) , blank = True )
2012-07-25 19:06:13 +02:00
creation_date = models . DateTimeField ( verbose_name = _ ( u ' Date de création ' ) , default = now , editable = False , db_index = True )
2012-07-13 10:56:02 +02:00
modification_date = models . DateTimeField ( verbose_name = _ ( u ' Date de modification ' ) , editable = False , db_index = True )
2012-06-14 01:22:04 +02:00
contact_email = models . EmailField ( verbose_name = _ ( u ' Email ' ) , blank = True )
contact_telephone1 = models . CharField ( max_length = 32 ,
verbose_name = _ ( u ' Téléphone ' ) ,
validators = [ TELEPHONE_VALIDATOR ] ,
blank = True )
contact_telephone2 = models . CharField ( max_length = 32 ,
verbose_name = _ ( u ' Téléphone (bis) ' ) ,
validators = [ TELEPHONE_VALIDATOR ] ,
blank = True )
contact_bureau = models . CharField ( max_length = 64 ,
verbose_name = _ ( ' Bureau ' ) ,
blank = True )
2012-06-29 16:33:31 +02:00
financial_code = models . CharField ( max_length = 64 ,
2017-11-29 10:47:58 +01:00
verbose_name = _ ( u ' Code d \' imputation ' ) , blank = True , db_index = True )
2012-06-29 16:33:31 +02:00
financial_comment = models . TextField (
verbose_name = _ ( u " Commentaire pour la facturation " ) , blank = True )
cost = models . DecimalField ( verbose_name = _ ( u ' Coût ' ) , blank = True , null = True ,
2015-04-03 21:33:24 +02:00
max_digits = 10 , decimal_places = 5 )
2012-10-03 11:22:31 +02:00
is_from_remote_request = models . BooleanField ( blank = True ,
2014-01-29 15:07:45 +01:00
verbose_name = _ ( u ' Demande initiée via un Web-Service ' ) ,
default = False )
2012-06-14 01:44:47 +02:00
2012-07-27 17:19:30 +02:00
def copyright_status ( self ) :
if self . copyright is None :
return _ ( u ' Inconnu ' )
else :
return dict ( self . COPYRIGHT_CHOICES ) . get ( self . copyright )
2012-07-16 14:35:11 +02:00
def request_number ( self ) :
2012-07-19 13:25:40 +02:00
s = unicode ( self . creation_date . strftime ( ' % Y- % m- ' ) )
s + = unicode ( self . month_order )
return s . replace ( u ' - ' , u ' \u2011 ' )
2012-07-16 14:35:11 +02:00
2012-09-28 16:37:58 +02:00
def request_number_csv ( self ) :
s = unicode ( self . creation_date . strftime ( ' % Y- % m- ' ) )
s + = unicode ( self . month_order )
return s
2013-11-15 15:45:56 +01:00
def get_copies ( self ) :
return self . copies or 0
def get_nb_pages ( self ) :
2013-12-02 16:13:23 +01:00
return self . nb_pages or 0
2013-11-15 15:45:56 +01:00
2012-07-13 16:37:35 +02:00
def total_pages ( self ) :
2013-11-15 15:45:56 +01:00
return self . get_copies ( ) * self . get_nb_pages ( )
2012-07-13 16:37:35 +02:00
2012-07-05 07:02:48 +02:00
def sponsor_display ( self ) :
fn = self . user . get_full_name ( )
if not fn :
fn = self . user . username
2012-07-16 20:00:14 +02:00
if self . sponsor . strip ( ) and self . sponsor != fn :
return ' %s ( %s ) ' % ( fn , self . sponsor . strip ( ) )
2012-07-05 07:02:48 +02:00
return fn
2012-12-06 17:48:34 +01:00
def sponsor_username ( self ) :
''' Try to extract a LDAP username from the sponsor field '''
m = re . search ( ' \ ((.*) \ ) ' , self . sponsor )
if m :
return m . group ( 1 )
return ' '
2012-06-14 01:44:47 +02:00
def estimated_cost ( self ) :
2012-07-18 12:57:04 +02:00
total = decimal . Decimal ( 0 )
2012-06-26 10:00:02 +02:00
if self . base_profile :
2013-11-15 15:45:56 +01:00
total + = ( ( self . base_profile . ppp * self . get_nb_pages ( ) ) + self . base_profile . ppd ) * self . get_copies ( )
2012-06-14 01:44:47 +02:00
for choice in self . choices . all ( ) :
2013-11-15 15:45:56 +01:00
total + = ( ( choice . ppp * self . get_nb_pages ( ) ) + choice . ppd ) * self . get_copies ( )
2012-07-18 12:57:04 +02:00
return total
2012-06-14 01:22:04 +02:00
def missing ( self ) :
null = [ None , ' ' , 0 ]
2013-08-29 13:38:05 +02:00
required = [ ' name ' , ' nb_pages ' , ' usage ' ,
2012-06-29 16:08:33 +02:00
' licence ' , ' entity ' , ' copies ' , ' base_profile ' ,
' delivery_place ' , ' delivery_date ' ]
2012-06-14 01:22:04 +02:00
for field in required :
v = getattr ( self , field , None )
for n in null :
if v is n :
yield field
2013-08-29 13:43:40 +02:00
if not self . no_diffusion ( ) and self . copyright is None :
2013-08-29 13:38:05 +02:00
yield ' copyright '
2012-06-14 01:22:04 +02:00
2012-06-29 17:55:24 +02:00
def validate ( self ) :
return not bool ( list ( self . missing ( ) ) )
2012-06-14 01:22:04 +02:00
2012-05-13 19:56:30 +02:00
def save ( self , * args , * * kwargs ) :
2012-07-27 17:59:28 +02:00
self . modification_date = now ( )
2012-07-16 14:35:11 +02:00
if self . month_order == - 1 :
2014-01-29 15:05:24 +01:00
date = self . creation_date . date ( )
date = date . replace ( day = 1 )
counter , created = Counter . objects . get_or_create ( month = date )
counter = Counter . objects . select_for_update ( ) . get ( month = date )
counter . counter + = 1
counter . save ( )
self . month_order = counter . counter
2012-05-13 19:56:30 +02:00
super ( Request , self ) . save ( * args , * * kwargs )
2012-06-14 01:22:04 +02:00
def act ( self , who , workflow , description = None ) :
2013-07-10 15:53:25 +02:00
from . . import rbac
2012-07-03 00:06:56 +02:00
history = self . history_set . all ( )
ctx = {
' request ' : self ,
' actor ' : who ,
' comment ' : description ,
' history ' : history ,
' reversed_history ' : reversed ( history ) ,
2014-01-29 16:55:03 +01:00
' request_url ' : settings . SITE_URL + self . get_absolute_url ( ) ,
2012-07-03 00:06:56 +02:00
}
ctx = Context ( ctx )
2012-07-25 23:36:36 +02:00
logger . info ( ' action %s par %s avec le commentaire %s sur la demande %s ' ,
unicode ( workflow ) . encode ( ' utf-8 ' ) ,
unicode ( who ) . encode ( ' utf-8 ' ) ,
unicode ( description ) . encode ( ' utf-8 ' ) ,
unicode ( self . request_number ( ) ) . encode ( ' utf-8 ' ) )
2012-07-03 00:06:56 +02:00
for mail_notification in workflow . action . mailnotification_set . all ( ) :
2012-07-25 23:44:23 +02:00
emails = [ ]
2012-07-03 00:06:56 +02:00
if mail_notification . to == ' requestor ' :
2012-07-25 23:44:23 +02:00
if self . user . email :
emails = [ self . user . email ]
2012-07-03 00:06:56 +02:00
elif mail_notification . to == ' last_actor ' :
for history in reversed ( history ) :
2012-07-25 23:44:23 +02:00
if history . old_status != history . new_status and history . user . email :
2012-07-03 00:06:56 +02:00
emails = [ history . user . email ]
break
elif mail_notification . to == ' all_actors ' :
emails = list ( set ( [ h . user . email for h in history ] ) - set ( [ who . email ] ) )
2013-07-10 15:53:25 +02:00
elif mail_notification . to == ' next_actors ' :
emails = set ( u . email for u in rbac . get_actors ( workflow . destination , self . entity ) )
2012-07-03 00:06:56 +02:00
else :
2013-07-09 16:16:34 +02:00
raise NotImplementedError
2013-07-10 15:53:25 +02:00
# remove empty strings
emails = filter ( None , emails )
2012-07-16 23:46:15 +02:00
if not emails :
continue
2012-07-19 15:59:28 +02:00
prefix = ' { % lo ad url from future % } '
subject = Template ( prefix + mail_notification . subject_template ) . render ( ctx )
body = Template ( prefix + mail_notification . body_template ) . render ( ctx )
2012-07-25 23:36:36 +02:00
logger . info ( " envoi d ' un mail à %s " ,
( ' , ' . join ( emails ) ) . encode ( ' utf-8 ' ) )
2012-07-03 00:06:56 +02:00
email = EmailMessage ( subject = subject , body = body , to = emails )
2012-07-25 23:36:36 +02:00
try :
email . send ( )
except :
2012-07-25 23:44:23 +02:00
logger . exception ( " l ' envoi du mail a echoue " )
2012-07-03 00:06:56 +02:00
2012-06-14 01:22:04 +02:00
History . objects . create ( request = self ,
user = who ,
old_status = self . status ,
new_status = workflow . destination ,
action = workflow . action ,
description = description or ' ' )
2012-07-03 00:06:56 +02:00
2012-06-14 01:22:04 +02:00
self . status = workflow . destination
self . save ( )
2012-05-10 18:11:03 +02:00
2012-06-29 16:08:33 +02:00
def file_name ( self ) :
if self . uploadfile :
return os . path . basename ( self . uploadfile . name )
return ' '
2013-06-07 17:56:35 +02:00
def sponsor_name ( self ) :
sponsor_name = re . match ( r ' [^(]* ' , self . sponsor ) . group ( 0 ) . strip ( )
if not sponsor_name :
sponsor_name = self . user . display_name ( )
return sponsor_name
2012-06-29 16:08:33 +02:00
def is_paper ( self ) :
2013-07-15 15:30:54 +02:00
return not bool ( self . uploadfile )
2012-06-29 16:08:33 +02:00
2013-08-29 13:38:05 +02:00
def no_diffusion ( self ) :
return self . is_from_remote_request or \
2013-07-15 15:17:17 +02:00
( self . usage and self . usage . no_diffusion ) \
2013-08-29 13:38:05 +02:00
or self . is_paper ( )
def clean ( self ) :
if self . no_diffusion ( ) :
2013-07-15 15:25:37 +02:00
self . licence = DocumentLicence ( id = 1 )
2013-07-15 15:08:01 +02:00
2013-06-07 13:46:21 +02:00
def __unicode__ ( self ) :
2012-09-05 18:05:17 +02:00
return ' <Request id: %s > ' % ( self . pk , )
2014-01-29 16:55:03 +01:00
def get_absolute_url ( self ) :
return reverse ( ' request_detail ' , kwargs = { ' pk ' : self . pk } )
2012-07-03 00:05:45 +02:00
class HistoryManager ( models . Manager ) :
def start ( self ) :
try :
return self . filter ( new_status__start = True ) . latest ( )
except History . DoesNotExist :
return None
def start_date ( self ) :
start = self . start ( )
if start :
return start . date
else :
2012-07-25 19:06:13 +02:00
return now ( )
2012-07-03 00:05:45 +02:00
def end ( self ) :
end = None
for history in self . select_related ( ' new_status ' ) . reverse ( ) :
if history . new_status . end :
end = history
elif end is not None :
return end
else :
return None
def end_date ( self ) :
end = self . end ( )
if end is None :
return None
else :
return end . date
2013-12-02 16:14:56 +01:00
def last_show_in_details ( self ) :
for h in self . all ( ) . reverse ( ) :
if h . action . special_type == ' show_in_details ' :
return h
return None
2012-07-03 00:05:45 +02:00
history_manager = HistoryManager ( )
history_manager . use_for_related_fields = True
2012-05-09 11:53:11 +02:00
class History ( models . Model ) :
2012-07-03 00:05:45 +02:00
objects = history_manager
2012-05-09 11:53:11 +02:00
class Meta :
app_label = ' base '
2012-05-13 21:20:35 +02:00
verbose_name = _ ( u " Historique " )
verbose_name_plural = _ ( u " Historiques des demandes " )
2012-06-14 01:22:04 +02:00
ordering = ( ' date ' , )
get_latest_by = ' date '
2012-05-09 11:53:11 +02:00
def __unicode__ ( self ) :
2012-07-11 17:17:49 +02:00
return self . date . strftime ( ' % Y- % m- %d % H: % M: % S ' ) + unicode ( self . action )
2012-05-09 11:53:11 +02:00
2012-07-13 10:56:02 +02:00
date = models . DateTimeField ( auto_now = True , db_index = True )
2012-05-13 19:56:30 +02:00
request = models . ForeignKey ( Request , verbose_name = _ ( u ' Demande ' ) )
2012-07-03 00:06:56 +02:00
user = models . ForeignKey ( User , verbose_name = _ ( u ' Utilisateur ' ) , blank = True , null = True , on_delete = models . SET_NULL )
action = models . ForeignKey ( workflow . Action , verbose_name = _ ( ' Action ' ) , on_delete = models . PROTECT )
2012-06-29 16:23:51 +02:00
old_status = models . ForeignKey ( workflow . Status ,
2012-07-03 00:06:56 +02:00
verbose_name = _ ( u " État de la demande avant l ' action " ) , blank = True ,
related_name = ' + ' , null = True , on_delete = models . PROTECT )
2012-06-29 16:23:51 +02:00
new_status = models . ForeignKey ( workflow . Status ,
2012-07-03 00:06:56 +02:00
verbose_name = _ ( u " État de la demande après l ' action " ) ,
related_name = ' + ' , on_delete = models . PROTECT )
2012-05-16 18:40:20 +02:00
description = models . TextField ( verbose_name = _ ( u " Détails éventuels sur l ' action " ) , blank = True )