From e2eab732ac355fe44d1a4c309c8a7d2bfa201d72 Mon Sep 17 00:00:00 2001 From: Brett Smith Date: Fri, 17 Feb 2017 11:41:39 -0500 Subject: [PATCH 1/3] python models: Add Date.strptime constructor. --- python/status_report.py | 5 ++--- python/supporters/models.py | 6 ++++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/python/status_report.py b/python/status_report.py index 44675b6..4ee3fb2 100755 --- a/python/status_report.py +++ b/python/status_report.py @@ -4,6 +4,7 @@ import argparse import collections import csv import datetime +import functools import os import sys @@ -15,14 +16,12 @@ from supporters.models import Date, Payment, Supporter MONTH_FMT = '%Y-%m' -def month_date(arg_s): - return Date.from_pydate(datetime.datetime.strptime(arg_s, MONTH_FMT)) - def parse_arguments(arglist): parser = argparse.ArgumentParser( prog='status_report', description="Print a CSV report counting Supporters over time", ) + month_date = functools.partial(Date.strptime, fmt=MONTH_FMT) parser.add_argument( '--start-month', type=month_date, metavar='YYYY-MM', default=Payment.objects.order_by('date').first().date, diff --git a/python/supporters/models.py b/python/supporters/models.py index 6cc2f3d..ba711d2 100644 --- a/python/supporters/models.py +++ b/python/supporters/models.py @@ -2,6 +2,7 @@ import datetime import operator +import time from django.db import models @@ -25,6 +26,11 @@ class Date(datetime.date): def from_pydate(cls, date): return cls(date.year, date.month, date.day) + @classmethod + def strptime(cls, s, fmt): + time_tuple = time.strptime(s, fmt) + return cls(*time_tuple[:3]) + def adjust_month(self, delta, day=None): if day is None: day = self.day From 8481bbf3b9fe2d4ecc5009dc06b17ffdf6fb867d Mon Sep 17 00:00:00 2001 From: Brett Smith Date: Fri, 17 Feb 2017 15:11:32 -0500 Subject: [PATCH 2/3] python models: Supporter.supporter_type() handles untagged payments. --- python/supporters/models.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/python/supporters/models.py b/python/supporters/models.py index ba711d2..b9e6e36 100644 --- a/python/supporters/models.py +++ b/python/supporters/models.py @@ -112,7 +112,12 @@ class Supporter: return expose_wrapper def _supporter_type(self, payments): - return payments.last().program.rsplit(':', 1)[-1] + for payment in payments.reverse(): + if payment.program is not None: + break + else: + return None + return payment.program.rsplit(':', 1)[-1] supporter_type = _expose(_supporter_type) def _calculate_lapse_date(self, last_payment_date, supporter_type): From 2b1bdb073dee48aff10a34e31ac579fbfd88e331 Mon Sep 17 00:00:00 2001 From: Brett Smith Date: Fri, 17 Feb 2017 15:24:40 -0500 Subject: [PATCH 3/3] python models: Implement Supporter.supperter_type() with filters. --- python/supporters/models.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/python/supporters/models.py b/python/supporters/models.py index b9e6e36..cc9e21d 100644 --- a/python/supporters/models.py +++ b/python/supporters/models.py @@ -112,12 +112,12 @@ class Supporter: return expose_wrapper def _supporter_type(self, payments): - for payment in payments.reverse(): - if payment.program is not None: - break - else: + try: + program = payments.filter(program__isnull=False).reverse()[0].program + except IndexError: return None - return payment.program.rsplit(':', 1)[-1] + else: + return program.rsplit(':', 1)[-1] supporter_type = _expose(_supporter_type) def _calculate_lapse_date(self, last_payment_date, supporter_type):