Demon has submitted this change and it was merged.

Change subject: Introducing Python Fundraiser Stats!
......................................................................


Introducing Python Fundraiser Stats!

Generate all your flat file needs with this one horrific script!

Change-Id: I6ab75c986fcc6823c2064d2ccd11c1d022e9e31b
---
A FundraiserStatisticsGen/fundstatgen.cfg
A FundraiserStatisticsGen/fundstatgen.py
2 files changed, 181 insertions(+), 0 deletions(-)

Approvals:
  Demon: Verified; Looks good to me, approved



diff --git a/FundraiserStatisticsGen/fundstatgen.cfg 
b/FundraiserStatisticsGen/fundstatgen.cfg
new file mode 100644
index 0000000..75b1d1e
--- /dev/null
+++ b/FundraiserStatisticsGen/fundstatgen.cfg
@@ -0,0 +1,6 @@
+[MySQL]
+hostname=
+port=3306
+username=
+password=
+database=civicrm
\ No newline at end of file
diff --git a/FundraiserStatisticsGen/fundstatgen.py 
b/FundraiserStatisticsGen/fundstatgen.py
new file mode 100644
index 0000000..98fcebc
--- /dev/null
+++ b/FundraiserStatisticsGen/fundstatgen.py
@@ -0,0 +1,175 @@
+#!/usr/bin/python
+
+import sys
+import MySQLdb as db
+import csv
+from optparse import OptionParser
+from ConfigParser import SafeConfigParser
+from operator import itemgetter
+
+def main():
+    # Extract any command line options
+    parser = OptionParser(usage="usage: %prog [options] <working directory>")
+    parser.add_option("-c", "--config", dest='configFile', default=None, 
help='Path to configuration file')
+    (options, args) = parser.parse_args()
+
+    if len(args) != 1:
+        parser.print_help()
+        exit(1)
+    workingDir = args[0]
+
+    # Load the configuration from the file
+    config = SafeConfigParser()
+    fileList = ['./fundstatgen.cfg']
+    if options.configFile is not None:
+        fileList.append(options.configFile)
+    config.read(fileList)
+
+    # === BEGIN PROCESSING ===
+    print("Running query...")
+    stats = getPerYearData(
+        config.get('MySQL', 'hostname'),
+        config.getint('MySQL', 'port'),
+        config.get('MySQL', 'username'),
+        config.get('MySQL', 'password'),
+        config.get('MySQL', 'database')
+    )
+
+    print("Pivoting data into year/day form...")
+    (years, pivot) = pivotDataByYear(stats)
+
+    print("Writing output files...")
+    createSingleOutFile(stats, 'date', workingDir + '/donationdata-vs-day.csv')
+    createOutputFiles(pivot, 'date', workingDir + '/yeardata-day-vs-', years)
+
+
+def getPerYearData(host, port, username, password, database):
+    """
+    Obtain basic statistics (USD sum, number donations, USD avg amount, USD 
max amount,
+    USD YTD sum) per day from the MySQL server.
+
+    Returns a dict like: {date => {report type => {value}} where report types 
are:
+    - sum, refund_sum, donations, refunds, avg, max, ytdsum, ytdloss
+    """
+    con = db.connect(host=host, port=port, user=username, passwd=password, 
db=database)
+    cur = con.cursor()
+    cur.execute("""
+        SELECT
+          DATE_FORMAT(receive_date, "%Y-%m-%d") as receive_date,
+          SUM(IF(total_amount >= 0, total_amount, 0)) as credit,
+          SUM(IF(total_amount >= 0, 1, 0)) as credit_count,
+          SUM(IF(total_amount < 0, total_amount, 0)) as refund,
+          SUM(IF(total_amount < 0, 1, 0)) as refund_count,
+          AVG(IF(total_amount >= 0, total_amount, 0)) as `avg`,
+          MAX(total_amount)
+        FROM civicrm_contribution
+        WHERE receive_date >= '2006-01-01'
+        GROUP BY DATE_FORMAT(receive_date, "%Y-%m-%d") ASC;
+        """)
+
+    data = {}
+    ytdCreditSum = 0
+    ytdRefundSum = 0
+    cyear = 0
+    for row in cur:
+        (date, credit_sum, credit_count, refund_sum, refund_count, avg, max) = 
row
+        year = int(date[0:4])
+        credit_sum = float(credit_sum)
+        credit_count = int(credit_count)
+        refund_sum = float(refund_sum)
+        refund_count = int(refund_count)
+        avg = float(avg)
+        max = float(max)
+
+        if cyear != year:
+            ytdCreditSum = 0
+            ytdRefundSum = 0
+        ytdCreditSum += credit_sum
+        ytdRefundSum += refund_sum
+
+        data[date] = {
+            'sum': credit_sum,
+            'refund_sum': refund_sum,
+            'donations': credit_count,
+            'refunds': refund_count,
+            'avg': avg,
+            'max': max,
+            'ytdsum': ytdCreditSum,
+            'ytdloss': ytdRefundSum
+        }
+
+    del cur
+    con.close()
+    return data
+
+
+def pivotDataByYear(stats):
+    """
+    Transformation of the statistical data -- grouping reports by date
+
+    Returns ((list of years), {report: {date: [year data]}})
+    """
+    years = []
+    pivot = {}
+
+    reports = stats.values()[0].keys()
+    for report in reports:
+        pivot[report] = {}
+
+    # Do the initial pivot
+    for date in stats:
+        (year, month, day) = date.split('-')
+        if year not in years:
+            years.append(year)
+
+        for report in reports:
+            if ('2006/%s/%s 23:59:59' % (month, day)) not in pivot[report]:
+                pivot[report]['2006/%s/%s 23:59:59' % (month, day)] = {}
+            pivot[report]['2006/%s/%s 23:59:59' % (month, day)][year] = 
stats[date][report]
+
+    # Now listify the data
+    years.sort()
+    for report in reports:
+        for linedate in pivot[report]:
+            newline = []
+            linedata = pivot[report][linedate]
+            for year in years:
+                if year in linedata:
+                    newline.append(linedata[year])
+                else:
+                    newline.append(None)
+            pivot[report][linedate] = newline
+
+    return years, pivot
+
+
+def createOutputFiles(stats, firstcol, basename, colnames = None):
+    """
+    Creates a CSV file for each report in stats
+    """
+    reports = stats.keys()
+    for report in reports:
+        createSingleOutFile(stats[report], firstcol, basename + report + 
'.csv', colnames)
+
+
+def createSingleOutFile(stats, firstcol, filename, colnames = None):
+    """
+    Creates a single report file from a keyed dict
+    """
+    if colnames is None:
+        colnames = stats.itervalues().next().keys()
+        colindices = colnames
+    else:
+        colindices = range(0, len(colnames))
+
+    f = file(filename, 'w')
+    csvf = csv.writer(f)
+    csvf.writerow([firstcol] + colnames)
+
+    for linekey in sorted(stats.keys()):
+        csvf.writerow([linekey] + [stats[linekey][col] for col in colindices])
+    f.close()
+
+
+if __name__ == "__main__":
+    main()

-- 
To view, visit https://gerrit.wikimedia.org/r/56547
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I6ab75c986fcc6823c2064d2ccd11c1d022e9e31b
Gerrit-PatchSet: 1
Gerrit-Project: wikimedia/fundraising/tools
Gerrit-Branch: master
Gerrit-Owner: Mwalker <mwal...@wikimedia.org>
Gerrit-Reviewer: Demon <ch...@wikimedia.org>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to