# HG changeset patch # User Madhusudan.C.S # Date 1290077188 -19800 # Node ID 325ec5a4126975241a1b0bafc94802231f881557 # Parent 2d47a3eb5ec4bb6000c794522c23e6cd2d06e361# Parent 679a9cab4bf1e5f148ddf202451d2d674f773408 Merge payments branch with the default mainline branch. diff -r 679a9cab4bf1 -r 325ec5a41269 .hgignore --- a/.hgignore Thu Nov 18 16:10:38 2010 +0530 +++ b/.hgignore Thu Nov 18 16:16:28 2010 +0530 @@ -39,4 +39,5 @@ project/static/media project/scipycon/user/*.pyc apache/* +*.db diff -r 679a9cab4bf1 -r 325ec5a41269 project/development.py --- a/project/development.py Thu Nov 18 16:10:38 2010 +0530 +++ b/project/development.py Thu Nov 18 16:16:28 2010 +0530 @@ -28,7 +28,7 @@ ) DATABASE_ENGINE = 'sqlite3' -DATABASE_NAME = 'scipycon.db' +DATABASE_NAME = 'scipyconpayment.db' DATABASE_USER = '' DATABASE_PASSWORD = '' diff -r 679a9cab4bf1 -r 325ec5a41269 project/scipycon/registration/forms.py --- a/project/scipycon/registration/forms.py Thu Nov 18 16:10:38 2010 +0530 +++ b/project/scipycon/registration/forms.py Thu Nov 18 16:16:28 2010 +0530 @@ -4,6 +4,7 @@ from project.scipycon.registration.models import SIZE_CHOICES from project.scipycon.registration.models import OCCUPATION_CHOICES from project.scipycon.registration.models import Accommodation +from project.scipycon.registration.models import Payment from project.scipycon.registration.models import Wifi @@ -61,7 +62,7 @@ id = forms.CharField(widget=forms.HiddenInput) class WifiForm(forms.ModelForm): - """PyCon wifi form + """SciPyCon wifi form """ def save(self, user, scope): @@ -82,7 +83,7 @@ class AccommodationForm(forms.ModelForm): - """PyCon Accommodation form + """SciPyCon Accommodation form """ def save(self, user, scope): @@ -128,6 +129,52 @@ fields = ('accommodation_required', 'sex', 'accommodation_days') +class PaymentForm(forms.ModelForm): + """SciPyCon Payment form + """ + + paid = forms.BooleanField( + required=False, label="Amount paid", + help_text="Check this box if you have already paid the fees.") + + def save(self, user, scope): + try: + payment = Payment.objects.get(user=user, scope=scope) + except ObjectDoesNotExist: + payment = Payment(user=user, scope=scope) + + paid = self.cleaned_data['paid'] + type = self.cleaned_data['type'] + details = self.cleaned_data['details'] + + payment.type = type + payment.details = details + + payment.save() + + return payment + + def clean(self): + """Makes sure that payment form is correct, i.e. type and details + are filled in when the required fees is paid. + """ + + paid = self.cleaned_data['paid'] + type = self.cleaned_data['type'] + details = self.cleaned_data['details'] + + if paid and (not type or not details): + raise forms.ValidationError( + u"If you have already paid the fee it is mandatory to " + "fill in the type and mandatory fields.") + + return super(PaymentForm, self).clean() + + class Meta: + model = Payment + fields = ('paid', 'type', 'details') + + PC = ( ('all', 'all'), ('paid', 'paid'), diff -r 679a9cab4bf1 -r 325ec5a41269 project/scipycon/registration/models.py --- a/project/scipycon/registration/models.py Thu Nov 18 16:10:38 2010 +0530 +++ b/project/scipycon/registration/models.py Thu Nov 18 16:16:28 2010 +0530 @@ -30,6 +30,12 @@ ('Female', 'Female'), ) +PAYMENT_MODE_CHOICES = ( + ('Cheque', 'Cheque'), + ('Demand Draft(DD)', 'Demand Draft(DD)'), + ('Net Banking', 'Net Banking') + ) + class Wifi(base_models.ScopedBase): """Defines wifi options at SciPy.in @@ -117,4 +123,25 @@ self.registrant.last_name, self.registrant.email) +class Payment(base_models.ScopedBase): + """Defines payment information for SciPy.in registrants + """ + user = models.ForeignKey(User) + + confirmed = models.BooleanField( + default=False, blank=True) + + type = models.CharField(max_length=25, choices=PAYMENT_MODE_CHOICES, + verbose_name="Type", blank=True, null=True) + + details = models.CharField( + max_length=255, verbose_name="Details", + help_text="If the payment mode was cheque or DD please provide " + "the cheque or DD number and the name of the bank " + "and branch. Example: 4536234, SBI, IIT Powai, Mumbai.
" + "If the payment mode was Net Banking please provide the last four digits of the account number and the name " + "of the account holder and the bank name from which the " + "transfer was made. Example: 8804, Harish Chandra", + blank=True, null=True) diff -r 679a9cab4bf1 -r 325ec5a41269 project/scipycon/registration/views.py --- a/project/scipycon/registration/views.py Thu Nov 18 16:10:38 2010 +0530 +++ b/project/scipycon/registration/views.py Thu Nov 18 16:16:28 2010 +0530 @@ -12,8 +12,10 @@ from project.scipycon.registration.forms import RegistrationEditForm from project.scipycon.registration.forms import RegistrationSubmitForm from project.scipycon.registration.forms import AccommodationForm +from project.scipycon.registration.forms import PaymentForm from project.scipycon.registration.forms import WifiForm from project.scipycon.registration.models import Accommodation +from project.scipycon.registration.models import Payment from project.scipycon.registration.models import Registration from project.scipycon.registration.models import Wifi from project.scipycon.registration.utils import send_confirmation @@ -59,11 +61,13 @@ reg = Registration.objects.get(pk=int(id)) wifi = Wifi.objects.get(user=reg.registrant) - # TODO: This is an ugly hack to add accommodation form - # details at later stage for SciPy.in 2010. This must be - # removed for SciPy.in 2011 - acco, created = Accommodation.objects.get_or_create(user=reg.registrant, - scope=scope_entity) + # TODO: This is an ugly hack to add accommodation and payment forms + # details at later stage for SciPy.in 2010. This must be removed for + # SciPy.in 2011 + acco, acco_created = Accommodation.objects.get_or_create( + user=reg.registrant, scope=scope_entity) + payment, payment_created = Payment.objects.get_or_create( + user=reg.registrant, scope=scope_entity) if reg.registrant != request.user: redirect_to = reverse('scipycon_account', kwargs={'scope': scope}) @@ -77,9 +81,10 @@ registration_form = RegistrationEditForm(data=request.POST) wifi_form = WifiForm(data=request.POST) acco_form = AccommodationForm(data=request.POST) + payment_form = PaymentForm(data=request.POST) if (registration_form.is_valid() and wifi_form.is_valid() and - acco_form.is_valid()): + acco_form.is_valid() and payment_form.is_valid()): reg.organisation = registration_form.data.get('organisation') reg.occupation = registration_form.data.get('occupation') reg.city = registration_form.data.get('city') @@ -98,6 +103,7 @@ wifi = wifi_form.save(reg.registrant, reg.scope) acco = acco_form.save(reg.registrant, reg.scope) + payment = payment_form.save(reg.registrant, reg.scope) # Saved.. redirect redirect_to = reverse('scipycon_account', kwargs={'scope': scope}) @@ -131,6 +137,13 @@ 'accommodation_required': acco.accommodation_required, 'accommodation_days': acco.accommodation_days, }) + payment_form = PaymentForm(initial={ + 'user': payment.user, + 'scope': payment.scope, + 'paid': payment.type or payment.details, + 'type': payment.type, + 'details': payment.details, + }) return render_to_response( template_name, RequestContext(request, { @@ -138,7 +151,8 @@ 'registration': {'id': id}, 'registration_form': registration_form, 'wifi_form': wifi_form, - 'acco_form': acco_form})) + 'acco_form': acco_form, + 'payment_form': payment_form})) def submit_registration(request, scope, template_name='registration/submit-registration.html'): @@ -176,6 +190,7 @@ registrant_form = RegistrantForm(data=request.POST) wifi_form = WifiForm(data=request.POST) acco_form = AccommodationForm(data=request.POST) + payment_form = PaymentForm(data=request.POST) if request.POST.get('action', None) == 'login': login_form = AuthenticationForm(data=request.POST) @@ -211,7 +226,7 @@ newuser = user if (registration_form.is_valid() and newuser and wifi_form.is_valid() - and acco_form.is_valid()): + and acco_form.is_valid() and payment_form.is_valid()): allow_contact = registration_form.cleaned_data.get( 'allow_contact') and True or False conference = registration_form.cleaned_data.get( @@ -247,7 +262,10 @@ wifi = wifi_form.save(registrant, scope_entity) acco = acco_form.save(registrant, scope_entity) + payment = payment_form.save(registrant, scope_entity) + send_confirmation(registrant, scope_entity, password=passwd) + redirect_to = reverse('scipycon_registrations', kwargs={'scope': scope}) return set_message_cookie(redirect_to, @@ -259,6 +277,7 @@ registrant_form = RegistrantForm() wifi_form = WifiForm() acco_form = AccommodationForm() + payment_form = PaymentForm() login_form = AuthenticationForm() @@ -269,6 +288,7 @@ 'registrant_form' : registrant_form, 'over_reg' : reg_count >= REG_TOTAL and True or False, 'acco_form': acco_form, + 'payment_form': payment_form, 'wifi_form' : wifi_form, 'message' : message, 'login_form' : login_form @@ -283,7 +303,9 @@ if not request.user.is_staff: redirect_to = reverse('scipycon_login', kwargs={'scope': scope}) - + return set_message_cookie( + redirect_to, msg = u'You must be a staff on this website to ' + 'access this page.') q = Registration.objects.all() conf_num = q.filter(conference=True).count() @@ -296,3 +318,56 @@ 'tut_num': tut_num, 'sprint_num': sprint_num, })) + + +@login_required +def manage_payments(request, scope, + template_name='registration/manage_payments.html'): + """View that gives a form to manage payments. + """ + + if not request.user.is_superuser: + redirect_to = reverse('scipycon_login', kwargs={'scope': scope}) + return set_message_cookie( + redirect_to, msg = u'You must be an admin on this website to ' + 'access this page.') + + message = None + + scope_entity = Event.objects.get(scope=scope) + + if request.method == 'POST': + post_data = request.POST + list_user_ids = [] + for user_id_string in post_data: + id_str_list = user_id_string.split('_') + if (len(id_str_list) == 3 and id_str_list[0] == 'registrant' and + id_str_list[1] == 'id'): + id = int(id_str_list[2]) + reg_user = User.objects.get(pk=id) + + payment, created = reg_user.payment_set.get_or_create( + user=reg_user, scope=scope_entity) + + payment.confirmed = True + payment.save() + + list_user_ids.append(id) + + # This is done to unset for the confirmation for users for whom + # mistakenly confirmation was set. + # (TODO) This is a very expensive operation, any better solution + # will be appreciated. + unpaid_users = User.objects.exclude(pk__in=list_user_ids) + for user in unpaid_users: + payment, created = user.payment_set.get_or_create( + user=user, scope=scope_entity) + payment.confirmed = False + payment.save() + + registrants = Registration.objects.all() + + return render_to_response(template_name, RequestContext(request, + {'params': {'scope': scope}, + 'registrants': registrants, + })) diff -r 679a9cab4bf1 -r 325ec5a41269 project/static/css/styles.css --- a/project/static/css/styles.css Thu Nov 18 16:10:38 2010 +0530 +++ b/project/static/css/styles.css Thu Nov 18 16:16:28 2010 +0530 @@ -583,4 +583,9 @@ color: #58585a; margin-left: 5em; text-align: justify; +} + +label.alert { + font-size: 1.2em; + color: #ff0000; } \ No newline at end of file diff -r 679a9cab4bf1 -r 325ec5a41269 project/templates/registration/manage_payments.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project/templates/registration/manage_payments.html Thu Nov 18 16:16:28 2010 +0530 @@ -0,0 +1,47 @@ +{% extends "base.html" %} + +{% block title %}Manage Payments - {% endblock %} + +{% block content %} +

Manage Payments

+ +
+ +
+ Payment Details + + {% for registrant in registrants %} + + + + + {% endfor %} + + + +
+ + + {{ field.errors }} +
+
+ +
+
+ +
+{% endblock content %} diff -r 679a9cab4bf1 -r 325ec5a41269 project/templates/registration/regstats.html --- a/project/templates/registration/regstats.html Thu Nov 18 16:10:38 2010 +0530 +++ b/project/templates/registration/regstats.html Thu Nov 18 16:16:28 2010 +0530 @@ -1,6 +1,6 @@ {% extends "base.html" %} -{% block title %}Registration Statistics{% endblock %} +{% block title %}Registration Statistics - {% endblock %} {% block content %}

Registration Statistics

diff -r 679a9cab4bf1 -r 325ec5a41269 project/templates/registration/submit-registration.html --- a/project/templates/registration/submit-registration.html Thu Nov 18 16:10:38 2010 +0530 +++ b/project/templates/registration/submit-registration.html Thu Nov 18 16:16:28 2010 +0530 @@ -19,6 +19,20 @@ $('#id_sex').removeAttr('disabled'); } }); + + if (!$('#id_paid').is(':checked')) { + $('#id_type').attr('disabled', 'disabled'); + $('#id_details').attr('disabled', 'disabled'); + } + $('#id_paid').change(function() { + if (!$('#id_paid').is(':checked')) { + $('#id_type').attr('disabled', 'disabled'); + $('#id_details').attr('disabled', 'disabled'); + } else { + $('#id_type').removeAttr('disabled'); + $('#id_details').removeAttr('disabled'); + } + }); }); @@ -147,6 +161,13 @@
+ Payment + + {{ payment_form }} +
+
+ +
Others {{ wifi_form }} diff -r 679a9cab4bf1 -r 325ec5a41269 project/urls.py --- a/project/urls.py Thu Nov 18 16:10:38 2010 +0530 +++ b/project/urls.py Thu Nov 18 16:16:28 2010 +0530 @@ -51,8 +51,10 @@ 'submit_registration', name='scipycon_submit_registration'), url(r'^%s/edit-registration/(?P\d+)/$' % (SCOPE_ARG_PATTERN), 'edit_registration', name='scipycon_edit_registration'), - url(r'^%s/regstats/'% (SCOPE_ARG_PATTERN), + url(r'^%s/regstats/$'% (SCOPE_ARG_PATTERN), 'regstats', name="scipycon_regstats"), + url(r'^%s/manage_payments/$'% (SCOPE_ARG_PATTERN), + 'manage_payments', name="scipycon_manage_payments"), ) # Authentication and Profile