This repository has been archived by the owner on Feb 8, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 308
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rewrite of the reconciliation for the finance
- Loading branch information
1 parent
6ef7d9b
commit 00b0f2b
Showing
1 changed file
with
163 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
import calendar | ||
import datetime | ||
from decimal import Decimal as D | ||
|
||
[---] | ||
_by_month = website.db.all(""" | ||
|
||
SELECT date_trunc('month', "timestamp") AS month | ||
, COALESCE(sum(case when amount > 0 then amount end), 0) as payins | ||
, COALESCE(-(sum(case when amount < 0 then amount end)), 0) as payouts | ||
, COALESCE(sum(case when amount > 0 then fee end), 0) as payins_income | ||
, COALESCE(sum(case when amount < 0 then fee end), 0) as payouts_income | ||
, status | ||
, network | ||
FROM exchanges, exchange_routes | ||
WHERE exchanges.route = exchange_routes.id | ||
GROUP BY month, network, status | ||
ORDER BY month ASC; | ||
""") | ||
|
||
def by_month(): | ||
balance = D(0) | ||
by_month = {} | ||
for month, payins, payouts, payins_income, payouts_income, status, network in _by_month: | ||
month = str(month)[:7] | ||
if month not in by_month.keys(): | ||
by_month[month] = { network: { 's_payin': 0, 'p_payin': 0, 'f_payin': 0, \ | ||
'total_payin': 0, 'payin_income': 0, \ | ||
's_payout': 0, 'p_payout': 0, 'f_payout': 0,\ | ||
'total_payout': 0, 'payout_income': 0 } } | ||
if network not in by_month[month].keys(): | ||
by_month[month][network] = { 's_payin': 0, 'p_payin': 0, 'f_payin': 0, \ | ||
'total_payin': 0, 'payin_income': 0, \ | ||
's_payout': 0, 'p_payout': 0, 'f_payout': 0,\ | ||
'total_payout': 0, 'payout_income': 0 } | ||
if status == 'succeeded': | ||
by_month[month][network]['s_payin'] = payins | ||
by_month[month][network]['s_payout'] = payouts | ||
by_month[month][network]['payin_income'] = payins_income | ||
by_month[month][network]['payout_income'] = payouts_income | ||
if status == 'pending': | ||
by_month[month][network]['p_payin'] = payins | ||
by_month[month][network]['p_payout'] = payouts | ||
if status == 'failed': | ||
by_month[month][network]['f_payin'] = payins | ||
by_month[month][network]['f_payout'] = payouts | ||
by_month[month][network]['total_payin'] += payins | ||
by_month[month][network]['total_payout'] += payouts | ||
|
||
|
||
return by_month | ||
|
||
|
||
def by_month_csv(by_month): | ||
output = [ ["Month", "Network", "Succeeded Payins", "Pending Payins", | ||
"Failed Payins", "Total Payins", "Payin Fee Income", | ||
"Succeeded Payouts", "Pending Payouts", | ||
"Failed Payouts","Total Payouts", "Payout Fee Income"] ] | ||
for month, recs in sorted(by_month.items()): | ||
for network,transfers in recs.items(): | ||
row = [] | ||
row.append( str(month)[:7] ) | ||
row.append( network ) | ||
row.append( transfers['s_payin'] ) | ||
row.append( transfers['p_payin'] ) | ||
row.append( transfers['f_payin'] ) | ||
row.append( transfers['total_payin'] ) | ||
row.append( transfers['payin_income'] ) | ||
row.append( transfers['s_payout'] ) | ||
row.append( transfers['p_payout'] ) | ||
row.append( transfers['f_payout'] ) | ||
row.append( transfers['total_payout'] ) | ||
row.append( transfers['payout_income'] ) | ||
output.append(row) | ||
return output | ||
|
||
by_month = by_month() | ||
by_month_csv = by_month_csv(by_month) | ||
fmt = lambda x: "{:,.2f}".format(x) | ||
|
||
[---] text/csv via csv_dump | ||
by_month_csv | ||
|
||
[---] application/json via json_dump | ||
by_month | ||
|
||
[---] text/html | ||
<html> | ||
<head> | ||
<title>Escrow Reconciliation Report by Month and Network</title> | ||
<style> | ||
body { | ||
font-family: monospace; | ||
} | ||
table { | ||
border-collapse: collapse; | ||
} | ||
tr:hover { | ||
background: #CCC; | ||
} | ||
th { | ||
text-align: left; | ||
font-family: monospace; | ||
padding-right: 30px; | ||
} | ||
td { | ||
text-align: right; | ||
padding-right: 20px; | ||
font-family: monospace; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<h1>Reconciliation Reports</h1> | ||
<p>These reports are used as part of Gratipay's <a | ||
href="https://github.com/gratipay/finances">financial accounting</a> | ||
process.</p> | ||
|
||
<h2>Escrow and Income by Month</h2> | ||
{% for month, recs in by_month|dictsort %} | ||
<h3>{{ str(month)[:7] }}</h3> | ||
<table> | ||
<tr> | ||
<th rowspan="2">Network</th> | ||
<th colspan="5">Payins ($)</th> | ||
<th> </th> | ||
<th colspan="5">Payouts ($)</th> | ||
</tr> | ||
<tr> | ||
<th>Succeeded</th> | ||
<th>Pending</th> | ||
<th>Failed</th> | ||
<th>Total</th> | ||
<th>Fee Income</th> | ||
<th> </th> | ||
<th>Succeeded</th> | ||
<th>Pending</th> | ||
<th>Failed</th> | ||
<th>Total</th> | ||
<th>Fee Income</th> | ||
</tr> | ||
{% for network, transfers in recs.items() %} | ||
<tr> | ||
<td>{{ network }}</td> | ||
<td>{{ fmt( transfers['s_payin'] ) }}</td> | ||
<td>{{ fmt( transfers['p_payin'] ) }}</td> | ||
<td>{{ fmt( transfers['f_payin'] ) }}</td> | ||
<td>{{ fmt( transfers['total_payin'] ) }}</td> | ||
<td>{{ fmt( transfers['payin_income'] ) }}</td> | ||
<td> </td> | ||
<td>{{ fmt( transfers['s_payout'] ) }}</td> | ||
<td>{{ fmt( transfers['p_payout'] ) }}</td> | ||
<td>{{ fmt( transfers['f_payout'] ) }}</td> | ||
<td>{{ fmt( transfers['total_payout'] ) }}</td> | ||
<td>{{ fmt( transfers['payout_income'] ) }}</td> | ||
</tr> | ||
{% endfor %} | ||
<tr><td colspan="12"><hr></td></tr> | ||
</table> | ||
{% endfor %} | ||
|
||
</body> | ||
</html> |