def _process_block_confirmation_email(request, user, form, block, action): 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, 'block': block, 'user': user, 'action': action, } send_mail('{} block {} has been {}'.format( settings.ACCOUNT_EMAIL_SUBJECT_PREFIX, block.name, action ), get_template( 'studioadmin/email/block_change_confirmation.txt' ).render(ctx), settings.DEFAULT_FROM_EMAIL, [user.email], html_message=get_template( 'studioadmin/email/block_change_confirmation.html' ).render(ctx), fail_silently=False) except Exception as e: # send mail to tech support with Exception send_support_email( e, __name__, "block_bookings_list - " "send confirmation email" )
def _process_confirmation_email(request, form, booking, action): 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, } 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 ) )
def update_block(request, pk): block = get_object_or_404(Block, id=pk) user = request.user user_bookings = [ bk for bk in block.bookings.all() if bk.user == user and bk.status == 'OPEN' ] for booking in user_bookings: # mark all the user's bookings for this block as paid; # payment_confirmed will be done by the organiser booking.paid = True booking.save() # send email to studio host = 'http://{}'.format(request.META.get('HTTP_HOST')) ctx = { 'host': host, 'user': request.user, 'block_obj': block } try: send_mail('{} Payment confirmed for {} by {} {}'.format( settings.ACCOUNT_EMAIL_SUBJECT_PREFIX, block.name, request.user.first_name, request.user.last_name ), get_template( 'flex_bookings/email/to_studio_payment_confirmed.txt' ).render(ctx), 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__, "update_block - email to studio") messages.success( request, "Thank you for confirming you have made Payment for " "block {}. The studio has been informed and your space " "will be secured for the relevant classes once payment has " "been reviewed and confirmed.".format(block) ) return HttpResponseRedirect(reverse('flexbookings:bookings'))
def _process_waiting_list(booking, request): 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__, "Automatic cancel job - waiting list email" )
def update_booking(request, pk): booking = get_object_or_404(Booking, id=pk) booking.paid = True booking.save() messages.success( request, "Thank you for confirming you have made Payment for " "{}. The studio has been informed and your space " "will be secured once payment has " "been reviewed and confirmed.".format(booking.event) ) # send email to studio host = 'http://{}'.format(request.META.get('HTTP_HOST')) ctx = { 'host': host, 'user': request.user, 'booking': booking } try: send_mail('{} Payment confirmed for {} by {} {}'.format( settings.ACCOUNT_EMAIL_SUBJECT_PREFIX, booking.event, request.user.first_name, request.user.last_name ), get_template( 'flex_bookings/email/to_studio_payment_confirmed.txt' ).render(ctx), 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__, "update_booking - email to studio") return HttpResponseRedirect(reverse('flexbookings:bookings'))
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, warning_sent=True, date_booked__lte=timezone.now() - timedelta(hours=4)): if booking.event.date - timedelta( hours=booking.event.cancellation_period ) < timezone.now(): bookings.append(booking) elif booking.event.payment_due_date: if booking.event.payment_due_date < timezone.now(): 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( 'flex_bookings/email/booking_auto_cancelled.txt' ).render(ctx), settings.DEFAULT_FROM_EMAIL, [booking.user.email], html_message=get_template( 'flex_bookings/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.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: # send single mail to Studio send_mail('{} Booking{} been automatically cancelled'.format( settings.ACCOUNT_EMAIL_SUBJECT_PREFIX, ' has' if len(bookings) == 1 else 's have'), get_template( 'flex_bookings/email/booking_auto_cancelled_studio_email.txt' ).render({'bookings': bookings}), settings.DEFAULT_FROM_EMAIL, [settings.DEFAULT_STUDIO_EMAIL], html_message=get_template( 'flex_bookings/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]) ) ) else: self.stdout.write('No bookings to cancel') ActivityLog.objects.create( log='cancel_unpaid_bookings job run; no bookings to cancel' )
def delete(self, request, *args, **kwargs): booking = self.get_object() block = booking.block if 'cancel_block' in request.POST: cancel_type = 'block' bookings = [ bk for bk in request.user.bookings.all() if bk.block == block and bk.event.date > timezone.now() and booking.status == 'OPEN' ] else: cancel_type = 'single' bookings = [booking] for booking in bookings: event_was_full = booking.event.spaces_left() == 0 booking.status = 'CANCELLED' # set block back to None. If user decides to rebook later, they # can either rebook the entire block if it hasn't started yet, or # book single class at the individual rate booking.block = None # set payment confirmed to False but leave paid unchanged; email # will be sent to studio to confirm refunded and mark as unpaid booking.payment_confirmed = False booking.save() # 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") # messages # logs if cancel_type == 'single': ActivityLog.objects.create( log='Booking id {} for event {}, user {}, was ' 'cancelled'.format( bookings[0].id, bookings[0].event, request.user.username ) ) messages.success( self.request, mark_safe(self.success_message.format(bookings[0].event)) ) else: ActivityLog.objects.create( log='User {} cancelled bookings from block {}: Booking ' 'ids {}'.format( request.user.username, block.name, ', '.join(['{} ({})'.format(booking.id, booking.event) for booking in bookings]) ) ) messages.success( self.request, mark_safe(self.success_message.format( '</br>'.join(['{}'.format(booking.event) for booking in bookings]) ) ) ) # send emails host = 'http://{}'.format(self.request.META.get('HTTP_HOST')) # send email to user ctx = { 'host': host, 'bookings': bookings, 'block_obj': block, 'user': request.user, 'contact_person': bookings[0].event.contact_person, 'contact_email': bookings[0].event.contact_email, } subject = "Block {} cancelled".format(block.name) \ if cancel_type == 'block' \ else "Booking for {} cancelled".format(bookings[0].event) try: send_mail('{} {}'.format( settings.ACCOUNT_EMAIL_SUBJECT_PREFIX, subject), get_template('flex_bookings/email/booking_cancelled.txt').render(ctx), settings.DEFAULT_FROM_EMAIL, [booking.user.email], html_message=get_template( 'flex_bookings/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") try: subject = "block {}".format(block) if cancel_type == 'block' else \ "a booking for {}".format(bookings[0].event) # send email to studio send_mail('{} {} {} has just cancelled {}'.format( settings.ACCOUNT_EMAIL_SUBJECT_PREFIX, 'ACTION REQUIRED!' if not block else '', request.user.username, subject), get_template( 'flex_bookings/email/to_studio_booking_cancelled.txt' ).render(ctx), 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__, "DeleteBookingView - cancelled email to studio" ) return HttpResponseRedirect(self.get_success_url())
def form_valid(self, form): booking = form.save(commit=False) open_user_booked_events = [ bk.event for bk in self.request.user.bookings.all() if bk.status == 'OPEN' ] if booking.event in open_user_booked_events: messages.info( self.request, 'Already booked for {}'.format(booking.event) ) return HttpResponseRedirect(reverse('flexbookings:lessons')) if 'book_block' in self.request.POST: block_id = int(self.request.POST['book_block']) block = Block.objects.get(id=block_id) # check that the user is not already booked into any of these events for event in block.events.all(): if event in open_user_booked_events: messages.error( self.request, 'You cannot book this block as you already have ' 'a booking for one or more classes in the block') return HttpResponseRedirect(reverse('flexbookings:lessons')) else: try: booking = Booking.objects.get( event=event, user=self.request.user, status='CANCELLED' ) # reopen booking booking.status = 'OPEN' booking.block = block cost=block.item_cost booking.save() except Booking.DoesNotExist: Booking.objects.create( event=event, block=block, user=self.request.user, cost=block.item_cost ) messages.success( self.request, mark_safe( 'You have been booked in to the following classes:</br>' '{}'.format('</br>'.join([str(event) for event in block.events.all()])) ) ) host = 'http://{}'.format(self.request.META.get('HTTP_HOST')) # send email to user ctx = { 'host': host, 'block_obj': block, 'block_name': block.name, 'block_events': block.events.all(), 'user': self.request.user } try: send_mail('{} Booking for {}'.format( settings.ACCOUNT_EMAIL_SUBJECT_PREFIX, block.name), get_template('flex_bookings/email/booking_received.txt').render(ctx), settings.DEFAULT_FROM_EMAIL, [self.request.user.email], html_message=get_template( 'flex_bookings/email/booking_received.html' ).render(ctx), fail_silently=False) ActivityLog.objects.create( log='Email sent to user {} regarding booking for ' 'block {}'.format( self.request.user.username, block.name ) ) except Exception as e: # send mail to tech support with Exception send_support_email(e, __name__, "BookingCreateView") try: send_mail('{} {} {} has just booked block {}'.format( settings.ACCOUNT_EMAIL_SUBJECT_PREFIX, self.request.user.first_name, self.request.user.last_name, block.name), get_template( 'flex_bookings/email/to_studio_booking.txt' ).render(ctx), settings.DEFAULT_FROM_EMAIL, [settings.DEFAULT_STUDIO_EMAIL], fail_silently=False) ActivityLog.objects.create( log='Email sent to studio ({}) regarding booking for ' 'block {} (for {})'.format( settings.DEFAULT_STUDIO_EMAIL, block.name, self.request.user.username, ) ) except Exception as e: # send mail to tech support with Exception send_support_email( e, __name__, "BookingCreateView - sending studio email" ) return HttpResponseRedirect(reverse('flexbookings:payments_pending')) else: try: cancelled_booking = Booking.objects.get( user=self.request.user, event=booking.event, status='CANCELLED' ) booking = cancelled_booking booking.status = 'OPEN' previously_cancelled = True except Booking.DoesNotExist: previously_cancelled = False # transaction_id = None # invoice_id = None # # if previously_cancelled and booking.paid: # 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 booking.user = self.request.user booking.cost = booking.event.cost try: booking.save() ActivityLog.objects.create( log='Booking {} {} for "{}" by user {}'.format( booking.id, 'created' if not previously_cancelled else 'rebooked', booking.event, booking.user.username) ) except IntegrityError: logger.warning( 'Integrity error; redirected to duplicate booking page' ) return HttpResponseRedirect(reverse('flexbookings:duplicate_booking', args=[self.event.slug])) except BookingError: return HttpResponseRedirect(reverse('flexbookings:fully_booked', args=[self.event.slug])) 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'), 'prev_cancelled_and_direct_paid': previously_cancelled and booking.paid, 'ev_type': 'workshop' if self.event.event_type.event_type == 'EV' else 'class' } try: send_mail('{} Booking for {}'.format( settings.ACCOUNT_EMAIL_SUBJECT_PREFIX, booking.event.name), get_template('flex_bookings/email/booking_received.txt').render(ctx), settings.DEFAULT_FROM_EMAIL, [booking.user.email], html_message=get_template( 'flex_bookings/email/booking_received.html' ).render(ctx), fail_silently=False) ActivityLog.objects.create( log='Email sent to user {} regarding {}booking id {} ' '(for {})'.format( booking.user.username, 're' if previously_cancelled else '', booking.id, booking.event ) ) except Exception as e: # send mail to tech support with Exception send_support_email(e, __name__, "BookingCreateView") # 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 booking.paid): additional_subject = "" if previously_cancelled and booking.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( 'flex_bookings/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 booking.paid, # 'transaction_id': transaction_id, # 'invoice_id': invoice_id } ), settings.DEFAULT_FROM_EMAIL, [settings.DEFAULT_STUDIO_EMAIL], fail_silently=False) ActivityLog.objects.create( log = 'Email sent to studio ({}) regarding {}booking id {} ' '(for {})'.format( settings.DEFAULT_STUDIO_EMAIL, 're' if previously_cancelled else '', booking.id, booking.event ) ) except Exception as e: # send mail to tech support with Exception send_support_email(e, __name__, "BookingCreateView - sending studio email") messages.success( self.request, self.success_message.format(booking.event) ) if previously_cancelled and booking.paid: messages.info( self.request, 'You previously paid for this booking; your ' 'booking will remain as pending until the ' 'organiser has reviewed your payment status.' ) 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 "book_one_off" in form.data and booking.event.cost > 0: return HttpResponseRedirect( reverse('flexbookings:payments_pending') ) return HttpResponseRedirect(reverse('flexbookings:bookings'))