annotate donations/models.py @ 619:00c14431e911

Created a donations side block for BB issue 21.
author Brian Neal <bgneal@gmail.com>
date Wed, 26 Sep 2012 19:33:26 -0500
parents ee87ea74d46b
children 40ae28f33b3d
rev   line source
bgneal@33 1 """
bgneal@33 2 Models for the donations application.
bgneal@33 3 """
bgneal@34 4 import datetime
bgneal@34 5 import decimal
bgneal@34 6
bgneal@33 7 from django.db import models
bgneal@259 8 from django.contrib.auth.models import User
bgneal@35 9 from django.conf import settings
bgneal@619 10 from django.db.models import Sum
bgneal@33 11
bgneal@34 12
bgneal@34 13 class DonationManager(models.Manager):
bgneal@619 14 """Manager for the Donations model."""
bgneal@619 15
bgneal@34 16 def monthly_stats(self, year=None, month=None):
bgneal@34 17 """
bgneal@35 18 Returns a tuple of items for the given month in the given
bgneal@34 19 year. If year is None, the current year is used. If month is None,
bgneal@34 20 the current month is used.
bgneal@35 21 The returned tuple has the following items, in order:
bgneal@35 22 (gross, net, donations)
bgneal@35 23 where:
bgneal@34 24 'gross': total gross donations
bgneal@34 25 'net': total net donations
bgneal@35 26 'donations': list of donation objects
bgneal@34 27 """
bgneal@34 28 today = datetime.date.today()
bgneal@34 29 if year is None:
bgneal@34 30 year = today.year
bgneal@34 31 if month is None:
bgneal@34 32 month = today.month
bgneal@34 33
bgneal@34 34 qs = self.filter(payment_date__year=year,
bgneal@34 35 payment_date__month=month,
bgneal@350 36 test_ipn=settings.DONATIONS_DEBUG).order_by(
bgneal@350 37 'payment_date').select_related('user')
bgneal@34 38
bgneal@35 39 gross = decimal.Decimal()
bgneal@35 40 net = decimal.Decimal()
bgneal@35 41 donations = []
bgneal@34 42 for donation in qs:
bgneal@35 43 gross += donation.mc_gross
bgneal@35 44 net += donation.mc_gross - donation.mc_fee
bgneal@35 45 donations.append(donation)
bgneal@34 46
bgneal@35 47 return gross, net, donations
bgneal@34 48
bgneal@619 49 def monthly_goal_pct(self, year=None, month=None, limit=True):
bgneal@619 50 """Returns progress towards the given monthly goal as an integer
bgneal@619 51 percent.
bgneal@619 52
bgneal@619 53 If year is None, the current year is used.
bgneal@619 54 If month is None, the current month is used.
bgneal@619 55 If limit is True, the return value is limited to 100.
bgneal@619 56
bgneal@619 57 """
bgneal@619 58 today = datetime.datetime.today()
bgneal@619 59 if year is None:
bgneal@619 60 year = today.year
bgneal@619 61 if month is None:
bgneal@619 62 month = today.month
bgneal@619 63
bgneal@619 64 r = self.filter(payment_date__year=year, payment_date__month=month).aggregate(
bgneal@619 65 Sum('mc_gross'), Sum('mc_fee'))
bgneal@619 66
bgneal@619 67 gross, fee = r['mc_gross__sum'], r['mc_fee__sum']
bgneal@619 68
bgneal@619 69 if gross is not None and fee is not None:
bgneal@619 70 pct = int((gross - fee) / settings.DONATIONS_GOAL * 100)
bgneal@619 71 else:
bgneal@619 72 pct = 0
bgneal@619 73
bgneal@619 74 if limit:
bgneal@619 75 pct = min(pct, 100)
bgneal@619 76
bgneal@619 77 return pct
bgneal@619 78
bgneal@34 79
bgneal@33 80 class Donation(models.Model):
bgneal@33 81 """Model to represent a donation to the website."""
bgneal@33 82
bgneal@259 83 user = models.ForeignKey(User, null=True, blank=True)
bgneal@33 84 is_anonymous = models.BooleanField()
bgneal@33 85 test_ipn = models.BooleanField(default=False, verbose_name="Test IPN")
bgneal@33 86 txn_id = models.CharField(max_length=20, verbose_name="Txn ID")
bgneal@33 87 txn_type = models.CharField(max_length=64)
bgneal@33 88 first_name = models.CharField(max_length=64, blank=True)
bgneal@33 89 last_name = models.CharField(max_length=64, blank=True)
bgneal@33 90 payer_email = models.EmailField(max_length=127, blank=True)
bgneal@33 91 payer_id = models.CharField(max_length=13, blank=True, verbose_name="Payer ID")
bgneal@33 92 mc_fee = models.DecimalField(max_digits=8, decimal_places=2, verbose_name="Fee")
bgneal@33 93 mc_gross = models.DecimalField(max_digits=8, decimal_places=2, verbose_name="Gross")
bgneal@33 94 memo = models.TextField(blank=True)
bgneal@33 95 payer_status = models.CharField(max_length=10, blank=True)
bgneal@33 96 payment_date = models.DateTimeField()
bgneal@33 97
bgneal@34 98 objects = DonationManager()
bgneal@34 99
bgneal@33 100 class Meta:
bgneal@33 101 ordering = ('-payment_date', )
bgneal@33 102
bgneal@33 103 def __unicode__(self):
bgneal@33 104 if self.user:
bgneal@33 105 return u'%s from %s' % (self.mc_gross, self.user.username)
bgneal@33 106 return u'%s from %s %s' % (self.mc_gross, self.first_name, self.last_name)
bgneal@33 107
bgneal@34 108 def donor(self):
bgneal@34 109 """Returns the donor name for the donation."""
bgneal@34 110 if self.is_anonymous:
bgneal@35 111 return settings.DONATIONS_ANON_NAME
bgneal@34 112 if self.user is not None:
bgneal@34 113 return self.user.username
bgneal@34 114 if self.first_name or self.last_name:
bgneal@34 115 name = u'%s %s' % (self.first_name, self.last_name)
bgneal@34 116 return name.strip()
bgneal@35 117 return settings.DONATIONS_ANON_NAME
bgneal@34 118