Esempio n. 1
0
def view_registration_badge(request, urlname, regid):
    conference = get_authenticated_conference(request, urlname)
    reg = get_object_or_404(ConferenceRegistration, conference=conference, pk=regid)

    resp = HttpResponse(content_type='application/pdf')
    render_jinja_badges(conference, [reg.safe_export(), ], resp, False, False)
    return resp
Esempio n. 2
0
def registration_dashboard_send_dm(request, urlname, regid):
    conference = get_authenticated_conference(request, urlname)
    reg = get_object_or_404(ConferenceRegistration, conference=conference, pk=regid)

    if not reg.messaging:
        # Should never have the link, but just in case
        messages.warning(request, 'This registration has no direct messaging configured')
        return HttpResponseRedirect("../")

    maxlength = get_messaging_class(reg.messaging.provider.classname).direct_message_max_length
    if request.method == 'POST':
        form = BackendRegistrationDmForm(maxlength, data=request.POST)
        if form.is_valid():
            send_reg_direct_message(reg, form.cleaned_data['message'])
            messages.info(request, "Direct message sent.")
            return HttpResponseRedirect("../")
    else:
        form = BackendRegistrationDmForm(maxlength)

    return render(request, 'confreg/admin_backend_form.html', {
        'conference': conference,
        'basetemplate': 'confreg/confadmin_base.html',
        'form': form,
        'what': 'new direct message',
        'savebutton': 'Send direct message',
        'cancelurl': '../',
        'breadcrumbs': [('../../', 'Registration list'), ('../', reg.fullname)],
    })
Esempio n. 3
0
def pendinginvoices_cancel(request, urlname, invoiceid):
    conference = get_authenticated_conference(request, urlname)
    invoice = get_object_or_404(Invoice, pk=invoiceid, paidat__isnull=True)

    # Have to verify that this invoice is actually for this conference
    if not (
            ConferenceRegistration.objects.filter(conference=conference, invoice=invoice).exists() or
            BulkPayment.objects.filter(conference=conference, invoice=invoice).exists() or
            Sponsor.objects.filter(conference=conference, invoice=invoice).exists()
    ):
        raise PermissionDenied("Invoice not for this conference")

    if request.method == 'POST':
        form = ConferenceInvoiceCancelForm(data=request.POST)
        if form.is_valid():
            manager = InvoiceManager()
            try:
                manager.cancel_invoice(invoice, form.cleaned_data['reason'], request.user.username)
                messages.info(request, 'Invoice {} canceled.'.format(invoice.id))
                return HttpResponseRedirect('../../')
            except Exception as e:
                messages.error(request, 'Failed to cancel invoice: {}'.format(e))
    else:
        form = ConferenceInvoiceCancelForm()

    return render(request, 'confreg/admin_backend_form.html', {
        'conference': conference,
        'basetemplate': 'confreg/confadmin_base.html',
        'form': form,
        'whatverb': 'Cancel invoice',
        'savebutton': 'Cancel invoice',
        'cancelname': 'Return without canceling',
        'cancelurl': '../../',
        'note': 'Canceling invoice #{} ({}) will disconnect it from the associated objects and send a notification to the recipient of the invoice ({}).'.format(invoice.id, invoice.title, invoice.recipient_name),
    })
Esempio n. 4
0
def edit_messaging(request, urlname, rest):
    conference = get_authenticated_conference(request, urlname)
    # How about this for ugly :) Make sure this conference has an instance for every
    # available messaging on the series.
    with connection.cursor() as curs:
        curs.execute(
            """INSERT INTO confreg_conferencemessaging (conference_id, provider_id, broadcast, privatebcast, notification, orgnotification, config)
SELECT %(confid)s, id, false, false, false, false, '{}'
FROM confreg_messagingprovider mp
WHERE mp.series_id=%(seriesid)s AND NOT EXISTS (
 SELECT 1 FROM confreg_conferencemessaging m2 WHERE m2.conference_id=%(confid)s AND m2.provider_id=mp.id
)""",
            {
                'confid': conference.id,
                'seriesid': conference.series_id,
            })

    return backend_list_editor(request,
                               urlname,
                               BackendMessagingForm,
                               rest,
                               conference=conference,
                               allow_new=False,
                               allow_delete=False,
    )
Esempio n. 5
0
def view_registration_ticket(request, urlname, regid):
    conference = get_authenticated_conference(request, urlname)
    reg = get_object_or_404(ConferenceRegistration, conference=conference, pk=regid)

    resp = HttpResponse(content_type='application/pdf')
    render_jinja_ticket(reg, resp, systemroot=JINJA_TEMPLATE_ROOT)
    return resp
Esempio n. 6
0
def purge_personal_data(request, urlname):
    conference = get_authenticated_conference(request, urlname)

    if conference.personal_data_purged:
        messages.warning(request, 'Personal data for this conference has already been purged')
        return HttpResponseRedirect('../')

    if request.method == 'POST':
        exec_no_result("INSERT INTO confreg_aggregatedtshirtsizes (conference_id, size_id, num) SELECT conference_id, shirtsize_id, count(*) FROM confreg_conferenceregistration WHERE conference_id=%(confid)s AND shirtsize_id IS NOT NULL GROUP BY conference_id, shirtsize_id", {'confid': conference.id, })
        exec_no_result("INSERT INTO confreg_aggregateddietary (conference_id, dietary, num) SELECT conference_id, lower(dietary), count(*) FROM confreg_conferenceregistration WHERE conference_id=%(confid)s AND dietary IS NOT NULL AND dietary != '' GROUP BY conference_id, lower(dietary)", {'confid': conference.id, })
        exec_no_result("UPDATE confreg_conferenceregistration SET shirtsize_id=NULL, dietary='', phone='', address='' WHERE conference_id=%(confid)s", {'confid': conference.id, })
        conference.personal_data_purged = timezone.now()
        conference.save()
        messages.info(request, "Personal data purged from conference")
        return HttpResponseRedirect('../')

    return render(request, 'confreg/admin_purge_personal_data.html', {
        'conference': conference,
        'helplink': 'personaldata',
        'counts': exec_to_dict("""SELECT
  count(1) FILTER (WHERE shirtsize_id IS NOT NULL) AS "T-shirt size registrations",
  count(1) FILTER (WHERE dietary IS NOT NULL AND dietary != '') AS "Dietary needs",
  count(1) FILTER (WHERE phone IS NOT NULL AND phone != '') AS "Phone numbers",
  count(1) FILTER (WHERE address IS NOT NULL AND address != '') AS "Addresses"
FROM confreg_conferenceregistration WHERE conference_id=%(confid)s""", {
            'confid': conference.id,
        })[0],
    })
Esempio n. 7
0
def feedback_report(request, confname):
    conference = get_authenticated_conference(request, confname)

    sections = []
    # Get the global conference feedback. Yes, this will be inefficient, but it will work
    currentsection = {}
    for q in ConferenceFeedbackQuestion.objects.filter(
            conference=conference).order_by('sortkey'):
        if q.newfieldset:
            if currentsection:
                sections.append(currentsection)
                currentsection = {}
            if not currentsection:
                # Either first row, or a new fieldset per above
                currentsection['title'] = q.newfieldset
                currentsection['questions'] = []
        currentsection['questions'].append(build_feedback_response(q))
    else:
        sections.append(currentsection)

    return render(request, 'confreg/admin_conference_feedback.html', {
        'conference': conference,
        'feedback': sections,
        'helplink': 'feedback',
    })
Esempio n. 8
0
def tweetcampaign(request, urlname, typeid):
    conference = get_authenticated_conference(request, urlname)

    campaign = get_campaign_from_id(typeid)

    if request.method == 'GET' and 'fieldpreview' in request.GET:
        try:
            return campaign.get_dynamic_preview(conference, request.GET['fieldpreview'], request.GET['previewval'])
        except Exception as e:
            return HttpResponse('Exception rendering preview: {}'.format(e), content_type='text/plain', status=500)

    if request.method == 'POST':
        form = campaign.form(conference, request.POST)
        if form.is_valid():
            try:
                with transaction.atomic():
                    form.generate_tweets(request.user)
                messages.info(request, "Campaign tweets generated")
                return HttpResponseRedirect("../../queue/")
            except Exception as e:
                form.add_error('content_template', 'Exception rendering template: {}'.format(e))
    else:
        form = campaign.form(conference)

    return render(request, 'confreg/admin_backend_form.html', {
        'conference': conference,
        'basetemplate': 'confreg/confadmin_base.html',
        'form': form,
        'whatverb': 'Create campaign',
        'savebutton': "Create campaign",
        'cancelurl': '../../../',
        'note': campaign.note,
        'helplink': 'integrations#campaigns',
    })
Esempio n. 9
0
def addoptorders(request, urlname):
    conference = get_authenticated_conference(request, urlname)

    return render(request, 'confreg/admin_addoptorder_list.html', {
        'conference': conference,
        'orders': PendingAdditionalOrder.objects.select_related('reg', 'invoice__paidusing').filter(reg__conference=conference).order_by('-payconfirmedat', '-createtime'),
        'helplink': 'registrations#options',
    })
Esempio n. 10
0
def prepaidorders(request, urlname):
    conference = get_authenticated_conference(request, urlname)

    return render(request, 'confreg/admin_prepaidorders_list.html', {
        'conference': conference,
        'orders': PurchasedVoucher.objects.select_related('sponsor', 'user', 'invoice', 'batch').filter(conference=conference).annotate(num_used=Count('batch__prepaidvoucher__user')).order_by('-invoice__paidat', '-invoice__id'),
        'helplink': 'vouchers',
    })
Esempio n. 11
0
def registration_dashboard_send_email(request, urlname):
    conference = get_authenticated_conference(request, urlname)

    return _attendee_email_form(request,
                                conference,
                                "SELECT id AS regid, attendee_id AS user_id, firstname || ' ' || lastname AS fullname, email FROM confreg_conferenceregistration WHERE conference_id=%(conference)s AND id=ANY(%(idlist)s)",
                                [('../', 'Registration list'), ],
                                )
Esempio n. 12
0
def multiregs(request, urlname):
    conference = get_authenticated_conference(request, urlname)

    return render(request, 'confreg/admin_multireg_list.html', {
        'conference': conference,
        'bulkpays': BulkPayment.objects.select_related('user', 'invoice__paidusing').prefetch_related('conferenceregistration_set').filter(conference=conference).order_by('-paidat', '-createdat'),
        'highlight': get_int_or_error(request.GET, 'b', -1),
        'helplink': 'registrations',
    })
Esempio n. 13
0
def prepaidorder_refund(request, urlname, orderid):
    conference = get_authenticated_conference(request, urlname)

    order = get_object_or_404(PurchasedVoucher, pk=orderid, conference=conference)

    if PrepaidBatch.objects.filter(pk=order.batch_id).aggregate(used=Count('prepaidvoucher__user'))['used'] > 0:
        # This link should not exist in the first place, but double check if someone
        # used the voucher in between the click.
        messages.error(request, 'Cannot refund order, there are used vouchers in the batch!')
        return HttpResponseRedirect("../../")

    invoice = order.invoice
    if not invoice:
        messages.error(request, 'Order does not have an invoice, there is nothing to refund!')
        return HttpResponseRedirect("../../")
    if not invoice.paidat:
        messages.error(request, 'Invoice for this order has not been paid, there is nothing to refund!')
        return HttpResponseRedirect("../../")

    if request.method == 'POST':
        form = PurchasedVoucherRefundForm(data=request.POST)
        if form.is_valid():
            # Actually issue the refund
            manager = InvoiceManager()
            manager.refund_invoice(invoice, 'Prepaid order refunded', invoice.total_amount - invoice.total_vat, invoice.total_vat, conference.vat_registrations)

            send_conference_notification(
                conference,
                'Prepaid order {} refunded'.format(order.id),
                'Prepaid order {} purchased by {} {} has been refunded.\nNo vouchers were in use, and the order and batch have both been deleted.\n'.format(order.id, order.user.first_name, order.user.last_name),
            )
            order.batch.delete()
            order.delete()

            messages.info(request, 'Order has been refunded and deleted.')
            return HttpResponseRedirect("../../")
    else:
        form = PurchasedVoucherRefundForm()

    if settings.EU_VAT:
        note = 'You are about to refund {}{} ({}{} + {}{} VAT) for invoice {}. Please confirm that this is what you want!'.format(settings.CURRENCY_SYMBOL, invoice.total_amount, settings.CURRENCY_SYMBOL, invoice.total_amount - invoice.total_vat, settings.CURRENCY_SYMBOL, invoice.total_vat, invoice.id)
    else:
        note = 'You are about to refund {}{} for invoice {}. Please confirm that this is what you want!'.format(settings.CURRENCY_SYMBOL, invoice.total_amount, invoice.id)

    return render(request, 'confreg/admin_backend_form.html', {
        'conference': conference,
        'basetemplate': 'confreg/confadmin_base.html',
        'form': form,
        'note': note,
        'whatverb': 'Refund',
        'what': 'repaid vouchers',
        'savebutton': 'Refund',
        'cancelurl': '../../',
        'breadcrumbs': [('/events/admin/{}/prepaidorders/'.format(conference.urlname), 'Prepaid Voucher Orders'), ],
        'helplink': 'vouchers',
    })
Esempio n. 14
0
def signup_admin_edit(request, urlname, signupid):
    conference = get_authenticated_conference(request, urlname)

    if signupid != 'new':
        signup = get_object_or_404(Signup, conference=conference, pk=signupid)
        # There can be results, so calculate them. We want both a list and
        # a summary.
        results = {}
        cursor = connection.cursor()
        cursor.execute("WITH t AS (SELECT choice, count(*) AS num FROM confwiki_attendeesignup WHERE signup_id=%(signup)s GROUP BY choice) SELECT choice, num, CAST(num*100/sum(num) OVER () AS integer), CAST(num*100*4/sum(num) OVER () AS integer) FROM t ORDER BY 2 DESC", {
            'signup': signup.id,
        })
        sumresults = cursor.fetchall()
        results['summary'] = [dict(list(zip(['choice', 'num', 'percent', 'percentwidth'], r))) for r in sumresults]
        cursor.execute("SELECT s.id, firstname || ' ' || lastname,choice,saved FROM confreg_conferenceregistration r INNER JOIN confwiki_attendeesignup s ON r.id=s.attendee_id WHERE s.signup_id=%(signup)s ORDER BY saved", {
            'signup': signup.id,
        })
        results['details'] = [dict(list(zip(['id', 'name', 'choice', 'when'], r))) for r in cursor.fetchall()]
        if signup.optionvalues:
            optionstrings = signup.options.split(',')
            optionvalues = [int(x) for x in signup.optionvalues.split(',')]
            totalvalues = 0
            for choice, num, percent, width in sumresults:
                totalvalues += num * optionvalues[optionstrings.index(choice)]
            results['totalvalues'] = totalvalues

        # If we have a limited number of attendees, then we can generate
        # a list of pending users. We don't even try if it's set for public.
        if not signup.public:
            cursor.execute("SELECT firstname || ' ' || lastname FROM confreg_conferenceregistration r WHERE payconfirmedat IS NOT NULL AND canceledat IS NULL AND (regtype_id IN (SELECT registrationtype_id FROM confwiki_signup_regtypes srt WHERE srt.signup_id=%(signup)s) OR id IN (SELECT conferenceregistration_id FROM confwiki_signup_attendees WHERE signup_id=%(signup)s)) AND id NOT IN (SELECT attendee_id FROM confwiki_attendeesignup WHERE signup_id=%(signup)s) ORDER BY lastname, firstname", {
                'signup': signup.id,
            })
            results['awaiting'] = [dict(list(zip(['name', ], r))) for r in cursor.fetchall()]
    else:
        author = get_object_or_404(ConferenceRegistration, conference=conference, attendee=request.user)
        signup = Signup(conference=conference, author=author)
        results = None

    if request.method == 'POST':
        form = SignupAdminEditForm(instance=signup, data=request.POST)
        if form.is_valid():
            # We don't bother with diffs here as the only one who can
            # edit things are admins anyway.
            form.save()
            return HttpResponseRedirect('../')
    else:
        form = SignupAdminEditForm(instance=signup)

    return render(request, 'confwiki/signup_admin_edit_form.html', {
        'conference': conference,
        'form': form,
        'signup': signup,
        'results': results,
        'breadcrumbs': (('/events/admin/{0}/signups/'.format(conference.urlname), 'Signups'),),
        'helplink': 'signups',
    })
Esempio n. 15
0
def edit_tweetqueue(request, urlname, rest):
    conference = get_authenticated_conference(request, urlname)

    return backend_list_editor(request,
                               urlname,
                               BackendTweetQueueForm,
                               rest,
                               return_url='../../',
                               instancemaker=lambda: ConferenceTweetQueue(conference=conference, author=request.user)
    )
Esempio n. 16
0
def signup_admin(request, urlname):
    conference = get_authenticated_conference(request, urlname)

    signups = Signup.objects.filter(conference=conference)

    return render(request, 'confwiki/signup_admin.html', {
        'conference': conference,
        'signups': signups,
        'helplink': 'signups',
    })
Esempio n. 17
0
def admin(request, urlname):
    conference = get_authenticated_conference(request, urlname)

    pages = Wikipage.objects.filter(conference=conference)

    return render(request, 'confwiki/admin.html', {
        'conference': conference,
        'pages': pages,
        'helplink': 'wiki',
    })
Esempio n. 18
0
def signup_admin_editsignup(request, urlname, signupid, id):
    conference = get_authenticated_conference(request, urlname)
    signup = get_object_or_404(Signup, conference=conference, pk=signupid)

    if id == 'new':
        attendeesignup = AttendeeSignup(signup=signup)
    else:
        attendeesignup = get_object_or_404(AttendeeSignup,
                                           signup=signup,
                                           pk=id)

    if request.method == 'POST' and request.POST['submit'] == 'Delete':
        attendeesignup.delete()
        return HttpResponseRedirect('../../')
    elif request.method == 'POST':
        form = SignupAdminEditSignupForm(signup,
                                         isnew=(id == 'new'),
                                         instance=attendeesignup,
                                         data=request.POST)
        if form.is_valid():
            if (not signup.options) and (not form.cleaned_data['choice']):
                # Yes/no signup changed to no means we actually delete the
                # record completeliy.
                attendeesignup.delete()
            else:
                form.save()
            return HttpResponseRedirect('../../')
    else:
        form = SignupAdminEditSignupForm(signup,
                                         isnew=(id == 'new'),
                                         instance=attendeesignup)

    return render(
        request, 'confreg/admin_backend_form.html', {
            'basetemplate':
            'confreg/confadmin_base.html',
            'conference':
            conference,
            'form':
            form,
            'what':
            'attendee signup',
            'cancelurl':
            '../../',
            'allow_delete': (id != 'new'),
            'breadcrumbs': (
                ('/events/admin/{0}/signups/'.format(
                    conference.urlname), 'Signups'),
                ('/events/admin/{0}/signups/{1}/'.format(
                    conference.urlname, signup.id), signup.title),
            ),
            'helplink':
            'signups',
        })
Esempio n. 19
0
def pendinginvoices(request, urlname):
    conference = get_authenticated_conference(request, urlname)

    return render(request, 'confreg/admin_pending_invoices.html', {
        'conference': conference,
        'invoices': OrderedDict((
            ('Attendee invoices', Invoice.objects.filter(paidat__isnull=True, conferenceregistration__conference=conference)),
            ('Multi-registration invoices', Invoice.objects.filter(paidat__isnull=True, bulkpayment__conference=conference)),
            ('Sponsor invoices', Invoice.objects.filter(paidat__isnull=True, sponsor__conference=conference)),
        )),
    })
Esempio n. 20
0
def edit_conference(request, urlname):
    conference = get_authenticated_conference(request, urlname)

    return backend_process_form(request,
                                urlname,
                                BackendConferenceForm,
                                conference.pk,
                                conference=conference,
                                bypass_conference_filter=True,
                                allow_new=False,
                                allow_delete=False)
Esempio n. 21
0
    def lookup(self, request, urlname=None):
        if urlname is None:
            self.validate_global_access(request)
            vals = self.get_values(request.GET['query'])
        else:
            conference = get_authenticated_conference(request, urlname)
            vals = self.get_values(request.GET['query'], conference)

        return HttpResponse(json.dumps({
            'values': vals,
        }),
                            content_type='application/json')
Esempio n. 22
0
def feedback_sessions(request, confname):
    conference = get_authenticated_conference(request, confname)

    # Get all sessions that have actual comments on them
    cursor = connection.cursor()
    cursor.execute(
        "SELECT concat(s.title, ' (' || (SELECT string_agg(fullname, ', ') FROM confreg_speaker spk INNER JOIN confreg_conferencesession_speaker css ON css.speaker_id=spk.id WHERE css.conferencesession_id=s.id) || ')'), conference_feedback FROM confreg_conferencesessionfeedback fb INNER JOIN confreg_conferencesession s ON fb.session_id=s.id WHERE s.conference_id=%s AND NOT conference_feedback='' ORDER BY 1,2"
        % (conference.id, ))
    commented_sessions = cursor.fetchall()

    # Now for all of our fancy toplists
    # The django ORM just can't do this...
    minvotes = 10
    if request.method == 'POST':
        minvotes = get_int_or_error(request.POST, 'minvotes')

    toplists = []

    # Start with top sessions
    toplists.extend(
        build_toplists(
            'Sessions',
            "SELECT s.title || ' (' || (SELECT string_agg(fullname, ', ') FROM confreg_speaker spk INNER JOIN confreg_conferencesession_speaker css ON css.speaker_id=spk.id WHERE css.conferencesession_id=s.id) || ')', avg(fb.{{key}}), count(*), stddev(fb.{{key}}) FROM confreg_conferencesessionfeedback fb INNER JOIN confreg_conferencesession s ON fb.session_id=s.id WHERE s.conference_id=%s AND fb.{{key}}>0 GROUP BY s.id HAVING count(*)>=%s ORDER BY 2 DESC"
            % (conference.id, minvotes)))

    # Now let's do the speakers
    toplists.extend(
        build_toplists(
            'Speakers',
            "SELECT (SELECT string_agg(fullname, ', ') FROM confreg_speaker spk INNER JOIN confreg_conferencesession_speaker css ON css.speaker_id=spk.id WHERE css.conferencesession_id=s.id) AS speakername, avg(fb.{{key}}), count(*), stddev(fb.{{key}}) FROM confreg_conferencesessionfeedback fb INNER JOIN confreg_conferencesession s ON fb.session_id=s.id WHERE s.conference_id=%s AND fb.{{key}}>0 GROUP BY speakername HAVING count(*)>=%s ORDER BY 2 DESC"
            % (conference.id, minvotes)))

    return render(
        request, 'confreg/admin_session_feedback.html', {
            'conference':
            conference,
            'toplists':
            toplists,
            'minvotes':
            minvotes,
            'commented_sessions':
            commented_sessions,
            'breadcrumbs': (('/events/admin/{0}/reports/feedback/'.format(
                conference.urlname), 'Feedback'), ),
            'helplink':
            'feedback',
        })
Esempio n. 23
0
def conference_session_send_email(request, urlname):
    conference = get_authenticated_conference(request, urlname)

    return _attendee_email_form(request,
                                conference,
                                """
SELECT r.id AS regid, s.user_id, s.fullname, COALESCE(r.email, u.email) AS email
FROM confreg_speaker s
INNER JOIN auth_user u ON u.id=s.user_id
LEFT JOIN confreg_conferenceregistration r ON (r.conference_id=%(conference)s AND r.attendee_id=s.user_id)
WHERE EXISTS (
 SELECT 1 FROM confreg_conferencesession sess
 INNER JOIN confreg_conferencesession_speaker ccs ON sess.id=ccs.conferencesession_id
 WHERE conferencesession_id=ANY(%(idlist)s) AND sess.conference_id=%(conference)s
 AND speaker_id=s.id)""",
                                [('../', 'Conference sessions'), ],
                                )
Esempio n. 24
0
def multireg_refund(request, urlname, bulkid):
    conference = get_authenticated_conference(request, urlname)

    bulkpay = get_object_or_404(BulkPayment, pk=bulkid, conference=conference)
    if bulkpay.conferenceregistration_set.exists():
        messages.error(request, "This bulk payment has registrations, cannot be canceled!")
        return HttpResponseRedirect("../../")

    invoice = bulkpay.invoice
    if not invoice:
        messages.error(request, "This bulk payment does not have an invoice!")
        return HttpResonseRedirect("../../")
    if not invoice.paidat:
        messages.error(request, "This bulk payment invoice has not been paid!")
        return HttpResonseRedirect("../../")

    if request.method == 'POST':
        form = BulkPaymentRefundForm(invoice, data=request.POST)
        if form.is_valid():
            manager = InvoiceManager()
            manager.refund_invoice(invoice, 'Multi registration refunded', form.cleaned_data['amount'], form.cleaned_data['vatamount'], conference.vat_registrations)

            send_conference_notification(
                conference,
                'Multi registration {} refunded'.format(bulkpay.id),
                'Multi registration {} purchased by {} {} has been refunded.\nNo registrations were active in this multi registration, and the multi registration has now been deleted.\n'.format(bulkpay.id, bulkpay.user.first_name, bulkpay.user.last_name),
            )
            bulkpay.delete()

            messages.info(request, 'Multi registration has been refunded and deleted.')
            return HttpResponseRedirect("../../")
    else:
        form = BulkPaymentRefundForm(invoice, initial={'amount': invoice.total_amount - invoice.total_vat, 'vatamount': invoice.total_vat})

    return render(request, 'confreg/admin_backend_form.html', {
        'conference': conference,
        'basetemplate': 'confreg/confadmin_base.html',
        'form': form,
        'whatverb': 'Refund',
        'what': 'multi registration',
        'savebutton': 'Refund',
        'cancelurl': '../../',
        'breadcrumbs': [('/events/admin/{}/multiregs/'.format(conference.urlname), 'Multi Registrations'), ],
        'helplink': 'registrations',
    })
Esempio n. 25
0
def edit_sponsor(request, urlname, sponsorid):
    conference = get_authenticated_conference(request, urlname)
    sponsor = Sponsor.objects.get(conference=conference, pk=sponsorid)

    return backend_process_form(
        request,
        urlname,
        BackendSponsorForm,
        sponsor.pk,
        conference=conference,
        allow_new=False,
        allow_delete=not sponsor.invoice,
        deleted_url='../../',
        breadcrumbs=[
            ('/events/sponsor/admin/{0}/'.format(urlname), 'Sponsors'),
            ('/events/sponsor/admin/{0}/{1}/'.format(urlname, sponsor.pk),
             sponsor.name),
        ])
Esempio n. 26
0
def tweetcampaignselect(request, urlname):
    conference = get_authenticated_conference(request, urlname)

    if request.method == 'POST':
        form = TweetCampaignSelectForm(data=request.POST)
        if form.is_valid():
            return HttpResponseRedirect("{}/".format(form.cleaned_data['campaigntype']))
    else:
        form = TweetCampaignSelectForm()

    return render(request, 'confreg/admin_backend_form.html', {
        'conference': conference,
        'basetemplate': 'confreg/confadmin_base.html',
        'form': form,
        'whatverb': 'Create campaign',
        'savebutton': 'Select campaign type',
        'cancelurl': '../../',
        'helplink': 'integrations#campaigns',
    })
Esempio n. 27
0
def pdfschedule(request, confname):
    conference = get_authenticated_conference(request, confname)

    if request.method == "POST":
        form = PdfScheduleForm(conference, data=request.POST)
        if form.is_valid():
            if form.cleaned_data.get('room', None):
                return build_linear_pdf_schedule(
                    conference,
                    form.cleaned_data['room'],
                    form.cleaned_data['tracks'],
                    form.cleaned_data.get('day', None),
                    form.cleaned_data.get('colored', None),
                    form.cleaned_data.get('pagesize', None),
                    form.cleaned_data.get('orientation', None),
                    form.cleaned_data.get('titledatefmt', None),
                )
            else:
                return build_complete_pdf_schedule(
                    conference,
                    form.cleaned_data['tracks'],
                    form.cleaned_data.get('day', None),
                    form.cleaned_data.get('colored', None),
                    form.cleaned_data.get('pagesize', None),
                    form.cleaned_data.get('orientation', None),
                    form.cleaned_data.get('pagesperday', None),
                    form.cleaned_data.get('titledatefmt', None),
                )

        # Fall through and render the form again if it's not valid
    else:
        form = PdfScheduleForm(conference)

    return render(request, 'confreg/pdfschedule.html', {
        'conference': conference,
        'form': form,
        'helplink': 'schedule#pdf',
    })
Esempio n. 28
0
def backend_process_form(request, urlname, formclass, id, cancel_url='../', saved_url='../', allow_new=True, allow_delete=True, breadcrumbs=None, permissions_already_checked=False, conference=None, bypass_conference_filter=False, instancemaker=None, deleted_url=None, topadmin=None):
    if not conference and not bypass_conference_filter:
        conference = get_authenticated_conference(request, urlname)

    if not formclass.Meta.fields:
        raise Exception("This view only works if fields are explicitly listed")

    if request.GET.get('fieldpreview', ''):
        f = request.GET.get('fieldpreview')
        if f not in formclass.dynamic_preview_fields:
            raise Http404()

        try:
            return HttpResponse(formclass.get_dynamic_preview(f, request.GET.get('previewval', ''), id), content_type='text/plain')
        except Exception:
            return HttpResponse('', content_type='text/plain')

    nopostprocess = False
    newformdata = None

    if not deleted_url:
        deleted_url = cancel_url

    if not instancemaker:
        if conference:
            instancemaker = lambda: formclass.Meta.model(conference=conference)
        else:
            instancemaker = lambda: formclass.Meta.model()

    if topadmin:
        basetemplate = 'adm/admin_base.html'
    else:
        basetemplate = 'confreg/confadmin_base.html'

    if allow_new and not id:
        if formclass.form_before_new:
            if request.method == 'POST' and '_validator' in request.POST:
                # This is a postback from the *actual* form
                newformdata = request.POST['_newformdata']
                instance = instancemaker()
            else:
                # Postback to the first step create form
                newinfo = False
                if request.method == 'POST':
                    # Making the new one!
                    newform = formclass.form_before_new(request.POST)
                    if newform.is_valid():
                        newinfo = True
                else:
                    newform = formclass.form_before_new()
                if not newinfo:
                    return render(request, 'confreg/admin_backend_form.html', {
                        'conference': conference,
                        'basetemplate': basetemplate,
                        'topadmin': topadmin,
                        'form': newform,
                        'whatverb': 'Create new',
                        'what': formclass._verbose_name(),
                        'savebutton': 'Create',
                        'cancelurl': cancel_url,
                        'helplink': newform.helplink,
                        'breadcrumbs': breadcrumbs,
                    })
                instance = instancemaker()
                newformdata = newform.get_newform_data()
                nopostprocess = True
        else:
            # No special form_before_new, so just create an empty instance
            instance = instancemaker()

        # Set initial values on newly created instance, if any are set
        for k, v in list(formclass.get_initial().items()):
            setattr(instance, k, v)
    else:
        if bypass_conference_filter:
            instance = get_object_or_404(formclass.Meta.model, pk=id)
        else:
            if hasattr(formclass.Meta, 'conference_queryset'):
                try:
                    instance = formclass.Meta.conference_queryset(conference).get(pk=id)
                except formclass.Meta.model.DoesNotExist:
                    raise Http404()
            else:
                instance = get_object_or_404(formclass.Meta.model, pk=id, conference=conference)

    if request.method == 'GET' and request.GET.get('validate', '') == '1':
        if not id:
            return HttpResponse("Record not saved, cannot preview", content_type='text/plain')
        else:
            try:
                return HttpResponse(formclass.validate_data_for(instance))
            except Exception as e:
                return HttpResponse("Validation failed: {}".format(e))

    if request.method == 'POST' and not nopostprocess:
        extra_error = None
        if allow_delete and request.POST.get('submit', None) == 'Delete':
            if instance.pk:
                if hasattr(instance, 'validate_object_delete'):
                    try:
                        instance.validate_object_delete()
                    except ValidationError as e:
                        extra_error = "This {0} cannot be deleted: {1}".format(formclass.Meta.model._meta.verbose_name, e.message)

                # Are there any associated objects here, by any chance?
                collector = NestedObjects(using='default')
                collector.collect([instance, ])
                to_delete = collector.nested()
                to_delete.remove(instance)
                if to_delete:
                    to_delete = [d for d in flatten_list(to_delete[0]) if d._meta.model_name not in formclass.auto_cascade_delete_to]

                if extra_error:
                    pass
                elif to_delete:
                    pieces = [str(to_delete[n]) for n in range(0, min(5, len(to_delete))) if not isinstance(to_delete[n], list)]
                    extra_error = "This {0} cannot be deleted. It would have resulted in the following other objects also being deleted: {1}".format(formclass._verbose_name(), ', '.join(pieces))
                else:
                    messages.info(request, "{0} {1} deleted.".format(formclass._verbose_name().capitalize(), instance))
                    instance.delete()
                    return HttpResponseRedirect(deleted_url)
            else:
                messages.warning(request, "New {0} not deleted, object was never saved.".format(formclass._verbose_name().capitalize()))
                return HttpResponseRedirect(cancel_url)

        form = formclass(request, conference, instance=instance, data=request.POST, files=request.FILES, newformdata=newformdata)
        if extra_error:
            form.add_error(None, extra_error)

        # Figure out if a custom submit button was pressed
        for k, v in request.POST.items():
            if k.startswith('submit_id_'):
                # We do!
                f = form.fields[k[10:]]
                if f.callback:
                    f.callback(request)
                return HttpResponseRedirect(".")

        if form.is_valid():
            # We don't want to use form.save(), because it actually saves all
            # fields on the model, including those we don't care about.
            # The savem2m model, however, *does* care about the listed fields.
            # Consistency is overrated!
            with transaction.atomic():
                if allow_new and ((not instance.pk) or form.force_insert):
                    form.pre_create_item()
                    form.save()
                form._save_m2m()
                all_excludes = ['_validator', '_newformdata'] + list(form.readonly_fields) + form.nosave_fields
                if form.json_form_fields:
                    for fn, ffields in form.json_form_fields.items():
                        all_excludes.extend(ffields)

                form.instance.save(update_fields=[f for f in form.fields.keys() if f not in all_excludes and not isinstance(form[f].field, forms.ModelMultipleChoiceField)])

                # Merge fields stored in json
                if form.json_form_fields:
                    for fn, ffields in form.json_form_fields.items():
                        d = getattr(form.instance, fn, {})
                        d.update({fld: form.cleaned_data[fld] for fld in ffields})
                        setattr(form.instance, fn, d)
                    form.instance.save(update_fields=form.json_form_fields.keys())

                return HttpResponseRedirect(saved_url)
    else:
        form = formclass(request, conference, instance=instance, newformdata=newformdata)

    if instance.pk:
        try:
            adminurl = reverse('admin:{0}_{1}_change'.format(instance._meta.app_label, instance._meta.model_name), args=(instance.pk,))
        except NoReverseMatch:
            adminurl = None
        what = formclass._verbose_name()
    else:
        adminurl = None
        what = 'new {0}'.format(formclass._verbose_name())

    return render(request, 'confreg/admin_backend_form.html', {
        'conference': conference,
        'basetemplate': basetemplate,
        'topadmin': topadmin,
        'form': form,
        'id': instance.pk,
        'what': what,
        'cancelurl': cancel_url,
        'breadcrumbs': breadcrumbs,
        'helplink': form.helplink,
        'allow_delete': allow_delete and instance.pk,
        'adminurl': adminurl,
        'linked': [(url, handler, handler.get_list(form.instance)) for url, handler in list(form.linked_objects.items()) if form.instance],
    })
Esempio n. 29
0
def backend_list_editor(request, urlname, formclass, resturl, allow_new=True, allow_delete=True, conference=None, breadcrumbs=[], bypass_conference_filter=False, instancemaker=None, return_url='../', topadmin=None, object_queryset=None):
    if not conference and not bypass_conference_filter:
        conference = get_authenticated_conference(request, urlname)

    if topadmin:
        basetemplate = 'adm/admin_base.html'
    else:
        basetemplate = 'confreg/confadmin_base.html'

    if resturl:
        resturl = resturl.rstrip('/')
    if resturl == '' or resturl is None:
        # Render the list of objects
        if bypass_conference_filter:
            if object_queryset is not None:
                objects = object_queryset.all()
            else:
                objects = formclass.Meta.model.objects.all()
        else:
            if hasattr(formclass.Meta, 'conference_queryset'):
                objects = formclass.Meta.conference_queryset(conference).all()
            else:
                objects = formclass.Meta.model.objects.filter(conference=conference)
        if formclass.list_order_by:
            objects = objects.order_by(*formclass.list_order_by)

        if formclass.queryset_select_related:
            objects = objects.select_related(*formclass.queryset_select_related)
        if formclass.queryset_extra_fields:
            objects = objects.extra(select=formclass.queryset_extra_fields)
        objects = objects.only(*(formclass.list_fields - formclass.queryset_extra_fields.keys()))

        if request.method == "POST":
            if request.POST.get('operation') == 'assign':
                what = request.POST.get('what')
                related = formclass.Meta.model._meta.get_field(what).related_model
                setval = request.POST.get('assignid')
                if setval:
                    setval = int(setval)
                if what not in formclass.Meta.fields:
                    # Trying to update invalid field!
                    raise PermissionDenied()
                with transaction.atomic():
                    for obj in objects.filter(id__in=request.POST.get('idlist').split(',')):
                        if isinstance(getattr(obj, what), bool):
                            # Special-case booleans, they can only be set to true or false, and clearfing
                            # means the same as set to false.
                            if setval:
                                setattr(obj, what, True)
                            else:
                                setattr(obj, what, False)
                        else:
                            if setval:
                                setattr(obj, what, related.objects.get(pk=setval))
                            else:
                                setattr(obj, what, None)
                        obj.save()
                return HttpResponseRedirect('.')
            else:
                raise Http404()

        values = [{
            'id': o.pk,
            'vals': [getattr(o, '_display_{0}'.format(f), getattr(o, f)) for f in formclass.list_fields],
            'rowclass': formclass.get_rowclass(o),
        } for o in objects]

        return render(request, 'confreg/admin_backend_list.html', {
            'conference': conference,
            'basetemplate': basetemplate,
            'topadmin': topadmin,
            'values': values,
            'title': formclass._verbose_name_plural().capitalize(),
            'singular_name': formclass._verbose_name(),
            'plural_name': formclass._verbose_name_plural(),
            'headers': [formclass.get_field_verbose_name(f) for f in formclass.list_fields],
            'coltypes': formclass.coltypes,
            'filtercolumns': formclass.get_column_filters(conference),
            'defaultsort': formclass.numeric_defaultsort(),
            'return_url': return_url,
            'allow_new': allow_new,
            'allow_delete': allow_delete,
            'allow_copy_previous': formclass.allow_copy_previous,
            'allow_email': formclass.allow_email,
            'assignable_columns': formclass.get_assignable_columns(conference),
            'breadcrumbs': breadcrumbs,
            'helplink': formclass.helplink,
        })

    if allow_new and resturl == 'new':
        # This one is more interesting...
        return backend_process_form(request,
                                    urlname,
                                    formclass,
                                    None,
                                    allow_new=True,
                                    allow_delete=allow_delete,
                                    breadcrumbs=breadcrumbs + [('../', formclass._verbose_name_plural().capitalize()), ],
                                    conference=conference,
                                    bypass_conference_filter=bypass_conference_filter,
                                    instancemaker=instancemaker,
                                    topadmin=topadmin,
        )

    restpieces = resturl.split('/')
    if formclass.allow_copy_previous and restpieces[0] == 'copy':
        return backend_handle_copy_previous(request, formclass, restpieces, conference)

    # Is it an id?
    try:
        id = int(restpieces[0])
    except ValueError:
        # No id. So we don't know. Fail.
        raise Http404()

    if len(restpieces) > 2 and restpieces[1] in formclass.linked_objects:
        # We are editing a sub-object!

        handler = formclass.linked_objects[restpieces[1]]
        if conference:
            if hasattr(formclass.Meta, 'conference_queryset'):
                masterobj = formclass.Meta.conference_queryset(conference).get(pk=id)
            else:
                masterobj = formclass.Meta.model.objects.get(pk=id, conference=conference)
        else:
            masterobj = formclass.Meta.model.objects.get(pk=id)

        if restpieces[2] == 'new':
            subid = None
            subobj = None
        else:
            try:
                subid = int(restpieces[2])
                subobj = handler.get_object(masterobj, subid)
                if not subobj:
                    raise Http404()
            except ValueError:
                # No proper subid. So fail.
                raise Http404()

        return backend_process_form(request,
                                    urlname,
                                    handler.get_form(subobj, request.POST),
                                    subid,
                                    breadcrumbs=breadcrumbs + [
                                        ('../../../', formclass._verbose_name_plural().capitalize()),
                                        ('../../', masterobj),
                                    ],
                                    cancel_url='../../',
                                    saved_url='../../',
                                    conference=conference,
                                    bypass_conference_filter=True,
                                    instancemaker=handler.get_instancemaker(masterobj),
                                    topadmin=topadmin,
        )

    if len(restpieces) > 1:
        raise Http404()

    return backend_process_form(request,
                                urlname,
                                formclass,
                                id,
                                allow_delete=allow_delete,
                                breadcrumbs=breadcrumbs + [('../', formclass._verbose_name_plural().capitalize()), ],
                                conference=conference,
                                bypass_conference_filter=bypass_conference_filter,
                                topadmin=topadmin,
    )
Esempio n. 30
0
def backend_handle_copy_previous(request, formclass, restpieces, conference):
    if len(restpieces) == 1:
        # No conference selected yet, so start by doing that
        if request.method == 'POST':
            form = BackendCopySelectConferenceForm(request, conference, formclass.Meta.model, data=request.POST)
            if form.is_valid():
                return HttpResponseRedirect("{0}/".format(form.cleaned_data.get('conference').pk))
        else:
            form = BackendCopySelectConferenceForm(request, conference, formclass.Meta.model)
        return render(request, 'confreg/admin_backend_copy_select_conf.html', {
            'conference': conference,
            'form': form,
            'what': formclass._verbose_name(),
            'savebutton': 'Copy',
            'cancelurl': '../',
            'breadcrumbs': [('../', formclass._verbose_name_plural().capitalize()), ],
            'helplink': formclass.helplink,
        })
    elif len(restpieces) == 2:
        idlist = None
        confirmed_transform_value = None
        confirmed_transform_example = None
        sourceconfid = int(restpieces[1])
        sourceconf = get_authenticated_conference(request, confid=sourceconfid)

        if request.method == "POST":
            idlist = sorted([int(k[2:]) for k, v in list(request.POST.items()) if k.startswith('c_') and v == '1'])
            if formclass.copy_transform_form:
                # First validate the transform form
                transform_form = formclass.copy_transform_form(conference, sourceconf, data=request.POST)
                if transform_form.is_valid():
                    # Transform input is valid, but is it correct?
                    if request.POST.get('confirmed_transform', '') == transform_form.confirm_value():
                        with transaction.atomic():
                            errors = list(formclass.copy_from_conference(conference, sourceconf, idlist, transform_form))
                            if errors:
                                for e in errors:
                                    messages.error(request, e)
                                    transaction.set_rollback(True)
                                    # Fall-through and re-render the form
                            else:
                                return HttpResponseRedirect("../../")
                    else:
                        # Transform input is valid, but it has not been confirmed.
                        confirmed_transform_example = formclass.get_transform_example(conference, sourceconf, idlist, transform_form)
                        if confirmed_transform_example:
                            confirmed_transform_value = transform_form.confirm_value()
                        # Fall-through to re-render the form
            else:
                with transaction.atomic():
                    errors = list(formclass.copy_from_conference(conference, sourceconf, idlist))
                    if errors:
                        for e in errors:
                            messages.error(request, e)
                        transaction.set_rollback(True)
                        transform_form = None
                        # Fall through and re-render our forms
                    else:
                        return HttpResponseRedirect("../../")

        else:
            if formclass.copy_transform_form:
                transform_form = formclass.copy_transform_form(conference, sourceconf)
            else:
                transform_form = None

        objects = formclass.Meta.model.objects.filter(conference=sourceconf)
        if formclass.queryset_extra_fields:
            objects = objects.extra(select=formclass.queryset_extra_fields)
        values = [{'id': o.pk, 'vals': [getattr(o, '_display_{0}'.format(f), getattr(o, f)) for f in formclass.list_fields]} for o in objects]
        return render(request, 'confreg/admin_backend_list.html', {
            'conference': conference,
            'basetemplate': 'confreg/confadmin_base.html',
            'values': values,
            'title': formclass._verbose_name_plural().capitalize(),
            'singular_name': formclass._verbose_name(),
            'plural_name': formclass._verbose_name_plural(),
            'headers': [formclass.get_field_verbose_name(f) for f in formclass.list_fields],
            'coltypes': formclass.coltypes,
            'filtercolumns': formclass.get_column_filters(conference),
            'defaultsort': formclass.numeric_defaultsort(),
            'return_url': '../',
            'allow_new': False,
            'allow_delete': False,
            'allow_copy_previous': False,
            'is_copy_previous': True,
            'transform_form': transform_form,
            'idlist': idlist,
            'confirmed_transform_value': confirmed_transform_value,
            'transform_example': confirmed_transform_example,
            'noeditlinks': True,
            'breadcrumbs': [
                ('../../', formclass._verbose_name_plural().capitalize()),
                ('../', 'Copy {0}'.format(formclass._verbose_name_plural().capitalize())),
            ],
            'helplink': formclass.helplink,
        })