Beispiel #1
0
    def test_block_queryset_with_existing_booking_with_active_user_block(self):
        """
        Existing booking should show only user's active blocks for the
        same event type.
        """
        active_user_block = mommy.make_recipe('booking.block',
                                              block_type=self.block_type,
                                              user=self.user,
                                              paid=True)
        active_user_block_diff_type = mommy.make_recipe('booking.block',
                                                        user=self.user,
                                                        paid=True)

        formset = UserBookingFormSet(data=self.formset_data(),
                                     instance=self.user,
                                     user=self.user)
        # get the first form
        form = formset.forms[0]
        block = form.fields['block']
        # queryset shows only the active blocks for this user and event type
        self.assertEquals(1, block.queryset.count())

        # empty_label shows the "None"
        self.assertEquals(
            block.empty_label,
            "--------None--------",
        )

        # assign this block to the user's booking
        self.booking.block = active_user_block
        self.booking.save()

        formset = UserBookingFormSet(data=self.formset_data(),
                                     instance=self.user,
                                     user=self.user)
        # get the first form
        form = formset.forms[0]
        block = form.fields['block']
        # queryset still only shows active blocks for this user and event type
        self.assertEquals(1, block.queryset.count())

        # empty_label shows the "Remove block" instruction
        self.assertEquals(
            block.empty_label,
            "---REMOVE BLOCK (TO CHANGE BLOCK, REMOVE AND SAVE FIRST)---",
        )
Beispiel #2
0
    def test_additional_data_in_form(self):
        mommy.make_recipe('booking.block',
                          block_type=self.block_type,
                          user=self.user,
                          paid=True)

        formset = UserBookingFormSet(data=self.formset_data(),
                                     instance=self.user,
                                     user=self.user)
        form = formset.forms[0]
        self.assertTrue(form.has_available_block)
        self.assertEquals(form.paid_id, 'paid_0')
Beispiel #3
0
    def test_block_queryset_with_existing_booking_no_active_user_block(self):

        active_user_block_diff_type = mommy.make_recipe('booking.block',
                                                        user=self.user,
                                                        paid=True)
        formset = UserBookingFormSet(data=self.formset_data(),
                                     instance=self.user,
                                     user=self.user)
        # get the first form
        form = formset.forms[0]
        block = form.fields['block']
        # no active blocks for this user and event type
        self.assertEquals(0, block.queryset.count())
Beispiel #4
0
 def test_event_choices_with_existing_booking(self):
     """
     Existing booking should show all events in event choices
     ).
     """
     events = mommy.make_recipe('booking.future_PC', _quantity=5)
     formset = UserBookingFormSet(data=self.formset_data(),
                                  instance=self.user,
                                  user=self.user)
     # get the first form
     form = formset.forms[0]
     event = form.fields['event']
     # queryset shows all events (will be hidden in the template)
     self.assertEquals(6, event.queryset.count())
Beispiel #5
0
    def test_event_choices_with_new_form(self):
        """
        New form should show all events the user is not booked for
        """

        events = mommy.make_recipe('booking.future_PC', _quantity=5)
        formset = UserBookingFormSet(instance=self.user, user=self.user)
        # get the last form, which will be the new empty one
        form = formset.forms[-1]
        event = form.fields['event']
        # queryset shows only the two active blocks for this user
        self.assertEquals(6, Event.objects.count())
        self.assertEquals(5, event.queryset.count())
        self.assertFalse(self.event in event.queryset)
Beispiel #6
0
    def test_block_queryset_with_new_form(self):
        """
        New form should show all active user blocks
        """
        mommy.make_recipe('booking.block',
                          block_type=self.block_type,
                          user=self.user,
                          paid=True)
        mommy.make_recipe('booking.block', user=self.user, paid=True)

        formset = UserBookingFormSet(instance=self.user, user=self.user)
        # get the last form, which will be the new empty one
        form = formset.forms[-1]
        block = form.fields['block']
        # queryset shows only the two active blocks for this user
        self.assertEquals(2, block.queryset.count())
Beispiel #7
0
    def test_block_choice_label_format(self):
        active_user_block = mommy.make_recipe('booking.block',
                                              block_type=self.block_type,
                                              user=self.user,
                                              paid=True)

        formset = UserBookingFormSet(data=self.formset_data(),
                                     instance=self.user,
                                     user=self.user)
        # get the first form
        form = formset.forms[0]
        block = form.fields['block']
        # queryset shows only the active blocks for this user and event type
        self.assertEquals(1, block.queryset.count())
        self.assertEquals(
            "{}; exp {}; {} left".format(
                active_user_block.block_type.event_type.subtype,
                active_user_block.expiry_date.strftime('%d/%m'),
                active_user_block.block_type.size -
                active_user_block.bookings_made()),
            block.label_from_instance(active_user_block))
Beispiel #8
0
def user_bookings_view(request,  user_id,  booking_status='future'):
    user = get_object_or_404(User,  id=user_id)

    if request.method == 'POST':
        booking_status = request.POST.getlist('booking_status')[0]
        userbookingformset = UserBookingFormSet(
            request.POST.copy(),  instance=user,  user=user, 
        )
        if userbookingformset.is_valid():
            if not userbookingformset.has_changed() and \
                    request.POST.get('formset_submitted'):
                messages.info(request,  "No changes were made")
            else:
                for form in userbookingformset:
                    if form.is_valid():
                        if form.has_changed():
                            if form.changed_data == ['send_confirmation']:
                                messages.info(
                                    request,  "'Send confirmation' checked for '{}' "
                                    "but no changes were made; email has not been "
                                    "sent to user.".format(form.instance.event))
                            else:
                                extra_msgs = [] # these will be displayed as a list in the email to the user

                                booking = form.save(commit=False)
                                event_was_full = booking.event.spaces_left == 0
                                action = 'updated' if form.instance.id else 'created'
                                transfer_block_created = False
                                block_removed = False

                                if 'status' in form.changed_data and action == 'updated':
                                    if booking.status == 'CANCELLED':
                                        if booking.block:
                                            booking.block = None
                                            block_removed = True
                                        elif booking.paid \
                                                and booking.event.event_type.event_type != 'EV':
                                            block_type, _ = BlockType.objects.get_or_create(
                                                event_type=booking.event.event_type,
                                                size=1, cost=0, duration=1,
                                                identifier='transferred',
                                                active=False
                                            )
                                            Block.objects.create(
                                                block_type=block_type, user=booking.user,
                                                transferred_booking_id=booking.id
                                            )
                                            transfer_block_created = True
                                        booking.deposit_paid = False
                                        booking.paid = False
                                        booking.payment_confirmed = False
                                        booking.free_class = False
                                        action = 'cancelled'
                                    elif booking.status == 'OPEN':
                                        action = 'reopened'

                                    extra_msgs.append("Booking status changed "
                                                      "to {}".format(action)
                                                      )

                                elif 'no_show' in form.changed_data \
                                    and action == 'updated' \
                                        and booking.status == 'OPEN':
                                    action = 'cancelled' if booking.no_show \
                                        else 'reopened'
                                    extra_msgs.append(
                                        "Booking {} as 'no-show'".format(action)
                                    )

                                if booking.block:
                                    booking.paid = True
                                    booking.payment_confirmed = True
                                elif 'block' in form.changed_data:
                                    booking.block = None
                                    booking.paid = False
                                    booking.payment_confirmed = False

                                # check for existence of free child block on pre-saved booking
                                has_free_block_pre_save = False
                                if booking.block and booking.block.children.exists():
                                    has_free_block_pre_save = True

                                if 'deposit_paid' in form.changed_data:
                                    if booking.deposit_paid:
                                        extra_msgs.append(
                                            "Booking payment status changed to "
                                            "'deposit paid'"
                                        )

                                if 'paid' in form.changed_data:
                                    if booking.paid:
                                        # assume that if booking is being done via
                                        # studioadmin,  marking paid also means payment
                                        # is confirmed
                                        booking.payment_confirmed = True
                                        extra_msgs.append(
                                            "Booking payment status changed to "
                                            "'fully paid and confirmed'"
                                        )
                                    else:
                                        booking.payment_confirmed = False

                                booking.save()

                                set_as_free = 'free_class' in \
                                              form.changed_data and \
                                              booking.free_class
                                if 'send_confirmation' in form.changed_data:
                                    try:
                                        # send confirmation email
                                        host = 'http://{}'.format(request.META.get('HTTP_HOST'))
                                        # send email to studio
                                        ctx = {
                                              'host': host, 
                                              'event': booking.event, 
                                              'user': booking.user, 
                                              'action': action, 
                                              'set_as_free': set_as_free, 
                                              'extra_msgs': extra_msgs
                                        }
                                        send_mail('{} Your booking for {} has been {}'.format(
                                            settings.ACCOUNT_EMAIL_SUBJECT_PREFIX,  booking.event,  action
                                            ), 
                                            get_template(
                                                'studioadmin/email/booking_change_confirmation.txt'
                                            ).render(ctx), 
                                            settings.DEFAULT_FROM_EMAIL, 
                                            [booking.user.email], 
                                            html_message=get_template(
                                                'studioadmin/email/booking_change_confirmation.html'
                                                ).render(ctx), 
                                            fail_silently=False)
                                        send_confirmation_msg = "and confirmation " \
                                        "email sent to user"
                                    except Exception as e:
                                        # send mail to tech support with Exception
                                        send_support_email(
                                            e,  __name__,  "user_booking_list - "
                                            "send confirmation email"
                                        )
                                        send_confirmation_msg = ". There was a " \
                                        "problem sending the confirmation email to the " \
                                        "user.  Tech support has been notified."
                                else:
                                    send_confirmation_msg = ""

                                messages.success(
                                    request, 
                                    'Booking for {} has been {} {}'.format(
                                        booking.event,  action,  send_confirmation_msg
                                    )
                                )
                                if set_as_free:
                                    extra_msg = "and marked as free class"
                                elif transfer_block_created:
                                    extra_msg = "and transfer block created as credit"
                                else:
                                    extra_msg = ''

                                ActivityLog.objects.create(
                                    log='Booking id {} (user {}) for "{}" {} '
                                            'by admin user {} {}'.format(
                                        booking.id,  booking.user.username,  booking.event, 
                                        action,  request.user.username, 
                                       extra_msg
                                    )
                                )

                                if not booking.block \
                                         and 'block' in form.changed_data:
                                     messages.info(
                                         request, 
                                         'Block removed for {}; booking is '
                                         'now marked as unpaid'.format(
                                             booking.event
                                         ), 
                                     )

                                if action == 'reopened':
                                    messages.info(
                                        request,  mark_safe(
                                            'Note: this booking was previously '
                                            'cancelled and has now been reopened. '
                                            '<span class="cancel-warning">Payment '
                                            'status has not been automatically '
                                            'updated. Please review the booking '
                                            'and update if paid '
                                            'and/or block used.</span>'
                                        )
                                    )
                                elif action == 'cancelled':
                                    if transfer_block_created:
                                        messages.info(
                                            request,
                                            mark_safe("Note: this booking has been "
                                            "cancelled. The booking has "
                                            "automatically been marked as "
                                            "unpaid and a transfer block "
                                            "has been created as credit.  If you wish to "
                                            "refund the user instead, go "
                                            "to the <a href={}>user's blocks</a> "
                                            "and delete "
                                            "the transfer block first.".format(
                                                reverse(
                                                    'studioadmin:user_blocks_list',
                                                    args=[booking.user.id]
                                                )
                                            ))
                                        )
                                    elif block_removed:
                                        messages.info(
                                            request,
                                            'Note: this booking has been '
                                            'cancelled. The booking has '
                                            'automatically been marked as '
                                            'unpaid and the block '
                                            'used has been updated.'
                                        )
                                    else:
                                        messages.info(
                                            request,  'Note: this booking has been '
                                            'cancelled. The booking has automatically '
                                            'been marked as unpaid (refunded).')

                                    if event_was_full:
                                        waiting_list_users = WaitingListUser.objects.filter(
                                            event=booking.event
                                        )
                                        if waiting_list_users:
                                            try:
                                                send_waiting_list_email(
                                                    booking.event, 
                                                    [wluser.user for \
                                                        wluser in waiting_list_users], 
                                                    host='http://{}'.format(
                                                        request.META.get('HTTP_HOST')
                                                    )
                                                )
                                                ActivityLog.objects.create(
                                                    log='Waiting list email sent to '
                                                    'user(s) {} for event {}'.format(
                                                        ',  '.join(
                                                            [wluser.user.username \
                                                                for wluser in \
                                                                waiting_list_users]
                                                        ), 
                                                        booking.event
                                                    )
                                                )
                                            except Exception as e:
                                                # send mail to tech support with Exception
                                                send_support_email(
                                                    e,  __name__, 
                                                    "Studioadmin user booking list - waiting list email"
                                                )

                                if action == 'created' or action == 'reopened':
                                    try:
                                        waiting_list_user = WaitingListUser.objects.get(
                                            user=booking.user,  event=booking.event
                                        )
                                        waiting_list_user.delete()
                                        ActivityLog.objects.create(
                                            log='User {} has been removed from the '
                                            'waiting list for {}'.format(
                                                booking.user.username, 
                                                booking.event
                                            )
                                        )
                                    except WaitingListUser.DoesNotExist:
                                        pass

                                if booking.block and not booking.block.active_block():
                                    if booking.block.children.exists() \
                                            and not has_free_block_pre_save:
                                         messages.info(
                                             request, 
                                            'You have added the last booking '
                                            'to a 10 class block; free class '
                                            'block has been created.'
                                         )

                    userbookingformset.save(commit=False)

            return HttpResponseRedirect(
                reverse(
                    'studioadmin:user_bookings_list', 
                    kwargs={
                        'user_id': user.id, 
                        'booking_status': booking_status
                    }
                )
            )
        else:
            messages.error(
                request, 
                mark_safe(
                    "Please correct the following errors:\n{}".format(
                        '\n'.join(
                            [
                                "{}".format(error)
                                for error in userbookingformset.errors
                            ]
                        )
                    )
                )
            )
    else:
        all_bookings = Booking.objects.filter(user=user)

        if booking_status == 'past':
            queryset = all_bookings.filter(
                event__date__lt=timezone.now()
            ).order_by('-event__date')
            userbookingformset = UserBookingFormSet(
                queryset=queryset,  instance=user,  user=user, 
            )
        else:
            # 'future' by default
            queryset = all_bookings.filter(
                event__date__gte=timezone.now()
            ).order_by('event__date')
            userbookingformset = UserBookingFormSet(
                queryset=queryset,  instance=user,  user=user, 
            )

        userbookingformset = UserBookingFormSet(
            instance=user, 
            queryset=queryset, 
            user=user
        )

    booking_status_filter = BookingStatusFilter(
        initial={'booking_status': booking_status}
    )

    template = 'studioadmin/user_booking_list.html'
    return TemplateResponse(
        request,  template,  {
            'userbookingformset': userbookingformset,  'user': user, 
            'sidenav_selection': 'users', 
            'booking_status_filter': booking_status_filter, 
            'booking_status': booking_status
        }
    )
Beispiel #9
0
def user_bookings_view(request, user_id, booking_status='future'):
    user = get_object_or_404(User, id=user_id)

    msg_texts = {
        'no change':  "No changes were made",
        'send_conf_no_change': "'Send confirmation' checked for '{}' "
                               "but no changes were made; email has not "
                               "been sent to user.",
        'bk_error': '<span class="cancel-warning">ERROR:</span> Booking '
                    'cannot be made for fully booked event {}',
    }

    if request.method == 'POST':
        booking_status = request.POST.getlist('booking_status')[0]
        userbookingformset = UserBookingFormSet(
            request.POST, instance=user, user=user,
        )
        if userbookingformset.is_valid():
            if not userbookingformset.has_changed() and \
                    request.POST.get('formset_submitted'):
                messages.info(request, msg_texts['no change'])
            else:
                for form in userbookingformset:
                    if form.is_valid() and form.has_changed():
                        if form.changed_data == ['send_confirmation']:
                            messages.info(
                                request, msg_texts['send_conf_no_change']
                                    .format(form.instance.event)
                            )
                        else:
                            booking = form.save(commit=False)
                            was_full = booking.event.spaces_left() == 0
                            action = 'updated' if form.instance.id else 'created'
                            if 'status' in form.changed_data and action == 'updated':
                                if booking.status == 'CANCELLED':
                                    if not booking.block:
                                        booking.paid = False
                                        booking.payment_confirmed = False
                                    action = 'cancelled'
                                elif booking.status == 'OPEN':
                                    action = 'reopened'

                            if 'paid' in form.changed_data:
                                if booking.paid:
                                    # assume that if booking is being done via
                                    # studioadmin, marking paid also means payment
                                    # is confirmed
                                    booking.payment_confirmed = True
                                else:
                                    booking.payment_confirmed = False

                            # save the form
                            try:
                                booking.save()
                            except BookingError:
                                messages.error(
                                    request,
                                    mark_safe(msg_texts['bk_error'].format(
                                        booking.event
                                    ))
                                )
                            else:
                                _process_confirmation_email(
                                    request, form, booking, action
                                )

                                ActivityLog.objects.create(
                                    log='Booking id {} (user {}) for "{}" {} '
                                            'by admin user {}'.format(
                                        booking.id, booking.user.username,
                                        booking.event,
                                        action, request.user.username
                                    )
                                )

                                _process_warning_msgs_and_waiting_list(
                                    request, booking, action, was_full
                                )
                    else:
                        for error in form.errors:
                            messages.error(request, mark_safe("{}".format(error)))

                    userbookingformset.save(commit=False)

            return HttpResponseRedirect(
                reverse(
                    'studioadmin:user_bookings_list',
                    kwargs={
                        'user_id': user.id,
                        'booking_status': booking_status
                    }
                )
            )
        else:
            messages.error(request,mark_safe(
                    "There were errors in the following fields:\n{}".format(
                        '\n'.join(
                            ["{}".format(error) for error in
                             userbookingformset.errors]
                        )
                    )
            ))
    else:
        all_bookings = Booking.objects.filter(user=user)
        if booking_status == 'all':
            queryset = all_bookings
        elif booking_status == 'past':
            queryset = all_bookings.filter(event__date__lt=timezone.now()).\
                order_by('event__date')
        else:
            # 'future' by default
            queryset = all_bookings.filter(event__date__gte=timezone.now()).\
                order_by('event__date')

        userbookingformset = UserBookingFormSet(
            instance=user,
            queryset=queryset,
            user=user
        )

    booking_status_filter = BookingStatusFilter(
        initial={'booking_status': booking_status}
    )

    template = 'studioadmin/user_booking_list.html'
    return TemplateResponse(
        request, template, {
            'userbookingformset': userbookingformset, 'user': user,
            'sidenav_selection': 'users',
            'booking_status_filter': booking_status_filter,
            'booking_status': booking_status
        }
    )
Beispiel #10
0
 def test_form_valid(self):
     formset = UserBookingFormSet(data=self.formset_data(),
                                  instance=self.user,
                                  user=self.user)
     self.assertTrue(formset.is_valid(), formset.errors)
Beispiel #11
0
    def test_widgets_disabled(self):
        """
        Cancelled: no_show widget, paid, deposit_paid, free_class disabled
        Block: paid, deposit_paid, free_class disabled
        No-show: no_show widget, paid, deposit_paid, free_class enabled but
            greyed
        No-show with block: no_show widget enabled but greyed, paid,
            deposit_paid, free_class disabled
        """
        events = mommy.make_recipe('booking.future_PC', _quantity=4)
        user = mommy.make_recipe('booking.user')
        block = mommy.make_recipe('booking.block',
                                  user=user,
                                  block_type__event_type=events[1].event_type)
        cancelled_booking = mommy.make_recipe('booking.booking',
                                              user=user,
                                              event=events[0],
                                              paid=True,
                                              payment_confirmed=True,
                                              status='CANCELLED')
        block_booking = mommy.make_recipe('booking.booking',
                                          user=user,
                                          event=events[1],
                                          paid=True,
                                          payment_confirmed=True,
                                          status='OPEN',
                                          block=block)
        no_show_booking = mommy.make_recipe('booking.booking',
                                            user=user,
                                            event=events[2],
                                            paid=True,
                                            payment_confirmed=True,
                                            status='OPEN',
                                            no_show=True)
        no_show_block_booking = mommy.make_recipe('booking.booking',
                                                  user=user,
                                                  event=events[3],
                                                  paid=True,
                                                  payment_confirmed=True,
                                                  status='OPEN',
                                                  block=block,
                                                  no_show=True)
        data = {
            'bookings-TOTAL_FORMS': 4,
            'bookings-INITIAL_FORMS': 4,
            'bookings-0-id': cancelled_booking.id,
            'bookings-0-event': cancelled_booking.event.id,
            'bookings-0-status': cancelled_booking.status,
            'bookings-1-id': block_booking.id,
            'bookings-1-event': block_booking.event.id,
            'bookings-1-status': block_booking.status,
            'bookings-2-id': no_show_booking.id,
            'bookings-2-event': no_show_booking.event.id,
            'bookings-2-status': no_show_booking.status,
            'bookings-3-id': no_show_block_booking.id,
            'bookings-3-event': no_show_block_booking.event.id,
            'bookings-3-status': no_show_block_booking.status,
        }

        formset = UserBookingFormSet(data=data, instance=user, user=self.user)
        cancelled_form = formset.forms[0]
        for field in ['no_show', 'paid', 'deposit_paid', 'free_class']:
            self.assertEqual(
                cancelled_form.fields[field].widget.attrs['class'],
                'regular-checkbox regular-checkbox-disabled')
            self.assertEqual(
                cancelled_form.fields[field].widget.attrs['OnClick'],
                'javascript:return ReadOnlyCheckBox()')

        block_form = formset.forms[1]
        for field in ['paid', 'deposit_paid', 'free_class']:
            self.assertEqual(block_form.fields[field].widget.attrs['class'],
                             'regular-checkbox regular-checkbox-disabled')
            self.assertEqual(block_form.fields[field].widget.attrs['OnClick'],
                             'javascript:return ReadOnlyCheckBox()')
        self.assertEqual(block_form.fields['no_show'].widget.attrs['class'],
                         'regular-checkbox')

        no_show_form = formset.forms[2]
        for field in ['no_show', 'paid', 'deposit_paid', 'free_class']:
            self.assertEqual(no_show_form.fields[field].widget.attrs['class'],
                             'regular-checkbox regular-checkbox-disabled')
            self.assertIsNone(no_show_form.fields[field].widget.attrs.get(
                'OnClick', None))

        no_show_block_form = formset.forms[3]
        for field in ['paid', 'deposit_paid', 'free_class']:
            self.assertEqual(
                no_show_block_form.fields[field].widget.attrs['class'],
                'regular-checkbox regular-checkbox-disabled')
            self.assertEqual(
                no_show_block_form.fields[field].widget.attrs['OnClick'],
                'javascript:return ReadOnlyCheckBox()')
        self.assertEqual(block_form.fields['no_show'].widget.attrs['class'],
                         'regular-checkbox')
        self.assertIsNone(no_show_form.fields['no_show'].widget.attrs.get(
            'OnClick', None))
Beispiel #12
0
 def test_form_valid(self):
     formset = UserBookingFormSet(data=self.formset_data(),
                                  instance=self.user,
                                  user=self.user)
     self.assertTrue(formset.is_valid(), formset.errors)