diff --git a/apiserver/apiserver/api/views.py b/apiserver/apiserver/api/views.py index 1ff3b45..a91bb25 100644 --- a/apiserver/apiserver/api/views.py +++ b/apiserver/apiserver/api/views.py @@ -557,6 +557,31 @@ class TransactionViewSet(Base, List, Create, Retrieve, Update): transaction.save() return Response(200) + @action(detail=False, methods=['get']) + def summary(self, request): + txs = models.Transaction.objects + month = self.request.query_params.get('month', '') + + try: + dt = datetime.datetime.strptime(month, '%Y-%m') + except ValueError: + raise exceptions.ValidationError(dict(month='Should be YYYY-MM.')) + + txs = txs.filter(date__year=dt.year) + txs = txs.filter(date__month=dt.month) + txs = txs.exclude(category='Memberships:Fake Months') + + result = [] + + for category in ['Membership', 'Snacks', 'OnAcct', 'Donation', 'Consumables', 'Purchases']: + result.append(dict( + category = category, + dollar = txs.filter(category=category).aggregate(Sum('amount'))['amount__sum'] or 0, + protocoin = -1 * (txs.filter(category=category).aggregate(Sum('protocoin'))['protocoin__sum'] or 0), + )) + + return Response(result) + class UserView(views.APIView): permission_classes = [AllowMetadata | IsAuthenticated] diff --git a/webclient/src/AdminTransactions.js b/webclient/src/AdminTransactions.js index fd24870..afc979c 100644 --- a/webclient/src/AdminTransactions.js +++ b/webclient/src/AdminTransactions.js @@ -1,7 +1,7 @@ import React, { useState, useEffect } from 'react'; import { Link } from 'react-router-dom'; import './light.css'; -import { Container, Checkbox, Form, Header, Segment } from 'semantic-ui-react'; +import { Container, Checkbox, Form, Header, Segment, Table } from 'semantic-ui-react'; import * as Datetime from 'react-datetime'; import 'react-datetime/css/react-datetime.css'; import moment from 'moment'; @@ -42,12 +42,14 @@ export function AdminReportedTransactions(props) { }; let transactionsCache = false; +let summaryCache = false; let excludePayPalCache = false; export function AdminHistoricalTransactions(props) { const { token } = props; const [input, setInput] = useState({ month: moment() }); const [transactions, setTransactions] = useState(transactionsCache); + const [summary, setSummary] = useState(summaryCache); const [excludePayPal, setExcludePayPal] = useState(excludePayPalCache); const [loading, setLoading] = useState(false); const [error, setError] = useState(false); @@ -75,6 +77,19 @@ export function AdminHistoricalTransactions(props) { console.log(err); setError(true); }); + + requester('/transactions/summary/?month=' + month, 'GET', token) + .then(res => { + setLoading(false); + setError(false); + setSummary(res); + summaryCache = res; + }) + .catch(err => { + setLoading(false); + console.log(err); + setError(true); + }); }; return ( @@ -96,10 +111,40 @@ export function AdminHistoricalTransactions(props) { + {transactions &&
Found {transactions.length} transactions.
} + + {!error ? + summary &&Error loading summary.
+ } + + {!error ? transactions &&Found {transactions.length} transactions.
{!!transactions.length &&