Example #1
0
    def form_valid(self, form):

        if "confirm_cancel" in form.data:
            ticket_booking = form.save(commit=False)
            err_msg = self.check_and_redirect(self.request, ticket_booking)
            if err_msg:
                messages.info(self.request, err_msg)
                return HttpResponseRedirect(reverse('booking:ticket_bookings'))

            ticket_booking.cancelled = True
            ticket_booking.save()
            ActivityLog.objects.create(
                log='Ticket booking ref {} (for {}) has been cancelled by '
                    'user {}'.format(
                        ticket_booking.booking_reference,
                        ticket_booking.ticketed_event,
                        ticket_booking.user.username,
                    )
            )

            try:
                # send email and set messages
                host = 'http://{}'.format(self.request.META.get('HTTP_HOST'))
                # send email to user; no need to send to studio as cancelled
                # before payment
                ctx = {
                      'host': host,
                      'ticket_booking': ticket_booking,
                }
                send_mail('{} Ticket booking ref {} cancelled'.format(
                        settings.ACCOUNT_EMAIL_SUBJECT_PREFIX,
                        ticket_booking.booking_reference,
                    ),
                    get_template(
                        'booking/email/ticket_booking_cancelled.txt'
                    ).render(ctx),
                    settings.DEFAULT_FROM_EMAIL,
                    [self.request.user.email],
                    html_message=get_template(
                        'booking/email/ticket_booking_cancelled.html'
                        ).render(ctx),
                    fail_silently=False)

            except Exception as e:
                # send mail to tech support with Exception
                send_support_email(
                    e, __name__, "TicketBookingCancelView - user email"
                )
                messages.error(
                    self.request,
                    "An error occured, please contact the studio for "
                    "information"
                )

            messages.success(
                self.request, self.success_message.format(
                   ticket_booking.booking_reference
               )
            )
        return HttpResponseRedirect(self.get_success_url())
Example #2
0
    def form_valid(self, form):

        if "confirm_cancel" in form.data:
            ticket_booking = form.save(commit=False)
            err_msg = self.check_and_redirect(self.request, ticket_booking)
            if err_msg:
                messages.info(self.request, err_msg)
                return HttpResponseRedirect(reverse('booking:ticket_bookings'))

            ticket_booking.cancelled = True
            ticket_booking.save()
            ActivityLog.objects.create(
                log='Ticket booking ref {} (for {}) has been cancelled by '
                'user {}'.format(
                    ticket_booking.booking_reference,
                    ticket_booking.ticketed_event,
                    ticket_booking.user.username,
                ))

            try:
                # send email and set messages
                host = 'http://{}'.format(self.request.META.get('HTTP_HOST'))
                # send email to user; no need to send to studio as cancelled
                # before payment
                ctx = {
                    'host': host,
                    'ticket_booking': ticket_booking,
                }
                send_mail(
                    '{} Ticket booking ref {} cancelled'.format(
                        settings.ACCOUNT_EMAIL_SUBJECT_PREFIX,
                        ticket_booking.booking_reference,
                    ),
                    get_template('booking/email/ticket_booking_cancelled.txt'
                                 ).render(ctx),
                    settings.DEFAULT_FROM_EMAIL, [self.request.user.email],
                    html_message=get_template(
                        'booking/email/ticket_booking_cancelled.html').render(
                            ctx),
                    fail_silently=False)

            except Exception as e:
                # send mail to tech support with Exception
                send_support_email(e, __name__,
                                   "TicketBookingCancelView - user email")
                messages.error(
                    self.request,
                    "An error occured, please contact the studio for "
                    "information")

            messages.success(
                self.request,
                self.success_message.format(ticket_booking.booking_reference))
        return HttpResponseRedirect(self.get_success_url())
Example #3
0
def _email_free_class_request(request, booking, booking_status):
    # if user is requesting a free class, send email to studio and
    # make booking unpaid (admin will update)
    ActivityLog.objects.create(
        log='Free class requested ({}) by user {}'.format(
            booking.event, request.user.username)
    )
    booking.free_class_requested = True
    booking.paid = False
    booking.payment_confirmed = False
    booking.block = None
    try:
        # send email and set messages
        host = 'http://{}'.format(request.META.get('HTTP_HOST'))
        # send email to studio
        ctx = {
              'host': host,
              'event': booking.event,
              'user': request.user,
              'booking_status': booking_status,
        }
        send_mail('{} Request to claim free class from {} {}'.format(
                settings.ACCOUNT_EMAIL_SUBJECT_PREFIX,
                request.user.first_name,
                request.user.last_name
            ),
            get_template(
                'studioadmin/email/free_class_request_to_studio.txt'
            ).render(ctx),
            settings.DEFAULT_FROM_EMAIL,
            [settings.DEFAULT_STUDIO_EMAIL],
            html_message=get_template(
                'studioadmin/email/free_class_request_to_studio.html'
                ).render(ctx),
            fail_silently=False)

        messages.success(
            request,
            "Your request to claim {} as a free class has been "
            "sent to the studio.  Your booking has been "
            "provisionally made and your place will be secured once "
            "your request has been approved.".format(booking.event)
        )
    except Exception as e:
        # send mail to tech support with Exception
        send_support_email(e, __name__, "UpdateBookingView - claim free class email")
        messages.error(request, "An error occured, please contact "
            "the studio for information")
Example #4
0
    def _send_confirmation_email(self, request, ticket_booking, action):
        try:
            # send confirmation email
            host = 'http://{}'.format(request.META.get('HTTP_HOST'))
            # send email to studio
            ctx = {
                  'host': host,
                  'ticketed_event': self.ticketed_event,
                  'action': action,
            }
            send_mail('{} Your ticket booking ref {} for {} has been {}'.format(
                settings.ACCOUNT_EMAIL_SUBJECT_PREFIX,
                ticket_booking.booking_reference,
                self.ticketed_event,
                action
                ),
                get_template(
                    'studioadmin/email/ticket_booking_change_confirmation.txt'
                ).render(ctx),
                settings.DEFAULT_FROM_EMAIL,
                [ticket_booking.user.email],
                html_message=get_template(
                    'studioadmin/email/ticket_booking_change_confirmation.html'
                    ).render(ctx),
                fail_silently=False)
            send_confirmation_msg = "Confirmation email was sent to " \
                                    "user {}.".format(
                ticket_booking.user.username
            )
        except Exception as e:
            # send mail to tech support with Exception
            send_support_email(
                e, __name__, "ticketed_event_booking_list - "
                "send confirmation email"
            )
            send_confirmation_msg = "There was a " \
            "problem sending the confirmation email to " \
            "user {}.  Tech support has been notified.".format(
                ticket_booking.user.username
            )

        return send_confirmation_msg
Example #5
0
    def _send_confirmation_email(self, request, ticket_booking, action):
        try:
            # send confirmation email
            host = 'http://{}'.format(request.META.get('HTTP_HOST'))
            # send email to studio
            ctx = {
                'host': host,
                'ticketed_event': self.ticketed_event,
                'action': action,
            }
            send_mail(
                '{} Your ticket booking ref {} for {} has been {}'.format(
                    settings.ACCOUNT_EMAIL_SUBJECT_PREFIX,
                    ticket_booking.booking_reference, self.ticketed_event,
                    action),
                get_template(
                    'studioadmin/email/ticket_booking_change_confirmation.txt'
                ).render(ctx),
                settings.DEFAULT_FROM_EMAIL, [ticket_booking.user.email],
                html_message=get_template(
                    'studioadmin/email/ticket_booking_change_confirmation.html'
                ).render(ctx),
                fail_silently=False)
            send_confirmation_msg = "Confirmation email was sent to " \
                                    "user {}.".format(
                ticket_booking.user.username
            )
        except Exception as e:
            # send mail to tech support with Exception
            send_support_email(
                e, __name__, "ticketed_event_booking_list - "
                "send confirmation email")
            send_confirmation_msg = "There was a " \
            "problem sending the confirmation email to " \
            "user {}.  Tech support has been notified.".format(
                ticket_booking.user.username
            )

        return send_confirmation_msg
Example #6
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
        }
    )
Example #7
0
def cancel_event_view(request, slug):
    event = get_object_or_404(Event, slug=slug)
    ev_type = 'class' if event.event_type.event_type == 'CL' else 'event'

    open_bookings = Booking.objects.filter(
        event=event, status='OPEN', no_show=False
    )
    no_shows_all = Booking.objects.filter(
        event=event, status='OPEN', no_show=True
    )
    no_shows = [bk for bk in no_shows_all if bk.paid or bk.deposit_paid]
    open_block_bookings = [
        bk for bk in open_bookings if bk.block and not bk.free_class
        ]
    open_unpaid_bookings = [
        bk for bk in open_bookings if not bk.deposit_paid and not bk.paid]
    open_free_non_block = [
        bk for bk in open_bookings if bk.free_class and not bk.block
        ]
    open_free_block = [bk for bk in open_bookings if bk.free_class and bk.block]
    open_direct_paid_deposit_only = [
        bk for bk in open_bookings if not bk.block
        and not bk.free_class and bk.deposit_paid and not bk.paid
    ]
    open_direct_paid = [
        bk for bk in open_bookings if not bk.block
        and not bk.free_class and bk.paid
    ]

    if request.method == 'POST':
        if 'confirm' in request.POST:
            transfer_direct_paid = request.POST.get('direct_paid_action') == 'transfer'

            for booking in open_bookings:
                transfer_block_created = False
                block_paid = bool(booking.block)  # block paid and free blocks
                free_block = bool(booking.block and booking.free_class)
                direct_paid = booking in open_direct_paid or \
                              booking in open_free_non_block
                deposit_only_paid = booking in open_direct_paid_deposit_only

                if booking.block:
                    booking.block = None
                    booking.deposit_paid = False
                    booking.paid = False
                    booking.payment_confirmed = False
                    # in case this was paid with a free class block
                    booking.free_class = False
                elif direct_paid and transfer_direct_paid:
                    # direct paid = paypal and free non-block paid
                    # create transfer block and make this booking unpaid
                    if booking.event.event_type.event_type != 'EV':
                        booking.deposit_paid = False
                        booking.paid = False
                        booking.payment_confirmed = False
                        booking.free_class = False
                        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.status = "CANCELLED"
                booking.save()

                try:
                    # send notification email to user
                    host = 'http://{}'.format(request.META.get('HTTP_HOST'))
                    ctx = {
                        'host': host,
                        'event_type': ev_type,
                        'block_paid': block_paid,
                        'direct_paid': direct_paid or deposit_only_paid,
                        'free_block': free_block,
                        'transfer_block_created': transfer_block_created,
                        'event': event,
                        'user': booking.user,
                    }
                    send_mail('{} {} has been cancelled'.format(
                        settings.ACCOUNT_EMAIL_SUBJECT_PREFIX, ev_type.title(),
                        ),
                        get_template(
                            'studioadmin/email/event_cancelled.txt'
                        ).render(ctx),
                        settings.DEFAULT_FROM_EMAIL,
                        [booking.user.email],
                        html_message=get_template(
                            'studioadmin/email/event_cancelled.html'
                            ).render(ctx),
                        fail_silently=False)
                except Exception as e:
                    # send mail to tech support with Exception
                    send_support_email(
                        e, __name__, "cancel event - "
                        "send notification email to user"
                    )

            event.cancelled = True
            event.booking_open = False
            event.payment_open = False
            event.save()

            # email studio with links for confirming refunds
            # direct paid (full and deposit only) and free non-block
            # if action selected is not transfer, otherwise just email for
            # deposits as we don't create
            # transfer blocks for deposit-only
            try:
                host = 'http://{}'.format(request.META.get('HTTP_HOST'))
                # send email to studio
                ctx = {
                    'host': host,
                    'event_type': ev_type,
                    'transfer_direct_paid': transfer_direct_paid,
                    'open_bookings': open_bookings,
                    'open_direct_paid_bookings': open_direct_paid,
                    'open_block_bookings': open_block_bookings,
                    'open_deposit_only_paid_bookings': open_direct_paid_deposit_only,
                    'open_unpaid_bookings': open_unpaid_bookings,
                    'open_free_non_block_bookings': open_free_non_block,
                    'open_free_block_bookings': open_free_block,
                    'no_shows': no_shows,
                    'event': event,
                }
                send_mail(
                    '{} {} has been cancelled - please review for refunds '
                    'required'.format(
                        settings.ACCOUNT_EMAIL_SUBJECT_PREFIX, ev_type.title(),
                    ),
                    get_template(
                        'studioadmin/email/to_studio_event_cancelled.txt'
                    ).render(ctx),
                    settings.DEFAULT_FROM_EMAIL,
                    [settings.DEFAULT_STUDIO_EMAIL],
                    html_message=get_template(
                        'studioadmin/email/to_studio_event_cancelled.html'
                        ).render(ctx),
                    fail_silently=False)
            except Exception as e:
                # send mail to tech support with Exception
                send_support_email(
                    e, __name__, "cancel event - "
                    "send refund notification email to studio"
                )

            if open_bookings:
                booking_cancelled_msg = 'open ' \
                                        'booking(s) have been cancelled{} ' \
                                        'Notification emails have been ' \
                                        'sent to {}.'.format(
                    ' and transfer blocks created for direct paid bookings.'
                    if request.POST.get('direct_paid_action') == 'transfer'
                    else '.',
                    ', '.join(
                        ['{} {}'.format(booking.user.first_name,
                                        booking.user.last_name)
                         for booking in open_bookings]
                        )
                    )
            else:
                booking_cancelled_msg = 'there were ' \
                                        'no open bookings for this {}'.format(
                    ev_type
                )
            messages.info(
                request,
                '{} has been cancelled; '.format(
                    ev_type.title()
                ) + booking_cancelled_msg
            )

            ActivityLog.objects.create(
                log="{} {} cancelled by admin user {}; {}".format(
                    ev_type.title(), event, request.user.username,
                    booking_cancelled_msg
                )
            )

            return HttpResponseRedirect(
                reverse('studioadmin:{}'.format(
                    'events' if ev_type == 'event' else 'lessons'
                ))
            )
        elif 'cancel' in request.POST:
            return HttpResponseRedirect(
                reverse('studioadmin:{}'.format(
                    'events' if ev_type == 'event' else 'lessons'
                ))
            )

    context = {
        'event': event,
        'event_type': ev_type,
        'open_bookings': bool(open_bookings),
        'open_direct_paid_bookings': open_direct_paid,
        'open_block_bookings': open_block_bookings,
        'open_deposit_only_paid_bookings': open_direct_paid_deposit_only,
        'open_unpaid_bookings': open_unpaid_bookings,
        'open_free_non_block_bookings': open_free_non_block,
        'open_free_block_bookings': open_free_block,
        'no_shows': no_shows
    }

    return TemplateResponse(
        request, 'studioadmin/cancel_event.html', context
    )
Example #8
0
    def handle(self, *args, **options):
        action = options['action'][0]
        prices = {
            'on': {
                'pc': 6,
                'pp': 2.75
            },
            'off': {
                'pc': 7.50,
                'pp': 4
            },
        }

        pole_classes = Event.objects.filter(
            date__gt=timezone.now(), event_type__subtype='Pole level class')
        pole_practices = Event.objects.filter(
            date__gt=timezone.now(), event_type__subtype='Pole practice')
        for pole_class in pole_classes:
            pole_class.cost = prices[action]['pc']
            if action == 'on':
                pole_class.booking_open = True
                pole_class.payment_open = True
            pole_class.save()

        for pole_practice in pole_practices:
            pole_practice.cost = prices[action]['pp']
            if action == 'on':
                pole_practice.booking_open = True
                pole_practice.payment_open = True
            pole_practice.save()

        if pole_classes:
            message = 'Pole classes have been updated with {} prices ' \
                      '(ids {})'.format(
                'sale' if action == 'on' else 'non-sale',
                ', '.join([str(pc.id) for pc in pole_classes])
                )
            ActivityLog.objects.create(log=message)
            self.stdout.write(message)

        if pole_practices:
            message = 'Pole practices have been updated with {} prices ' \
                      '(ids {})'.format(
                'sale' if action == 'on' else 'non-sale',
                ', '.join([str(pp.id) for pp in pole_practices])
            )
            ActivityLog.objects.create(log=message)
            self.stdout.write(message)

        if pole_classes or pole_practices:
            try:
                send_mail(
                    '{} Pole classes and/or practices sale {}'.format(
                        settings.ACCOUNT_EMAIL_SUBJECT_PREFIX,
                        'activated' if action == 'on' else 'deactivated'),
                    'The following pole class ids have '
                    'been {actioned}:\n{pc_ids}\n'
                    'The following pole practice ids have '
                    'been {actioned}:\n{pp_ids}'.format(
                        pc_ids=', '.join([str(pc.id) for pc in pole_classes]),
                        pp_ids=', '.join([str(pp.id)
                                          for pp in pole_practices]),
                        actioned='activated'
                        if action == 'on' else 'deactivated',
                    ),
                    settings.DEFAULT_FROM_EMAIL, [settings.SUPPORT_EMAIL],
                    fail_silently=False)
            except Exception as e:
                # send mail to tech support with Exception
                send_support_email(
                    e, __name__,
                    "Activate class/practice sale - support email")
        else:
            self.stdout.write('No classes/practices to {}'.format(
                'activate' if action == 'on' else 'deactivate'))
Example #9
0
def email_users_view(request,
                     mailing_list=False,
                     template_name='studioadmin/email_users_form.html'):

    if mailing_list:
        subscribed, _ = Group.objects.get_or_create(name='subscribed')
        users_to_email = subscribed.user_set.all()
    else:
        users_to_email = User.objects.filter(
            id__in=request.session['users_to_email'])

    if request.method == 'POST':

        form = EmailUsersForm(request.POST)
        test_email = request.POST.get('send_test', False)

        if form.is_valid():
            subject = '{}{}'.format(form.cleaned_data['subject'],
                                    ' [TEST EMAIL]' if test_email else '')
            from_address = form.cleaned_data['from_address']
            message = form.cleaned_data['message']
            cc = form.cleaned_data['cc']

            # bcc recipients
            email_addresses = [user.email for user in users_to_email]
            email_count = len(email_addresses)
            number_of_emails = ceil(email_count / 99)

            if test_email:
                email_lists = [[from_address]]
            else:
                email_lists = [email_addresses]  # will be a list of lists
                # split into multiple emails of 99 bcc plus 1 cc
                if email_count > 99:
                    email_lists = [
                        email_addresses[i:i + 99]
                        for i in range(0, email_count, 99)
                    ]

            host = 'http://{}'.format(request.META.get('HTTP_HOST'))

            try:
                for i, email_list in enumerate(email_lists):
                    ctx = {
                        'subject': subject,
                        'message': message,
                        'number_of_emails': number_of_emails,
                        'email_count': email_count,
                        'is_test': test_email,
                        'mailing_list': mailing_list,
                        'host': host,
                    }
                    msg = EmailMultiAlternatives(
                        subject,
                        get_template(
                            'studioadmin/email/email_users.txt').render(ctx),
                        bcc=email_list,
                        cc=[from_address] if
                        (i == 0 and cc and not test_email) else [],
                        reply_to=[from_address])
                    msg.attach_alternative(
                        get_template(
                            'studioadmin/email/email_users.html').render(ctx),
                        "text/html")
                    msg.send(fail_silently=False)

                    if not test_email:
                        ActivityLog.objects.create(
                            log='{} email with subject "{}" sent to users {} by'
                            ' admin user {}'.format(
                                'Mailing list' if mailing_list else 'Bulk',
                                subject, ', '.join(
                                    email_list), request.user.username))
            except Exception as e:
                # send mail to tech support with Exception
                send_support_email(e, __name__, "Bulk Email to students")
                ActivityLog.objects.create(
                    log="Possible error with sending {} email; "
                    "notification sent to tech support".format(
                        'mailing list' if mailing_list else 'bulk'))

                if not test_email:
                    ActivityLog.objects.create(
                        log='{} email error '
                        '(email subject "{}"), sent by '
                        'by admin user {}'.format(
                            'Mailing list' if mailing_list else 'Bulk',
                            subject, request.user.username))

            if not test_email:
                messages.success(
                    request, '{} email with subject "{}" has been sent to '
                    'users'.format('Mailing list' if mailing_list else 'Bulk',
                                   subject))
                return HttpResponseRedirect(reverse('studioadmin:users'))
            else:
                messages.success(
                    request, 'Test email has been sent to {} only. Click '
                    '"Send Email" below to send this email to '
                    'users.'.format(from_address))

        # Do this if form not valid OR sending test email
        event_ids = request.session.get('events', [])
        lesson_ids = request.session.get('lessons', [])
        events = Event.objects.filter(id__in=event_ids)
        lessons = Event.objects.filter(id__in=lesson_ids)

        if form.errors:
            totaleventids = event_ids + lesson_ids
            totalevents = Event.objects.filter(id__in=totaleventids)
            messages.error(
                request,
                mark_safe("Please correct errors in form: {}".format(
                    form.errors)))
            form = EmailUsersForm(
                initial={
                    'subject': "; ".join((str(event) for event in totalevents))
                })

        if test_email:
            form = EmailUsersForm(request.POST)

    else:
        event_ids = ast.literal_eval(request.GET.get('events', '[]'))
        events = Event.objects.filter(id__in=event_ids)
        lesson_ids = ast.literal_eval(request.GET.get('lessons', '[]'))
        lessons = Event.objects.filter(id__in=lesson_ids)
        totaleventids = event_ids + lesson_ids
        totalevents = Event.objects.filter(id__in=totaleventids)
        form = EmailUsersForm(
            initial={
                'subject': "; ".join((str(event) for event in totalevents))
            })

    return TemplateResponse(
        request, template_name, {
            'form': form,
            'users_to_email': users_to_email,
            'sidenav_selection':
            'mailing_list' if mailing_list else 'email_users',
            'events': events,
            'lessons': lessons,
            'mailing_list': mailing_list
        })
Example #10
0
def email_users_view(request, mailing_list=False,
                     template_name='studioadmin/email_users_form.html'):

        if mailing_list:
            subscribed, _ = Group.objects.get_or_create(name='subscribed')
            users_to_email = subscribed.user_set.all()
        else:
            users_to_email = User.objects.filter(
                id__in=request.session['users_to_email']
            )

        if request.method == 'POST':

            form = EmailUsersForm(request.POST)
            test_email = request.POST.get('send_test', False)

            if form.is_valid():
                subject = '{}{}'.format(
                    form.cleaned_data['subject'],
                    ' [TEST EMAIL]' if test_email else ''
                )
                from_address = form.cleaned_data['from_address']
                message = form.cleaned_data['message']
                cc = form.cleaned_data['cc']

                # bcc recipients
                email_addresses = [user.email for user in users_to_email]
                email_count = len(email_addresses)
                number_of_emails = ceil(email_count / 99)

                if test_email:
                    email_lists = [[from_address]]
                else:
                    email_lists = [email_addresses]  # will be a list of lists
                    # split into multiple emails of 99 bcc plus 1 cc
                    if email_count > 99:
                        email_lists = [
                            email_addresses[i : i + 99]
                            for i in range(0, email_count, 99)
                            ]

                host = 'http://{}'.format(request.META.get('HTTP_HOST'))

                try:
                    for i, email_list in enumerate(email_lists):
                        ctx = {
                                  'subject': subject,
                                  'message': message,
                                  'number_of_emails': number_of_emails,
                                  'email_count': email_count,
                                  'is_test': test_email,
                                  'mailing_list': mailing_list,
                                  'host': host,
                              }
                        msg = EmailMultiAlternatives(
                            subject,
                            get_template(
                                'studioadmin/email/email_users.txt').render(
                                    ctx
                                ),
                            bcc=email_list,
                            cc=[from_address]
                            if (i == 0 and cc and not test_email) else [],
                            reply_to=[from_address]
                            )
                        msg.attach_alternative(
                            get_template(
                                'studioadmin/email/email_users.html').render(
                                  ctx
                              ),
                            "text/html"
                        )
                        msg.send(fail_silently=False)

                        if not test_email:
                            ActivityLog.objects.create(
                                log='{} email with subject "{}" sent to users {} by'
                                    ' admin user {}'.format(
                                        'Mailing list' if mailing_list else 'Bulk',
                                        subject, ', '.join(email_list),
                                        request.user.username
                                    )
                            )
                except Exception as e:
                    # send mail to tech support with Exception
                    send_support_email(
                        e, __name__, "Bulk Email to students"
                    )
                    ActivityLog.objects.create(
                        log="Possible error with sending {} email; "
                            "notification sent to tech support".format(
                                'mailing list' if mailing_list else 'bulk'
                        )
                    )

                    if not test_email:
                        ActivityLog.objects.create(
                            log='{} email error '
                                '(email subject "{}"), sent by '
                                'by admin user {}'.format(
                                    'Mailing list' if mailing_list else 'Bulk',
                                    subject, request.user.username
                                )
                        )

                if not test_email:
                    messages.success(
                        request,
                        '{} email with subject "{}" has been sent to '
                        'users'.format(
                            'Mailing list' if mailing_list else 'Bulk',
                            subject
                        )
                    )
                    return HttpResponseRedirect(reverse('studioadmin:users'))
                else:
                    messages.success(
                        request, 'Test email has been sent to {} only. Click '
                                 '"Send Email" below to send this email to '
                                 'users.'.format(
                                    from_address
                                    )
                    )



            # Do this if form not valid OR sending test email
            event_ids = request.session.get('events', [])
            lesson_ids = request.session.get('lessons', [])
            events = Event.objects.filter(id__in=event_ids)
            lessons = Event.objects.filter(id__in=lesson_ids)

            if form.errors:
                totaleventids = event_ids + lesson_ids
                totalevents = Event.objects.filter(id__in=totaleventids)
                messages.error(
                    request,
                    mark_safe(
                        "Please correct errors in form: {}".format(form.errors)
                    )
                )
                form = EmailUsersForm(
                    initial={
                        'subject': "; ".join(
                            (str(event) for event in totalevents)
                        )
                    }
                )

            if test_email:
                form = EmailUsersForm(request.POST)

        else:
            event_ids = ast.literal_eval(request.GET.get('events', '[]'))
            events = Event.objects.filter(id__in=event_ids)
            lesson_ids = ast.literal_eval(request.GET.get('lessons', '[]'))
            lessons = Event.objects.filter(id__in=lesson_ids)
            totaleventids = event_ids + lesson_ids
            totalevents = Event.objects.filter(id__in=totaleventids)
            form = EmailUsersForm(
                initial={
                    'subject': "; ".join((str(event) for event in totalevents))
                }
            )

        return TemplateResponse(
            request, template_name, {
                'form': form,
                'users_to_email': users_to_email,
                'sidenav_selection': 'mailing_list'
                if mailing_list else 'email_users',
                'events': events,
                'lessons': lessons,
                'mailing_list': mailing_list
            }
        )
Example #11
0
    def handle(self, *args, **options):
        identifiers = options['identifiers']
        action = options['action'][0]
        actions = {
            'on': True,
            'off': False
        }
        blocktypes = BlockType.objects.filter(identifier__in=identifiers)
        for blocktype in blocktypes:
            blocktype.active = actions[action]
            blocktype.save()

        if blocktypes:
            message = 'Blocktypes with the identifier(s) "{}" {} ' \
                      '(ids {})'.format(
                ', '.join(identifiers),
                'activated' if action == 'on' else 'deactivated',
                ', '.join([str(bt.id) for bt in blocktypes])
                )
            ActivityLog.objects.create(log=message)
            self.stdout.write(message)

            try:
                send_mail('{} Block types {}'.format(
                    settings.ACCOUNT_EMAIL_SUBJECT_PREFIX,
                    'activated' if action == 'on' else 'deactivated'
                ),
                    'The following blocktype ids with the identifier(s) "{}" have '
                    'been {}:\n{}'.format(
                        ', '.join(identifiers),
                        'activated' if action == 'on' else 'deactivated',
                        ', '.join([str(bt.id) for bt in blocktypes])
                    ),
                    settings.DEFAULT_FROM_EMAIL,
                    [settings.SUPPORT_EMAIL],
                    fail_silently=False)
            except Exception as e:
                # send mail to tech support with Exception
                send_support_email(
                    e, __name__, "Activate blocktypes - support email"
                )
        else:
            self.stdout.write('No blocktypes matching identifiers')
            try:
                send_mail('{} Block types {} attempt failed'.format(
                    settings.ACCOUNT_EMAIL_SUBJECT_PREFIX,
                    'activation' if action == 'on' else 'deactivation'
                ),
                    'Blocktype {} command run but no blocktypes matched the '
                    'identifier(s) "{}"'.format(
                        'activation' if action == 'on' else 'deactivation',
                        ', '.join(identifiers),
                    ),
                    settings.DEFAULT_FROM_EMAIL,
                    [settings.SUPPORT_EMAIL],
                    fail_silently=False)
            except Exception as e:
                # send mail to tech support with Exception
                send_support_email(
                    e, __name__, "Activate blocktypes - support email"
                )
    def handle(self, *args, **options):

        bookings = []
        for booking in Booking.objects.filter(
            event__date__gte=timezone.now(),
            event__advance_payment_required=True,
            status='OPEN',
            paid=False,
            payment_confirmed=False,
            date_booked__lte=timezone.now() - timedelta(hours=6)):

            # ignore any which have been rebooked in the past 6 hrs
            if booking.date_rebooked and \
                    (booking.date_rebooked >=
                         (timezone.now() - timedelta(hours=6))):
                pass
            elif booking.event.date - timedelta(
                    hours=booking.event.cancellation_period
            ) < timezone.now() and booking.warning_sent:
                bookings.append(booking)
            elif booking.event.payment_due_date and booking.warning_sent:
                if booking.event.payment_due_date < timezone.now():
                    bookings.append(booking)
            elif booking.event.payment_time_allowed:
                # if there's a payment time allowed, cancel bookings booked
                # longer ago than this (bookings already filtered out
                # any booked or rebooked within 6 hrs)
                # don't check for warning sent this time
                # for free class requests, always allow them 24 hrs so admin
                # have time to mark classes as free (i.e.paid)
                last_booked_date = booking.date_rebooked \
                        if booking.date_rebooked else booking.date_booked
                if booking.free_class_requested:
                    if last_booked_date < timezone.now() - timedelta(hours=24):
                        bookings.append(booking)
                elif last_booked_date < timezone.now() \
                        - timedelta(hours=booking.event.payment_time_allowed):
                        bookings.append(booking)

        for booking in bookings:
            event_was_full = booking.event.spaces_left == 0

            ctx = {
                  'booking': booking,
                  'event': booking.event,
                  'date': booking.event.date.strftime('%A %d %B'),
                  'time': booking.event.date.strftime('%I:%M %p'),
            }
            # send mails to users
            try:
                send_mail('{} Booking cancelled: {}'.format(
                    settings.ACCOUNT_EMAIL_SUBJECT_PREFIX, booking.event.name),
                    get_template(
                        'booking/email/booking_auto_cancelled.txt'
                    ).render(ctx),
                    settings.DEFAULT_FROM_EMAIL,
                    [booking.user.email],
                    html_message=get_template(
                        'booking/email/booking_auto_cancelled.html'
                        ).render(ctx),
                    fail_silently=False)
            except Exception as e:
                # send mail to tech support with Exception
                send_support_email(
                    e, __name__, "Automatic cancel job - cancelled email"
                )
            booking.status = 'CANCELLED'
            booking.block = None
            booking.save()
            ActivityLog.objects.create(
                log='Unpaid booking id {} for event {}, user {} '
                    'automatically cancelled'.format(
                        booking.id, booking.event, booking.user
                )
            )
            if event_was_full:
                waiting_list_users = WaitingListUser.objects.filter(
                    event=booking.event
                )
                try:
                    send_waiting_list_email(
                        booking.event, [user.user for user in waiting_list_users]
                    )
                    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__, "Automatic cancel job - waiting list email"
                    )

        if bookings:
            if settings.SEND_ALL_STUDIO_EMAILS:
                # send single mail to Studio
                try:
                    send_mail('{} Booking{} been automatically cancelled'.format(
                        settings.ACCOUNT_EMAIL_SUBJECT_PREFIX,
                        ' has' if len(bookings) == 1 else 's have'),
                        get_template(
                            'booking/email/booking_auto_cancelled_studio_email.txt'
                        ).render({'bookings': bookings}),
                        settings.DEFAULT_FROM_EMAIL,
                        [settings.DEFAULT_STUDIO_EMAIL],
                        html_message=get_template(
                            'booking/email/booking_auto_cancelled_studio_email.html'
                            ).render({'bookings': bookings}),
                        fail_silently=False)
                    self.stdout.write(
                        'Cancellation emails sent for booking ids {}'.format(
                            ', '.join([str(booking.id) for booking in bookings])
                        )
                    )
                except Exception as e:
                    # send mail to tech support with Exception
                    send_support_email(
                        e, __name__, "Automatic cancel job - studio email"
                    )
        else:
            self.stdout.write('No bookings to cancel')
Example #13
0
    def handle(self, *args, **options):

        # get relevant ticketed_events
        ticketed_events = TicketedEvent.objects.filter(
            date__gte=timezone.now(),
            cancelled=False,
            ticket_cost__gt=0,
            advance_payment_required=True,
        )

        bookings_to_cancel = []
        # import ipdb; ipdb.set_trace()
        for event in ticketed_events:
            # get open unpaid ticket bookings made > 6 hrs ago
            ticket_bookings = [
                bkg for bkg in event.ticket_bookings.all()
                if not bkg.cancelled and not bkg.paid
                and (bkg.date_booked < timezone.now() - timedelta(hours=6))
                ]

            # if payment due date is past and warning has been sent, cancel
            if event.payment_due_date and event.payment_due_date < timezone.now():
                for bkg in ticket_bookings:
                    if bkg.warning_sent:
                        bookings_to_cancel.append(bkg)

            elif event.payment_time_allowed:
                # if there's a payment time allowed, cancel bookings booked
                # longer ago than this (ticket_bookings already filtered out
                # any booked within 6 hrs)
                # don't check for warning sent this time
                for bkg in ticket_bookings:
                    if bkg.date_booked < timezone.now() \
                            - timedelta(hours=event.payment_time_allowed):
                        bookings_to_cancel.append(bkg)

        for ticket_booking in bookings_to_cancel:

            ctx = {
                  'ticket_booking': ticket_booking,
                  'ticketed_event': ticket_booking.ticketed_event,
            }
            # send mails to users
            try:
                send_mail('{} Ticket Booking ref {} cancelled'.format(
                    settings.ACCOUNT_EMAIL_SUBJECT_PREFIX,
                    ticket_booking.booking_reference
                ),
                    get_template(
                        'booking/email/ticket_booking_auto_cancelled.txt'
                    ).render(ctx),
                    settings.DEFAULT_FROM_EMAIL,
                    [ticket_booking.user.email],
                    html_message=get_template(
                        'booking/email/ticket_booking_auto_cancelled.html'
                        ).render(ctx),
                    fail_silently=False)
            except Exception as e:
                # send mail to tech support with Exception
                send_support_email(
                    e, __name__, "Automatic cancel ticket booking job - cancelled email"
                )
            ticket_booking.cancelled = True
            ticket_booking.save()

            ActivityLog.objects.create(
                log='Unpaid ticket booking ref {} for event {}, user {} '
                    'automatically cancelled'.format(
                    ticket_booking.booking_reference,
                    ticket_booking.ticketed_event,
                    ticket_booking.user.username
                )
            )

        if bookings_to_cancel:
            if settings.SEND_ALL_STUDIO_EMAILS:
                try:
                    # send single mail to Studio
                    send_mail('{} Ticket Booking{} been automatically cancelled'.format(
                        settings.ACCOUNT_EMAIL_SUBJECT_PREFIX,
                        ' has' if len(bookings_to_cancel) == 1 else 's have'),
                        get_template(
                            'booking/email/ticket_booking_auto_cancelled_studio_email.txt'
                        ).render({'bookings': bookings_to_cancel}),
                        settings.DEFAULT_FROM_EMAIL,
                        [settings.DEFAULT_STUDIO_EMAIL],
                        html_message=get_template(
                            'booking/email/ticket_booking_auto_cancelled_studio_email.html'
                            ).render({'bookings': bookings_to_cancel}),
                        fail_silently=False)
                    self.stdout.write(
                        'Cancellation emails sent for ticket booking refs {}'.format(
                            ', '.join(
                                [str(booking.booking_reference)
                                 for booking in bookings_to_cancel]
                            )
                        )
                    )
                except Exception as e:
                    # send mail to tech support with Exception
                    send_support_email(
                        e, __name__,
                        "Automatic cancel ticket booking job - studio email"
                    )
        else:
            self.stdout.write('No ticket bookings to cancel')
    def handle(self, *args, **options):

        # get relevant users

        expire_date = timezone.now() - timedelta(days=365)

        expired_users = []

        for user in User.objects.all():
            if not user.bookings.exists():
                expired_users.append(user)
            else:
                recent_bookings = [
                    True for booking in user.bookings.all()
                    if (booking.event.date > expire_date) and booking.paid
                ]
                if not recent_bookings:
                    expired_users.append(user)

        old_print_disclaimers = PrintDisclaimer.objects.filter(
            date__lt=expire_date)
        old_online_disclaimers = OnlineDisclaimer.objects.filter(
            Q(date__lt=expire_date)
            & (Q(date_updated__isnull=True) | Q(date_updated__lt=expire_date)))
        print_disclaimer_users_to_delete = old_print_disclaimers.filter(
            user__in=expired_users)
        print_disclaimer_users = [
            '{} {}'.format(disc.user.first_name, disc.user.last_name)
            for disc in print_disclaimer_users_to_delete
        ]

        online_disclaimer_users_to_delete = old_online_disclaimers.filter(
            user__in=expired_users)
        online_disclaimer_users = [
            '{} {}'.format(disc.user.first_name, disc.user.last_name)
            for disc in online_disclaimer_users_to_delete
        ]

        print_disclaimer_users_to_delete.delete()
        online_disclaimer_users_to_delete.delete()

        if print_disclaimer_users or online_disclaimer_users:
            # email studio
            ctx = {
                'print_disclaimer_users': print_disclaimer_users,
                'online_disclaimer_users': online_disclaimer_users
            }

            # send mail to studio
            try:
                send_mail(
                    '{} Disclaimers deleted for expired users'.format(
                        settings.ACCOUNT_EMAIL_SUBJECT_PREFIX, ),
                    get_template(
                        'account/email/delete_disclaimers.txt').render(ctx),
                    settings.DEFAULT_FROM_EMAIL,
                    [settings.DEFAULT_STUDIO_EMAIL],
                    html_message=get_template(
                        'account/email/delete_disclaimers.html').render(ctx),
                    fail_silently=False)
            except Exception as e:
                # send mail to tech support with Exception
                send_support_email(
                    e, __name__,
                    "Automatic disclaimer deletion - studio email")

            ActivityLog.objects.create(
                log='Print disclaimers deleted for expired users: {}'.format(
                    ', '.format(print_disclaimer_users)))
            ActivityLog.objects.create(
                log='Online disclaimers deleted for expired users: {}'.format(
                    ', '.format(online_disclaimer_users)))
        else:
            self.stdout.write('No disclaimers to delete')
            ActivityLog.objects.create(
                log='Delete disclaimers job run; no expired users')
Example #15
0
    def post(self, request, *args, **kwargs):
        if 'cancel' in request.POST:
            self.ticket_booking.delete()
            messages.info(
                request, 'Ticket booking for {} has been cancelled.'.format(
                    self.ticketed_event))
            return HttpResponseRedirect(reverse('booking:ticketed_events'))

        context = self.get_context_data()
        ticket_purchase_form = context['ticket_purchase_form']
        ticket_formset = context['ticket_formset']

        if ticket_purchase_form.has_changed():
            # tickets on current booking are only included in the tickets_left
            # calculation if purchase has been confirmed
            old_tickets = self.ticket_booking.tickets.all()
            old_ticket_count = old_tickets.count()

            if self.ticket_booking.purchase_confirmed:
                tickets_left_excl_this = self.ticketed_event.tickets_left() \
                                            + old_ticket_count
            else:
                tickets_left_excl_this = self.ticketed_event.tickets_left()

            new_quantity = int(
                request.POST.get('ticket_purchase_form-quantity'))

            if new_quantity > tickets_left_excl_this:
                messages.error(
                    request,
                    'Cannot purchase the number of tickets requested.  '
                    'Only {} tickets left.'.format(
                        self.ticketed_event.tickets_left()))
            else:
                # create the correct number of tickets on this booking
                if old_ticket_count < new_quantity:
                    for i in range(new_quantity - old_ticket_count):
                        Ticket.objects.create(
                            ticket_booking=self.ticket_booking)
                if old_ticket_count > new_quantity:
                    for ticket in old_tickets[new_quantity:]:
                        ticket.delete()

                if old_ticket_count > 0:
                    ActivityLog.objects.create(
                        log="Ticket quantity updated on booking ref {}".format(
                            self.ticket_booking.booking_reference))

            tickets = self.ticket_booking.tickets.all()
            context['tickets'] = tickets

            return TemplateResponse(request, self.template_name, context)

        if 'ticket_formset-submit' in request.POST:
            if ticket_formset.is_valid():
                ticket_formset.save()

                # we only create the paypal form if there is a ticket cost and
                # online payments are open
                if self.ticketed_event.ticket_cost and \
                        self.ticketed_event.payment_open:
                    invoice_id = create_ticket_booking_paypal_transaction(
                        self.request.user, self.ticket_booking).invoice_id
                    host = 'http://{}'.format(
                        self.request.META.get('HTTP_HOST'))
                    paypal_form = PayPalPaymentsUpdateForm(
                        initial=context_helpers.get_paypal_dict(
                            host,
                            self.ticketed_event.ticket_cost,
                            self.ticketed_event,
                            invoice_id,
                            '{} {}'.format('ticket_booking',
                                           self.ticket_booking.id),
                            paypal_email=self.ticketed_event.paypal_email,
                            quantity=self.ticket_booking.tickets.count()))
                    context["paypalform"] = paypal_form
                self.ticket_booking.purchase_confirmed = True
                # reset the ticket_booking booked date to the date user confirms
                context['purchase_confirmed'] = True
                self.ticket_booking.date_booked = timezone.now()
                self.ticket_booking.save()
                ActivityLog.objects.create(
                    log="Ticket Purchase confirmed: event {}, user {}, "
                    "booking ref {}".format(
                        self.ticketed_event.name, request.user.username,
                        self.ticket_booking.booking_reference))

                host = 'http://{}'.format(request.META.get('HTTP_HOST'))
                ctx = {
                    'host': host,
                    'ticketed_event': self.ticketed_event,
                    'ticket_booking': self.ticket_booking,
                    'ticket_count': self.ticket_booking.tickets.count(),
                    'user': request.user,
                }

                try:
                    # send notification email to user
                    send_mail(
                        '{} Ticket booking confirmed for {}: ref {}'.format(
                            settings.ACCOUNT_EMAIL_SUBJECT_PREFIX,
                            self.ticketed_event,
                            self.ticket_booking.booking_reference,
                        ),
                        get_template('booking/email/ticket_booking_made.txt'
                                     ).render(ctx),
                        settings.DEFAULT_FROM_EMAIL, [request.user.email],
                        html_message=get_template(
                            'booking/email/ticket_booking_made.html').render(
                                ctx),
                        fail_silently=False)
                except Exception as e:
                    # send mail to tech support with Exception
                    send_support_email(
                        e, __name__, "ticket booking created - "
                        "send email to user")

                if self.ticketed_event.email_studio_when_purchased:
                    try:
                        send_mail(
                            '{} Ticket booking confirmed for {}: ref {}'.
                            format(
                                settings.ACCOUNT_EMAIL_SUBJECT_PREFIX,
                                self.ticketed_event,
                                self.ticket_booking.booking_reference,
                            ),
                            get_template(
                                'booking/email/to_studio_ticket_booking_made.txt'
                            ).render(ctx),
                            settings.DEFAULT_FROM_EMAIL,
                            [settings.DEFAULT_STUDIO_EMAIL],
                            html_message=get_template(
                                'booking/email/to_studio_ticket_booking_made.html'
                            ).render(ctx),
                            fail_silently=False)
                    except Exception as e:
                        # send mail to tech support with Exception
                        send_support_email(
                            e, __name__, "ticket booking created - "
                            "send email to studio")
            else:
                messages.error(request,
                               "Please correct errors in the form below")

            tickets = self.ticket_booking.tickets.all()
            context['tickets'] = tickets
            ticket_purchase_form = TicketPurchaseForm(
                prefix='ticket_purchase_form',
                ticketed_event=self.ticketed_event,
                ticket_booking=self.ticket_booking,
                initial={'quantity': self.ticket_booking.tickets.count()})
            context["ticket_purchase_form"] = ticket_purchase_form
            return TemplateResponse(request, self.template_name, context)
Example #16
0
def cancel_ticketed_event_view(request, slug):
    ticketed_event = get_object_or_404(TicketedEvent, slug=slug)

    open_paid_ticket_bookings = [
        booking for booking in ticketed_event.ticket_bookings.all()
        if not booking.cancelled and booking.purchase_confirmed
        and booking.tickets.exists() and booking.paid
    ]

    open_unpaid_ticket_bookings = [
        booking for booking in ticketed_event.ticket_bookings.all()
        if not booking.cancelled and booking.purchase_confirmed
        and booking.tickets.exists() and not booking.paid
    ]

    unconfirmed_ticket_bookings = TicketBooking.objects.filter(
        ticketed_event=ticketed_event, purchase_confirmed=False)

    if request.method == 'POST':
        if 'confirm' in request.POST:

            host = 'http://{}'.format(request.META.get('HTTP_HOST'))

            for booking in open_paid_ticket_bookings + \
                    open_unpaid_ticket_bookings:
                booking.cancelled = True
                booking.save()

                try:
                    # send notification email to user to all ticket booking,
                    # paid or unpaid
                    ctx = {
                        'host': host,
                        'ticketed_event': ticketed_event,
                        'ticket_booking': booking,
                    }
                    send_mail(
                        '{} {} has been cancelled'.format(
                            settings.ACCOUNT_EMAIL_SUBJECT_PREFIX,
                            ticketed_event.name,
                        ),
                        get_template(
                            'studioadmin/email/ticketed_event_cancelled.txt'
                        ).render(ctx),
                        settings.DEFAULT_FROM_EMAIL, [booking.user.email],
                        html_message=get_template(
                            'studioadmin/email/ticketed_event_cancelled.html').
                        render(ctx),
                        fail_silently=False)
                except Exception as e:
                    # send mail to tech support with Exception
                    send_support_email(
                        e, __name__, "cancel ticketed event - "
                        "send notification email to user")
            for booking in unconfirmed_ticket_bookings:
                booking.delete()

            ticketed_event.cancelled = True
            ticketed_event.show_on_site = False
            ticketed_event.payment_open = False
            ticketed_event.save()

            if open_paid_ticket_bookings:
                # email studio with links for confirming refunds for paid only

                try:
                    # send email to studio
                    ctx = {
                        'host': host,
                        'open_paid_ticket_bookings': open_paid_ticket_bookings,
                        'ticketed_event': ticketed_event,
                    }
                    send_mail(
                        '{} Refunds due for ticket bookings for '
                        'cancelled event {}'.format(
                            settings.ACCOUNT_EMAIL_SUBJECT_PREFIX,
                            ticketed_event.name,
                        ),
                        get_template(
                            'studioadmin/email/to_studio_ticketed_event_cancelled.txt'
                        ).render(ctx),
                        settings.DEFAULT_FROM_EMAIL,
                        [settings.DEFAULT_STUDIO_EMAIL],
                        html_message=get_template(
                            'studioadmin/email/to_studio_ticketed_event_cancelled.html'
                        ).render(ctx),
                        fail_silently=False)
                except Exception as e:
                    # send mail to tech support with Exception
                    send_support_email(
                        e, __name__, "cancel ticketed event - "
                        "send refund notification email to studio")

            if open_paid_ticket_bookings and open_unpaid_ticket_bookings:
                booking_cancelled_msg = '{} has been cancelled; open ticket ' \
                                        'booking refs {} have been ' \
                                        'cancelled'.format(
                    ticketed_event,
                    ', '.join(['{}'.format(booking.booking_reference) for
                               booking in open_paid_ticket_bookings]
                    )
                )
                messages.info(
                    request,
                    booking_cancelled_msg + 'and notification emails have '
                    'been sent.')
            else:
                booking_cancelled_msg = '{} has been cancelled; there were ' \
                                        'no open ticket bookings for this ' \
                                        'event'.format(ticketed_event)
                messages.info(request, booking_cancelled_msg)

            ActivityLog.objects.create(
                log="{} cancelled by admin user {}. {}".format(
                    ticketed_event, request.user.username,
                    booking_cancelled_msg))

            return HttpResponseRedirect(reverse('studioadmin:ticketed_events'))

        elif 'cancel' in request.POST:
            return HttpResponseRedirect(reverse('studioadmin:ticketed_events'))

    context = {
        'ticketed_event': ticketed_event,
        'open_paid_ticket_bookings': open_paid_ticket_bookings,
        'open_unpaid_ticket_bookings': open_unpaid_ticket_bookings,
        'already_cancelled': ticketed_event.cancelled
    }

    return TemplateResponse(request, 'studioadmin/cancel_ticketed_event.html',
                            context)
Example #17
0
    def delete(self, request, *args, **kwargs):
        booking = self.get_object()

        # Booking can be fully cancelled if the event allows cancellation AND
        # the cancellation period is not past
        # If not, we let people cancel but leave the booking status OPEN and
        # set to no-show
        can_cancel_and_refund = booking.event.allow_booking_cancellation \
            and booking.event.can_cancel()

        event_was_full = booking.event.spaces_left == 0

        host = 'http://{}'.format(self.request.META.get('HTTP_HOST'))
        # send email to user

        ctx = {
                  'host': host,
                  'booking': booking,
                  'event': booking.event,
                  'date': booking.event.date.strftime('%A %d %B'),
                  'time': booking.event.date.strftime('%I:%M %p'),
              }
        try:
            send_mail('{} Booking for {} cancelled'.format(
                settings.ACCOUNT_EMAIL_SUBJECT_PREFIX, booking.event.name),
                get_template('booking/email/booking_cancelled.txt').render(ctx),
                settings.DEFAULT_FROM_EMAIL,
                [booking.user.email],
                html_message=get_template(
                    'booking/email/booking_cancelled.html').render(ctx),
                fail_silently=False)
        except Exception as e:
            # send mail to tech support with Exception
            send_support_email(e, __name__, "DeleteBookingView - cancelled email")
            messages.error(self.request, "An error occured, please contact "
                "the studio for information")

        if can_cancel_and_refund:
            transfer_block_created = False
            if booking.paid and (not booking.block or booking.block.expired):
                # booking was paid directly, either in cash or by paypal
                # OR booking was free class but not made with free block
                # OR booking was made with block (normal/free/transfer) but
                # block has now expired and we can't credit by reassigning
                # space to block.
                # NOTE: this does mean that potentially someone could defer
                # a class indefinitely by cancelling and rebooking, but
                # let's assume that would be a rare occurrence

                # If event is CL or RH, get or create transfer block type,
                # create transfer block for user and set transferred_
                # booking_id to the cancelled one
                if 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

                # send email to studio only for 'EV' which are not transferable
                else:
                    send_mail(
                        '{} {} {} has just cancelled a booking for {}'.format(
                            settings.ACCOUNT_EMAIL_SUBJECT_PREFIX,
                            'ACTION REQUIRED!' if not booking.block else '',
                            booking.user.username,
                            booking.event.name
                            ),
                          get_template(
                              'booking/email/to_studio_booking_cancelled.txt'
                          ).render(
                              {
                                  'host': host,
                                  'booking': booking,
                                  'event': booking.event,
                                  'date': booking.event.date.strftime('%A %d %B'),
                                  'time': booking.event.date.strftime('%I:%M %p'),
                              }
                          ),
                        settings.DEFAULT_FROM_EMAIL,
                        [settings.DEFAULT_STUDIO_EMAIL],
                        fail_silently=False)

            # if booking was bought with a block, remove from block and set
            # paid and payment_confirmed to False. If paid directly, paid is only
            # changed to False for bookings that have created transfer blocks; for
            # EV event types, leave paid as True as refunds need to be dealt with
            # manually but change payment_confirmed to False
            # reassigning free class blocks is done in model save
            if booking.block:
                booking.block = None
                booking.paid = False

            if booking.free_class:
                booking.free_class = False
                booking.paid = False
            booking.status = 'CANCELLED'
            booking.payment_confirmed = False
            booking.save()

            messages.success(
                self.request,
                self.success_message.format(booking.event)
            )
            ActivityLog.objects.create(
                log='Booking id {} for event {}, user {}, was cancelled by user '
                    '{}'.format(
                        booking.id, booking.event, booking.user.username,
                        self.request.user.username
                    )
            )

            if transfer_block_created:
                ActivityLog.objects.create(
                    log='Transfer block created for user {} (for {}; transferred '
                        'booking id {} '.format(
                            booking.user.username, booking.event.event_type.subtype,
                            booking.id
                        )
                )
                messages.info(
                    self.request,
                    mark_safe(
                        'A transfer block has been created for you as '
                        'credit for your cancelled booking and is valid for '
                        '1 month (<a href="/blocks">View your blocks</a>)'
                    )
                )
        else:
            # if the booking wasn't paid, just cancel it
            if not booking.paid:
                booking.status = 'CANCELLED'
                booking.payment_confirmed = False
                booking.save()
                messages.success(
                    self.request,
                    self.success_message.format(booking.event)
                )
                ActivityLog.objects.create(
                    log='Booking id {} for event {}, user {}, was cancelled by user '
                        '{}'.format(
                            booking.id, booking.event, booking.user.username,
                            self.request.user.username
                        )
                )
            else:  # set to no-show
                booking.no_show = True
                booking.save()

                if not booking.event.allow_booking_cancellation:
                    messages.success(
                        self.request,
                        self.success_message.format(booking.event) +
                        ' Please note that this booking is not eligible for refunds '
                        'or transfer credit.'
                    )
                    ActivityLog.objects.create(
                        log='Booking id {} for NON-CANCELLABLE event {}, user {}, '
                            'was cancelled and set to no-show'.format(
                                booking.id, booking.event, booking.user.username,
                                self.request.user.username
                            )
                    )
                else:
                    messages.success(
                        self.request,
                        self.success_message.format(booking.event) +
                        ' Please note that this booking is not eligible for '
                        'refunds or transfer credit as the allowed '
                        'cancellation period has passed.'
                    )
                    ActivityLog.objects.create(
                        log='Booking id {} for event {}, user {}, was cancelled '
                            'after the cancellation period and set to '
                            'no-show'.format(
                                booking.id, booking.event, booking.user.username,
                                self.request.user.username
                            )
                    )

        # if applicable, email users on waiting list
        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__, "DeleteBookingView - waiting list email")
                    messages.error(self.request, "An error occured, please contact "
                        "the studio for information")

        return HttpResponseRedirect(self.get_success_url())
Example #18
0
    def handle(self, *args, **options):

        inputfilepath = options.get('file')

        with open(inputfilepath, 'r') as file:
            reader = csv.reader(file)
            fail_count = 0
            for i, row in enumerate(reader):
                if i == 0:  # header row
                    pass
                else:
                    name = row[0]
                    first_name = name.split()[0]
                    username1 = row[1]
                    email1 = row[2]
                    email1_used = True if row[3].lower() == 'y' else False
                    email1_is_fb = True if row[6].lower() == 'y' else False
                    username2 = row[7]
                    email2 = row[8]
                    email2_used = True if row[9].lower() == 'y' else False
                    email2_is_fb = True if row[12].lower() == 'y' else False
                    username3 = row[13] if row[13] else None
                    email3 = row[14] if row[14] else None
                    email3_used = True if row[15].lower() == 'y' else False
                    email3_is_fb = True if row[18].lower() == 'y' else False

                    emails = [
                        em for em in [email1, email2, email3] if em is not None
                    ]

                    email_used = None
                    num_used = sum([email1_used, email2_used, email3_used])
                    if num_used == 1:  # only include email_used if one
                        # and only one used
                        email_used = [
                            em[0]
                            for em in [(email1,
                                        email1_used), (
                                            email2,
                                            email2_used), (email3,
                                                           email3_used)]
                            if em[1] is True
                        ][0]

                    ctx = {
                        'first_name': first_name,
                        'username1': username1,
                        'email1': email1,
                        'email1_is_fb': email1_is_fb,
                        'username2': username2,
                        'email2': email2,
                        'email2_is_fb': email2_is_fb,
                        'username3': username3,
                        'email3': email3,
                        'email3_is_fb': email3_is_fb,
                        'email_count': 3 if username3 else 2,
                        'more_than_1_used': True if num_used > 1 else False,
                        'email_used': email_used
                    }

                    # send email
                    try:
                        email_msg = EmailMessage(
                            '{} Duplicate accounts on booking system'.format(
                                settings.ACCOUNT_EMAIL_SUBJECT_PREFIX, ),
                            get_template('account/email/duplicate_account.txt'
                                         ).render(ctx),
                            from_email=settings.DEFAULT_FROM_EMAIL,
                            to=emails,
                            reply_to=[settings.SUPPORT_EMAIL])
                        email_msg.send()
                    except Exception as e:
                        fail_count += 1
                        # send mail to tech support with Exception
                        send_support_email(e, __name__,
                                           "Duplicate account emails")

            self.stdout.write('Emails sent for {} accounts'.format(i -
                                                                   fail_count))
            self.stdout.write('{} failed sends'.format(fail_count))
Example #19
0
    def form_valid(self, form):
        booking = form.save(commit=False)
        try:
            # We shouldn't even get here with a booking that isn't either
            # cancelled or no_show; those get redirected in the dispatch()
            existing_booking = Booking.objects.get(
                user=self.request.user,
                event=booking.event,
                )
            booking = existing_booking
            if booking.status == 'CANCELLED':
                previously_cancelled = True
                previously_no_show = False
            elif booking.no_show:
                previously_no_show = True
                previously_cancelled = False
            booking.status = 'OPEN'
            booking.no_show = False
        except Booking.DoesNotExist:
            previously_cancelled = False
            previously_no_show = False

        booking.user = self.request.user
        transaction_id = None
        invoice_id = None
        previously_cancelled_and_direct_paid = False

        if "claim_free" in form.data:
            _email_free_class_request(
                self.request, booking,
                'rebook' if previously_cancelled else 'create'
            )

        elif previously_cancelled and booking.paid:
            previously_cancelled_and_direct_paid = True
            pptrans = PaypalBookingTransaction.objects.filter(booking=booking)\
                .exclude(transaction_id__isnull=True)
            if pptrans:
                transaction_id = pptrans[0].transaction_id
                invoice_id = pptrans[0].invoice_id

        elif previously_no_show and booking.paid:
            # leave paid no_show booking with existing payment method
            pass

        elif 'block_book' in form.data:
            active_block = _get_active_user_block(self.request.user, booking)
            if active_block:
                booking.block = active_block
                booking.paid = True
                booking.payment_confirmed = True

        # check for existence of free child block on pre-saved booking
        # note for prev no-shows booked with block, any free child blocks should
        # have already been created.  Rebooking prev no-show doesn;t add a new
        # block booking
        has_free_block_pre_save = False
        if booking.block and booking.block.children.exists():
            has_free_block_pre_save = True

        try:
            booking.save()
            ActivityLog.objects.create(
                log='Booking {} {} for "{}" by user {}'.format(
                    booking.id,
                    'created' if not
                    (previously_cancelled or previously_no_show)
                    else 'rebooked',
                    booking.event, booking.user.username)
            )
        except ValidationError:  # pragma: no cover
            # we shouldn't ever get here, because the dispatch should deal
            # with it
            logger.warning(
                'Validation error, most likely due to duplicate booking '
                'attempt; redirected to duplicate booking page'
            )
            return HttpResponseRedirect(reverse('booking:duplicate_booking',
                                                args=[self.event.slug]))

        # set flag on session so if user clicks "back" after posting the form,
        # we can redirect
        self.request.session['booking_created_{}'.format(booking.id)] = True

        blocks_used, total_blocks = _get_block_status(booking, self.request)

        host = 'http://{}'.format(self.request.META.get('HTTP_HOST'))
        # send email to user
        ctx = {
              'host': host,
              'booking': booking,
              'event': booking.event,
              'date': booking.event.date.strftime('%A %d %B'),
              'time': booking.event.date.strftime('%H:%M'),
              'blocks_used':  blocks_used,
              'total_blocks': total_blocks,
              'prev_cancelled_and_direct_paid':
              previously_cancelled_and_direct_paid,
              'claim_free': True if "claim_free" in form.data else False,
              'ev_type': self.ev_type[:-1]
        }
        try:
            send_mail('{} Booking for {}'.format(
                settings.ACCOUNT_EMAIL_SUBJECT_PREFIX, booking.event.name),
                get_template('booking/email/booking_received.txt').render(ctx),
                settings.DEFAULT_FROM_EMAIL,
                [booking.user.email],
                html_message=get_template(
                    'booking/email/booking_received.html'
                    ).render(ctx),
                fail_silently=False)

        except Exception as e:
            # send mail to tech support with Exception
            send_support_email(e, __name__, "BookingCreateView")
            messages.error(self.request, "An error occured, please contact "
                "the studio for information")
        # send email to studio if flagged for the event or if previously
        # cancelled and direct paid
        if (booking.event.email_studio_when_booked or
                previously_cancelled_and_direct_paid):
            additional_subject = ""
            if previously_cancelled_and_direct_paid:
                additional_subject = "ACTION REQUIRED!"
            try:
                send_mail('{} {} {} {} has just booked for {}'.format(
                    settings.ACCOUNT_EMAIL_SUBJECT_PREFIX, additional_subject,
                    booking.user.first_name, booking.user.last_name, booking.event.name),
                          get_template(
                            'booking/email/to_studio_booking.txt'
                            ).render(
                              {
                                  'host': host,
                                  'booking': booking,
                                  'event': booking.event,
                                  'date': booking.event.date.strftime('%A %d %B'),
                                  'time': booking.event.date.strftime('%H:%M'),
                                  'prev_cancelled_and_direct_paid':
                                  previously_cancelled_and_direct_paid,
                                  'transaction_id': transaction_id,
                                  'invoice_id': invoice_id
                              }
                          ),
                          settings.DEFAULT_FROM_EMAIL,
                          [settings.DEFAULT_STUDIO_EMAIL],
                          fail_silently=False)
            except Exception as e:
                # send mail to tech support with Exception
                send_support_email(e, __name__, "BookingCreateView")

        extra_msg = ''
        if 'claim_free' in form.data:
            extra_msg = 'Your place will be secured once your free class ' \
                        'request has been reviewed and approved. '
        elif previously_cancelled_and_direct_paid:
            extra_msg = 'You previously paid for this booking; your booking ' \
                        'will remain as pending until the organiser has ' \
                        'reviewed your payment status.'
        elif previously_no_show:
            if booking.block:
                extra_msg = "You previously paid for this booking with a " \
                            "block and your booking has been reopened."
            elif booking.paid:
                extra_msg = "You previously paid for this booking and your " \
                            "booking has been reopened."
        elif not booking.block:
            if booking.event.cost and not booking.paid:
                # prev no_show could still be paid
                cancellation_warning = ""
                if booking.event.advance_payment_required and \
                        booking.event.allow_booking_cancellation:

                    if booking.event.payment_due_date:
                        cancel_str = "by the payment due date"
                    elif booking.event.payment_time_allowed:
                        cancel_str = "within {} hours".format(
                            booking.event.payment_time_allowed
                        )
                    else:
                        cancel_str = "by the cancellation period"

                    cancellation_warning = "Note that if payment " \
                        "has not been received {}, " \
                        "your booking will be automatically cancelled.".format(
                            cancel_str
                        )
                extra_msg = 'Please make your payment as soon as possible. ' \
                            '<strong>{}</strong>'.format(cancellation_warning)
        elif not booking.block.active_block():
            transfer_block = booking.block.block_type.identifier\
                .startswith('transferred') \
                if booking.block.block_type.identifier else False
            if not transfer_block:
                extra_msg = 'You have just used the last space in your block. '
                if booking.block.children.exists() and not has_free_block_pre_save:
                    extra_msg += '</br><span style="color: #9A2EFE;">' \
                                 '<strong>You have qualified for a extra free ' \
                                 'class which has been added to ' \
                                 '<a href="/blocks">your blocks</a></strong><span>  '
                else:
                    extra_msg += 'Go to <a href="/blocks">Your Blocks</a> to ' \
                                 'buy a new one.'

        messages.success(
            self.request,
            mark_safe("{}<br>{}".format(
                self.success_message.format(booking.event),
                extra_msg))
        )

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

        if not booking.paid and booking.event.cost:
            return HttpResponseRedirect(
                reverse('booking:update_booking', args=[booking.id])
            )
        return HttpResponseRedirect(reverse('booking:bookings'))
    def handle(self, *args, **options):

        inputfilepath = options.get('file')

        with open(inputfilepath, 'r') as file:
            reader = csv.reader(file)
            fail_count = 0
            for i, row in enumerate(reader):
                if i == 0:  # header row
                    pass
                else:
                    name = row[0]
                    first_name = name.split()[0]
                    username1 = row[1]
                    email1 = row[2]
                    email1_used = True if row[3].lower() == 'y' else False
                    email1_is_fb = True if row[6].lower() == 'y' else False
                    username2 = row[7]
                    email2 = row[8]
                    email2_used = True if row[9].lower() == 'y' else False
                    email2_is_fb = True if row[12].lower() == 'y' else False
                    username3 = row[13] if row[13] else None
                    email3 = row[14] if row[14] else None
                    email3_used = True if row[15].lower() == 'y' else False
                    email3_is_fb = True if row[18].lower() == 'y' else False

                    emails = [
                        em for em in [email1, email2, email3]
                        if em is not None
                        ]

                    email_used = None
                    num_used = sum([email1_used, email2_used, email3_used])
                    if num_used == 1:  # only include email_used if one
                        # and only one used
                        email_used = [
                            em[0] for em in [
                                (email1, email1_used),
                                (email2, email2_used),
                                (email3, email3_used)
                            ] if em[1] is True
                            ][0]

                    ctx = {
                        'first_name': first_name,
                        'username1': username1,
                        'email1': email1,
                        'email1_is_fb': email1_is_fb,
                        'username2': username2,
                        'email2': email2,
                        'email2_is_fb': email2_is_fb,
                        'username3': username3,
                        'email3': email3,
                        'email3_is_fb': email3_is_fb,
                        'email_count': 3 if username3 else 2,
                        'more_than_1_used': True if num_used > 1 else False,
                        'email_used': email_used
                    }

                    # send email
                    try:
                        email_msg = EmailMessage(
                            '{} Duplicate accounts on booking system'.format(
                                settings.ACCOUNT_EMAIL_SUBJECT_PREFIX,
                            ),
                            get_template(
                                'account/email/duplicate_account.txt'
                            ).render(ctx),
                            from_email=settings.DEFAULT_FROM_EMAIL,
                            to=emails,
                            reply_to=[settings.SUPPORT_EMAIL]
                            )
                        email_msg.send()
                    except Exception as e:
                        fail_count += 1
                        # send mail to tech support with Exception
                        send_support_email(
                            e, __name__, "Duplicate account emails"
                        )

            self.stdout.write(
                'Emails sent for {} accounts'.format(i - fail_count)
            )
            self.stdout.write('{} failed sends'.format(fail_count))
    def handle(self, *args, **options):

        bookings = []
        for booking in Booking.objects.filter(
                event__date__gte=timezone.now(),
                event__advance_payment_required=True,
                status='OPEN',
                paid=False,
                payment_confirmed=False,
                date_booked__lte=timezone.now() - timedelta(hours=6)):

            # ignore any which have been rebooked in the past 6 hrs
            if booking.date_rebooked and \
                    (booking.date_rebooked >=
                         (timezone.now() - timedelta(hours=6))):
                pass
            elif booking.event.date - timedelta(
                    hours=booking.event.cancellation_period) < timezone.now(
                    ) and booking.warning_sent:
                bookings.append(booking)
            elif booking.event.payment_due_date and booking.warning_sent:
                if booking.event.payment_due_date < timezone.now():
                    bookings.append(booking)
            elif booking.event.payment_time_allowed:
                # if there's a payment time allowed, cancel bookings booked
                # longer ago than this (bookings already filtered out
                # any booked or rebooked within 6 hrs)
                # don't check for warning sent this time
                # for free class requests, always allow them 24 hrs so admin
                # have time to mark classes as free (i.e.paid)
                last_booked_date = booking.date_rebooked \
                        if booking.date_rebooked else booking.date_booked
                if booking.free_class_requested:
                    if last_booked_date < timezone.now() - timedelta(hours=24):
                        bookings.append(booking)
                elif last_booked_date < timezone.now() \
                        - timedelta(hours=booking.event.payment_time_allowed):
                    bookings.append(booking)

        for booking in bookings:
            event_was_full = booking.event.spaces_left == 0

            ctx = {
                'booking': booking,
                'event': booking.event,
                'date': booking.event.date.strftime('%A %d %B'),
                'time': booking.event.date.strftime('%I:%M %p'),
            }
            # send mails to users
            try:
                send_mail(
                    '{} Booking cancelled: {}'.format(
                        settings.ACCOUNT_EMAIL_SUBJECT_PREFIX,
                        booking.event.name),
                    get_template('booking/email/booking_auto_cancelled.txt'
                                 ).render(ctx),
                    settings.DEFAULT_FROM_EMAIL, [booking.user.email],
                    html_message=get_template(
                        'booking/email/booking_auto_cancelled.html').render(
                            ctx),
                    fail_silently=False)
            except Exception as e:
                # send mail to tech support with Exception
                send_support_email(e, __name__,
                                   "Automatic cancel job - cancelled email")
            booking.status = 'CANCELLED'
            booking.block = None
            booking.save()
            ActivityLog.objects.create(
                log='Unpaid booking id {} for event {}, user {} '
                'automatically cancelled'.format(booking.id, booking.event,
                                                 booking.user))
            if event_was_full:
                waiting_list_users = WaitingListUser.objects.filter(
                    event=booking.event)
                try:
                    send_waiting_list_email(
                        booking.event,
                        [user.user for user in waiting_list_users])
                    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__,
                        "Automatic cancel job - waiting list email")

        if bookings:
            if settings.SEND_ALL_STUDIO_EMAILS:
                # send single mail to Studio
                try:
                    send_mail(
                        '{} Booking{} been automatically cancelled'.format(
                            settings.ACCOUNT_EMAIL_SUBJECT_PREFIX,
                            ' has' if len(bookings) == 1 else 's have'),
                        get_template(
                            'booking/email/booking_auto_cancelled_studio_email.txt'
                        ).render({'bookings': bookings}),
                        settings.DEFAULT_FROM_EMAIL,
                        [settings.DEFAULT_STUDIO_EMAIL],
                        html_message=get_template(
                            'booking/email/booking_auto_cancelled_studio_email.html'
                        ).render({'bookings': bookings}),
                        fail_silently=False)
                    self.stdout.write(
                        'Cancellation emails sent for booking ids {}'.format(
                            ', '.join(
                                [str(booking.id) for booking in bookings])))
                except Exception as e:
                    # send mail to tech support with Exception
                    send_support_email(e, __name__,
                                       "Automatic cancel job - studio email")
        else:
            self.stdout.write('No bookings to cancel')
Example #22
0
def cancel_ticketed_event_view(request, slug):
    ticketed_event = get_object_or_404(TicketedEvent, slug=slug)

    open_paid_ticket_bookings = [
        booking for booking in ticketed_event.ticket_bookings.all()
        if not booking.cancelled and booking.purchase_confirmed and
        booking.tickets.exists() and booking.paid
        ]

    open_unpaid_ticket_bookings = [
        booking for booking in ticketed_event.ticket_bookings.all()
        if not booking.cancelled and booking.purchase_confirmed and
        booking.tickets.exists()
        and not booking.paid
        ]

    unconfirmed_ticket_bookings = TicketBooking.objects.filter(
        ticketed_event=ticketed_event, purchase_confirmed=False
    )

    if request.method == 'POST':
        if 'confirm' in request.POST:

            host = 'http://{}'.format(request.META.get('HTTP_HOST'))

            for booking in open_paid_ticket_bookings + \
                    open_unpaid_ticket_bookings:
                booking.cancelled = True
                booking.save()

                try:
                    # send notification email to user to all ticket booking,
                    # paid or unpaid
                    ctx = {
                          'host': host,
                          'ticketed_event': ticketed_event,
                          'ticket_booking': booking,
                    }
                    send_mail('{} {} has been cancelled'.format(
                        settings.ACCOUNT_EMAIL_SUBJECT_PREFIX,
                        ticketed_event.name,
                        ),
                        get_template(
                            'studioadmin/email/ticketed_event_cancelled.txt'
                        ).render(ctx),
                        settings.DEFAULT_FROM_EMAIL,
                        [booking.user.email],
                        html_message=get_template(
                            'studioadmin/email/ticketed_event_cancelled.html'
                            ).render(ctx),
                        fail_silently=False)
                except Exception as e:
                    # send mail to tech support with Exception
                    send_support_email(
                        e, __name__, "cancel ticketed event - "
                        "send notification email to user"
                    )
            for booking in unconfirmed_ticket_bookings:
                booking.delete()

            ticketed_event.cancelled = True
            ticketed_event.show_on_site = False
            ticketed_event.payment_open = False
            ticketed_event.save()

            if open_paid_ticket_bookings:
                # email studio with links for confirming refunds for paid only

                try:
                    # send email to studio
                    ctx = {
                          'host': host,
                          'open_paid_ticket_bookings': open_paid_ticket_bookings,
                          'ticketed_event': ticketed_event,
                    }
                    send_mail('{} Refunds due for ticket bookings for '
                              'cancelled event {}'.format(
                        settings.ACCOUNT_EMAIL_SUBJECT_PREFIX,
                        ticketed_event.name,
                        ),
                        get_template(
                            'studioadmin/email/to_studio_ticketed_event_cancelled.txt'
                        ).render(ctx),
                        settings.DEFAULT_FROM_EMAIL,
                        [settings.DEFAULT_STUDIO_EMAIL],
                        html_message=get_template(
                            'studioadmin/email/to_studio_ticketed_event_cancelled.html'
                            ).render(ctx),
                        fail_silently=False)
                except Exception as e:
                    # send mail to tech support with Exception
                    send_support_email(
                        e, __name__, "cancel ticketed event - "
                        "send refund notification email to studio"
                    )

            if open_paid_ticket_bookings and open_unpaid_ticket_bookings:
                booking_cancelled_msg = '{} has been cancelled; open ticket ' \
                                        'booking refs {} have been ' \
                                        'cancelled'.format(
                    ticketed_event,
                    ', '.join(['{}'.format(booking.booking_reference) for
                               booking in open_paid_ticket_bookings]
                    )
                )
                messages.info(
                    request,
                    booking_cancelled_msg + 'and notification emails have '
                                            'been sent.'
                )
            else:
                booking_cancelled_msg = '{} has been cancelled; there were ' \
                                        'no open ticket bookings for this ' \
                                        'event'.format(ticketed_event)
                messages.info(request, booking_cancelled_msg)

            ActivityLog.objects.create(
                log="{} cancelled by admin user {}. {}".format(
                    ticketed_event, request.user.username,
                    booking_cancelled_msg
                )
            )

            return HttpResponseRedirect(reverse('studioadmin:ticketed_events'))

        elif 'cancel' in request.POST:
            return HttpResponseRedirect(reverse('studioadmin:ticketed_events'))

    context = {
        'ticketed_event': ticketed_event,
        'open_paid_ticket_bookings': open_paid_ticket_bookings,
        'open_unpaid_ticket_bookings': open_unpaid_ticket_bookings,
        'already_cancelled': ticketed_event.cancelled
    }

    return TemplateResponse(
        request, 'studioadmin/cancel_ticketed_event.html', context
    )
Example #23
0
    def post(self, request, *args, **kwargs):
        if 'cancel' in request.POST:
            self.ticket_booking.delete()
            messages.info(
                request,
                'Ticket booking for {} has been cancelled.'.format(
                    self.ticketed_event
                )
            )
            return HttpResponseRedirect(reverse('booking:ticketed_events'))

        context = self.get_context_data()
        ticket_purchase_form = context['ticket_purchase_form']
        ticket_formset = context['ticket_formset']

        if ticket_purchase_form.has_changed():
            # tickets on current booking are only included in the tickets_left
            # calculation if purchase has been confirmed
            old_tickets = self.ticket_booking.tickets.all()
            old_ticket_count = old_tickets.count()

            if self.ticket_booking.purchase_confirmed:
                tickets_left_excl_this = self.ticketed_event.tickets_left() \
                                            + old_ticket_count
            else:
                tickets_left_excl_this = self.ticketed_event.tickets_left()

            new_quantity = int(request.POST.get('ticket_purchase_form-quantity'))

            if new_quantity > tickets_left_excl_this:
                messages.error(
                    request, 'Cannot purchase the number of tickets requested.  '
                             'Only {} tickets left.'.format(
                        self.ticketed_event.tickets_left()
                    )
                )
            else:
                # create the correct number of tickets on this booking
                if old_ticket_count < new_quantity:
                    for i in range(new_quantity-old_ticket_count):
                        Ticket.objects.create(ticket_booking=self.ticket_booking)
                if old_ticket_count > new_quantity:
                    for ticket in old_tickets[new_quantity:]:
                        ticket.delete()

                if old_ticket_count > 0:
                    ActivityLog.objects.create(
                        log="Ticket quantity updated on booking ref {}".format(
                            self.ticket_booking.booking_reference
                            )
                    )

            tickets = self.ticket_booking.tickets.all()
            context['tickets'] = tickets

            return TemplateResponse(request, self.template_name, context)

        if 'ticket_formset-submit' in request.POST:
            if ticket_formset.is_valid():
                ticket_formset.save()

                # we only create the paypal form if there is a ticket cost and
                # online payments are open
                if self.ticketed_event.ticket_cost and \
                        self.ticketed_event.payment_open:
                    invoice_id = create_ticket_booking_paypal_transaction(
                        self.request.user, self.ticket_booking
                    ).invoice_id
                    host = 'http://{}'.format(self.request.META.get('HTTP_HOST')
                                                      )
                    paypal_form = PayPalPaymentsUpdateForm(
                        initial=context_helpers.get_paypal_dict(
                            host,
                            self.ticketed_event.ticket_cost,
                            self.ticketed_event,
                            invoice_id,
                            '{} {}'.format('ticket_booking', self.ticket_booking.id),
                            paypal_email=self.ticketed_event.paypal_email,
                            quantity=self.ticket_booking.tickets.count()
                        )
                    )
                    context["paypalform"] = paypal_form
                self.ticket_booking.purchase_confirmed = True
                # reset the ticket_booking booked date to the date user confirms
                context['purchase_confirmed'] = True
                self.ticket_booking.date_booked = timezone.now()
                self.ticket_booking.save()
                ActivityLog.objects.create(
                    log="Ticket Purchase confirmed: event {}, user {}, "
                        "booking ref {}".format(
                            self.ticketed_event.name, request.user.username,
                            self.ticket_booking.booking_reference
                        )
                )

                host = 'http://{}'.format(request.META.get('HTTP_HOST'))
                ctx = {
                      'host': host,
                      'ticketed_event': self.ticketed_event,
                      'ticket_booking': self.ticket_booking,
                      'ticket_count': self.ticket_booking.tickets.count(),
                      'user': request.user,
                }

                try:
                    # send notification email to user
                    send_mail('{} Ticket booking confirmed for {}: ref {}'.format(
                            settings.ACCOUNT_EMAIL_SUBJECT_PREFIX,
                            self.ticketed_event,
                            self.ticket_booking.booking_reference,

                        ),
                        get_template(
                            'booking/email/ticket_booking_made.txt'
                        ).render(ctx),
                        settings.DEFAULT_FROM_EMAIL,
                        [request.user.email],
                        html_message=get_template(
                            'booking/email/ticket_booking_made.html'
                            ).render(ctx),
                        fail_silently=False)
                except Exception as e:
                    # send mail to tech support with Exception
                    send_support_email(
                        e, __name__, "ticket booking created - "
                        "send email to user"
                    )

                if self.ticketed_event.email_studio_when_purchased:
                    try:
                        send_mail('{} Ticket booking confirmed for {}: ref {}'.format(
                                settings.ACCOUNT_EMAIL_SUBJECT_PREFIX,
                                self.ticketed_event,
                                self.ticket_booking.booking_reference,
                            ),
                            get_template(
                                'booking/email/to_studio_ticket_booking_made.txt'
                            ).render(ctx),
                            settings.DEFAULT_FROM_EMAIL,
                            [settings.DEFAULT_STUDIO_EMAIL],
                            html_message=get_template(
                                'booking/email/to_studio_ticket_booking_made.html'
                                ).render(ctx),
                            fail_silently=False)
                    except Exception as e:
                        # send mail to tech support with Exception
                        send_support_email(
                            e, __name__, "ticket booking created - "
                            "send email to studio"
                        )
            else:
                messages.error(
                    request, "Please correct errors in the form below"
                )

            tickets = self.ticket_booking.tickets.all()
            context['tickets'] = tickets
            ticket_purchase_form = TicketPurchaseForm(
                prefix='ticket_purchase_form',
                ticketed_event=self.ticketed_event,
                ticket_booking=self.ticket_booking,
                initial={'quantity': self.ticket_booking.tickets.count()}
            )
            context["ticket_purchase_form"] = ticket_purchase_form
            return TemplateResponse(request, self.template_name, context)