changeset 35:f77a1cdd7a46

Donations: first cut at a donations view and a form built for paypal.
author Brian Neal <bgneal@gmail.com>
date Sun, 07 Jun 2009 00:22:50 +0000
parents d5d7e510ecd7
children 296b610ee507
files gpp/donations/models.py gpp/donations/urls.py gpp/donations/views.py gpp/settings.py gpp/templates/donations/index.html gpp/urls.py
diffstat 6 files changed, 178 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/gpp/donations/models.py	Thu Jun 04 02:22:55 2009 +0000
+++ b/gpp/donations/models.py	Sun Jun 07 00:22:50 2009 +0000
@@ -6,19 +6,21 @@
 
 from django.db import models
 from django.contrib import auth
+from django.conf import settings
 
-ANONYMOUS = u'Anonymous'
 
 class DonationManager(models.Manager):
     def monthly_stats(self, year=None, month=None):
         """
-        Returns a dictionary of statistics for the given month in the given
+        Returns a tuple of items for the given month in the given
         year. If year is None, the current year is used. If month is None,
         the current month is used.
-        The returned dict has the following keys:
+        The returned tuple has the following items, in order:
+            (gross, net, donations)
+        where:
             'gross': total gross donations
             'net': total net donations
-            'donors': list of donor names
+            'donations': list of donation objects
         """
         today = datetime.date.today()
         if year is None:
@@ -28,19 +30,17 @@
 
         qs = self.filter(payment_date__year=year,
                 payment_date__month=month,
-                test_ipn=False)
+                test_ipn=False).select_related('user')
 
-        stats = {
-            'gross': decimal.Decimal(), 
-            'net': decimal.Decimal(), 
-            'donors': [],
-            }
+        gross = decimal.Decimal()
+        net = decimal.Decimal()
+        donations = []
         for donation in qs:
-            stats['gross'] += donation.mc_gross
-            stats['net'] += donation.mc_gross - donation.mc_fee
-            stats['donors'].append(donation.donor())
+            gross += donation.mc_gross
+            net += donation.mc_gross - donation.mc_fee
+            donations.append(donation)
 
-        return stats
+        return gross, net, donations
 
 
 class Donation(models.Model):
@@ -71,19 +71,14 @@
             return u'%s from %s' % (self.mc_gross, self.user.username)
         return u'%s from %s %s' % (self.mc_gross, self.first_name, self.last_name)
 
-    def save(self, *args, **kwargs):
-        if self.user is None:
-            self.is_anonymous = True
-        super(Donation, self).save(*args, **kwargs)
-
     def donor(self):
         """Returns the donor name for the donation."""
         if self.is_anonymous:
-            return ANONYMOUS
+            return settings.DONATIONS_ANON_NAME
         if self.user is not None:
             return self.user.username
         if self.first_name or self.last_name:
             name = u'%s %s' % (self.first_name, self.last_name)
             return name.strip()
-        return ANONYMOUS
+        return settings.DONATIONS_ANON_NAME
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gpp/donations/urls.py	Sun Jun 07 00:22:50 2009 +0000
@@ -0,0 +1,10 @@
+"""
+URLs for the donations application.
+"""
+from django.conf.urls.defaults import *
+
+urlpatterns = patterns('donations.views',
+    url(r'^$', 'index', name='donations-index'),
+    url(r'^ipn/$', 'ipn', name='donations-ipn'),
+    url(r'^thanks/$', 'thanks', name='donations-thanks'),
+)
--- a/gpp/donations/views.py	Thu Jun 04 02:22:55 2009 +0000
+++ b/gpp/donations/views.py	Sun Jun 07 00:22:50 2009 +0000
@@ -1,1 +1,46 @@
-# Create your views here.
+"""
+Views for the donations application.
+"""
+from django.shortcuts import render_to_response
+from django.template import RequestContext
+from django.http import Http404     # TODO: remove
+from django.conf import settings
+from django.contrib.sites.models import Site
+
+from donations.models import Donation
+
+
+def index(request):
+    gross, net, donations = Donation.objects.monthly_stats()
+    current_site = Site.objects.get_current()
+
+    if settings.DEBUG:
+        form_action = 'https://www.sandbox.paypal.com/cgi-bin/webscr'
+        business = settings.DONATIONS_BUSINESS_DEBUG
+    else:
+        form_action = 'https://www.paypal.com/cgi-bin/webscr'
+        business = settings.DONATIONS_BUSINESS
+
+    return render_to_response('donations/index.html', {
+        'goal': settings.DONATIONS_GOAL,
+        'gross': gross,
+        'net': net,
+        'left': settings.DONATIONS_GOAL - net,
+        'donations': donations,
+        'form_action': form_action,
+        'business': business,
+        'anonymous': settings.DONATIONS_ANON_NAME,
+        'item_name': settings.DONATIONS_ITEM_NAME,
+        'item_number': settings.DONATIONS_ITEM_NUM,
+        'item_anon_number': settings.DONATIONS_ITEM_ANON_NUM,
+        'domain': current_site.domain,
+        },
+        context_instance = RequestContext(request))
+
+
+def ipn(request):
+    raise Http404       #TODO
+
+
+def thanks(request):
+    raise Http404       #TODO
--- a/gpp/settings.py	Thu Jun 04 02:22:55 2009 +0000
+++ b/gpp/settings.py	Sun Jun 07 00:22:50 2009 +0000
@@ -3,6 +3,8 @@
 import os
 import platform
 import local_settings
+from decimal import Decimal
+
 project_path = os.path.abspath(os.path.split(__file__)[0])
 
 DEBUG = local_settings.DEBUG
@@ -144,6 +146,13 @@
 MAX_AVATAR_SIZE_BYTES = 2 * 1024 * 1024
 MAX_AVATAR_SIZE_PIXELS = 100
 AVATAR_DEFAULT_URL = MEDIA_URL + AVATAR_DIR + '/default.png'
+DONATIONS_ITEM_NAME = 'Donation for SurfGuitar101.com'
+DONATIONS_BUSINESS = 'brian@surfguitar101.com'
+DONATIONS_BUSINESS_DEBUG = 'brian@surfguitar101.com'
+DONATIONS_GOAL = Decimal('100.00')  # montly goal
+DONATIONS_ANON_NAME = u'Anonymous'
+DONATIONS_ITEM_NUM = 500            # donation w/name listed
+DONATIONS_ITEM_ANON_NUM = 501       # donation listed as anonymous
 
 # URL's of 3rd party Javascript and CSS files.
 # These dictionaries are used by core/templatetags/script_tags, and
@@ -185,4 +194,3 @@
     ),
 }
 
-# vim: ts=4 sw=4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gpp/templates/donations/index.html	Sun Jun 07 00:22:50 2009 +0000
@@ -0,0 +1,96 @@
+{% extends 'base.html' %}
+{% block title %}Donations{% endblock %}
+{% block content %}
+<h2>Donations</h2>
+<p>
+SurfGuitar101.com is a member supported website. We don't display ads or have other forms of
+sponsorship. If you enjoy this website, the forums, chatting in IRC, the podcasts, surf music news, 
+the show calendar, and everything else, please consider making a small donation to help cover server 
+and hosting costs.
+</p>
+<p>
+We are currently using Paypal to receive donations. You don't have to be a Paypal member to donate;
+major credit cards are also accepted. If you really don't do Paypal, please 
+<a href="{% url contact-form %}">contact me</a> and we can work something else out.
+</p>
+<p>Thank you for donating to SurfGuitar101.com!</p>
+<h3>Statistics for {% now "F, Y" %}:</h3>
+<table>
+   <tr><th>Goal:</th><td>${{ goal }}</td></tr>
+   <tr><th>Gross:</th><td>${{ gross }}</td></tr>
+   <tr><th>Net:</th><td>${{ net }}</td></tr>
+   <tr><th>Left to Go:</th><td>${{ left }}</td></tr>
+</table>
+{% if donations %}
+<h3>Donors for {% now "F, Y" %}:</h3>
+<ul>
+   {% for donation in donations %}
+   <li>
+      {% if donation.is_anonymous %}
+         {{ anonymous }}
+      {% else %}
+         {% if donation.user %}
+            <a href="{% url bio-view_profile donation.user.username %}">{{ donation.user.username }}</a>
+         {% else %}
+            {{ donation.donor }}
+         {% endif %}
+      {% endif %}
+   </li>
+   {% endfor %}
+</ul>
+{% endif %}
+
+<h3>Donation Form</h3>
+<form action="{{ form_action }}" method="post">
+<fieldset>
+   <legend>Make A Donation</legend>
+   <p>Please select an amount:</p>
+   <ul class="icon-list">
+   <li><input name="amount" type="radio" value="" id="amount_other" />
+      <label for="amount_other">Other:</label>
+      <input name="amount" type="text" value="25.00" id="amount_other" size="7" /></li>
+   <li><input name="amount" type="radio" value="5.00" id="amount_5" />
+      <label for="amount_5">$5</label></li>
+   <li><input name="amount" type="radio" value="10.00" id="amount_10" />
+      <label for="amount_10">$10</label></li>
+   <li><input name="amount" type="radio" value="15.00" id="amount_15" />
+      <label for="amount_15">$15</label></li>
+   <li><input name="amount" type="radio" value="20.00" id="amount_20" />
+      <label for="amount_20">$20</label></li>
+   </ul>
+   {% if user.is_authenticated %}
+      <input type="hidden" name="custom" value="{{ user.username }}" />
+      <p>You are currently logged in. Would you like your site username listed with your donation?</p>
+      <ul class="icon-list">
+         <li><input name="item_number" type="radio" value="{{ item_number }}" id="name_yes" />
+         <label for="name_yes">Yes, list me as {{ user.username }}</label></li>
+   {% else %}
+   <p>You are not currently logged in. Please <a href="{% url accounts-login %}">log in</a>
+   if you would like your site username listed with your donation. Otherwise you can have your 
+   actual name (from Paypal) listed, or you can be listed as {{ anonymous }}.</p>
+      <ul class="icon-list">
+         <li><input name="item_number" type="radio" value="{{ item_number }}" id="name_yes" />
+         <label for="name_yes">Yes, list my name as gathered from Paypal</label></li>
+   {% endif %}
+   <li><input name="item_number" type="radio" value="{{ item_anon_number }}" id="name_no" />
+      <label for="name_no">No, list me as {{ anonymous }}</label></li>
+   </ul>
+   <input type="hidden" name="cmd" value="_donations" />
+   <input type="hidden" name="business" value="{{ business }}" />
+   <input type="hidden" name="charset" value="utf-8" />
+   <input type="hidden" name="return" value="http://{{ domain }}{% url donations-thanks %}" />
+   <input type="hidden" name="currency_code" value="USD" />
+   <input type="hidden" name="item_name" value="{{ item_name }}" />
+   <input type="hidden" name="rm" value="1" />
+   <input type="hidden" name="no_note" value="0" />
+   <input type="hidden" name="cn" value="Do you have any comments for {{ domain }}?" />
+   <input type="hidden" name="no_shipping" value="1" />
+   <input type="hidden" name="cancel_return" value="http://{{ domain }}{% url donations-index %}" />
+
+
+   <p><input type="image" src="https://www.paypal.com/en_US/i/btn/btn_donateCC_LG.gif" name="I1" 
+      alt="Submit Button" /></p>
+</fieldset>
+</form>
+
+{% endblock %}
--- a/gpp/urls.py	Thu Jun 04 02:22:55 2009 +0000
+++ b/gpp/urls.py	Sun Jun 07 00:22:50 2009 +0000
@@ -17,6 +17,7 @@
    (r'^calendar/', include('gcalendar.urls')),
    (r'^comments/', include('comments.urls')),
    (r'^contact/', include('contact.urls')),
+   (r'^donations/', include('donations.urls')),
    (r'^downloads/', include('downloads.urls')),
    url(r'^feeds/(?P<url>.*)/$', 
       'django.contrib.syndication.views.feed',