Changeset - c56c7498700b
[Not reviewed]
1 4 1
Christopher Neugebauer - 8 years ago 2016-04-26 09:11:06
chrisjrn@gmail.com
Prepares registrasion-demo to match the 0.1 release of registrasion.
6 files changed with 29 insertions and 68 deletions:
0 comments (0 inline, 0 general)
README.md
Show inline comments
 
deleted file
README.rst
Show inline comments
 
new file 100644
 
registrasion-demo
 
=================
 

	
 
PinaxCon
 
---------
 
`PinaxCon` is a working demo of Symposion and the Symposion Starter Project. It usually lives at https://github.com/pinax/PinaxCon
 

	
 
This is a fork of PinaxCon to demonstrate Registrasion, a registration package that works well with Symposion. You can find Registrasion at https://github.com/chrisjrn/registrasion
 

	
 
Registrasion has relaively complete docs at http://registrasion.readthedocs.org
 

	
 

	
 
What is the point of this?
 
--------------------------
 
This project provides some starter templates for much of the functionality of Registrasion, as well as demos of how to make payments and enter user profiles.
 

	
 
If you care to, you can also use this project as a starting point for your own Registrasion-based site.
fixtures/registrasion.json
Show inline comments
 
[
 
{
 
  "model": "registrasion.category",
 
  "pk": 1,
 
  "fields": {
 
    "name": "Ticket",
 
    "description": "Admission to the conference",
 
    "limit_per_user": 1,
 
    "required": false,
 
    "order": 1,
 
    "render_type": 1
 
  }
 
},
 
{
 
  "model": "registrasion.category",
 
  "pk": 2,
 
  "fields": {
 
    "name": "Dinner Ticket",
 
    "description": "Tickets for the conference dinner",
 
    "limit_per_user": null,
 
    "required": false,
 
    "order": 10,
 
    "render_type": 2
 
  }
 
},
 
{
 
  "model": "registrasion.category",
 
  "pk": 3,
 
  "fields": {
 
    "name": "T-shirt",
 
    "description": "The conference t-shirt",
 
    "limit_per_user": null,
 
    "required": false,
 
    "order": 30,
 
    "render_type": 2
 
  }
 
},
 
{
 
  "model": "registrasion.category",
 
  "pk": 4,
 
  "fields": {
 
    "name": "Accommodation",
 
    "description": "Accommodation in the student dormitories",
 
    "limit_per_user": null,
 
    "required": false,
 
    "order": 40,
 
    "render_type": 2
 
  }
 
},
 
{
 
  "model": "registrasion.category",
 
  "pk": 5,
 
  "fields": {
 
    "name": "Extra accommodation nights",
 
    "description": "Extra nights at the student dorms. You will need to purchase the week block before you can add extra nights",
 
    "limit_per_user": null,
 
    "required": false,
 
    "order": 50,
 
    "render_type": 2
 
  }
 
},
 
{
 
  "model": "registrasion.product",
 
  "pk": 1,
 
  "fields": {
 
    "name": "Professional",
 
    "description": "",
 
    "category": 1,
 
    "price": "1000.00",
 
    "limit_per_user": null,
 
    "reservation_duration": "1 00:00:00",
 
    "order": 10
 
  }
 
},
 
{
 
  "model": "registrasion.product",
 
  "pk": 2,
 
  "fields": {
 
    "name": "Enthusiast",
 
    "description": "",
 
    "category": 1,
 
    "price": "450.00",
 
    "limit_per_user": null,
 
    "reservation_duration": "1 00:00:00",
 
    "order": 20
 
  }
 
},
 
{
 
  "model": "registrasion.product",
 
  "pk": 3,
 
  "fields": {
 
    "name": "Student",
 
    "description": "",
 
    "category": 1,
 
    "price": "160.00",
 
    "limit_per_user": null,
 
    "reservation_duration": "1 00:00:00",
 
    "order": 30
 
  }
 
},
 
{
 
  "model": "registrasion.product",
 
  "pk": 4,
 
  "fields": {
 
    "name": "Adult",
 
    "description": "Includes a full meal and drinks",
 
    "category": 2,
 
    "price": "85.00",
 
    "limit_per_user": null,
 
    "reservation_duration": "01:00:00",
 
    "order": 10
 
  }
 
},
 
{
 
  "model": "registrasion.product",
 
  "pk": 5,
 
  "fields": {
 
    "name": "Child",
 
    "description": "Includes a children's meal and soft drinks",
 
    "category": 2,
 
    "price": "40.00",
 
    "limit_per_user": null,
 
    "reservation_duration": "01:00:00",
 
    "order": 20
 
  }
 
},
 
{
 
  "model": "registrasion.product",
 
  "pk": 6,
 
  "fields": {
 
    "name": "Infant",
 
    "description": "A seat for an infant in lap",
 
    "category": 2,
 
    "price": "0.00",
 
    "limit_per_user": null,
 
    "reservation_duration": "01:00:00",
 
    "order": 30
 
  }
 
},
 
{
 
  "model": "registrasion.product",
 
  "pk": 7,
 
  "fields": {
 
    "name": "S",
 
    "description": "",
 
    "category": 3,
 
    "price": "25.00",
 
    "limit_per_user": null,
 
    "reservation_duration": "01:00:00",
 
    "order": 10
 
  }
 
},
 
{
 
  "model": "registrasion.product",
 
  "pk": 8,
 
  "fields": {
 
    "name": "M",
 
    "description": "",
 
    "category": 3,
 
    "price": "25.00",
 
    "limit_per_user": null,
 
    "reservation_duration": "01:00:00",
 
    "order": 20
 
  }
 
},
 
{
 
  "model": "registrasion.product",
 
  "pk": 9,
 
  "fields": {
 
    "name": "L",
 
    "description": "",
 
    "category": 3,
 
    "price": "25.00",
 
    "limit_per_user": null,
 
    "reservation_duration": "01:00:00",
 
    "order": 30
 
  }
 
},
 
{
 
  "model": "registrasion.product",
 
  "pk": 10,
 
  "fields": {
 
    "name": "Sunday 19-Saturday 25",
 
    "description": "6 nights",
 
    "category": 4,
 
    "price": "480.00",
 
    "limit_per_user": null,
 
    "reservation_duration": "01:00:00",
 
    "order": 1
 
  }
 
},
 
{
 
  "model": "registrasion.product",
 
  "pk": 11,
 
  "fields": {
 
    "name": "Friday 17",
 
    "description": "",
 
    "category": 5,
 
    "price": "80.00",
 
    "limit_per_user": null,
 
    "reservation_duration": "01:00:00",
 
    "order": 10
 
  }
 
},
 
{
 
  "model": "registrasion.product",
 
  "pk": 12,
 
  "fields": {
 
    "name": "Saturday 18",
 
    "description": "",
 
    "category": 5,
 
    "price": "80.00",
 
    "limit_per_user": null,
 
    "reservation_duration": "01:00:00",
 
    "order": 20
 
  }
 
},
 
{
 
  "model": "registrasion.product",
 
  "pk": 13,
 
  "fields": {
 
    "name": "Saturday 25",
 
    "description": "",
 
    "category": 5,
 
    "price": "80.00",
 
    "limit_per_user": null,
 
    "reservation_duration": "01:00:00",
 
    "order": 30
 
  }
 
},
 
{
 
  "model": "registrasion.product",
 
  "pk": 14,
 
  "fields": {
 
    "name": "Sunday 26",
 
    "description": "",
 
    "category": 5,
 
    "price": "80.00",
 
    "limit_per_user": null,
 
    "reservation_duration": "01:00:00",
 
    "order": 40
 
  }
 
},
 
{
 
  "model": "registrasion.voucher",
 
  "pk": 1,
 
  "fields": {
 
    "recipient": "FooCorp",
 
    "code": "FOOCORP",
 
    "limit": 10
 
  }
 
},
 
{
 
  "model": "registrasion.discountbase",
 
  "pk": 1,
 
  "fields": {
 
    "description": "Early bird discount"
 
  }
 
},
 
{
 
  "model": "registrasion.discountbase",
 
  "pk": 2,
 
  "fields": {
 
    "description": "FooCorp complimentary sponsor ticket"
 
  }
 
},
 
{
 
  "model": "registrasion.discountbase",
 
  "pk": 3,
 
  "fields": {
 
    "description": "1 Dinner Ticket included with Professional Tickets"
 
  }
 
},
 
{
 
  "model": "registrasion.discountbase",
 
  "pk": 4,
 
  "fields": {
 
    "description": "1 T-Shirt included with all tickets"
 
  }
 
},
 
{
 
  "model": "registrasion.discountforproduct",
 
  "pk": 1,
 
  "fields": {
 
    "discount": 1,
 
    "product": 1,
 
    "percentage": null,
 
    "price": "200.00",
 
    "quantity": 1
 
  }
 
},
 
{
 
  "model": "registrasion.discountforproduct",
 
  "pk": 2,
 
  "fields": {
 
    "discount": 1,
 
    "product": 2,
 
    "percentage": null,
 
    "price": "100.00",
 
    "quantity": 1
 
  }
 
},
 
{
 
  "model": "registrasion.discountforproduct",
 
  "pk": 3,
 
  "fields": {
 
    "discount": 2,
 
    "product": 1,
 
    "percentage": "100.0",
 
    "price": null,
 
    "quantity": 1
 
  }
 
},
 
{
 
  "model": "registrasion.discountforcategory",
 
  "pk": 1,
 
  "fields": {
 
    "discount": 3,
 
    "category": 2,
 
    "percentage": "100.0",
 
    "quantity": 1
 
  }
 
},
 
{
 
  "model": "registrasion.discountforcategory",
 
  "pk": 2,
 
  "fields": {
 
    "discount": 4,
 
    "category": 3,
 
    "percentage": "100.0",
 
    "quantity": 1
 
  }
 
},
 
{
 
  "model": "registrasion.timeorstocklimitdiscount",
 
  "pk": 1,
 
  "fields": {
 
    "start_time": null,
 
    "end_time": null,
 
    "limit": 10
 
  }
 
},
 
{
 
  "model": "registrasion.voucherdiscount",
 
  "pk": 2,
 
  "fields": {
 
    "voucher": 1
 
  }
 
},
 
{
 
  "model": "registrasion.includedproductdiscount",
 
  "pk": 3,
 
  "fields": {
 
    "enabling_products": [
 
      1
 
    ]
 
  }
 
},
 
{
 
  "model": "registrasion.includedproductdiscount",
 
  "pk": 4,
 
  "fields": {
 
    "enabling_products": [
 
      1,
 
      2,
 
      3
 
    ]
 
  }
 
},
 
{
 
  "model": "registrasion.enablingconditionbase",
 
  "model": "registrasion.flagbase",
 
  "pk": 1,
 
  "fields": {
 
    "description": "Extra accommodation depends on Accommodation",
 
    "condition": 2,
 
    "products": [],
 
    "categories": [
 
      5
 
    ]
 
  }
 
},
 
{
 
  "model": "registrasion.categoryflag",
 
  "pk": 1,
 
  "fields": {
 
    "enabling_category": 4,
 
    "products": [],
 
    "categories": [
 
      5
 
    ]
 
  }
 
}
 
]
pinaxcon/registrasion/models.py
Show inline comments
 
from django.db import models
 
from registrasion import models as rego
 

	
 
class AttendeeProfile(rego.AttendeeProfileBase):
 

	
 
    @classmethod
 
    def name_field(cls):
 
        ''' This is used to pre-fill the attendee's name from the
 
        speaker profile. If it's None, that functionality is disabled. '''
 
        return "name"
 

	
 
    def invoice_recipient(self):
 
        if self.company:
 
            base = "%(name_per_invoice)s c/- %(company)s"
 
            base = "\n%(company)s\nAttention: %(name_per_invoice)s"
 
        else:
 
            base = "%(name_per_invoice)s"
 
        return base % self.__dict__
 

	
 
    def save(self):
 
        if not self.name_per_invoice:
 
            self.name_per_invoice = self.name
 
        super(AttendeeProfile, self).save()
 

	
 
    # Things that appear on badge
 
    name = models.CharField(
 
        verbose_name="Your name (for your conference nametag)",
 
        max_length=64,
 
        help_text="Your name, as you'd like it to appear on your badge. ",
 
    )
 

	
 
    company = models.CharField(
 
        max_length=64,
 
        help_text="The name of your company, as you'd like it on your badge",
 
        blank=True,
 
    )
 
    free_text_1 = models.CharField(
 
        max_length=64,
 
        verbose_name="Free text line 1",
 
        help_text="A line of free text that will appear on your badge. Use "
 
                  "this for your Twitter handle, IRC nick, your preferred "
 
                  "pronouns or anything else you'd like people to see on "
 
                  "your badge.",
 
        blank=True,
 
    )
 
    free_text_2 = models.CharField(
 
        max_length=64,
 
        verbose_name="Free text line 2",
 
        blank=True,
 
    )
 

	
 
    # Other important Information
 
    name_per_invoice = models.CharField(
 
        verbose_name="Your legal name (for invoicing purposes)",
 
        max_length=64,
 
        help_text="If your legal name is different to the name on your badge, "
 
                  "fill this in, and we'll put it on your invoice. Otherwise, "
 
                  "leave it blank.",
 
        blank=True,
 
        )
 
    of_legal_age = models.BooleanField(
 
        default=False,
 
        verbose_name="18+?",
 
        blank=True,
 
    )
 
    dietary_requirements = models.CharField(
 
        max_length=256,
 
        blank=True,
 
    )
 
    accessibility_requirements = models.CharField(
 
        max_length=256,
 
        blank=True,
 
    )
 
    gender = models.CharField(
 
        max_length=64,
 
        blank=True,
 
    )
 

	
 

	
 
class DemoPayment(rego.PaymentBase):
 
    ''' A subclass of PaymentBase for use in our demo payments function. '''
 

	
 
    pass  # No custom features here, but yours could be here.
pinaxcon/templates/registrasion/invoice.html
Show inline comments
 
{% extends "site_base.html" %}
 
{% load bootstrap %}
 
{% load registrasion_tags %}
 
{% block body %}
 

	
 

	
 
{% if invoice.is_unpaid %}
 
  <p><strong>NOTICE:</strong> The below invoice is automatically generated, and will be voided
 
    if you amend your registration before payment, or if discounts or products contained in the
 
    invoice become unavailable. The items and discounts are only reserved until
 
    the invoice due time.</p>
 

	
 
  {% url "invoice_access" invoice.user.attendee.access_code as access_url %}
 
  <p>Your most recent unpaid invoice will be available at
 
    <a href="{{ access_url }}">{{ request.scheme }}://{{ request.get_host }}{{ access_url }}</a>
 
    You can give this URL to your accounts department to pay your registration.</p>
 

	
 
  <div>
 
    <a class="btn btn-default" href="{% url "demopay" invoice.id invoice.user.attendee.access_code %}">Pay this invoice</a>
 
    {% if user.is_staff %}
 
      <a class="btn btn-default" href="{% url "manual_payment" invoice.id %}">Apply manual payment</a>
 
    {% endif %}
 
  </div>
 
{% elif invoice.is_paid %}
 
  {% if user.is_staff %}
 
  <div>
 
    {% if user.is_staff %}
 
      <a class="btn btn-default" href="{% url "manual_payment" invoice.id %}">Apply manual payment/refund</a>
 
    <a class="btn btn-default" href="{% url "manual_payment" invoice.id %}">Apply manual payment/refund</a>
 
    <a class="btn btn-default" href="{% url "refund" invoice.id %}">Refund by issuing credit note</a>
 
    {% endif %}
 
  </div>
 
  {% endif %}
 
{% endif %}
 

	
 
<hr />
 

	
 
<h2>Invoice</h2>
 

	
 
{% with invoice_user=invoice.cart.user %}
 
  <ul>
 
    <li><strong>Invoice number:</strong> {{ invoice.id }}
 
    <li><strong>Invoice status:</strong> {{ invoice.get_status_display }}</li>
 
    <li><strong>Issue date:</strong> {{ invoice.issue_time|date:"DATE_FORMAT" }}
 
    {% if not invoice.is_void %}
 
      <li><strong>Due:</strong> {{ invoice.due_time|date:"DATETIME_FORMAT"}}</li>
 
    {% endif %}
 
    <li><strong>Attention:</strong> {{ invoice_user.attendee.attendeeprofilebase.invoice_recipient }}</li>
 
    <li><strong>Recipient:</strong> {{ invoice_user.attendee.attendeeprofilebase.invoice_recipient|linebreaksbr}}</li>
 
  </ul>
 
{% endwith %}
 

	
 
<p>This invoice has been issued as a result of an application to attend (conference name).</p>
 

	
 

	
 
<table class="table table-striped">
 
  <tr>
 
    <th>Description</th>
 
    <th class="text-right">Quantity</th>
 
    <th class="text-right">Price/Unit</th>
 
    <th class="text-right">Total</th>
 
  </tr>
 
  {% for line_item in invoice.lineitem_set.all %}
 
    <tr>
 
      <td>{{ line_item.description }}</td>
 
      <td class="text-right">{{ line_item.quantity }}</td>
 
      <td class="text-right">${{ line_item.price }}</td>
 
      <td class="text-right">${{ line_item.price|multiply:line_item.quantity }}</td>
 
    </tr>
 
  {% endfor %}
 
  <tr>
 
    <th>TOTAL</th>
 
    <td></td>
 
    <td></td>
 
    <td class="text-right">${{ invoice.value }}</td>
 
  </tr>
 
</table>
 

	
 
{% if invoice.paymentbase_set.all %}
 
<h4>Payments received</h4>
 
{% include "registrasion/payment_list.html" with payments=invoice.paymentbase_set.all %}
 
{% endif %}
 

	
 
{% endblock %}
requirements.txt
Show inline comments
 
Django==1.9.2
 
pinax-theme-bootstrap==7.3.0
 
django-user-accounts==1.3.1
 
metron==1.3.7
 
pinax-eventlog==1.1.1
 
dj-static==0.0.6
 
dj-database-url==0.4.0
 
pinax-pages==0.4.2
 
pinax-boxes==2.1.2
 

	
 
# run off of master for now
 
git+https://github.com/pinax/symposion.git
 
git+https://github.com/chrisjrn/registrasion.git@demo_site_integration
 
# For testing
 
django-nose==1.4.3
 
coverage==4.0.3
 

	
 
# Registrasion
 
registrasion==0.1.0
 
https://github.com/pinax/symposion/tarball/ad81810#egg=symposion
0 comments (0 inline, 0 general)