Project

General

Profile

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

calebasse / calebasse / agenda / models.py @ 74ba9776

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

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

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

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

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

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

    
38

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

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

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

    
52

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

    
59
    title = models.CharField(_('title'), max_length=32)
60
    description = models.CharField(_('description'), max_length=100)
61
    event_type = models.ForeignKey(EventType, verbose_name=_('event type'))
62
    notes = generic.GenericRelation(Note, verbose_name=_('notes'))
63

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

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

    
76

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

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

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

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

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

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

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

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

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

    
126

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

    
138
    objects = managers.OccurrenceManager()
139

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

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

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

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

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

    
159

    
(7-7/10)