def clean_regtype(self): newval = self.cleaned_data.get('regtype') if self.instance and newval == self.instance.regtype: # Registration type not changed, so it's ok to save # (we don't want to prohibit other edits for somebody who has # an already-made registration with an expired registration type) return newval if newval and not newval.active: raise forms.ValidationError( 'Registration type "%s" is currently not available.' % newval) if newval and newval.activeuntil and newval.activeuntil <= today_conference( ): raise forms.ValidationError( 'Registration type "%s" was only available until %s.' % (newval, newval.activeuntil)) if self.instance and self.instance.payconfirmedat: raise forms.ValidationError( 'You cannot change type of registration once your payment has been confirmed!' ) if newval and newval.specialtype: validate_special_reg_type(newval.specialtype, self.instance) return newval
def render_claimdata(self, claimedbenefit): if claimedbenefit.declined: return "" if claimedbenefit.confirmed: if self.level.conference.enddate < today_conference(): data = StringIO.StringIO() c = csv.writer(data, delimiter=';') for r in ConferenceRegistration.objects.filter(conference=self.level.conference, payconfirmedat__isnull=False, canceledat__isnull=True, shareemail=True).order_by('lastname', 'firstname'): c.writerow([r.lastname, r.firstname, r.email, r.company, r.country]) ret = StringIO.StringIO() ret.write("<p>This benefit lets you download a list of users who have explicitly opted in to having their information shared. You can download the list by clicking <a href=\"data:text/plain;charset=utf8;base64,") ret.write(base64.b64encode(data.getvalue().encode('utf8')).decode('utf8')) ret.write("\">here</a>. Please be careful with how you handle this personal data!</p>") return ret.getvalue() else: return "List of attendees will be made available here once the conference is over." else: return ""
def clean_vouchercode(self): newval = self.cleaned_data.get('vouchercode') if newval == '': return newval try: v = PrepaidVoucher.objects.get(vouchervalue=newval, conference=self.instance.conference) if v.usedate: raise forms.ValidationError( 'This voucher has already been used') r = ConferenceRegistration.objects.filter( vouchercode=newval, conference=self.instance.conference) if r: if r[0].id != self.instance.id: raise forms.ValidationError( 'This voucher is already pending on another registration' ) except PrepaidVoucher.DoesNotExist: # It could be that it's a discount code try: c = DiscountCode.objects.get( code=newval, conference=self.instance.conference) if c.is_invoiced: raise forms.ValidationError( 'This discount code is not valid anymore.') if c.validuntil and c.validuntil < today_conference(): raise forms.ValidationError( 'This discount code has expired.') if c.maxuses > 0: if c.registrations.count() >= c.maxuses: raise forms.ValidationError( 'All allowed instances of this discount code have been used.' ) required_regtypes = c.requiresregtype.all() if required_regtypes: # If the list is empty, any goes. But if there's something # in the list, we have to enforce it. if not self.cleaned_data.get( 'regtype') in required_regtypes: raise forms.ValidationError( "This discount code is only valid for registration type(s): {0}" .format(", ".join( [r.regtype for r in required_regtypes]))) selected = self.cleaned_data.get('additionaloptions') or () for o in c.requiresoption.all(): if o not in selected: raise forms.ValidationError( "This discount code requires the option '%s' to be picked." % o) except DiscountCode.DoesNotExist: raise forms.ValidationError( 'This voucher or discount code was not found') return newval
def create_sponsor_invoice(user, sponsor, override_duedate=None): conference = sponsor.conference level = sponsor.level invoicerows, reverse_vat = _invoicerows_for_sponsor(sponsor) if override_duedate: duedate = override_duedate elif conference.startdate < today_conference() + timedelta(days=5): # If conference happens in the next 5 days, invoice is due immediately duedate = timezone.now() elif conference.startdate < today_conference() + timedelta(days=30): # Less than 30 days before the conference, set the due date to # 5 days before the conference duedate = timezone.make_aware( datetime.combine(conference.startdate - timedelta(days=5), timezone.now().time())) else: # More than 30 days before the conference, set the due date # to 30 days from now. duedate = timezone.now() + timedelta(days=30) manager = InvoiceManager() processor = invoicemodels.InvoiceProcessor.objects.get( processorname="confsponsor processor") i = manager.create_invoice( user, user.email, user.first_name + ' ' + user.last_name, get_sponsor_invoice_address(sponsor.name, sponsor.invoiceaddr, sponsor.vatnumber), '%s sponsorship' % conference.conferencename, timezone.now(), duedate, invoicerows, processor=processor, processorid=sponsor.pk, accounting_account=settings.ACCOUNTING_CONFSPONSOR_ACCOUNT, accounting_object=conference.accounting_object, reverse_vat=reverse_vat, extra_bcc_list=conference.sponsoraddr, paymentmethods=level.paymentmethods.all(), ) return i
def __init__(self, conference, showconfirm=False, *args, **kwargs): self.conference = conference super(PurchaseDiscountForm, self).__init__(*args, **kwargs) self.fields[ 'requiredoptions'].queryset = ConferenceAdditionalOption.objects.filter( conference=conference, public=True) self.fields['expires'].initial = conference.startdate - timedelta( days=2) self.fields['expires'].validators.append( BeforeValidator(conference.startdate - timedelta(days=1))) self.fields['expires'].validators.append( AfterValidator(today_conference() - timedelta(days=1))) if not showconfirm: del self.fields['confirm']
def __init__(self, conference, *args, **kwargs): self.conference = conference super(PurchaseVouchersForm, self).__init__(*args, **kwargs) activeQ = Q(activeuntil__isnull=True) | Q( activeuntil__gte=today_conference()) if self.data and self.data.get('regtype', None) and self.data.get( 'num', None) and _int_with_default(self.data['num'], 0) > 0: RegistrationType.objects.get(pk=self.data['regtype']) self.fields[ 'confirm'].help_text = 'Check this box to confirm that you will pay the generated invoice' self.fields['num'].widget.attrs['readonly'] = True self.fields['regtype'].queryset = RegistrationType.objects.filter( pk=self.data['regtype']) else: self.fields['regtype'].queryset = RegistrationType.objects.filter( Q(conference=self.conference, active=True, specialtype__isnull=True, cost__gt=0) & activeQ) del self.fields['confirm']
def create_voucher_invoice(conference, invoiceaddr, user, rt, num): invoicerows = [[ 'Voucher for "%s"' % rt.regtype, 1, rt.cost, rt.conference.vat_registrations ]] * num manager = InvoiceManager() processor = invoicemodels.InvoiceProcessor.objects.get( processorname="confsponsor voucher processor") i = manager.create_invoice( user, user.email, user.first_name + ' ' + user.last_name, invoiceaddr, 'Prepaid vouchers for %s' % conference.conferencename, timezone.now(), today_conference(), invoicerows, processor=processor, accounting_account=settings.ACCOUNTING_CONFREG_ACCOUNT, accounting_object=conference.accounting_object, paymentmethods=conference.paymentmethods.all(), ) return i
def invoicerows_for_registration(reg, update_used_vouchers): # Return the rows that would be used to build an invoice for this # registration. Format is tuple of (description, num, cost) # Main conference registration r = [[ '%s - %s' % (reg.email, reg.regtype.regtype), 1, reg.regtype.cost, reg.conference.vat_registrations, ]] # Any additional options for a in reg.additionaloptions.all(): if a.cost > 0: r.append([ ' %s' % a.name, 1, a.cost, reg.conference.vat_registrations ]) # Any voucher if present if reg.vouchercode: try: v = PrepaidVoucher.objects.get(vouchervalue=reg.vouchercode, conference=reg.conference) if v.usedate: # Find a way to raise an exception here if the voucher is # already used? For now, we just ignore it. raise InvoicerowsException("Prepaid voucher already used") else: # Valid voucher found! if update_used_vouchers: v.usedate = timezone.now() v.user = reg v.save() # Add a row with the discount of the registration type r.append([ ' Discount voucher %s...' % reg.vouchercode[:30], 1, -reg.regtype.cost, reg.conference.vat_registrations ]) except PrepaidVoucher.DoesNotExist: # Nonexistant voucher code means discount code was used try: d = DiscountCode.objects.get(code=reg.vouchercode, conference=reg.conference) if d.validuntil and d.validuntil < today_conference(): raise InvoicerowsException( "Discount code is no longer valid") elif d.maxuses > 0 and d.registrations.count() >= d.maxuses: raise InvoicerowsException( "Discount code does not have enough remaining instances" ) elif d.is_invoiced: raise InvoicerowsException( "Discount code has already been invoiced and is no longer valid" ) else: # Valid discount code found! selected_options = reg.additionaloptions.all() for o in d.requiresoption.all(): if o not in selected_options: raise InvoicerowsException( "Discount code requires option {0}".format( o.name)) required_regtypes = d.requiresregtype.all() if required_regtypes: if reg.regtype not in required_regtypes: raise InvoicerowsException( "Discount code requires registration types {0}" .format(",".join(required_regtypes))) if update_used_vouchers: d.registrations.add(reg) d.save() # Add a row with the discount current_total = sum([rr[2] for rr in r]) discount = 0 if d.discountamount: # Fixed amount discount discount = d.discountamount > current_total and current_total or d.discountamount else: # Percentage discount. Can be either off the total or just the reg if d.regonly: # regtype.cost is Decimal discount = reg.regtype.cost * d.discountpercentage / 100 else: discount = Decimal( current_total) * d.discountpercentage / 100 if discount > 0: r.append([ ' Discount code %s' % d.code, 1, -discount, reg.conference.vat_registrations ]) except DiscountCode.DoesNotExist: raise InvoicerowsException("Invalid voucher code") return r