Completed
Push — master ( ae4c33...78debe )
by Vijay
11s
created

Workshop.save()   B

Complexity

Conditions 2

Size

Total Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 2
c 2
b 1
f 0
dl 0
loc 38
rs 8.8571
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
        from wye.profiles.models import Profile
71
        if not self.id:
72
            domain = Site.objects.get_current().domain
73
            context = {
74
                'workshop': self,
75
                'date': self.expected_date,
76
                'workshop_url': domain + '/workshop/{}/'.format(self.id),
77
                'workshop_topic': self.workshop_section.name
78
            }
79
            # get region_interested_member email ids to notify them
80
            region_interested_member = Profile.objects.filter(
81
                interested_locations=self.requester.location,
82
                usertype__slug='tutor'
83
            ).values_list('user__email', flat=True)
84
85
            subject = '[PythonExpress] Workshop request status.'
86
            email_body = loader.get_template(
87
                'email_messages/workshop/create_workshop/message.html').render(context)
88
            text_body = loader.get_template(
89
                'email_messages/workshop/create_workshop/message.txt').render(context)
90
            send_email_to_list(
91
                subject,
92
                body=email_body,
93
                users_list=region_interested_member,
94
                text_body=text_body)
95
96
        super(Workshop, self).save(force_insert, force_update, using)
97
98
    def is_presenter(self, user):
99
        return self.presenter.filter(pk=user.pk).exists()
100
101
    def is_organiser(self, user):
102
        return self.requester.user.filter(pk=user.pk).exists()
103
104
    def manage_action(self, user, **kwargs):
105
        actions = {
106
            'accept': ("opt-in", self.assign_me),
107
            'reject': ("opt-out", self.assign_me),
108
            'decline': (WorkshopStatus.DECLINED, self.set_status),
109
            'publish': (WorkshopStatus.REQUESTED, self.set_status),
110
            'hold': (WorkshopStatus.HOLD, self.set_status),
111
            'assign': ""
112
        }
113
        if kwargs.get('action') not in actions:
114
            return {
115
                'status': False,
116
                'msg': 'Action not allowed'
117
            }
118
119
        action, func = actions.get(kwargs.get('action'))
120
        kwargs["action"] = action
121
        return func(user, **kwargs)
122
123
    def set_status(self, user, **kwargs):
124
        self.status = kwargs.get('action')
125
        presenter_list = self.presenter.all()
126
        for u in presenter_list:
127
            self.presenter.remove(u)
128
        if kwargs.get('action') == WorkshopStatus.DECLINED:
129
            self.is_active = False
130
        else:
131
            self.is_active = True
132
        self.save()
133
        return {
134
            'status': True,
135
            'msg': 'Workshop successfully updated.'}
136
137
    @validate_action_param(WorkshopAction.ACTIVE)
138
    def toggle_active(self, user, **kwargs):
139
        """
140
        Helper method to toggle is_active for the model.
141
        """
142
143
        action_map = {'active': True, 'deactive': False}
144
        action = kwargs.get('action')
145
        self.is_active = action_map.get(action)
146
        self.save()
147
        return {
148
            'status': True,
149
            'msg': 'Workshop successfully updated.'}
150
151
    # @validate_action_param(WorkshopAction.ASSIGNME)
152
    @validate_assignme_action
153
    def assign_me(self, user, **kwargs):
154
        """
155
        Method to assign workshop by presenter self.
156
        """
157
158
        action_map = {
159
            'opt-in': self.presenter.add,
160
            'opt-out': self.presenter.remove
161
        }
162
        message_map = {
163
            'opt-in': 'Assigned successfully.',
164
            'opt-out': 'Unassigned successfully.'
165
        }
166
        assigned = {
167
            'opt-in': True,
168
            'opt-out': False
169
        }
170
        action = kwargs.get('action')
171
        if assigned[action] and self.presenter.filter(pk=user.pk).exists():
172
            # This save has been added as fail safe
173
            # once the logic is consolidated may be
174
            # it can be removed
175
            self.status = WorkshopStatus.ACCEPTED
176
            self.save()
177
            return {
178
                'status': False,
179
                'msg': 'Workshop has already been assigned.'
180
            }
181
182
        func = action_map.get(action)
183
        func(user)
184
185
        if self.presenter.count() > 0:
186
            self.status = WorkshopStatus.ACCEPTED
187
        else:
188
            self.status = WorkshopStatus.REQUESTED
189
        self.save()
190
191
        return {
192
            'status': True,
193
            'assigned': assigned[action],
194
            'msg': message_map[action],
195
            'notify': True
196
        }
197
198
    def get_presenter_list(self):
199
        return [user.get_full_name() for user in self.presenter.all()]
200
201
    def get_tweet(self, context):
202
        workshop = self
203
        date = workshop.expected_date
204
        topic = workshop.workshop_section
205
        organization = workshop.requester
206
        location = workshop.location
207
        workshop_url = context.get('workshop_url', None)
208
        message = "{} workshop at {} on {} confirmed! Details at {}".format(
209
            topic, organization, date, workshop_url)
210
        if len(message) >= 140:
211
            message = "{} workshop at {} on {} confirmed! Details at {}".format(
212
                topic, location, date, workshop_url)
213
        if len(message) >= 140:
214
            message = "{} workshop on {} confirmed! Details at {}".format(
215
                topic, date, workshop_url)
216
217
        return message
218
219
220
class WorkshopRatingValues(TimeAuditModel):
221
    '''
222
    Requesting Rating values -2, -1, 0 , 1, 2
223
    '''
224
225
    name = models.CharField(max_length=300)
226
227
    class Meta:
228
        db_table = 'workshop_vote_value'
229
230
    def __str__(self):
231
        return '{}'.format(self.name)
232
233
    @classmethod
234
    def get_questions(cls):
235
        return cls.objects.values('name', 'pk')
236
237
238
class WorkshopFeedBack(TimeAuditModel):
239
    '''
240
    Requesting for Feedback from requester and Presenter
241
    '''
242
243
    workshop = models.ForeignKey(Workshop)
244
    comment = models.TextField()
245
    feedback_type = models.PositiveSmallIntegerField(
246
        choices=FeedbackType.CHOICES, verbose_name="User_type")
247
248
    class Meta:
249
        db_table = 'workshop_feedback'
250
251
    def __str__(self):
252
        return '{}'.format(self.workshop)
253
254
    @classmethod
255
    def save_feedback(cls, user, workshop_id, **kwargs):
256
        workshop = Workshop.objects.get(pk=workshop_id)
257
        presenter = workshop.is_presenter(user)
258
        organiser = workshop.is_organiser(user)
259
        comment = kwargs.get('comment', '')
260
        del kwargs['comment']
261
262
        if presenter:
263
            feedback_type = FeedbackType.PRESENTER
264
        elif organiser:
265
            feedback_type = FeedbackType.ORGANISATION
266
267
        workshop_feedback = cls.objects.create(
268
            workshop=workshop,
269
            comment=comment,
270
            feedback_type=feedback_type
271
        )
272
        WorkshopVoting.save_rating(workshop_feedback, **kwargs)
273
274
275
class WorkshopVoting(TimeAuditModel):
276
    workshop_feedback = models.ForeignKey(
277
        WorkshopFeedBack, related_name='workshop_feedback')
278
    workshop_rating = models.ForeignKey(
279
        WorkshopRatingValues, related_name='workshop_rating')
280
    rating = models.IntegerField()
281
282
    class Meta:
283
        db_table = 'workshop_votes'
284
285
    def __str__(self):
286
        return '{}-{}-{}'.format(self.workshop_feedback,
287
                                 self.workshop_rating,
288
                                 self.rating)
289
290
    @classmethod
291
    def save_rating(cls, workshop_feedback, **kwargs):
292
        object_list = [
293
            cls(workshop_feedback=workshop_feedback,
294
                workshop_rating_id=int(k), rating=v)
295
            for k, v in kwargs.items()
296
        ]
297
298
        cls.objects.bulk_create(object_list)
299