Add summary table to admin transactions

This commit is contained in:
Tanner Collin 2023-02-03 00:02:20 +00:00
parent 0e629151ba
commit b5f69b6b98
2 changed files with 72 additions and 2 deletions

View File

@ -557,6 +557,31 @@ class TransactionViewSet(Base, List, Create, Retrieve, Update):
transaction.save() transaction.save()
return Response(200) 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): class UserView(views.APIView):
permission_classes = [AllowMetadata | IsAuthenticated] permission_classes = [AllowMetadata | IsAuthenticated]

View File

@ -1,7 +1,7 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import './light.css'; 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 * as Datetime from 'react-datetime';
import 'react-datetime/css/react-datetime.css'; import 'react-datetime/css/react-datetime.css';
import moment from 'moment'; import moment from 'moment';
@ -42,12 +42,14 @@ export function AdminReportedTransactions(props) {
}; };
let transactionsCache = false; let transactionsCache = false;
let summaryCache = false;
let excludePayPalCache = false; let excludePayPalCache = false;
export function AdminHistoricalTransactions(props) { export function AdminHistoricalTransactions(props) {
const { token } = props; const { token } = props;
const [input, setInput] = useState({ month: moment() }); const [input, setInput] = useState({ month: moment() });
const [transactions, setTransactions] = useState(transactionsCache); const [transactions, setTransactions] = useState(transactionsCache);
const [summary, setSummary] = useState(summaryCache);
const [excludePayPal, setExcludePayPal] = useState(excludePayPalCache); const [excludePayPal, setExcludePayPal] = useState(excludePayPalCache);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [error, setError] = useState(false); const [error, setError] = useState(false);
@ -75,6 +77,19 @@ export function AdminHistoricalTransactions(props) {
console.log(err); console.log(err);
setError(true); 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 ( return (
@ -96,10 +111,40 @@ export function AdminHistoricalTransactions(props) {
</Form.Button> </Form.Button>
</Form.Group> </Form.Group>
</Form> </Form>
{transactions && <p>Found {transactions.length} transactions.</p>}
{!error ?
summary && <div>
<Header size='small'>Summary</Header>
<Table basic='very'>
<Table.Header>
<Table.Row>
<Table.HeaderCell>Category</Table.HeaderCell>
<Table.HeaderCell>Dollar</Table.HeaderCell>
<Table.HeaderCell>Protocoin</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{summary.map(x =>
<Table.Row key={x.category}>
<Table.Cell>{x.category}</Table.Cell>
<Table.Cell>{'$' + x.dollar.toFixed(2)}</Table.Cell>
<Table.Cell>{'₱ ' + x.protocoin.toFixed(2)}</Table.Cell>
</Table.Row>
)}
</Table.Body>
</Table>
</div>
:
<p>Error loading summary.</p>
}
<p/>
{!error ? {!error ?
transactions && <div> transactions && <div>
<p>Found {transactions.length} transactions.</p>
{!!transactions.length && {!!transactions.length &&
<Header size='small'>{moment(transactions[0].date, 'YYYY-MM-DD').format('MMMM YYYY')} Transactions</Header> <Header size='small'>{moment(transactions[0].date, 'YYYY-MM-DD').format('MMMM YYYY')} Transactions</Header>
} }