Project

General

Profile

Download (4.91 KB) Statistics
| Branch: | Tag: | Revision:

calebasse / calebasse / agenda / models.py @ 72dbfaca

1
# -*- coding: utf-8 -*-
2

    
3
from datetime import datetime
4

    
5
from dateutil import rrule
6

    
7
from django.utils.translation import ugettext_lazy as _
8
from django.contrib.contenttypes.models import ContentType
9
from django.contrib.contenttypes import generic
10
from django.db import models
11

    
12
from calebasse.agenda import managers
13
from interval import Interval
14

    
15
__all__ = (
16
    'Note',
17
    'EventType',
18
    'Event',
19
    'Occurrence',
20
)
21

    
22
class Note(models.Model):
23
    '''
24
    A generic model for adding simple, arbitrary notes to other models such as
25
    ``Event`` or ``Occurrence``.
26
    '''
27

    
28
    class Meta:
29
        verbose_name = u'Note'
30
        verbose_name_plural = u'Notes'
31

    
32
    def __unicode__(self):
33
        return self.note
34

    
35
    note = models.TextField(_('note'))
36
    created = models.DateTimeField(_('created'), auto_now_add=True)
37
    content_type = models.ForeignKey(ContentType)
38

    
39

    
40
class EventType(models.Model):
41
    '''
42
    Simple ``Event`` classifcation.
43
    '''
44
    class Meta:
45
        verbose_name = u'Type d\'événement'
46
        verbose_name_plural = u'Types d\'événement'
47

    
48
    def __unicode__(self):
49
        return self.label
50

    
51
    label = models.CharField(_('label'), max_length=50)
52

    
53

    
54
class Event(models.Model):
55
    '''
56
    Container model for general metadata and associated ``Occurrence`` entries.
57
    '''
58
    objects = managers.EventManager()
59

    
60
    title = models.CharField(_('Titre'), max_length=32)
61
    description = models.TextField(_('Description'), max_length=100)
62
    event_type = models.ForeignKey(EventType, verbose_name=u"Type d'événement")
63
    notes = generic.GenericRelation(Note, verbose_name=_('notes'))
64

    
65
    services = models.ManyToManyField('ressources.Service',
66
            null=True, blank=True, default=None)
67
    participants = models.ManyToManyField('personnes.People',
68
            null=True, blank=True, default=None)
69
    room = models.ForeignKey('ressources.Room', blank=True, null=True,
70
            verbose_name=u'Salle')
71

    
72
    class Meta:
73
        verbose_name = u'Evénement'
74
        verbose_name_plural = u'Evénements'
75
        ordering = ('title', )
76

    
77

    
78
    def __unicode__(self):
79
        return self.title
80

    
81
    def add_occurrences(self, start_time, end_time, room=None, **rrule_params):
82
        '''
83
        Add one or more occurences to the event using a comparable API to 
84
        ``dateutil.rrule``. 
85

    
86
        If ``rrule_params`` does not contain a ``freq``, one will be defaulted
87
        to ``rrule.DAILY``.
88

    
89
        Because ``rrule.rrule`` returns an iterator that can essentially be
90
        unbounded, we need to slightly alter the expected behavior here in order
91
        to enforce a finite number of occurrence creation.
92

    
93
        If both ``count`` and ``until`` entries are missing from ``rrule_params``,
94
        only a single ``Occurrence`` instance will be created using the exact
95
        ``start_time`` and ``end_time`` values.
96
        '''
97
        rrule_params.setdefault('freq', rrule.DAILY)
98

    
99
        if 'count' not in rrule_params and 'until' not in rrule_params:
100
            self.occurrence_set.create(start_time=start_time, end_time=end_time)
101
        else:
102
            delta = end_time - start_time
103
            for ev in rrule.rrule(dtstart=start_time, **rrule_params):
104
                self.occurrence_set.create(start_time=ev, end_time=ev + delta)
105

    
106
    def upcoming_occurrences(self):
107
        '''
108
        Return all occurrences that are set to start on or after the current
109
        time.
110
        '''
111
        return self.occurrence_set.filter(start_time__gte=datetime.now())
112

    
113
    def next_occurrence(self):
114
        '''
115
        Return the single occurrence set to start on or after the current time
116
        if available, otherwise ``None``.
117
        '''
118
        upcoming = self.upcoming_occurrences()
119
        return upcoming and upcoming[0] or None
120

    
121
    def daily_occurrences(self, dt=None):
122
        '''
123
        Convenience method wrapping ``Occurrence.objects.daily_occurrences``.
124
        '''
125
        return Occurrence.objects.daily_occurrences(dt=dt, event=self)
126

    
127

    
128
class Occurrence(models.Model):
129
    '''
130
    Represents the start end time for a specific occurrence of a master ``Event``
131
    object.
132
    '''
133
    start_time = models.DateTimeField()
134
    end_time = models.DateTimeField()
135
    event = models.ForeignKey('Event', verbose_name=_('event'), editable=False)
136
    notes = models.ManyToManyField('Note', verbose_name=_('notes'),
137
            null=True, blank=True, default=None)
138

    
139
    objects = managers.OccurrenceManager()
140

    
141
    class Meta:
142
        verbose_name = u'Occurrence'
143
        verbose_name_plural = u'Occurrences'
144
        ordering = ('start_time', 'end_time')
145

    
146
    def __unicode__(self):
147
        return u'%s: %s' % (self.title, self.start_time.isoformat())
148

    
149
    def __cmp__(self, other):
150
        return cmp(self.start_time, other.start_time)
151

    
152
    @property
153
    def title(self):
154
        return self.event.title
155

    
156
    @property
157
    def event_type(self):
158
        return self.event.event_type
159

    
160
    def to_interval(self):
161
        return Interval(self.start_time, self.end_time)
162

    
(7-7/10)