cciw-website2 / cciw / bookings /

from autocomplete.fields import ModelChoiceField
from django.contrib import admin
from django import forms

from cciw.bookings.models import Price, BookingAccount, Booking, ChequePayment, RefundPayment
from cciw.cciwmain.common import get_thisyear
from cciw.utils.views import close_window_response

from .widgets import AccountAutoCompleteWidget

class PriceAdmin(admin.ModelAdmin):
    list_display = ['price_type', 'year', 'price']
    ordering = ['-year', 'price_type']

class BookingAccountForm(forms.ModelForm):

    class Meta:
        model = BookingAccount

    # We need to ensure that email/name/post_code that are blank get saved as
    # NULL, so that they can pass our uniqueness constraints if they are empty
    # (NULLs do not compare equal, but empty strings do)

    def clean_email(self):
        email = self.cleaned_data['email']
        if email == u'':
            email = None
        return email

    def clean_name(self):
        name = self.cleaned_data['name']
        if name == u'':
            name = None
        return name

    def clean_post_code(self):
        post_code = self.cleaned_data['post_code']
        if post_code == u'':
            post_code = None
        return post_code

    def clean(self):
        super(BookingAccountForm, self).clean()
        if (self.cleaned_data['name'] == None and
            self.cleaned_data['email'] == None):
            raise forms.ValidationError("Either name or email must be defined")
        return self.cleaned_data

class BookingAccountAdmin(admin.ModelAdmin):
    list_display = ['id', 'name', 'email', 'post_code', 'phone_number']
    ordering = ['email']
    search_fields = ['email', 'name']
    readonly_fields = ['first_login', 'last_login', 'total_received']
    form = BookingAccountForm

    def get_fieldsets(self, request, obj=None):
        fieldsets = [
        if '_popup' not in request.GET:
                ('Automatically managed',
        return fieldsets

    def response_change(self, request, obj):
        # Little hack to allow popups for changing BookingAccount
        if '_popup' in request.POST:
            return close_window_response()
            return super(BookingAccountAdmin, self).response_change(request, obj)

class YearFilter(admin.SimpleListFilter):
    title = "Year"
    parameter_name = "year"

    def lookups(self, request, model_admin):
        # No easy way to create efficient query with Django's ORM,
        # so hard code first year we did bookings online:
        vals = range(2012, get_thisyear() + 1)
        return [(str(v),str(v)) for v in vals]

    def queryset(self, request, queryset):
        val = self.value()
        if val is None:
            return queryset
        return queryset.filter(camp__year__exact=val)

account_autocomplete_field = \
    lambda: ModelChoiceField('account',

class BookingAdminForm(forms.ModelForm):

    account = account_autocomplete_field()

    def __init__(self, *args, **kwargs):
        super(BookingAdminForm, self).__init__(*args, **kwargs)

    class Meta:
        model = Booking

class BookingAdmin(admin.ModelAdmin):
    def camp(obj):
        return "%s-%s" % (,
    camp.admin_order_field = 'camp__year'
    list_display = ['first_name', 'last_name', 'sex', 'account', camp, 'state', 'confirmed_booking']
    del camp
    search_fields = ['first_name', 'last_name']
    ordering = ['-camp__year', 'camp__number']
    date_hierarchy = 'created'
    list_filter = [YearFilter, 'sex', 'price_type', 'serious_illness', 'south_wales_transport',

    form = BookingAdminForm

    fieldsets = (
          'description': "Enter the account name, then choose from the suggestions, or choose 'New account' if there is no match. Use 'edit' to change the details of a selected account." }),
        ('Camper details',
         {'fields': ['church']}),
        ('Contact details',
        ('GP details',
        ('Medical details',
        ('Camper/parent agree to terms',

class ChequePaymentAdminFormBase(forms.ModelForm):

    account = account_autocomplete_field()

    def clean(self):
        retval = super(ChequePaymentAdminFormBase, self).clean()
        if self.instance is not None and is not None:
            raise forms.ValidationError("Cheque payments cannot be changed "
                                        "after being created. If an error was made, "
                                        "delete this record and create a new one. ")
        return retval

class ChequePaymentAdminForm(ChequePaymentAdminFormBase):

    class Meta:
        model = ChequePayment

class RefundPaymentAdminForm(ChequePaymentAdminFormBase):

    class Meta:
        model = RefundPayment

class ChequePaymentAdminBase(admin.ModelAdmin):
    list_display = ['account', 'amount', 'created']
    search_fields = ['account__name']
    date_hierarchy = 'created'
    fieldsets = [(None,
                       ['account', 'amount', 'created']})]

    def get_readonly_fields(self, request, obj=None):
        if obj is not None:
            return ['account', 'amount', 'created']
            return []

class ChequePaymentAdmin(ChequePaymentAdminBase):
    form = ChequePaymentAdminForm

class RefundPaymentAdmin(ChequePaymentAdminBase):
    form = RefundPaymentAdminForm, PriceAdmin), BookingAccountAdmin), BookingAdmin), ChequePaymentAdmin), RefundPaymentAdmin)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.