Completed
Pull Request — master (#320)
by
unknown
01:15
created

Workshop

Size/Duplication

Total Lines 177
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 177

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __str__() 0 2 1
A get_presenter_list() 0 2 2
B assign_me() 0 44 4
A get_tweet() 0 13 2
A is_organiser() 0 2 1
A is_presenter() 0 2 1
A set_status() 0 13 3
B save() 0 36 2
A manage_action() 0 18 2
A toggle_active() 0 13 1
1
from django.contrib.auth.models import User
2
from django.contrib.sites.models import Site
3
from django.core.validators import MaxValueValidator
4
from django.core.urlresolvers import reverse_lazy
5
from django.db import models
6
from django.template import loader
7
8
from wye.base.constants import (
9
    FeedbackType,
10
    WorkshopAction,
11
    WorkshopLevel,
12
    WorkshopStatus,
13
)
14
from wye.base.emailer_html import send_email_to_list
15
from wye.base.models import TimeAuditModel
16
from wye.organisations.models import Organisation
17
from wye.profiles.models import Profile
18
from wye.regions.models import Location
19
20
from .decorators import validate_action_param, validate_assignme_action
21
22
23
class WorkshopSections(TimeAuditModel):
24
    '''
25
    python2, Python3, Django, Flask, Gaming
26
    '''
27
    name = models.CharField(max_length=300, unique=True)
28
29
    class Meta:
30
        db_table = 'workshop_section'
31
32
    def __str__(self):
33
        return '{}'.format(self.name)
34
35
36
class Workshop(TimeAuditModel):
37
    no_of_participants = models.PositiveIntegerField(
38
        validators=[MaxValueValidator(1000)])
39
    expected_date = models.DateField()
40
    description = models.TextField()
41
    requester = models.ForeignKey(
42
        Organisation, related_name='workshop_requester')
43
    presenter = models.ManyToManyField(User, related_name='workshop_presenter')
44
    location = models.ForeignKey(Location, related_name='workshop_location')
45
    workshop_level = models.PositiveSmallIntegerField(
46
        choices=WorkshopLevel.CHOICES, verbose_name="Workshop Level")
47
    workshop_section = models.ForeignKey(WorkshopSections)
48
    is_active = models.BooleanField(default=True)
49
    status = models.PositiveSmallIntegerField(
50
        choices=WorkshopStatus.CHOICES, verbose_name="Current Status",
51
        default=WorkshopStatus.REQUESTED)
52
53
    class Meta:
54
        db_table = 'workshops'
55
56
    def __str__(self):
57
        return '{}-{}'.format(self.requester, self.workshop_section)
58
59
    def save(self, force_insert=False, force_update=False, using=None):
60
        """
61
        send mail to region interested member whenever new workshop
62
        is requested in respective region, therefore overriding
63
        pre save method so mails are only send when new object
64
        is created.
65
        :param force_insert: bool force_insert
66
        :param force_update: bool force_insert
67
        :param using: using
68
        :return: instance
69
        """
70
        if not self.id:
71
            domain = Site.objects.get_current().domain
72
            context = {
73
                'workshop': self,
74
                'date': self.expected_date,
75
                'workshop_url': domain + '/workshop/{}/'.format(self.id)
76
            }
77
            # get region_interested_member email ids to notify them
78
            region_interested_member = Profile.objects.filter(
79
                interested_locations=self.requester.location,
80
                usertype__slug='tutor'
81
            ).values_list('user__email', flat=True)
82
83
            subject = '[PythonExpress] Workshop request status.'
84
            email_body = loader.get_template(
85
                'email_messages/workshop/create_workshop/message.html').render(context)
86
            text_body = loader.get_template(
87
                'email_messages/workshop/create_workshop/message.txt').render(context)
88
            send_email_to_list(
89
                subject,
90
                body=email_body,
91
                users_list=region_interested_member,
92
                text_body=text_body)
93
94
        super(Workshop, self).save(force_insert, force_update, using)
95
96
97
    def is_presenter(self, user):
98
        return self.presenter.filter(pk=user.pk).exists()
99
100
    def is_organiser(self, user):
101
        return self.requester.user.filter(pk=user.pk).exists()
102
103
    def manage_action(self, user, **kwargs):
104
        actions = {
105
            'accept': ("opt-in", self.assign_me),
106
            'reject': ("opt-out", self.assign_me),
107
            'decline': (WorkshopStatus.DECLINED, self.set_status),
108
            'publish': (WorkshopStatus.REQUESTED, self.set_status),
109
            'hold': (WorkshopStatus.HOLD, self.set_status),
110
            'assign': ""
111
        }
112
        if kwargs.get('action') not in actions:
113
            return {
114
                'status': False,
115
                'msg': 'Action not allowed'
116
            }
117
118
        action, func = actions.get(kwargs.get('action'))
119
        kwargs["action"] = action
120
        return func(user, **kwargs)
121
122
    def set_status(self, user, **kwargs):
123
        self.status = kwargs.get('action')
124
        presenter_list = self.presenter.all()
125
        for u in presenter_list:
126
            self.presenter.remove(u)
127
        if kwargs.get('action') == WorkshopStatus.DECLINED:
128
            self.is_active = False
129
        else:
130
            self.is_active = True
131
        self.save()
132
        return {
133
            'status': True,
134
            'msg': 'Workshop successfully updated.'}
135
136
    @validate_action_param(WorkshopAction.ACTIVE)
137
    def toggle_active(self, user, **kwargs):
138
        """
139
        Helper method to toggle is_active for the model.
140
        """
141
142
        action_map = {'active': True, 'deactive': False}
143
        action = kwargs.get('action')
144
        self.is_active = action_map.get(action)
145
        self.save()
146
        return {
147
            'status': True,
148
            'msg': 'Workshop successfully updated.'}
149
150
    # @validate_action_param(WorkshopAction.ASSIGNME)
151
    @validate_assignme_action
152
    def assign_me(self, user, **kwargs):
153
        """
154
        Method to assign workshop by presenter self.
155
        """
156
157
        action_map = {
158
            'opt-in': self.presenter.add,
159
            'opt-out': self.presenter.remove
160
        }
161
        message_map = {
162
            'opt-in': 'Assigned successfully.',
163
            'opt-out': 'Unassigned successfully.'
164
        }
165
        assigned = {
166
            'opt-in': True,
167
            'opt-out': False
168
        }
169
        action = kwargs.get('action')
170
        if assigned[action] and self.presenter.filter(pk=user.pk).exists():
171
            # This save has been added as fail safe
172
            # once the logic is consolidated may be
173
            # it can be removed
174
            self.status = WorkshopStatus.ACCEPTED
175
            self.save()
176
            return {
177
                'status': False,
178
                'msg': 'Workshop has already been assigned.'
179
            }
180
181
        func = action_map.get(action)
182
        func(user)
183
184
        if self.presenter.count() > 0:
185
            self.status = WorkshopStatus.ACCEPTED
186
        else:
187
            self.status = WorkshopStatus.REQUESTED
188
        self.save()
189
190
        return {
191
            'status': True,
192
            'assigned': assigned[action],
193
            'msg': message_map[action],
194
            'notify': True
195
        }
196
197
    def get_presenter_list(self):
198
        return [user.get_full_name() for user in self.presenter.all()]
199
200
    def get_tweet(self, context):
201
        workshop = self
202
        date = workshop.expected_date
203
        topic = workshop.workshop_section
204
        organization = workshop.requester
205
        workshop_url = context.get('workshop_url', None)
206
        message = "{} workshop at {} on {} confirmed! Details at {}".format(
207
            topic, organization, date, workshop_url)
208
        if len(message) >= 140:
209
            message = "{} workshop on {} confirmed! Details at {}".format(
210
                topic, date, workshop_url)
211
212
        return message
213
214
215
class WorkshopRatingValues(TimeAuditModel):
216
    '''
217
    Requesting Rating values -2, -1, 0 , 1, 2
218
    '''
219
220
    name = models.CharField(max_length=300)
221
222
    class Meta:
223
        db_table = 'workshop_vote_value'
224
225
    def __str__(self):
226
        return '{}'.format(self.name)
227
228
    @classmethod
229
    def get_questions(cls):
230
        return cls.objects.values('name', 'pk')
231
232
233
class WorkshopFeedBack(TimeAuditModel):
234
    '''
235
    Requesting for Feedback from requester and Presenter
236
    '''
237
238
    workshop = models.ForeignKey(Workshop)
239
    comment = models.TextField()
240
    feedback_type = models.PositiveSmallIntegerField(
241
        choices=FeedbackType.CHOICES, verbose_name="User_type")
242
243
    class Meta:
244
        db_table = 'workshop_feedback'
245
246
    def __str__(self):
247
        return '{}'.format(self.workshop)
248
249
    @classmethod
250
    def save_feedback(cls, user, workshop_id, **kwargs):
251
        workshop = Workshop.objects.get(pk=workshop_id)
252
        presenter = workshop.is_presenter(user)
253
        organiser = workshop.is_organiser(user)
254
        comment = kwargs.get('comment', '')
255
        del kwargs['comment']
256
257
        if presenter:
258
            feedback_type = FeedbackType.PRESENTER
259
        elif organiser:
260
            feedback_type = FeedbackType.ORGANISATION
261
262
        workshop_feedback = cls.objects.create(
263
            workshop=workshop,
264
            comment=comment,
265
            feedback_type=feedback_type
266
        )
267
        WorkshopVoting.save_rating(workshop_feedback, **kwargs)
268
269
270
class WorkshopVoting(TimeAuditModel):
271
    workshop_feedback = models.ForeignKey(
272
        WorkshopFeedBack, related_name='workshop_feedback')
273
    workshop_rating = models.ForeignKey(
274
        WorkshopRatingValues, related_name='workshop_rating')
275
    rating = models.IntegerField()
276
277
    class Meta:
278
        db_table = 'workshop_votes'
279
280
    def __str__(self):
281
        return '{}-{}-{}'.format(self.workshop_feedback,
282
                                 self.workshop_rating,
283
                                 self.rating)
284
285
    @classmethod
286
    def save_rating(cls, workshop_feedback, **kwargs):
287
        object_list = [
288
            cls(workshop_feedback=workshop_feedback,
289
                workshop_rating_id=int(k), rating=v)
290
            for k, v in kwargs.items()
291
        ]
292
293
        cls.objects.bulk_create(object_list)
294