• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

chiefonboarding / ChiefOnboarding / 16131770315

08 Jul 2025 01:33AM UTC coverage: 90.64% (-0.009%) from 90.649%
16131770315

Pull #560

github

web-flow
Merge 528f891fb into 652164dab
Pull Request #560: Add ipware for correctly blocking users when behind proxy

8270 of 9124 relevant lines covered (90.64%)

0.91 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.84
back/admin/people/new_hire_views.py
1
from datetime import datetime
1✔
2

3
from django.apps import apps
1✔
4
from django.conf import settings
1✔
5
from django.contrib import messages
1✔
6
from django.contrib.auth import get_user_model
1✔
7
from django.contrib.messages.views import SuccessMessageMixin
1✔
8
from django.http import Http404
1✔
9
from django.shortcuts import get_object_or_404, redirect, render
1✔
10
from django.urls import reverse, reverse_lazy
1✔
11
from django.utils import translation
1✔
12
from django.utils.translation import gettext as _
1✔
13
from django.views.generic.base import TemplateView, View
1✔
14
from django.views.generic.detail import DetailView
1✔
15
from django.views.generic.edit import CreateView, DeleteView, FormView, UpdateView
1✔
16
from django.views.generic.list import ListView
1✔
17
from django_q.tasks import async_task
1✔
18
from twilio.rest import Client
1✔
19

20
from admin.admin_tasks.models import AdminTask
1✔
21
from admin.integrations.forms import IntegrationExtraUserInfoForm
1✔
22
from admin.notes.models import Note
1✔
23
from admin.sequences.models import Condition, Sequence
1✔
24
from admin.templates.utils import get_templates_model, get_user_field
1✔
25
from organization.models import Notification, Organization, WelcomeMessage
1✔
26
from slack_bot.slack_resource import SlackResource
1✔
27
from slack_bot.slack_to_do import SlackToDo
1✔
28
from slack_bot.tasks import link_slack_users
1✔
29
from slack_bot.utils import Slack, paragraph
1✔
30
from users.emails import (
1✔
31
    email_reopen_task,
32
    send_new_hire_credentials,
33
    send_new_hire_preboarding,
34
    send_reminder_email,
35
)
36
from users.mixins import (
1✔
37
    IsAdminOrNewHireManagerMixin,
38
    LoginRequiredMixin,
39
    ManagerPermMixin,
40
)
41
from users.models import NewHireWelcomeMessage, PreboardingUser, ResourceUser, ToDoUser
1✔
42

43
from .forms import (
1✔
44
    NewHireAddForm,
45
    NewHireProfileForm,
46
    OnboardingSequenceChoiceForm,
47
    PreboardingSendForm,
48
    RemindMessageForm,
49
)
50

51

52
class NewHireListView(LoginRequiredMixin, ManagerPermMixin, ListView):
1✔
53
    template_name = "new_hires.html"
1✔
54
    paginate_by = 10
1✔
55

56
    def get_queryset(self):
1✔
57
        all_new_hires = get_user_model().new_hires.all().order_by("-start_day")
1✔
58
        if self.request.user.is_admin:
1✔
59
            return all_new_hires
1✔
60
        return all_new_hires.filter(manager=self.request.user)
1✔
61

62
    def get_context_data(self, **kwargs):
1✔
63
        context = super().get_context_data(**kwargs)
1✔
64
        context["title"] = _("New hires")
1✔
65
        context["subtitle"] = _("people")
1✔
66
        context["add_action"] = reverse_lazy("people:new_hire_add")
1✔
67
        return context
1✔
68

69

70
class NewHireAddView(
1✔
71
    LoginRequiredMixin, ManagerPermMixin, SuccessMessageMixin, CreateView
72
):
73
    template_name = "new_hire_add.html"
1✔
74
    model = get_user_model()
1✔
75
    form_class = NewHireAddForm
1✔
76
    success_message = _("New hire has been created")
1✔
77
    success_url = reverse_lazy("people:new_hires")
1✔
78

79
    def get_context_data(self, **kwargs):
1✔
80
        context = super().get_context_data(**kwargs)
1✔
81
        context["title"] = _("Add new hire")
1✔
82
        context["subtitle"] = _("people")
1✔
83
        return context
1✔
84

85
    def form_valid(self, form):
1✔
86
        sequences = form.cleaned_data.pop("sequences")
1✔
87

88
        # Set new hire role
89
        form.instance.role = get_user_model().Role.NEWHIRE
1✔
90

91
        new_hire = form.save()
1✔
92

93
        # Add sequences to new hire
94
        new_hire.add_sequences(sequences)
1✔
95

96
        # Send credentials email if the user was created after their start day
97
        org = Organization.object.get()
1✔
98
        new_hire_datetime = new_hire.get_local_time()
1✔
99
        if (
1✔
100
            new_hire_datetime.date() >= new_hire.start_day
101
            and new_hire_datetime.hour >= 7
102
            and new_hire_datetime.weekday() < 5
103
            and org.new_hire_email
104
        ):
105
            async_task(
×
106
                "users.tasks.send_new_hire_credentials",
107
                new_hire.id,
108
                task_name=f"Send login credentials: {new_hire.full_name}",
109
            )
110

111
        # Linking user in Slack and sending welcome message (if exists)
112
        link_slack_users([new_hire])
1✔
113

114
        Notification.objects.create(
1✔
115
            notification_type=Notification.Type.ADDED_NEWHIRE,
116
            extra_text=new_hire.full_name,
117
            created_by=self.request.user,
118
            created_for=new_hire,
119
        )
120

121
        # Update user amount completed
122
        new_hire.update_progress()
1✔
123

124
        # Check if there are items that will not be triggered since date passed
125
        conditions = Condition.objects.none()
1✔
126
        for seq in sequences:
1✔
127
            if new_hire.workday == 0:
1✔
128
                # User has not started yet, so we only need the items before they new
129
                # hire started that passed
130
                conditions |= seq.conditions.filter(
1✔
131
                    condition_type=Condition.Type.BEFORE,
132
                    days__gte=new_hire.days_before_starting,
133
                )
134
            else:
135
                # user has already started, check both before start day and after for
136
                # conditions that are not triggered
137
                conditions |= seq.conditions.filter(
1✔
138
                    condition_type=Condition.Type.BEFORE
139
                ) | seq.conditions.filter(
140
                    condition_type=Condition.Type.AFTER, days__lte=new_hire.workday
141
                )
142

143
        if conditions.count():
1✔
144
            return render(
1✔
145
                self.request,
146
                "not_triggered_conditions.html",
147
                {
148
                    "conditions": conditions,
149
                    "title": new_hire.full_name,
150
                    "subtitle": "new hire",
151
                    "employee": new_hire,
152
                },
153
            )
154

155
        return super().form_valid(form)
1✔
156

157

158
class NewHireSendPreboardingNotificationView(
1✔
159
    LoginRequiredMixin, IsAdminOrNewHireManagerMixin, FormView
160
):
161
    template_name = "trigger_preboarding_notification.html"
1✔
162
    form_class = PreboardingSendForm
1✔
163

164
    def form_valid(self, form):
1✔
165
        new_hire = get_object_or_404(get_user_model(), id=self.kwargs.get("pk", -1))
1✔
166
        if form.cleaned_data["send_type"] == "email":
1✔
167
            send_new_hire_preboarding(new_hire, form.cleaned_data["email"])
1✔
168
        else:
169
            client = Client(settings.TWILIO_ACCOUNT_SID, settings.TWILIO_AUTH_TOKEN)
×
170
            client.messages.create(
×
171
                to=new_hire.phone,
172
                from_=settings.TWILIO_FROM_NUMBER,
173
                body=new_hire.personalize(
174
                    WelcomeMessage.objects.get(
175
                        language=new_hire.language,
176
                        message_type=WelcomeMessage.Type.TEXT_WELCOME,
177
                    ).message
178
                ),
179
            )
180
        return redirect("people:new_hire", pk=new_hire.id)
1✔
181

182
    def get_context_data(self, **kwargs):
1✔
183
        context = super().get_context_data(**kwargs)
1✔
184
        user_id = self.kwargs.get("pk", -1)
1✔
185
        new_hire = get_object_or_404(get_user_model(), id=user_id)
1✔
186
        context["title"] = new_hire.full_name
1✔
187
        context["subtitle"] = "new hire"
1✔
188
        return context
1✔
189

190

191
class NewHireAddSequenceView(
1✔
192
    LoginRequiredMixin, IsAdminOrNewHireManagerMixin, FormView
193
):
194
    template_name = "new_hire_add_sequence.html"
1✔
195
    form_class = OnboardingSequenceChoiceForm
1✔
196

197
    def form_valid(self, form):
1✔
198
        user_id = self.kwargs.get("pk", -1)
1✔
199
        new_hire = get_object_or_404(get_user_model(), id=user_id)
1✔
200
        sequences = Sequence.objects.filter(id__in=form.cleaned_data["sequences"])
1✔
201
        new_hire.add_sequences(sequences)
1✔
202
        messages.success(
1✔
203
            self.request, _("Sequence(s) have been added to this new hire")
204
        )
205

206
        # Check if there are items that will not be triggered since date passed
207
        conditions = Condition.objects.none()
1✔
208
        for seq in sequences:
1✔
209
            if new_hire.workday == 0:
1✔
210
                # User has not started yet, so we only need the items before they new
211
                # hire started that passed
212
                conditions |= seq.conditions.filter(
×
213
                    condition_type=Condition.Type.BEFORE,
214
                    days__gte=new_hire.days_before_starting,
215
                )
216
            else:
217
                # user has already started, check both before start day and after for
218
                # conditions that are not triggered
219
                conditions |= seq.conditions.filter(
1✔
220
                    condition_type=Condition.Type.BEFORE
221
                ) | seq.conditions.filter(
222
                    condition_type=Condition.Type.AFTER, days__lte=new_hire.workday
223
                )
224

225
        if conditions.count():
1✔
226
            # Prefetch records to avoid a massive amount of queries
227
            conditions = Condition.objects.prefetched().filter(
1✔
228
                id__in=conditions.values_list("pk", flat=True)
229
            )
230
            return render(
1✔
231
                self.request,
232
                "not_triggered_conditions.html",
233
                {
234
                    "conditions": conditions,
235
                    "title": new_hire.full_name,
236
                    "subtitle": "new hire",
237
                    "employee": new_hire,
238
                },
239
            )
240
        return redirect("people:new_hire", pk=new_hire.id)
1✔
241

242
    def get_context_data(self, **kwargs):
1✔
243
        context = super().get_context_data(**kwargs)
1✔
244
        user_id = self.kwargs.get("pk", -1)
1✔
245
        new_hire = get_object_or_404(get_user_model(), id=user_id)
1✔
246
        context["title"] = new_hire.full_name
1✔
247
        context["subtitle"] = "new hire"
1✔
248
        return context
1✔
249

250

251
class NewHireRemoveSequenceView(LoginRequiredMixin, IsAdminOrNewHireManagerMixin, View):
1✔
252
    def post(self, request, pk, sequence_pk, *args, **kwargs):
1✔
253
        sequence = get_object_or_404(Sequence, id=sequence_pk)
1✔
254
        new_hire = get_object_or_404(get_user_model(), id=pk)
1✔
255
        new_hire.remove_sequence(sequence)
1✔
256

257
        # Update user amount and completed
258
        new_hire.update_progress()
1✔
259

260
        messages.success(request, _("Sequence items were removed from this new hire"))
1✔
261

262
        return redirect("people:new_hire", pk=new_hire.id)
1✔
263

264

265
class NewHireTriggerConditionView(
1✔
266
    LoginRequiredMixin, IsAdminOrNewHireManagerMixin, TemplateView
267
):
268
    template_name = "_trigger_sequence_items.html"
1✔
269

270
    def post(self, request, pk, condition_pk, *args, **kwargs):
1✔
271
        condition = get_object_or_404(Condition, id=condition_pk)
1✔
272
        new_hire = get_object_or_404(get_user_model(), id=pk)
1✔
273
        condition.process_condition(new_hire, skip_notification=True)
1✔
274

275
        # Update user amount completed
276
        new_hire.update_progress()
1✔
277

278
        context = self.get_context_data(**kwargs)
1✔
279
        return self.render_to_response(context)
1✔
280

281
    def get_context_data(self, **kwargs):
1✔
282
        context = super().get_context_data(**kwargs)
1✔
283
        condition_id = self.kwargs.get("condition_pk", -1)
1✔
284
        condition = get_object_or_404(Condition, id=condition_id)
1✔
285
        context["completed"] = True
1✔
286
        context["condition"] = condition
1✔
287
        # not relevant, still needed for processing the template
288
        context["employee"] = get_object_or_404(
1✔
289
            get_user_model(), id=self.kwargs.get("pk")
290
        )
291
        return context
1✔
292

293

294
class NewHireSendLoginEmailView(LoginRequiredMixin, IsAdminOrNewHireManagerMixin, View):
1✔
295
    def post(self, request, pk, *args, **kwargs):
1✔
296
        new_hire = get_object_or_404(get_user_model(), id=pk)
1✔
297
        send_new_hire_credentials(new_hire.id)
1✔
298
        messages.success(request, _("Sent email to new hire"))
1✔
299
        return redirect("people:new_hire", pk=new_hire.id)
1✔
300

301

302
class NewHireSequenceView(LoginRequiredMixin, IsAdminOrNewHireManagerMixin, DetailView):
1✔
303
    template_name = "new_hire_detail.html"
1✔
304
    model = get_user_model()
1✔
305

306
    def get_context_data(self, **kwargs):
1✔
307
        context = super().get_context_data(**kwargs)
1✔
308
        new_hire = context["object"]
1✔
309
        context["title"] = new_hire.full_name
1✔
310
        context["subtitle"] = _("new hire")
1✔
311

312
        conditions = new_hire.conditions.prefetched()
1✔
313

314
        # condition items
315
        context["conditions"] = (
1✔
316
            (
317
                conditions.filter(
318
                    condition_type=2, days__lte=new_hire.days_before_starting
319
                )
320
                | conditions.filter(
321
                    condition_type=Condition.Type.AFTER, days__gte=new_hire.workday
322
                )
323
                | conditions.filter(condition_type=Condition.Type.TODO)
324
                | conditions.filter(condition_type=Condition.Type.ADMIN_TASK)
325
            )
326
            .alias_days_order()
327
            .order_by("days_order")
328
        )
329

330
        context["notifications"] = Notification.objects.filter(
1✔
331
            created_for=new_hire
332
        ).select_related("created_by")
333

334
        context["completed_todos"] = ToDoUser.objects.filter(
1✔
335
            user=new_hire, completed=True
336
        ).values_list("to_do__pk", flat=True)
337
        context["completed_admin_tasks"] = AdminTask.objects.filter(
1✔
338
            new_hire=new_hire, completed=True
339
        ).values_list("based_on__pk", flat=True)
340
        return context
1✔
341

342

343
class NewHireProfileView(
1✔
344
    LoginRequiredMixin, SuccessMessageMixin, IsAdminOrNewHireManagerMixin, UpdateView
345
):
346
    template_name = "new_hire_profile.html"
1✔
347
    model = get_user_model()
1✔
348
    form_class = NewHireProfileForm
1✔
349
    success_message = _("New hire has been updated")
1✔
350

351
    def get_success_url(self):
1✔
352
        return self.request.path
1✔
353

354
    def get_context_data(self, **kwargs):
1✔
355
        context = super().get_context_data(**kwargs)
1✔
356
        new_hire = context["object"]
1✔
357
        context["title"] = new_hire.full_name
1✔
358
        context["subtitle"] = _("new hire")
1✔
359
        return context
1✔
360

361

362
class NewHireMigrateToNormalAccountView(
1✔
363
    LoginRequiredMixin, IsAdminOrNewHireManagerMixin, View
364
):
365
    def post(self, request, pk, *args, **kwargs):
1✔
366
        user = get_object_or_404(
1✔
367
            get_user_model(), id=pk, role=get_user_model().Role.NEWHIRE
368
        )
369
        user.role = 3
1✔
370
        user.save()
1✔
371
        messages.info(request, _("New hire is now a normal account."))
1✔
372
        return redirect("people:new_hires")
1✔
373

374

375
class NewHireExtraInfoUpdateView(
1✔
376
    LoginRequiredMixin,
377
    UpdateView,
378
    IsAdminOrNewHireManagerMixin,
379
    SuccessMessageMixin,
380
):
381
    template_name = "token_create.html"
1✔
382
    form_class = IntegrationExtraUserInfoForm
1✔
383
    queryset = get_user_model().new_hires.all()
1✔
384
    success_message = _("Extra info has been added!")
1✔
385

386
    def get_success_url(self):
1✔
387
        user = get_object_or_404(get_user_model(), pk=self.kwargs.get("pk"))
1✔
388
        return reverse("people:new_hire", args=[user.id])
1✔
389

390
    def get_context_data(self, **kwargs):
1✔
391
        context = super().get_context_data(**kwargs)
1✔
392
        new_hire = context["object"]
1✔
393
        context["title"] = new_hire.full_name
1✔
394
        context["subtitle"] = _("new hire")
1✔
395
        context["button_text"] = _("Update")
1✔
396
        return context
1✔
397

398

399
class NewHireNotesView(
1✔
400
    LoginRequiredMixin,
401
    IsAdminOrNewHireManagerMixin,
402
    SuccessMessageMixin,
403
    CreateView,
404
):
405
    template_name = "new_hire_notes.html"
1✔
406
    model = Note
1✔
407
    fields = [
1✔
408
        "content",
409
    ]
410
    success_message = _("Note has been added")
1✔
411

412
    def get_success_url(self):
1✔
413
        return self.request.path
1✔
414

415
    def form_valid(self, form):
1✔
416
        new_hire = get_object_or_404(get_user_model(), pk=self.kwargs.get("pk"))
1✔
417
        form.instance.admin = self.request.user
1✔
418
        form.instance.new_hire = new_hire
1✔
419
        return super().form_valid(form)
1✔
420

421
    def get_context_data(self, **kwargs):
1✔
422
        context = super().get_context_data(**kwargs)
1✔
423
        new_hire = get_object_or_404(get_user_model(), pk=self.kwargs.get("pk"))
1✔
424
        context["object"] = new_hire
1✔
425
        context["title"] = new_hire.full_name
1✔
426
        context["subtitle"] = _("new hire")
1✔
427
        context["notes"] = (
1✔
428
            Note.objects.filter(new_hire=new_hire)
429
            .order_by("-id")
430
            .select_related("admin")
431
        )
432
        return context
1✔
433

434

435
class NewHireWelcomeMessagesView(
1✔
436
    LoginRequiredMixin, IsAdminOrNewHireManagerMixin, ListView
437
):
438
    template_name = "new_hire_welcome_messages.html"
1✔
439

440
    def get_queryset(self):
1✔
441
        new_hire = get_object_or_404(get_user_model(), pk=self.kwargs.get("pk"))
1✔
442
        return (
1✔
443
            NewHireWelcomeMessage.objects.filter(new_hire=new_hire)
444
            .order_by("-id")
445
            .select_related("colleague")
446
        )
447

448
    def get_context_data(self, **kwargs):
1✔
449
        context = super().get_context_data(**kwargs)
1✔
450
        new_hire = get_object_or_404(get_user_model(), pk=self.kwargs.get("pk"))
1✔
451
        context["object"] = new_hire
1✔
452
        context["title"] = new_hire.full_name
1✔
453
        context["subtitle"] = _("new hire")
1✔
454
        return context
1✔
455

456

457
class NewHireAdminTasksView(
1✔
458
    LoginRequiredMixin, IsAdminOrNewHireManagerMixin, TemplateView
459
):
460
    template_name = "new_hire_admin_tasks.html"
1✔
461

462
    def get_context_data(self, **kwargs):
1✔
463
        context = super().get_context_data(**kwargs)
1✔
464
        new_hire = get_object_or_404(get_user_model(), pk=self.kwargs.get("pk"))
1✔
465
        context["object"] = new_hire
1✔
466
        context["title"] = new_hire.full_name
1✔
467
        context["subtitle"] = _("new hire")
1✔
468
        context["tasks_completed"] = AdminTask.objects.filter(
1✔
469
            new_hire=new_hire, completed=True
470
        ).select_related("new_hire", "assigned_to")
471
        context["tasks_open"] = AdminTask.objects.filter(
1✔
472
            new_hire=new_hire, completed=False
473
        ).select_related("new_hire", "assigned_to")
474
        return context
1✔
475

476

477
class NewHireFormsView(LoginRequiredMixin, IsAdminOrNewHireManagerMixin, DetailView):
1✔
478
    template_name = "new_hire_forms.html"
1✔
479
    model = get_user_model()
1✔
480

481
    def get_context_data(self, **kwargs):
1✔
482
        context = super().get_context_data(**kwargs)
1✔
483
        new_hire = self.object
1✔
484
        context["title"] = new_hire.full_name
1✔
485
        context["subtitle"] = _("new hire")
1✔
486
        context["preboarding_forms"] = (
1✔
487
            PreboardingUser.objects.filter(user=new_hire, form__isnull=False)
488
            .exclude(form=[])
489
            .defer("preboarding__content")
490
        )
491
        context["todo_forms"] = (
1✔
492
            ToDoUser.objects.filter(user=new_hire, completed=True)
493
            .exclude(form=[])
494
            .select_related("to_do")
495
            .defer("to_do__content")
496
        )
497
        return context
1✔
498

499

500
class NewHireProgressView(LoginRequiredMixin, IsAdminOrNewHireManagerMixin, DetailView):
1✔
501
    template_name = "new_hire_progress.html"
1✔
502
    model = get_user_model()
1✔
503

504
    def get_context_data(self, **kwargs):
1✔
505
        context = super().get_context_data(**kwargs)
1✔
506
        new_hire = self.object
1✔
507
        context["title"] = new_hire.full_name
1✔
508
        context["subtitle"] = _("new hire")
1✔
509
        context["resources"] = ResourceUser.objects.filter(
1✔
510
            user=new_hire, resource__course=True
511
        )
512
        context["todos"] = (
1✔
513
            ToDoUser.objects.filter(user=new_hire)
514
            .select_related("to_do")
515
            .only("completed", "to_do__name", "to_do__id")
516
        )
517
        return context
1✔
518

519

520
class NewHireRemindView(LoginRequiredMixin, IsAdminOrNewHireManagerMixin, View):
1✔
521
    def post(self, request, pk, template_type, template_pk, *args, **kwargs):
1✔
522
        if template_type not in ["todouser", "resourceuser"]:
1✔
523
            raise Http404
1✔
524

525
        template_user_model = apps.get_model("users", template_type)
1✔
526

527
        template_user_obj = template_user_model.objects.get(pk=template_pk)
1✔
528
        template_user_obj.reminded = datetime.now()
1✔
529
        template_user_obj.save()
1✔
530

531
        translation.activate(template_user_obj.user.language)
1✔
532
        if template_user_obj.user.has_slack_account:
1✔
533
            if template_type == "todouser":
1✔
534
                block = SlackToDo(template_user_obj, template_user_obj.user).get_block()
1✔
535
            else:
536
                block = SlackResource(
1✔
537
                    template_user_obj, template_user_obj.user
538
                ).get_block()
539

540
            Slack().send_message(
1✔
541
                blocks=[paragraph(_("Don't forget this item!")), block],
542
                channel=template_user_obj.user.slack_user_id,
543
            )
544
        else:
545
            send_reminder_email(template_user_obj.object_name, template_user_obj.user)
1✔
546

547
        # Revert language as reminder should be sent in admin language
548
        translation.activate(request.user.language)
1✔
549
        messages.success(self.request, _("Reminder has been sent!"))
1✔
550

551
        return redirect("people:new_hire_progress", pk=template_user_obj.user.id)
1✔
552

553

554
class NewHireReopenTaskView(LoginRequiredMixin, IsAdminOrNewHireManagerMixin, FormView):
1✔
555
    template_name = "new_hire_reopen_task.html"
1✔
556
    form_class = RemindMessageForm
1✔
557

558
    def dispatch(self, *args, **kwargs):
1✔
559
        if self.request.user.is_authenticated:
1✔
560
            template_type = self.kwargs.get("template_type", "")
1✔
561
            if template_type not in ["todouser", "resourceuser"]:
1✔
562
                raise Http404
1✔
563

564
        return super().dispatch(*args, **kwargs)
1✔
565

566
    def form_valid(self, form):
1✔
567
        template_pk = self.kwargs.get("template_pk", -1)
1✔
568
        template_type = self.kwargs.get("template_type", "")
1✔
569

570
        template_user_model = apps.get_model("users", template_type)
1✔
571

572
        template_user_obj = template_user_model.objects.get(pk=template_pk)
1✔
573
        if template_type == "todouser":
1✔
574
            template_user_obj.completed = False
1✔
575
            template_user_obj.form = []
1✔
576
        else:
577
            template_user_obj.completed_course = False
1✔
578
            template_user_obj.step = 0
1✔
579
            template_user_obj.answers.clear()
1✔
580

581
        template_user_obj.save()
1✔
582

583
        translation.activate(template_user_obj.user.language)
1✔
584
        if template_user_obj.user.has_slack_account:
1✔
585
            if template_type == "todouser":
1✔
586
                block = SlackToDo(template_user_obj, template_user_obj.user).get_block()
1✔
587
            else:
588
                block = SlackResource(
1✔
589
                    template_user_obj, template_user_obj.user
590
                ).get_block()
591

592
            Slack().send_message(
1✔
593
                blocks=[paragraph(form.cleaned_data["message"]), block],
594
                text=form.cleaned_data["message"],
595
                channel=template_user_obj.user.slack_user_id,
596
            )
597
        else:
598
            email_reopen_task(
1✔
599
                template_user_obj.object_name,
600
                form.cleaned_data["message"],
601
                template_user_obj.user,
602
            )
603

604
        # Revert language as reminder should be sent in admin language
605
        translation.activate(self.request.user.language)
1✔
606
        messages.success(self.request, _("Item has been reopened"))
1✔
607

608
        # Update user amount completed
609
        template_user_obj.user.update_progress()
1✔
610

611
        return redirect("people:new_hire_progress", pk=template_user_obj.user.id)
1✔
612

613

614
class NewHireCourseAnswersView(
1✔
615
    LoginRequiredMixin, IsAdminOrNewHireManagerMixin, DetailView
616
):
617
    template_name = "new_hire_course_answers.html"
1✔
618
    model = get_user_model()
1✔
619

620
    def get_context_data(self, **kwargs):
1✔
621
        context = super().get_context_data(**kwargs)
1✔
622
        new_hire = self.object
1✔
623
        context["title"] = new_hire.full_name
1✔
624
        context["subtitle"] = _("new hire")
1✔
625
        context["resource_user"] = get_object_or_404(
1✔
626
            ResourceUser, user=new_hire, pk=self.kwargs.get("resource_user", -1)
627
        )
628
        return context
1✔
629

630

631
class NewHireTasksView(LoginRequiredMixin, IsAdminOrNewHireManagerMixin, DetailView):
1✔
632
    template_name = "new_hire_tasks.html"
1✔
633
    model = get_user_model()
1✔
634

635
    def get_context_data(self, **kwargs):
1✔
636
        context = super().get_context_data(**kwargs)
1✔
637
        context["title"] = self.object.full_name
1✔
638
        context["subtitle"] = _("new hire")
1✔
639
        return context
1✔
640

641

642
class NewHireTaskListView(LoginRequiredMixin, IsAdminOrNewHireManagerMixin, DetailView):
1✔
643
    template_name = "new_hire_add_task.html"
1✔
644
    model = get_user_model()
1✔
645

646
    def get_context_data(self, **kwargs):
1✔
647
        context = super().get_context_data(**kwargs)
1✔
648
        templates_model = get_templates_model(self.kwargs.get("type", ""))
1✔
649
        if templates_model is None:
1✔
650
            raise Http404
1✔
651

652
        context["title"] = _("Add/Remove templates for %(name)s") % {
1✔
653
            "name": self.object.full_name
654
        }
655
        context["subtitle"] = _("new hire")
1✔
656
        context["object_list"] = templates_model.templates.defer_content().all()
1✔
657
        context["user_items"] = getattr(
1✔
658
            self.object, get_user_field(self.kwargs.get("type", ""))
659
        ).values_list("id", flat=True)
660
        return context
1✔
661

662

663
class NewHireToggleTaskView(
1✔
664
    LoginRequiredMixin, IsAdminOrNewHireManagerMixin, TemplateView
665
):
666
    template_name = "_toggle_button_new_hire_template.html"
1✔
667

668
    def post(self, request, pk, template_id, type):
1✔
669
        user = get_object_or_404(get_user_model(), id=pk)
1✔
670
        templates_model = get_templates_model(type)
1✔
671

672
        if templates_model is None:
1✔
673
            raise Http404
1✔
674

675
        template = get_object_or_404(templates_model, id=template_id, template=True)
1✔
676
        user_items = getattr(user, get_user_field(type))
1✔
677
        if user_items.filter(id=template.id).exists():
1✔
678
            user_items.remove(template)
1✔
679
        else:
680
            user_items.add(template)
1✔
681

682
        user_items = user_items.values_list("id", flat=True)
1✔
683
        # Update user amount completed
684
        user.update_progress()
1✔
685

686
        context = self.get_context_data(
1✔
687
            **{
688
                "template": template,
689
                "user_items": user_items,
690
                "object": user,
691
                "id": id,
692
                "template_type": type,
693
            }
694
        )
695
        return self.render_to_response(context)
1✔
696

697

698
class NewHireDeleteView(
1✔
699
    LoginRequiredMixin, IsAdminOrNewHireManagerMixin, SuccessMessageMixin, DeleteView
700
):
701
    template_name = "new_hire_delete.html"
1✔
702
    queryset = get_user_model().new_hires.all()
1✔
703
    success_url = reverse_lazy("people:new_hires")
1✔
704
    success_message = _("New hire has been removed")
1✔
705

706

707
class CompleteAdminTaskView(
1✔
708
    LoginRequiredMixin, IsAdminOrNewHireManagerMixin, DetailView
709
):
710
    def post(self, request, pk, admin_task_pk, *args, **kwargs):
1✔
711
        task = get_object_or_404(AdminTask, id=admin_task_pk)
×
712
        task.mark_completed()
×
713

714
        messages.success(request, _("The admin task was successfully completed"))
×
715

716
        return redirect("people:new_hire_admin_tasks", pk=pk)
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc