From 8096f29f44f4334f8b17e668592d373dd5f45fcc Mon Sep 17 00:00:00 2001 From: Kwesi Aguillera Date: Thu, 31 Mar 2016 16:22:23 -0400 Subject: [PATCH 01/11] Rewrite of the reconciliation for the finance --- www/dashboard/reconciliation_new.spt | 163 +++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 www/dashboard/reconciliation_new.spt diff --git a/www/dashboard/reconciliation_new.spt b/www/dashboard/reconciliation_new.spt new file mode 100644 index 0000000000..e30ee6e8d5 --- /dev/null +++ b/www/dashboard/reconciliation_new.spt @@ -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 + + + Escrow Reconciliation Report by Month and Network + + + +

Reconciliation Reports

+

These reports are used as part of Gratipay's financial accounting + process.

+ +

Escrow and Income by Month

+ {% for month, recs in by_month|dictsort %} +

{{ str(month)[:7] }}

+ + + + + + + + + + + + + + + + + + + + + {% for network, transfers in recs.items() %} + + + + + + + + + + + + + + + {% endfor %} + +
NetworkPayins ($) Payouts ($)
SucceededPendingFailedTotalFee Income SucceededPendingFailedTotalFee Income
{{ network }}{{ fmt( transfers['s_payin'] ) }}{{ fmt( transfers['p_payin'] ) }}{{ fmt( transfers['f_payin'] ) }}{{ fmt( transfers['total_payin'] ) }}{{ fmt( transfers['payin_income'] ) }} {{ fmt( transfers['s_payout'] ) }}{{ fmt( transfers['p_payout'] ) }}{{ fmt( transfers['f_payout'] ) }}{{ fmt( transfers['total_payout'] ) }}{{ fmt( transfers['payout_income'] ) }}

+ {% endfor %} + + + From a1d4d8a51cfcd088d3546a0351a2cf20f2014908 Mon Sep 17 00:00:00 2001 From: Kwesi Aguillera Date: Fri, 9 Sep 2016 13:20:53 -0400 Subject: [PATCH 02/11] Resolving rebase again --- www/dashboard/reconciliation.spt | 180 +++++++++++++++++---------- www/dashboard/reconciliation_new.spt | 163 ------------------------ 2 files changed, 113 insertions(+), 230 deletions(-) delete mode 100644 www/dashboard/reconciliation_new.spt diff --git a/www/dashboard/reconciliation.spt b/www/dashboard/reconciliation.spt index 277116a56a..e30ee6e8d5 100644 --- a/www/dashboard/reconciliation.spt +++ b/www/dashboard/reconciliation.spt @@ -5,46 +5,89 @@ from decimal import Decimal as D [---] _by_month = website.db.all(""" - SELECT date_trunc('month', "timestamp") as month - , sum(case when amount > 0 then amount end) as payins - , -(sum(case when amount < 0 then amount end)) as payouts - , sum(fee) as income - - FROM exchanges - GROUP BY month - ORDER BY month ASC - +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) - for month, payins, payouts, income in _by_month: - if payins is None: - payins = D(0) - if payouts is None: - payouts = 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 + - balance = balance + payins - payouts - yield month, payins, payouts, balance, income -by_month = by_month() + return by_month -if user.ADMIN: - by_day = website.db.all(""" - SELECT date_trunc('day', timestamp)::date as day - , sum(case when amount > 0 then amount + fee else 0 end) as charge_amount - , sum(case when amount < 0 then -(amount - fee) else 0 end) as payout_amount - , sum(amount) as liability_delta - , sum(fee) as income - FROM exchanges - GROUP BY day - ORDER BY day ASC; - """) +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 - Escrow Reconciliation Report + Escrow Reconciliation Report by Month and Network - - -

Reconciliation Reports

-

These reports are used as part of Gratipay's financial accounting - process.

- -

Escrow and Income by Month

- {% for month, recs in by_month|dictsort %} -

{{ str(month)[:7] }}

- - - - - - - - - - - - - - - - - - - - - {% for network, transfers in recs.items() %} - - - - - - - - - - - - - - - {% endfor %} - -
NetworkPayins ($) Payouts ($)
SucceededPendingFailedTotalFee Income SucceededPendingFailedTotalFee Income
{{ network }}{{ fmt( transfers['s_payin'] ) }}{{ fmt( transfers['p_payin'] ) }}{{ fmt( transfers['f_payin'] ) }}{{ fmt( transfers['total_payin'] ) }}{{ fmt( transfers['payin_income'] ) }} {{ fmt( transfers['s_payout'] ) }}{{ fmt( transfers['p_payout'] ) }}{{ fmt( transfers['f_payout'] ) }}{{ fmt( transfers['total_payout'] ) }}{{ fmt( transfers['payout_income'] ) }}

- {% endfor %} - - - From a639c27b8195e5acdc3f36f837a1a78470157f84 Mon Sep 17 00:00:00 2001 From: Chad Whitacre Date: Wed, 13 Apr 2016 17:48:02 -0400 Subject: [PATCH 03/11] Trim trailing whitespace --- www/dashboard/reconciliation.spt | 42 ++++++++++++++++---------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/www/dashboard/reconciliation.spt b/www/dashboard/reconciliation.spt index e30ee6e8d5..269ed8bc18 100644 --- a/www/dashboard/reconciliation.spt +++ b/www/dashboard/reconciliation.spt @@ -34,48 +34,48 @@ def by_month(): '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_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 + 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_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", + 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'] ) + 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 + return output by_month = by_month() -by_month_csv = by_month_csv(by_month) +by_month_csv = by_month_csv(by_month) fmt = lambda x: "{:,.2f}".format(x) [---] text/csv via csv_dump From 7acc5be2c9f7586783dfeac89beb44373cf65f39 Mon Sep 17 00:00:00 2001 From: Chad Whitacre Date: Wed, 13 Apr 2016 17:49:25 -0400 Subject: [PATCH 04/11] Reformat SQL query --- www/dashboard/reconciliation.spt | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/www/dashboard/reconciliation.spt b/www/dashboard/reconciliation.spt index 269ed8bc18..b8fb9a62fb 100644 --- a/www/dashboard/reconciliation.spt +++ b/www/dashboard/reconciliation.spt @@ -5,17 +5,18 @@ 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; + 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(): From 0410b2dca863898bfe8419e968eb8a24932cba78 Mon Sep 17 00:00:00 2001 From: Kwesi Aguillera Date: Thu, 31 Mar 2016 16:22:23 -0400 Subject: [PATCH 05/11] Rewrite of the reconciliation for the finance --- www/dashboard/reconciliation_new.spt | 163 +++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 www/dashboard/reconciliation_new.spt diff --git a/www/dashboard/reconciliation_new.spt b/www/dashboard/reconciliation_new.spt new file mode 100644 index 0000000000..e30ee6e8d5 --- /dev/null +++ b/www/dashboard/reconciliation_new.spt @@ -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 + + + Escrow Reconciliation Report by Month and Network + + + +

Reconciliation Reports

+

These reports are used as part of Gratipay's financial accounting + process.

+ +

Escrow and Income by Month

+ {% for month, recs in by_month|dictsort %} +

{{ str(month)[:7] }}

+ + + + + + + + + + + + + + + + + + + + + {% for network, transfers in recs.items() %} + + + + + + + + + + + + + + + {% endfor %} + +
NetworkPayins ($) Payouts ($)
SucceededPendingFailedTotalFee Income SucceededPendingFailedTotalFee Income
{{ network }}{{ fmt( transfers['s_payin'] ) }}{{ fmt( transfers['p_payin'] ) }}{{ fmt( transfers['f_payin'] ) }}{{ fmt( transfers['total_payin'] ) }}{{ fmt( transfers['payin_income'] ) }} {{ fmt( transfers['s_payout'] ) }}{{ fmt( transfers['p_payout'] ) }}{{ fmt( transfers['f_payout'] ) }}{{ fmt( transfers['total_payout'] ) }}{{ fmt( transfers['payout_income'] ) }}

+ {% endfor %} + + + From d52f936eda669002b2957e78314fc9b6a7e50e81 Mon Sep 17 00:00:00 2001 From: Kwesi Aguillera Date: Fri, 15 Apr 2016 11:22:17 -0400 Subject: [PATCH 06/11] Altered a exchanges and exchane_route to handle NULL values fir reconciliations --- sql/branch.sql | 29 +++++++++++++++++++++++++++++ www/dashboard/reconciliation.spt | 25 +++++++++++++++++-------- 2 files changed, 46 insertions(+), 8 deletions(-) create mode 100644 sql/branch.sql diff --git a/sql/branch.sql b/sql/branch.sql new file mode 100644 index 0000000000..cddf03caa3 --- /dev/null +++ b/sql/branch.sql @@ -0,0 +1,29 @@ +-- Alter the enums to cater for missing data. +ALTER TYPE payment_net ADD VALUE 'unknown'; +ALTER TYPE exchange_status ADD VALUE 'unknown'; + +-- Update the field status in the exchanges table from NULL to 'unknown' +UPDATE exchanges SET status = 'unknown' WHERE status IS NULL; + +-- Alter the exchanges table to ensure that no more NULL values are entered +ALTER TABLE exchanges ALTER COLUMN status SET NOT NULL; + +-- Insert records for ‘unknown’ (previously NULL in exchanges table +-- network in exchange_route table +INSERT INTO exchange_routes (participant, network, address, error) + ( + SELECT DISTINCT participants.id, 'unknown'::payment_net, 'None', 'None' + FROM exchanges, participants + WHERE exchanges.participant = participants.username + AND route IS NULL + ); + +-- Update exchanges records with exchange_route ids pointing to ‘unknown’ network records for that participants +UPDATE exchanges +SET route = exchange_routes.id +FROM exchange_routes, participants +WHERE exchange_routes.participant = participants.id +AND participants.username = exchanges.participant; + +-- Alter exchanges table and set route to not null +ALTER TABLE exchanges ALTER COLUMN route SET NOT NULL; diff --git a/www/dashboard/reconciliation.spt b/www/dashboard/reconciliation.spt index b8fb9a62fb..c122480a88 100644 --- a/www/dashboard/reconciliation.spt +++ b/www/dashboard/reconciliation.spt @@ -26,14 +26,14 @@ def 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, \ + 'u_payin': 0, 'total_payin': 0, 'payin_income': 0, \ 's_payout': 0, 'p_payout': 0, 'f_payout': 0,\ - 'total_payout': 0, 'payout_income': 0 } } + 'u_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, \ + 'u_payin': 0, 'total_payin': 0, 'payin_income': 0, \ 's_payout': 0, 'p_payout': 0, 'f_payout': 0,\ - 'total_payout': 0, 'payout_income': 0 } + 'u_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 @@ -45,6 +45,9 @@ def by_month(): if status == 'failed': by_month[month][network]['f_payin'] = payins by_month[month][network]['f_payout'] = payouts + if status == 'unknown': + by_month[month][network]['u_payin'] = payins + by_month[month][network]['u_payout'] = payouts by_month[month][network]['total_payin'] += payins by_month[month][network]['total_payout'] += payouts @@ -54,9 +57,9 @@ def 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"] ] + "Failed Payins", "Unknown Payin", "Total Payins", "Payin Fee Income", + "Succeeded Payouts", "Pending Payouts", "Failed Payouts", + "Unknown Payout", "Total Payouts", "Payout Fee Income"] ] for month, recs in sorted(by_month.items()): for network,transfers in recs.items(): row = [] @@ -65,11 +68,13 @@ def by_month_csv(by_month): row.append( transfers['s_payin'] ) row.append( transfers['p_payin'] ) row.append( transfers['f_payin'] ) + row.append( transfers['u_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['u_payout'] ) row.append( transfers['total_payout'] ) row.append( transfers['payout_income'] ) output.append(row) @@ -131,12 +136,14 @@ by_month Succeeded Pending Failed + Unknown Total Fee Income   Succeeded Pending Failed + Unknown Total Fee Income @@ -146,17 +153,19 @@ by_month {{ fmt( transfers['s_payin'] ) }} {{ fmt( transfers['p_payin'] ) }} {{ fmt( transfers['f_payin'] ) }} + {{ fmt( transfers['u_payin'] ) }} {{ fmt( transfers['total_payin'] ) }} {{ fmt( transfers['payin_income'] ) }}   {{ fmt( transfers['s_payout'] ) }} {{ fmt( transfers['p_payout'] ) }} {{ fmt( transfers['f_payout'] ) }} + {{ fmt( transfers['u_payout'] ) }} {{ fmt( transfers['total_payout'] ) }} {{ fmt( transfers['payout_income'] ) }} {% endfor %} -
+
{% endfor %} From ecfa27324a34d1178fafc9f7d67fd3c20c2204dc Mon Sep 17 00:00:00 2001 From: Chad Whitacre Date: Wed, 13 Apr 2016 17:47:26 -0400 Subject: [PATCH 07/11] Move new sptfile over the old one --- www/dashboard/reconciliation_new.spt | 163 --------------------------- 1 file changed, 163 deletions(-) delete mode 100644 www/dashboard/reconciliation_new.spt diff --git a/www/dashboard/reconciliation_new.spt b/www/dashboard/reconciliation_new.spt deleted file mode 100644 index e30ee6e8d5..0000000000 --- a/www/dashboard/reconciliation_new.spt +++ /dev/null @@ -1,163 +0,0 @@ -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 - - - Escrow Reconciliation Report by Month and Network - - - -

Reconciliation Reports

-

These reports are used as part of Gratipay's financial accounting - process.

- -

Escrow and Income by Month

- {% for month, recs in by_month|dictsort %} -

{{ str(month)[:7] }}

- - - - - - - - - - - - - - - - - - - - - {% for network, transfers in recs.items() %} - - - - - - - - - - - - - - - {% endfor %} - -
NetworkPayins ($) Payouts ($)
SucceededPendingFailedTotalFee Income SucceededPendingFailedTotalFee Income
{{ network }}{{ fmt( transfers['s_payin'] ) }}{{ fmt( transfers['p_payin'] ) }}{{ fmt( transfers['f_payin'] ) }}{{ fmt( transfers['total_payin'] ) }}{{ fmt( transfers['payin_income'] ) }} {{ fmt( transfers['s_payout'] ) }}{{ fmt( transfers['p_payout'] ) }}{{ fmt( transfers['f_payout'] ) }}{{ fmt( transfers['total_payout'] ) }}{{ fmt( transfers['payout_income'] ) }}

- {% endfor %} - - - From 0843b82446ffccbfda91962dd51aacf346e5d910 Mon Sep 17 00:00:00 2001 From: Kwesi Aguillera Date: Thu, 31 Mar 2016 16:22:23 -0400 Subject: [PATCH 08/11] Rewrite of the reconciliation for the finance --- www/dashboard/reconciliation_new.spt | 163 +++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 www/dashboard/reconciliation_new.spt diff --git a/www/dashboard/reconciliation_new.spt b/www/dashboard/reconciliation_new.spt new file mode 100644 index 0000000000..e30ee6e8d5 --- /dev/null +++ b/www/dashboard/reconciliation_new.spt @@ -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 + + + Escrow Reconciliation Report by Month and Network + + + +

Reconciliation Reports

+

These reports are used as part of Gratipay's financial accounting + process.

+ +

Escrow and Income by Month

+ {% for month, recs in by_month|dictsort %} +

{{ str(month)[:7] }}

+ + + + + + + + + + + + + + + + + + + + + {% for network, transfers in recs.items() %} + + + + + + + + + + + + + + + {% endfor %} + +
NetworkPayins ($) Payouts ($)
SucceededPendingFailedTotalFee Income SucceededPendingFailedTotalFee Income
{{ network }}{{ fmt( transfers['s_payin'] ) }}{{ fmt( transfers['p_payin'] ) }}{{ fmt( transfers['f_payin'] ) }}{{ fmt( transfers['total_payin'] ) }}{{ fmt( transfers['payin_income'] ) }} {{ fmt( transfers['s_payout'] ) }}{{ fmt( transfers['p_payout'] ) }}{{ fmt( transfers['f_payout'] ) }}{{ fmt( transfers['total_payout'] ) }}{{ fmt( transfers['payout_income'] ) }}

+ {% endfor %} + + + From 0eb41a4ead73db07a6207a8302a1a54fb37e4cb7 Mon Sep 17 00:00:00 2001 From: Kwesi Aguillera Date: Thu, 22 Sep 2016 15:03:28 -0400 Subject: [PATCH 09/11] Removed and unnecessary file. --- www/dashboard/reconciliation_new.spt | 163 --------------------------- 1 file changed, 163 deletions(-) delete mode 100644 www/dashboard/reconciliation_new.spt diff --git a/www/dashboard/reconciliation_new.spt b/www/dashboard/reconciliation_new.spt deleted file mode 100644 index e30ee6e8d5..0000000000 --- a/www/dashboard/reconciliation_new.spt +++ /dev/null @@ -1,163 +0,0 @@ -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 - - - Escrow Reconciliation Report by Month and Network - - - -

Reconciliation Reports

-

These reports are used as part of Gratipay's financial accounting - process.

- -

Escrow and Income by Month

- {% for month, recs in by_month|dictsort %} -

{{ str(month)[:7] }}

- - - - - - - - - - - - - - - - - - - - - {% for network, transfers in recs.items() %} - - - - - - - - - - - - - - - {% endfor %} - -
NetworkPayins ($) Payouts ($)
SucceededPendingFailedTotalFee Income SucceededPendingFailedTotalFee Income
{{ network }}{{ fmt( transfers['s_payin'] ) }}{{ fmt( transfers['p_payin'] ) }}{{ fmt( transfers['f_payin'] ) }}{{ fmt( transfers['total_payin'] ) }}{{ fmt( transfers['payin_income'] ) }} {{ fmt( transfers['s_payout'] ) }}{{ fmt( transfers['p_payout'] ) }}{{ fmt( transfers['f_payout'] ) }}{{ fmt( transfers['total_payout'] ) }}{{ fmt( transfers['payout_income'] ) }}

- {% endfor %} - - - From bac13defde718a3755ac24dc35c3b260d84f644c Mon Sep 17 00:00:00 2001 From: Chad Whitacre Date: Wed, 23 Nov 2016 16:46:09 -0500 Subject: [PATCH 10/11] Minor cleanups Change default values for route address and error (and tweak comment) --- sql/branch.sql | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/branch.sql b/sql/branch.sql index cddf03caa3..78e37bb706 100644 --- a/sql/branch.sql +++ b/sql/branch.sql @@ -8,11 +8,11 @@ UPDATE exchanges SET status = 'unknown' WHERE status IS NULL; -- Alter the exchanges table to ensure that no more NULL values are entered ALTER TABLE exchanges ALTER COLUMN status SET NOT NULL; --- Insert records for ‘unknown’ (previously NULL in exchanges table +-- Insert records for 'unknown' (previously NULL) in exchanges table -- network in exchange_route table -INSERT INTO exchange_routes (participant, network, address, error) +INSERT INTO exchange_routes (participant, network, address, error) ( - SELECT DISTINCT participants.id, 'unknown'::payment_net, 'None', 'None' + SELECT DISTINCT participants.id, 'unknown'::payment_net, 'n/a', '' FROM exchanges, participants WHERE exchanges.participant = participants.username AND route IS NULL From fea453320228d6569bc593bbf88116ff50ad24b3 Mon Sep 17 00:00:00 2001 From: Chad Whitacre Date: Wed, 23 Nov 2016 16:49:53 -0500 Subject: [PATCH 11/11] More comment --- sql/branch.sql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/branch.sql b/sql/branch.sql index 78e37bb706..94895ceac6 100644 --- a/sql/branch.sql +++ b/sql/branch.sql @@ -18,7 +18,8 @@ INSERT INTO exchange_routes (participant, network, address, error) AND route IS NULL ); --- Update exchanges records with exchange_route ids pointing to ‘unknown’ network records for that participants +-- Update exchanges records with exchange_route ids pointing to 'unknown' +-- network records for that participants UPDATE exchanges SET route = exchange_routes.id FROM exchange_routes, participants