def availableDurations(self): ''' A lesson can always be booked for the length of a single slot, but this method checks if multiple slots are available. This method requires that slots are non-overlapping, which needs to be enforced on slot save. ''' potential_slots = InstructorAvailabilitySlot.objects.filter( instructor=self.instructor, location=self.location, room=self.room, pricingTier=self.pricingTier, startTime__gte=self.startTime, startTime__lte=self.startTime + timedelta(minutes=getConstant('privateLessons__maximumLessonLength')), ).exclude(id=self.id).order_by('startTime') duration_list = [self.duration,] last_start = self.startTime last_duration = self.duration max_duration = self.duration for slot in potential_slots: if max_duration + slot.duration > getConstant('privateLessons__maximumLessonLength'): break if ( slot.startTime == last_start + timedelta(minutes=last_duration) and slot.isAvailable ): duration_list.append(max_duration + slot.duration) last_start = slot.startTime last_duration = slot.duration max_duration += slot.duration return duration_list
def createReferrerVoucher(customer): voucherId = generateUniqueVoucherId( getConstant('referrals__voucherPrefix')) category = getConstant('referrals__referrerCategory') originalAmount = 0 maxAmountPerUse = None singleUse = False forFirstTimeCustomersOnly = False expirationDate = None disabled = False name = _("Referral Bonus for %s, %s" % (customer.fullName, customer.email)) voucher = Voucher(voucherId=voucherId, name=name, category=category, originalAmount=originalAmount, maxAmountPerUse=maxAmountPerUse, singleUse=singleUse, forFirstTimeCustomersOnly=forFirstTimeCustomersOnly, expirationDate=expirationDate, disabled=disabled) voucher.save() cv = CustomerVoucher(customer=customer, voucher=voucher) cv.save() return voucher
def createReferrerVoucher(customer): voucherId = generateUniqueVoucherId(getConstant('referrals__voucherPrefix')) category = getConstant('referrals__referrerCategory') originalAmount = 0 maxAmountPerUse = None singleUse = False forFirstTimeCustomersOnly = False expirationDate = None disabled = False name = _("Referral Bonus for %s, %s" % (customer.fullName,customer.email)) voucher = Voucher( voucherId=voucherId,name=name, category=category, originalAmount=originalAmount, maxAmountPerUse=maxAmountPerUse, singleUse=singleUse, forFirstTimeCustomersOnly=forFirstTimeCustomersOnly, expirationDate=expirationDate, disabled=disabled ) voucher.save() cv = CustomerVoucher(customer=customer,voucher=voucher) cv.save() return voucher
def createReferreeVoucher(name, amountPerUse): voucherId = generateUniqueVoucherId( getConstant('referrals__voucherPrefix')) category = getConstant('referrals__refereeCategory') originalAmount = 1e9 maxAmountPerUse = amountPerUse singleUse = False forFirstTimeCustomersOnly = True expirationDate = None disabled = False voucher = Voucher(voucherId=voucherId, name=name, category=category, originalAmount=originalAmount, maxAmountPerUse=maxAmountPerUse, singleUse=singleUse, forFirstTimeCustomersOnly=forFirstTimeCustomersOnly, expirationDate=expirationDate, disabled=disabled) voucher.save() # Find all beginner classes dts = DanceTypeLevel.objects.filter(name="Beginner", danceType__name="Lindy Hop") classes = ClassDescription.objects.filter(danceTypeLevel=dts.first()) for c in classes: cv = ClassVoucher(voucher=voucher, classDescription=c) cv.save() return voucher
def ensureReferralVouchersExist(customer): # is there a referral voucher for this person? # Find all CustomerVouchers for this person vrd = referralVoucherExists(customer) referreeDiscount = getConstant('referrals__refereeDiscount') referrerDiscount = getConstant('referrals__referrerDiscount') if vrd: vrd.amount = referrerDiscount vrd.save() vrd.referreeVoucher.maxAmountPerUse = referreeDiscount vrd.referreeVoucher.save() else: name = _('Referral: %s' % customer.fullName) # create the referree voucher referreeVoucher = createReferreeVoucher(name, referreeDiscount) # create the referrer voucher referrerVoucher = createReferrerVoucher(customer) # create the thing that ties them together vrd = VoucherReferralDiscount.objects.get_or_create( referrerVoucher=referrerVoucher, referreeVoucher=referreeVoucher, referrerBonus=referrerDiscount) return vrd
def createReferreeVoucher(name,amountPerUse): voucherId = generateUniqueVoucherId(getConstant('referrals__voucherPrefix')) category = getConstant('referrals__refereeCategory') originalAmount = 1e9 maxAmountPerUse = amountPerUse singleUse = False forFirstTimeCustomersOnly = True expirationDate = None disabled = False voucher = Voucher( voucherId=voucherId,name=name, category=category, originalAmount=originalAmount, maxAmountPerUse=maxAmountPerUse, singleUse=singleUse, forFirstTimeCustomersOnly=forFirstTimeCustomersOnly, expirationDate=expirationDate, disabled=disabled ) voucher.save() # Find all beginner classes dts = DanceTypeLevel.objects.filter(name="Beginner",danceType__name="Lindy Hop") classes = ClassDescription.objects.filter(danceTypeLevel=dts.first()) for c in classes: cv = ClassVoucher(voucher=voucher,classDescription=c) cv.save() return voucher
def availableDurations(self): ''' A lesson can always be booked for the length of a single slot, but this method checks if multiple slots are available. This method requires that slots are non-overlapping, which needs to be enforced on slot save. ''' potential_slots = InstructorAvailabilitySlot.objects.filter( instructor=self.instructor, location=self.location, room=self.room, pricingTier=self.pricingTier, startTime__gte=self.startTime, startTime__lte=self.startTime + timedelta( minutes=getConstant('privateLessons__maximumLessonLength')), ).exclude(id=self.id).order_by('startTime') duration_list = [ self.duration, ] last_start = self.startTime last_duration = self.duration max_duration = self.duration for slot in potential_slots: if max_duration + slot.duration > getConstant( 'privateLessons__maximumLessonLength'): break if (slot.startTime == last_start + timedelta(minutes=last_duration) and slot.isAvailable): duration_list.append(max_duration + slot.duration) last_start = slot.startTime last_duration = slot.duration max_duration += slot.duration return duration_list
def revenueMismatch(self): comparison = self.revenueReported + self.revenueRefundsReported if not getConstant('registration__buyerPaysProcessingFees'): comparison += self.feesReported if not getConstant('registration__buyerPaysSalesTax'): comparison += self.taxesReported return round(self.total, 2) != round(comparison, 2)
def title(self, obj): if not obj: return _('%s Events Calendar' % getConstant('contact__businessName')) else: this_instructor = self.get_member(obj) return _('%s Staff Calendar for %s' % (getConstant('contact__businessName'), this_instructor.fullName))
def provideCustomerReferralCode(sender, **kwargs): ''' If the vouchers app is installed and referrals are enabled, then the customer's profile page can show their voucher referral code. ''' customer = kwargs.pop('customer') if getConstant('vouchers__enableVouchers') and getConstant( 'referrals__enableReferralProgram'): vrd = ensureReferralVouchersExist(customer) return {'referralVoucherId': vrd.referreeVoucher.voucherId}
def __str__(self): if self.accrualDate: return '%s %s: %s = %s%s' % ( self.category.name, self.accrualDate.strftime('%B %Y'), self.description, getConstant('general__currencySymbol'), self.total) else: return '%s: %s = %s%s' % (self.category.name, self.description, getConstant('general__currencySymbol'), self.total)
def provideCustomerReferralCode(sender,**kwargs): ''' If the vouchers app is installed and referrals are enabled, then the customer's profile page can show their voucher referral code. ''' customer = kwargs.pop('customer') if getConstant('vouchers__enableVouchers') and getConstant('referrals__enableReferralProgram'): vrd = ensureReferralVouchersExist(customer) return { 'referralVoucherId': vrd.referreeVoucher.voucherId }
def render(self, context, instance, placeholder): ''' Add the cart-specific context to this form ''' context = super(StripePaymentFormPlugin, self).render(context, instance, placeholder) context.update({ 'stripe_key': getattr(settings,'STRIPE_PUBLIC_KEY',''), 'business_name': getConstant('contact__businessName'), 'currencyCode': getConstant('general__currencyCode'), }) return context
def render(self, context, instance, placeholder): ''' Create a UUID and check if a voucher with that ID exists before rendering ''' context = super(StripeGiftCertificateFormPlugin, self).render(context, instance, placeholder) context.update({ 'stripe_key': getattr(settings,'STRIPE_PUBLIC_KEY',''), 'business_name': getConstant('contact__businessName'), 'currencyCode': getConstant('general__currencyCode'), }) return context
def checkRequirements(sender,**kwargs): ''' Check that the customer meets all prerequisites for the items in the registration. ''' if not getConstant('requirements__enableRequirements'): return logger.debug('Signal to check RegistrationContactForm handled by prerequisites app.') formData = kwargs.get('formData',{}) first = formData.get('firstName') last = formData.get('lastName') email = formData.get('email') request = kwargs.get('request',{}) registration = kwargs.get('registration',None) customer = Customer.objects.filter( first_name=first, last_name=last, email=email).first() requirement_warnings = [] requirement_errors = [] for ter in registration.temporaryeventregistration_set.all(): if hasattr(ter.event,'getRequirements'): for req in ter.event.getRequirements(): if not req.customerMeetsRequirement( customer=customer, danceRole=ter.role ): if req.enforcementMethod == Requirement.EnforcementChoice.error: requirement_errors.append((ter.event.name, req.name)) if req.enforcementMethod == Requirement.EnforcementChoice.warning: requirement_warnings.append((ter.event.name,req.name)) if requirement_errors: raise ValidationError(format_html( '<p>{}</p> <ul>{}</ul> <p>{}</p>', ugettext('Unfortunately, you do not meet the following requirements/prerequisites for the items you have chosen:\n'), mark_safe(''.join(['<li><em>%s:</em> %s</li>\n' % x for x in requirement_errors])), getConstant('requirements__errorMessage') or '', )) if requirement_warnings: messages.warning(request,format_html( '<p>{}</p> <ul>{}</ul> <p>{}</p>', mark_safe(ugettext('<strong>Please Note:</strong> It appears that you do not meet the following requirements/prerequisites for the items you have chosen:\n')), mark_safe(''.join(['<li><em>%s:</em> %s</li>\n' % x for x in requirement_warnings])), getConstant('requirements__warningMessage') or '', ))
def render(self, context, instance, placeholder): ''' Add the cart-specific context to this form ''' context = super(PayAtDoorFormPlugin, self).render(context, instance, placeholder) context.update({ 'business_name': getConstant('contact__businessName'), 'currencyCode': getConstant('general__currencyCode'), 'form': self.get_form(context, instance, placeholder), }) return context
def refund(self, amount=None): saleIds = self.getSaleIds() refundData = [] leftToRefund = amount or 0 for this_id in saleIds: # No need to continue if the full amount requested has been refunded if amount is not None and leftToRefund <= 0: break this_sale = Sale.find(this_id) if amount is not None: this_amount = min(float(this_sale.amount.total), leftToRefund) refund = this_sale.refund({ 'amount': { 'total': '{0:.2f}'.format(this_amount), 'currency': getConstant('general__currencyCode'), } }) else: refund = this_sale.refund() if refund.success(): logger.info('Refund successfully processed.') refundData.append({ 'status': 'success', 'refund_id': refund.id, 'sale_id': refund.sale_id, 'refundAmount': float(refund.amount.total), # This is (annoyingly) hard-coded for now because the Paypal REST API does # not yet report fees in the event of a refund. Hopefully this can be removed # soon. 'fees': -1 * ((float(this_sale.transaction_fee.value) - getConstant('paypal__fixedTransactionFee')) * (float(refund.amount.total) / float(this_sale.amount.total))), }) leftToRefund -= this_amount else: logger.error('Error processing refund.') refundData.append({'status': 'error', 'errors': refund.error}) return refundData
def updateFinancialItems(): ''' Every hour, create any necessary revenue items and expense items for activities that need them. ''' logger.info('Creating automatically-generated financial items.') if getConstant('financial__autoGenerateExpensesCompletedEvents'): createExpenseItemsForCompletedEvents() if getConstant('financial__autoGenerateExpensesVenueRental'): createExpenseItemsForVenueRental() if getConstant('financial__autoGenerateRevenueRegistrations'): createRevenueItemsForRegistrations()
def updateFinancialItems(): ''' Every hour, create any necessary revenue items and expense items for activities that need them. ''' logger.info('Creating automatically-generated financial items.') if getConstant('financial__autoGenerateExpensesEventStaff'): createExpenseItemsForEvents() if getConstant('financial__autoGenerateExpensesVenueRental'): createExpenseItemsForVenueRental() if getConstant('financial__autoGenerateRevenueRegistrations'): createRevenueItemsForRegistrations()
def createRevenueItemsForRegistrations(request=None, datetimeTuple=None): if hasattr(request, 'user'): submissionUser = request.user else: submissionUser = None this_category = getConstant('financial__registrationsRevenueCat') filters_events = { 'revenueitem__isnull': True, 'finalEventRegistration__isnull': False } if datetimeTuple: timelist = list(datetimeTuple) timelist.sort() filters_events[ 'finalEventRegistration__event__eventoccurrence__startTime__gte'] = timelist[ 0] filters_events[ 'finalEventRegistration__event__eventoccurrence__startTime__lte'] = timelist[ 1] else: c = getConstant( 'financial__autoGenerateRevenueRegistrationsWindow') or 0 if c > 0: filters_events[ 'finalEventRegistration__event__eventoccurrence__startTime__gte'] = timezone.now( ) - relativedelta(months=c) for item in InvoiceItem.objects.filter(**filters_events).distinct(): if item.finalRegistration.paidOnline: received = True else: received = False revenue_description = _('Event Registration ') + str( item.finalEventRegistration.id ) + ': ' + item.invoice.finalRegistration.fullName RevenueItem.objects.create(invoiceItem=item, category=this_category, description=revenue_description, submissionUser=submissionUser, grossTotal=item.grossTotal, total=item.total, received=received, receivedDate=item.invoice.modifiedDate)
def checkIfAvailable(self, dateTime=timezone.now()): ''' Available slots are available, but also tentative slots that have been held as tentative past their expiration date ''' return ( self.startTime >= dateTime + timedelta(days=getConstant('privateLessons__closeBookingDays')) and self.startTime <= dateTime + timedelta(days=getConstant('privateLessons__openBookingDays')) and not self.eventRegistration and ( self.status == self.SlotStatus.available or ( self.status == self.SlotStatus.tentative and getattr(getattr(self.temporaryEventRegistration,'registration',None),'expirationDate',timezone.now()) <= timezone.now() ) ) )
def checkIfAvailable(self, dateTime=timezone.now()): ''' Available slots are available, but also tentative slots that have been held as tentative past their expiration date ''' return (self.startTime >= dateTime + timedelta(days=getConstant('privateLessons__closeBookingDays')) and self.startTime <= dateTime + timedelta(days=getConstant('privateLessons__openBookingDays')) and not self.eventRegistration and (self.status == self.SlotStatus.available or (self.status == self.SlotStatus.tentative and getattr( getattr(self.temporaryEventRegistration, 'registration', None), 'expirationDate', timezone.now()) <= timezone.now())))
def sendReminderEmails(): if not getConstant('general__enableCronTasks'): return reminders_needed = EventReminder.objects.filter( **{ 'time__lte': timezone.now(), 'completed': False, 'notifyList__isnull': False }) if reminders_needed: for note in reminders_needed: for user in note.notifyList.all(): sent = sendReminderEmailToUser(user, note) if sent: # Mark reminder as sent so it won't be sent twice. note.completed = True note.save() logger.info("Email notification sent to user: "******"Unable to send email to user: "******"No notifications to send!") pass
def applyReferrerVouchersTemporarily(sender, **kwargs): ''' Unlike voucher codes which have to be manually supplied, referrer discounts are automatically applied here, assuming that the referral program is enabled. ''' # Only continue if the referral program is enabled if not getConstant('referrals__enableReferralProgram'): return logger.debug('Signal fired to temporarily apply referrer vouchers.') regSession = kwargs.pop('data', {}) reg = kwargs.pop('registration') email = regSession.get("email", '') # Email address is unique for users, so use that try: c = Customer.objects.get(user__email=email) vouchers = c.getReferralVouchers() except ObjectDoesNotExist: vouchers = None if not vouchers: logger.debug('No referral vouchers found.') return for v in vouchers: TemporaryVoucherUse(voucher=v, registration=reg, amount=0).save()
def clean(self): ''' Only allow submission if there are not already slots in the submitted window, and only allow rooms associated with the chosen location. ''' super(SlotCreationForm, self).clean() startDate = self.cleaned_data.get('startDate') endDate = self.cleaned_data.get('endDate') startTime = self.cleaned_data.get('startTime') endTime = self.cleaned_data.get('endTime') instructor = self.cleaned_data.get('instructorId') existingSlots = InstructorAvailabilitySlot.objects.filter( instructor=instructor, startTime__gt=( ensure_localtime(datetime.combine(startDate, startTime)) - timedelta(minutes=getConstant( 'privateLessons__lessonLengthInterval'))), startTime__lt=ensure_localtime(datetime.combine(endDate, endTime)), ) if existingSlots.exists(): raise ValidationError(_( 'Newly created slots cannot overlap existing slots for this instructor.' ), code='invalid')
def applyFinalDiscount(sender,**kwargs): # Get the registration and the customer if not getConstant('general__discountsEnabled'): return logger.debug('Signal fired to finalize application of discounts.') reg = kwargs.pop('registration',None) if not reg: logger.debug('No registration passed, discounts not applied.') return trds = TemporaryRegistrationDiscount.objects.filter(registration=reg.temporaryRegistration) obj = None for temp_discount in trds: obj = RegistrationDiscount.objects.create( registration=reg, discount=temp_discount.discount, discountAmount=temp_discount.discountAmount, ) logger.debug('Discounts applied.') return obj
def applyReferrerVouchersTemporarily(sender,**kwargs): ''' Unlike voucher codes which have to be manually supplied, referrer discounts are automatically applied here, assuming that the referral program is enabled. ''' # Only continue if the referral program is enabled if not getConstant('referrals__enableReferralProgram'): return logger.debug('Signal fired to temporarily apply referrer vouchers.') reg = kwargs.pop('registration') # Email address is unique for users, so use that try: c = Customer.objects.get(user__email=reg.email) vouchers = c.getReferralVouchers() except ObjectDoesNotExist: vouchers = None if not vouchers: logger.debug('No referral vouchers found.') return for v in vouchers: TemporaryVoucherUse(voucher=v,registration=reg,amount=0).save()
def updateFinancialItems(): ''' Every hour, create any necessary revenue items and expense items for activities that need them. ''' if not getConstant('general__enableCronTasks'): return logger.info('Creating automatically-generated financial items.') if getConstant('financial__autoGenerateExpensesEventStaff'): createExpenseItemsForEvents() if getConstant('financial__autoGenerateExpensesVenueRental'): createExpenseItemsForVenueRental() if getConstant('financial__autoGenerateRevenueRegistrations'): createRevenueItemsForRegistrations()
def getAddonItems(sender, **kwargs): # Check if this is a new customer if not getConstant('general__discountsEnabled'): return logger.debug('Signal fired to request free add-ons.') reg = kwargs.pop('registration', None) if not reg: logger.warning('No registration passed, addons not applied.') return newCustomer = True customer = Customer.objects.filter(email=reg.email, first_name=reg.firstName, last_name=reg.lastName).first() if (customer and customer.numClassSeries > 0) or sender != RegistrationSummaryView: newCustomer = False # No need to get all objects, just the ones that could qualify one for an add-on cart_object_list = reg.temporaryeventregistration_set.filter( dropIn=False).filter( Q(event__series__pricingTier__isnull=False) | Q(event__publicevent__pricingTier__isnull=False)) availableAddons = getApplicableDiscountCombos(cart_object_list, newCustomer, reg.student, customer=customer, addOn=True, dateTime=reg.dateTime) return [x.code.name for x in availableAddons]
def __init__(self, object, **kwargs): timeZone = pytz.timezone(getattr(settings, 'TIME_ZONE', 'UTC')) if kwargs.get('timeZone', None): try: timeZone = pytz.timezone(kwargs.get('timeZone', None)) except pytz.exceptions.UnknownTimeZoneError: pass self.id = 'privateEvent_' + str(object.event.id) self.type = 'privateEvent' self.id_number = object.event.id self.title = object.event.name self.description = object.event.description if hasattr(object.event, 'category') and object.event.category: self.category = object.event.category.name self.color = object.event.category.displayColor else: self.category = None self.color = getConstant('calendar__defaultEventColor') self.start = timezone.localtime(object.startTime, timeZone) self.end = timezone.localtime(object.endTime, timeZone) self.allDay = object.allDayForDate(object.startTime) if hasattr(object, 'event.location'): self.location = object.event.location.name + '\n' + object.event.location.address + '\n' + object.event.location.city + ', ' + object.event.location.state + ' ' + object.event.location.zip else: self.location = None self.url = reverse('admin:management_privateevent_change', args=([object.event.id]))
def applyFinalDiscount(sender, **kwargs): # Get the registration and the customer if not getConstant('general__discountsEnabled'): return logger.debug('Signal fired to finalize application of discounts.') reg = kwargs.pop('registration', None) if not reg: logger.debug('No registration passed, discounts not applied.') return trds = TemporaryRegistrationDiscount.objects.filter( registration=reg.temporaryRegistration) obj = None for temp_discount in trds: obj = RegistrationDiscount.objects.create( registration=reg, discount=temp_discount.discount, discountAmount=temp_discount.discountAmount, ) logger.debug('Discounts applied.') return obj
def ensureReferralVouchersExist(customer,referreeDiscount=getConstant('referrals__refereeDiscount'),referrerDiscount=getConstant('referrals__referrerDiscount')): # is there a referral voucher for this person? # Find all CustomerVouchers for this person exists,vrd = referralVoucherExists(customer) if not exists: name = _('Referral: %s' % customer.fullName) # create the referree voucher referreeVoucher = createReferreeVoucher(name,referreeDiscount) # create the referrer voucher referrerVoucher = createReferrerVoucher(customer) # create the thing that ties them together vrd = VoucherReferralDiscount(referrerVoucher=referrerVoucher, referreeVoucher=referreeVoucher, referrerBonus=referrerDiscount) vrd.save() # TODO: Do I need to save? vrd.amount = referrerDiscount vrd.save() vrd.referreeVoucher.maxAmountPerUse = referreeDiscount vrd.referreeVoucher.save() return vrd
def form_valid(self, form): ''' Create slots and return success message. ''' startDate = form.cleaned_data['startDate'] endDate = form.cleaned_data['endDate'] startTime = form.cleaned_data['startTime'] endTime = form.cleaned_data['endTime'] instructor = form.cleaned_data['instructorId'] interval_minutes = getConstant('privateLessons__lessonLengthInterval') this_date = startDate while this_date <= endDate: this_time = startTime while this_time < endTime: InstructorAvailabilitySlot.objects.create( instructor=instructor, startTime=ensure_localtime(datetime.combine(this_date, this_time)), duration=interval_minutes, location=form.cleaned_data.get('location'), room=form.cleaned_data.get('room'), pricingTier=form.cleaned_data.get('pricingTier'), ) this_time = (ensure_localtime(datetime.combine(this_date, this_time)) + timedelta(minutes=interval_minutes)).time() this_date += timedelta(days=1) return JsonResponse({'valid': True})
def __init__(self,object,**kwargs): timeZone = pytz.timezone(getattr(settings,'TIME_ZONE','UTC')) if kwargs.get('timeZone',None): try: timeZone = pytz.timezone(kwargs.get('timeZone',None)) except pytz.exceptions.UnknownTimeZoneError: pass self.id = 'privateEvent_' + str(object.event.id) self.type = 'privateEvent' self.id_number = object.event.id self.title = object.event.name self.description = object.event.description if hasattr(object.event,'category') and object.event.category: self.category = object.event.category.name self.color = object.event.category.displayColor else: self.category = None self.color = getConstant('calendar__defaultEventColor') self.start = timezone.localtime(object.startTime,timeZone) self.end = timezone.localtime(object.endTime,timeZone) self.allDay = object.allDayForDate(object.startTime) if hasattr(object,'event.location'): self.location = object.event.location.name + '\n' + object.event.location.address + '\n' + object.event.location.city + ', ' + object.event.location.state + ' ' + object.event.location.zip self.room = getattr(object.event,'room',None) else: self.location = None self.room = None self.url = object.event.link
def form_valid(self, form): ''' Create slots and return success message. ''' startDate = form.cleaned_data['startDate'] endDate = form.cleaned_data['endDate'] startTime = form.cleaned_data['startTime'] endTime = form.cleaned_data['endTime'] instructor = form.cleaned_data['instructorId'] interval_minutes = getConstant('privateLessons__lessonLengthInterval') this_date = startDate while this_date <= endDate: this_time = startTime while this_time < endTime: InstructorAvailabilitySlot.objects.create( instructor=instructor, startTime=ensure_localtime( datetime.combine(this_date, this_time)), duration=interval_minutes, location=form.cleaned_data.get('location'), room=form.cleaned_data.get('room'), pricingTier=form.cleaned_data.get('pricingTier'), ) this_time = ( ensure_localtime(datetime.combine(this_date, this_time)) + timedelta(minutes=interval_minutes)).time() this_date += timedelta(days=1) return JsonResponse({'valid': True})
def refund(self, amount=None): saleIds = self.getSaleIds() refundData = [] leftToRefund = amount or 0 for this_id in saleIds: # No need to continue if the full amount requested has been refunded if amount is not None and leftToRefund <= 0: break this_sale = Sale.find(this_id) if amount is not None: this_amount = min(float(this_sale.amount.total), leftToRefund) refund = this_sale.refund({ 'amount': { 'total': '{0:.2f}'.format(this_amount), 'currency': getConstant('general__currencyCode'), } }) else: refund = this_sale.refund() if refund.success(): logger.info('Refund successfully processed.') refundData.append({ 'status': 'success', 'refund_id': refund.id, 'sale_id': refund.sale_id, 'refundAmount': float(refund.amount.total), # This is (annoyingly) hard-coded for now because the Paypal REST API does # not yet report fees in the event of a refund. Hopefully this can be removed # soon. 'fees': -1 * ( (float(this_sale.transaction_fee.value) - getConstant('paypal__fixedTransactionFee')) * (float(refund.amount.total) / float(this_sale.amount.total)) ), }) leftToRefund -= this_amount else: logger.error('Error processing refund.') refundData.append({'status': 'error', 'errors': refund.error}) return refundData
def createExpenseItemsForVenueRental(request=None, datetimeTuple=None): filters = {'venueexpense': None, 'location__rentalRate__gt': 0} if datetimeTuple: timelist = list(datetimeTuple) timelist.sort() filters['eventoccurrence__startTime__gte'] = timelist[0] filters['eventoccurrence__startTime__lte'] = timelist[1] else: c = getConstant( 'financial__autoGenerateExpensesVenueRentalWindow') or 0 if c > 0: filters['eventoccurrence__startTime__gte'] = timezone.now( ) - relativedelta(months=c) # Only create expense items for venues with a positive rental rate for event in Event.objects.filter(**filters).distinct(): replacements = { 'month': month_name[event.month], 'year': event.year, 'type': _('Event/Series venue rental'), 'location': event.location.name, 'for': _('for'), 'name': event.name, } expense_description = '%(month)s %(year)s %(type)s: %(location)s %(for)s %(name)s' % replacements if hasattr(request, 'user'): submissionUser = request.user else: submissionUser = None hoursRented = event.duration rentalRate = event.location.rentalRate total = hoursRented * rentalRate this_category = getConstant('financial__venueRentalExpenseCat') ExpenseItem.objects.create(eventvenue=event, category=this_category, description=expense_description, submissionUser=submissionUser, hours=hoursRented, wageRate=rentalRate, total=total)
def get_context_data(self,**kwargs): context = super(BookPrivateLessonView,self).get_context_data(**kwargs) context.update({ 'instructor_list': Instructor.objects.filter( availableForPrivates=True,instructorprivatelessondetails__isnull=False ), 'defaultLessonLength': getConstant('privateLessons__defaultLessonLength'), }) return context
def getCustomerReferralVouchers(customer): cvs = CustomerVoucher.objects.filter( **{ 'customer': customer, 'voucher__category': getConstant('referrals__referrerCategory'), }) return [cv.voucher for cv in cvs]
def checkVoucherCode(sender, **kwargs): ''' Check that the given voucher code is valid ''' logger.debug( 'Signal to check RegistrationContactForm handled by vouchers app.') formData = kwargs.get('formData', {}) request = kwargs.get('request', {}) registration = kwargs.get('registration', None) session = getattr(request, 'session', {}).get(REG_VALIDATION_STR, {}) id = formData.get('gift', '') first = formData.get('firstName') last = formData.get('lastName') email = formData.get('email') # Clean out the session data relating to vouchers so that we can revalidate it. session.pop('total_voucher_amount', 0) session.pop('voucher_names', None) session.pop('gift', None) if id == '': return if not getConstant('vouchers__enableVouchers'): raise ValidationError({'gift': _('Vouchers are disabled.')}) if session.get('gift', '') != '': raise ValidationError({'gift': _('Can\'t have more than one voucher')}) eventids = [ x.event.id for x in registration.temporaryeventregistration_set.exclude( dropIn=True) ] seriess = Series.objects.filter(id__in=eventids) obj = Voucher.objects.filter(voucherId=id).first() if not obj: raise ValidationError({'gift': _('Invalid Voucher Id')}) else: customer = Customer.objects.filter(first_name=first, last_name=last, email=email).first() # This will raise any other errors that may be relevant try: obj.validateForCustomerAndSeriess(customer, seriess) except ValidationError as e: # Ensures that the error is applied to the correct field raise ValidationError({'gift': e}) # If we got this far, then the voucher is determined to be valid, so the registration # can proceed with no errors. return
def checkVoucherCode(sender, **kwargs): ''' Check that the given voucher code is valid ''' logger.debug( 'Signal to check RegistrationContactForm handled by vouchers app.') formData = kwargs.get('formData', {}) request = kwargs.get('request', {}) session = getattr(request, 'session', {}).get(REG_VALIDATION_STR, {}) id = formData.get('gift', '') first = formData.get('firstName') last = formData.get('lastName') email = formData.get('email') # Clean out the session data relating to vouchers so that we can revalidate it. session.pop('total_voucher_amount', 0) session.pop('voucher_names', None) session.pop('gift', None) if id == '': return if not getConstant('vouchers__enableVouchers'): raise ValidationError({'gift': _('Vouchers are disabled.')}) if session.get('gift', '') != '': raise ValidationError({'gift': _('Can\'t have more than one voucher')}) seriesinfo = session['regInfo'].get('events', {}) seriesids = [ int(k) for k, v in seriesinfo.items() if v.get('register', False) and not [x for x in v.keys() if x.startswith('dropin_')] ] seriess = Series.objects.filter(id__in=seriesids) obj = Voucher.objects.filter(voucherId=id).first() if not obj: raise ValidationError({'gift': _('Invalid Voucher Id')}) else: customer = Customer.objects.filter(first_name=first, last_name=last, email=email).first() # This will raise any other errors that may be relevant try: obj.validateForCustomerAndSeriess(customer, seriess) except ValidationError as e: # Ensures that the error is applied to the correct field raise ValidationError({'gift': e}) # If we got this far, then the voucher is determined to be valid, so # we can enter it into the session data. session['gift'] = id
def createExpenseItemsForCompletedEvents(request=None, datetimeTuple=None): filters = {'expenseitem': None} if datetimeTuple: timelist = list(datetimeTuple) timelist.sort() filters['event__eventoccurrence__startTime__gte'] = timelist[0] filters['event__eventoccurrence__startTime__lte'] = timelist[1] else: c = getConstant( 'financial__autoGenerateExpensesCompletedEventsWindow') or 0 if c > 0: filters['event__eventoccurrence__startTime__gte'] = timezone.now( ) - relativedelta(months=c) for member in EventStaffMember.objects.filter(**filters).distinct(): # If an EventStaffMember object for a completed class has no associated ExpenseItem, then create one. if member.event.isCompleted and not hasattr(member, 'expenseitem'): replacements = { 'month': month_name[member.event.month], 'year': member.event.year, 'type': _('event'), 'name': member.event.name, 'memberName': member.staffMember.fullName, } expense_description = '%(month)s %(year)s %(type)s: %(name)s - %(memberName)s' % replacements if hasattr(request, 'user'): submissionUser = request.user else: submissionUser = None # Hours should be net of substitutes hours_taught = member.netHours wage_rate = member.category.defaultRate if member.category == getConstant( 'general__eventStaffCategoryAssistant'): this_category = getConstant( 'financial__assistantClassInstructionExpenseCat') elif member.category in [ getConstant('general__eventStaffCategoryInstructor'), getConstant('general__eventStaffCategorySubstitute') ]: this_category = getConstant( 'financial__classInstructionExpenseCat') else: this_category = getConstant('financial__otherStaffExpenseCat') ExpenseItem.objects.create(eventstaffmember=member, category=this_category, description=expense_description, submissionUser=submissionUser, hours=hours_taught, wageRate=wage_rate)
def checkVoucherCode(sender,**kwargs): ''' Check that the given voucher code is valid ''' logger.debug('Signal to check RegistrationContactForm handled by vouchers app.') formData = kwargs.get('formData',{}) request = kwargs.get('request',{}) registration = kwargs.get('registration',None) session = getattr(request,'session',{}).get(REG_VALIDATION_STR,{}) id = formData.get('gift','') first = formData.get('firstName') last = formData.get('lastName') email = formData.get('email') # Clean out the session data relating to vouchers so that we can revalidate it. session.pop('total_voucher_amount',0) session.pop('voucher_names',None) session.pop('gift',None) if id == '': return if not getConstant('vouchers__enableVouchers'): raise ValidationError({'gift': _('Vouchers are disabled.')}) if session.get('gift','') != '': raise ValidationError({'gift': _('Can\'t have more than one voucher')}) eventids = [x.event.id for x in registration.temporaryeventregistration_set.exclude(dropIn=True)] seriess = Series.objects.filter(id__in=eventids) obj = Voucher.objects.filter(voucherId=id).first() if not obj: raise ValidationError({'gift':_('Invalid Voucher Id')}) else: customer = Customer.objects.filter( first_name=first, last_name=last, email=email).first() # This will raise any other errors that may be relevant try: obj.validateForCustomerAndSeriess(customer,seriess) except ValidationError as e: # Ensures that the error is applied to the correct field raise ValidationError({'gift': e}) # If we got this far, then the voucher is determined to be valid, so the registration # can proceed with no errors. return
def items(self,obj): if not getattr(obj,'is_staff') or not getConstant('calendar__privateCalendarFeedEnabled'): return [] this_user = obj instructor_groups = list(this_user.groups.all().values_list('id',flat=True)) occurrences = EventOccurrence.objects.filter(event__privateevent__isnull=False).filter( Q(event__privateevent__displayToGroup__in=instructor_groups) | Q(event__privateevent__displayToUsers=this_user) | (Q(event__privateevent__displayToGroup__isnull=True) & Q(event__privateevent__displayToUsers__isnull=True))).order_by('-startTime') return [EventFeedItem(x) for x in occurrences]
def createRevenueItemsForRegistrations(request=None,datetimeTuple=None): if hasattr(request,'user'): submissionUser = request.user else: submissionUser = None this_category = getConstant('financial__registrationsRevenueCat') filters_events = {'revenueitem__isnull': True,'finalEventRegistration__isnull': False} if datetimeTuple: timelist = list(datetimeTuple) timelist.sort() filters_events['finalEventRegistration__event__eventoccurrence__startTime__gte'] = timelist[0] filters_events['finalEventRegistration__event__eventoccurrence__startTime__lte'] = timelist[1] else: c = getConstant('financial__autoGenerateRevenueRegistrationsWindow') or 0 if c > 0: filters_events['finalEventRegistration__event__eventoccurrence__startTime__gte'] = timezone.now() - relativedelta(months=c) for item in InvoiceItem.objects.filter(**filters_events).distinct(): if item.finalRegistration.paidOnline: received = True else: received = False revenue_description = _('Event Registration ') + str(item.finalEventRegistration.id) + ': ' + item.invoice.finalRegistration.fullName RevenueItem.objects.create( invoiceItem=item, category=this_category, description=revenue_description, submissionUser=submissionUser, grossTotal=item.grossTotal, total=item.total, received=received, receivedDate=item.invoice.modifiedDate )
def __init__(self, *args, **kwargs): super(PrivateLessonTeacherInlineForm,self).__init__(*args,**kwargs) self.fields['staffMember'].label = _('Instructor') self.fields['category'].initial = getConstant('privateLessons__eventStaffCategoryPrivateLesson').id # Impose restrictions on new records, but not on existing ones. if not kwargs.get('instance',None): # Filter out retired teachers self.fields['staffMember'].queryset = Instructor.objects.exclude(status__in=[Instructor.InstructorStatus.retired,Instructor.InstructorStatus.hidden,Instructor.InstructorStatus.retiredGuest]) else: self.fields['staffMember'].queryset = Instructor.objects.all() self.fields['staffMember'].queryset = self.fields['staffMember'].queryset.order_by('status','firstName','lastName')
def createRevenueItemForInvoiceItem(sender,instance,**kwargs): if 'loaddata' in sys.argv or ('raw' in kwargs and kwargs['raw']): return logger.debug('RevenueItem signal fired for InvoiceItem %s.' % instance.id) received_status = (instance.invoice.status == Invoice.PaymentStatus.paid) related_item = getattr(instance, 'revenueitem', None) if not related_item: related_item = RevenueItem.objects.create( invoiceItem=instance, invoiceNumber=instance.id, grossTotal=instance.grossTotal, total=instance.total, adjustments=instance.adjustments, fees=instance.fees, taxes=instance.taxes, buyerPaysSalesTax=instance.invoice.buyerPaysSalesTax, category=getConstant('financial__registrationsRevenueCat'), submissionUser=instance.invoice.submissionUser, currentlyHeldBy=instance.invoice.collectedByUser, received=received_status, paymentMethod=instance.invoice.get_payment_method(), description=_('Registration invoice %s' % instance.id) ) logger.debug('RevenueItem created.') else: # Check that the existing revenueItem is still correct saveFlag = False for field in ['grossTotal','total','adjustments','fees','taxes']: if getattr(related_item,field) != getattr(instance,field): setattr(related_item,field,getattr(instance,field)) saveFlag = True for field in ['buyerPaysSalesTax',]: if getattr(related_item,field) != getattr(instance.invoice,field): setattr(related_item,field,getattr(instance.invoice,field)) saveFlag = True if related_item.received != received_status: related_item.received = received_status related_item.paymentMethod = instance.invoice.get_payment_method() saveFlag = True if saveFlag: related_item.save() logger.info('RevenueItem associated with InvoiceItem %s updated.' % instance.id)
def applyVoucherCodesFinal(sender,**kwargs): ''' Once a registration has been completed, vouchers are used and referrers are awarded ''' logger.debug('Signal fired to mark voucher codes as applied.') finalReg = kwargs.pop('registration') tr = finalReg.temporaryRegistration tvus = TemporaryVoucherUse.objects.filter(registration=tr) for tvu in tvus: vu = VoucherUse(voucher=tvu.voucher,registration=finalReg,amount=tvu.amount) vu.save() if getConstant('referrals__enableReferralProgram'): awardReferrers(vu)
def create_series(self,**kwargs): """ This method just creates a new series with the loaded class description that can be modified or used for various tests. """ # Create one or more occurrences. By default, the series # starts tomorrow, is a Level One Lindy Hop class with default # pricing and location, is enabled for registration, and is taught # by Frankie Manning. occurrences = max(kwargs.get('occurrences',1),1) startTime = kwargs.get('startTime', timezone.now() + timedelta(days=1)) classDescription = kwargs.get('classDescription', self.levelOneClassDescription) pricingTier = kwargs.get('pricingTier', self.defaultPricing) location = kwargs.get('location', self.defaultLocation) status = kwargs.get('status', Event.RegStatus.enabled) instructors = kwargs.get('instructors', [self.defaultInstructor,]) s = Series( classDescription=classDescription, pricingTier=pricingTier, location=location, status=status, ) s.save() # Add an occurrence at the start Time # and if requested to set more than one occurrence, then # each additional occurrence is the day after the last one. for k in range(1,occurrences + 1): EventOccurrence.objects.create( event=s, startTime=startTime + timedelta(days=k - 1), endTime=startTime + timedelta(days=k - 1,hours=1) ) # Add instructors (Frankie Manning by default) for i in instructors: seriesteacher = EventStaffMember.objects.create( event=s, category=getConstant('general__eventStaffCategoryInstructor'), staffMember=i, ) seriesteacher.occurrences = s.eventoccurrence_set.all() seriesteacher.save() # Must save after adding event occurrences to ensure that # registration status is updated properly. s.save() return s
def applyTemporaryDiscount(sender,**kwargs): # Get the registration and the customer if not getConstant('general__discountsEnabled'): return logger.debug('Signal fired to apply discounts.') reg = kwargs.pop('registration',None) discount = kwargs.pop('discount',None) discountAmount = kwargs.pop('discount_amount',None) if not reg or not discount: logger.warning('Incomplete information passed, discounts not applied.') return obj, created = TemporaryRegistrationDiscount.objects.update_or_create( registration=reg, discount=discount, defaults={'discountAmount': discountAmount,}, ) logger.debug('Discount applied.') return obj
def applyTemporaryVouchers(sender,**kwargs): reg = kwargs.get('registration') price = kwargs.get('initial_price') logger.debug('Signal fired to apply temporary vouchers.') # Put referral vouchers first, so that they are applied last in the loop. referral_cat = getConstant('referrals__referrerCategory') tvus = list(reg.temporaryvoucheruse_set.filter( voucher__category=referral_cat )) + list(reg.temporaryvoucheruse_set.exclude( voucher__category=referral_cat )) if not tvus: logger.debug('No applicable vouchers found.') return ([],0) voucher_names = [] total_voucher_amount = 0 remaining_price = price while remaining_price > 0 and tvus: tvu = tvus.pop() if tvu.voucher.maxAmountPerUse: amount = min(tvu.voucher.amountLeft,tvu.voucher.maxAmountPerUse) else: amount = tvu.voucher.amountLeft amount = min(remaining_price,amount) tvu.amount = amount tvu.save() remaining_price -= amount voucher_names += [tvu.voucher.name] total_voucher_amount += amount return (voucher_names,total_voucher_amount)
def json_event_feed(request,location_id=None,room_id=None): ''' The Jquery fullcalendar app requires a JSON news feed, so this function creates the feed from upcoming PrivateEvent objects ''' if not getConstant('calendar__privateCalendarFeedEnabled') or not request.user.is_staff: return JsonResponse({}) this_user = request.user startDate = request.GET.get('start','') endDate = request.GET.get('end','') timeZone = request.GET.get('timezone',getattr(settings,'TIME_ZONE','UTC')) time_filter_dict_events = {} if startDate: time_filter_dict_events['startTime__gte'] = ensure_timezone(datetime.strptime(startDate,'%Y-%m-%d')) if endDate: time_filter_dict_events['endTime__lte'] = ensure_timezone(datetime.strptime(endDate,'%Y-%m-%d')) + timedelta(days=1) instructor_groups = list(this_user.groups.all().values_list('id',flat=True)) filters = Q(event__privateevent__isnull=False) & ( Q(event__privateevent__displayToGroup__in=instructor_groups) | Q(event__privateevent__displayToUsers=this_user) | (Q(event__privateevent__displayToGroup__isnull=True) & Q(event__privateevent__displayToUsers__isnull=True)) ) if location_id: filters = filters & Q(event__location__id=location_id) if room_id: filters = filters & Q(event__room_id=room_id) occurrences = EventOccurrence.objects.filter(filters).filter(**time_filter_dict_events).order_by('-startTime') eventlist = [EventFeedItem(x,timeZone=timeZone).__dict__ for x in occurrences] return JsonResponse(eventlist,safe=False)
def getAddonItems(sender, **kwargs): # Check if this is a new customer if not getConstant('general__discountsEnabled'): return logger.debug('Signal fired to request free add-ons.') reg = kwargs.pop('registration',None) if not reg: logger.warning('No registration passed, addons not applied.') return newCustomer = True customers = Customer.objects.filter(user__email=reg.email) for c in customers: if c.numClassSeries > 0: newCustomer = False break # No need to get all objects, just the ones that could qualify one for an add-on cart_object_list = reg.temporaryeventregistration_set.filter(dropIn=False).filter(Q(event__series__pricingTier__isnull=False) | Q(event__publicevent__pricingTier__isnull=False)) availableAddons = getApplicableDiscountCombos(cart_object_list, newCustomer, reg.student, addOn=True) return [x.code.name for x in availableAddons]
def form_valid(self, form): slotId = form.cleaned_data.pop('slotId') payAtDoor = form.cleaned_data.pop('payAtDoor',False) # Check that passed duration is valid. try: duration = int(form.cleaned_data.pop('duration')) except ValueError: form.add_error(None,ValidationError(_('Invalid duration.'),code='invalid')) return self.form_invalid(form) # Include the submission user if the user is authenticated if self.request.user.is_authenticated: submissionUser = self.request.user else: submissionUser = None try: thisSlot = InstructorAvailabilitySlot.objects.get(id=slotId) except ObjectDoesNotExist: form.add_error(None,ValidationError(_('Invalid slot ID.'),code='invalid')) return self.form_invalid(form) # Check that passed role is valid try: role = DanceRole.objects.filter( instructorprivatelessondetails__instructor=thisSlot.instructor, ).get(id=int(form.cleaned_data.pop('role'))) except (ValueError, ObjectDoesNotExist): form.add_error(None,ValidationError(_('Invalid dance role.'),code='invalid')) return self.form_invalid(form) affectedSlots = InstructorAvailabilitySlot.objects.filter( instructor=thisSlot.instructor, location=thisSlot.location, room=thisSlot.room, pricingTier=thisSlot.pricingTier, startTime__gte=thisSlot.startTime, startTime__lt=thisSlot.startTime + timedelta(minutes=duration), ).filter( Q(status=InstructorAvailabilitySlot.SlotStatus.available) | ( Q(status=InstructorAvailabilitySlot.SlotStatus.tentative) & ~Q(temporaryEventRegistration__registration__expirationDate__gte=timezone.now()) ) ) # If someone cancels, there will already be one or more events associated # with these slots. These need to be deleted, and we also validate to be # certain that we are not cancelling any Event which has finalized or in progress # registrations attached to it. existingEvents = PrivateLessonEvent.objects.filter( instructoravailabilityslot__id__in=[x.id for x in affectedSlots] ).distinct() if existingEvents.filter( Q(eventregistration__isnull=False) | Q(temporaryeventregistration__registration__expirationDate__gte=timezone.now()) ).exists(): form.add_error(None,ValidationError(_('Some or all of your requested lesson time is currently in the process of registration. Please select a new slot or try again later.'),code='invalid')) return self.form_invalid(form) else: existingEvents.delete() # Create the lesson record and set related info lesson = PrivateLessonEvent.objects.create( pricingTier=thisSlot.pricingTier, location=thisSlot.location, room=thisSlot.room, participants=form.cleaned_data.pop('participants'), comments=form.cleaned_data.pop('comments'), status=Event.RegStatus.hidden, ) lesson_instructor = EventStaffMember.objects.create( event=lesson, category=getConstant('privateLessons__eventStaffCategoryPrivateLesson'), submissionUser=submissionUser, staffMember=thisSlot.instructor, ) lesson_occurrence = EventOccurrence.objects.create( event=lesson, startTime=thisSlot.startTime, endTime=thisSlot.startTime + timedelta(minutes=duration), ) lesson_instructor.occurrences.add(lesson_occurrence) # Ensure that lesson start and end time are saved appropriately for # the event. lesson.save() # The temporary expires after a period of inactivity that is specified in preferences. expiry = timezone.now() + timedelta(minutes=getConstant('registration__sessionExpiryMinutes')) # Slots without pricing tiers can't go through the actual registration process. # Instead, they are sent to another view to get contact information. if not thisSlot.pricingTier or not getConstant('privateLessons__allowRegistration'): affectedSlots.update( lessonEvent=lesson, status=InstructorAvailabilitySlot.SlotStatus.tentative, ) self.request.session[PRIVATELESSON_VALIDATION_STR] = { 'lesson': lesson.id, 'payAtDoor': payAtDoor, 'expiry': expiry.strftime('%Y-%m-%dT%H:%M:%S%z'), } return HttpResponseRedirect(reverse('privateLessonStudentInfo')) # Slots with pricing tiers require an TemporaryRegistration to be created, # and then they are redirected through the registration system. else: regSession = self.request.session.get(REG_VALIDATION_STR, {}) # Create a Temporary Registration associated with this lesson. reg = TemporaryRegistration( submissionUser=submissionUser,dateTime=timezone.now(), payAtDoor=payAtDoor, expirationDate=expiry, ) tr = TemporaryEventRegistration( event=lesson, role=role, price=lesson.getBasePrice(payAtDoor=payAtDoor) * affectedSlots.count() ) # Any remaining form data goes into the JSONfield. reg.data = form.cleaned_data or {} # Now we are ready to save and proceed. reg.priceWithDiscount = tr.price reg.save() tr.registration = reg tr.save() affectedSlots.update( lessonEvent=lesson, status=InstructorAvailabilitySlot.SlotStatus.tentative, temporaryEventRegistration=tr, ) # Load the temporary registration into session data like a regular registration # and redirect to Step 2 as usual. regSession["temporaryRegistrationId"] = reg.id regSession["temporaryRegistrationExpiry"] = expiry.strftime('%Y-%m-%dT%H:%M:%S%z') self.request.session[REG_VALIDATION_STR] = regSession return HttpResponseRedirect(reverse('getStudentInfo'))
def __str__(self): if self.accrualDate: return '%s %s: %s = %s%s' % (self.category.name, self.accrualDate.strftime('%B %Y'),self.description, getConstant('general__currencySymbol'), self.total) else: return '%s: %s = %s%s' % (self.category.name, self.description, getConstant('general__currencySymbol'), self.total)
def finalizeBooking(self,**kwargs): notifyStudent = kwargs.get('notifyStudent',True) notifyTeachers = kwargs.get('notifyTeachers',getConstant('privateLessons__notifyInstructor')) eventRegistration = kwargs.get('eventRegistration',None) affectedSlots = self.instructoravailabilityslot_set.all() affectedSlots.update( status=InstructorAvailabilitySlot.SlotStatus.booked, eventRegistration=eventRegistration, ) if notifyStudent: # This is the email template used to notify students that their private lesson has been # successfully scheduled template = getConstant('privateLessons__lessonBookedEmailTemplate') if template.defaultFromAddress and template.content: for customer in self.customers: customer.email_recipient( template.subject, template.content, send_html=False, from_address=template.defaultFromAddress, from_name=template.defaultFromName, cc=template.defaultCC, to=customer.email, lesson=self, ) if notifyTeachers: # This is the email template used to notify individuals who run registration # that they have been compensated template = getConstant('privateLessons__lessonBookedInstructorEmailTemplate') if template.defaultFromAddress and template.content: emailMixin = EmailRecipientMixin() instructors = [ x.staffMember for x in self.eventstaffmember_set.exclude( Q(staffMember__privateEmail__isnull=True) & Q(staffMember__publicEmail__isnull=True) ) ] for instructor in instructors: if not instructor.privateEmail and not instructor.publicEmail: # Without an email address, instructor cannot be notified continue emailMixin.email_recipient( template.subject, template.content, send_html=False, from_address=template.defaultFromAddress, from_name=template.defaultFromName, cc=template.defaultCC, to=instructor.privateEmail or instructor.publicEmail, lesson=self, instructor=instructor, customers=self.customers, calendarUrl=reverse('privateCalendar'), )