Completed
Pull Request — master (#408)
by Vijay
01:05
created

Workshop

Size/Duplication

Total Lines 204
Duplicated Lines 0 %

Importance

Changes 6
Bugs 1 Features 1
Metric Value
c 6
b 1
f 1
dl 0
loc 204

12 Methods

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