Make expire and paused date read-only, add fake months individually

This commit is contained in:
Tanner Collin 2020-01-20 00:29:28 +00:00
parent 8ca8970092
commit 45965b29b2
5 changed files with 69 additions and 35 deletions

View File

@ -138,6 +138,7 @@ class MemberSerializer(serializers.ModelSerializer):
'current_start_date', 'current_start_date',
'application_date', 'application_date',
'vetted_date', 'vetted_date',
'paused_date',
'monthly_fees', 'monthly_fees',
'photo_large', 'photo_large',
'photo_medium', 'photo_medium',
@ -170,6 +171,8 @@ class AdminMemberSerializer(MemberSerializer):
read_only_fields = [ read_only_fields = [
'id', 'id',
'status', 'status',
'expire_date',
'paused_date',
'photo_large', 'photo_large',
'photo_medium', 'photo_medium',
'photo_small', 'photo_small',
@ -214,7 +217,7 @@ class AdminSearchSerializer(serializers.Serializer):
queryset = obj.user.transactions queryset = obj.user.transactions
else: else:
queryset = models.Transaction.objects.filter(member_id=obj.id) queryset = models.Transaction.objects.filter(member_id=obj.id)
queryset = queryset.order_by('-date') queryset = queryset.order_by('-id', '-date')
serializer = TransactionSerializer(data=queryset, many=True) serializer = TransactionSerializer(data=queryset, many=True)
serializer.is_valid() serializer.is_valid()
return serializer.data return serializer.data
@ -318,13 +321,21 @@ class UserTrainingSerializer(serializers.ModelSerializer):
class UserSerializer(serializers.ModelSerializer): class UserSerializer(serializers.ModelSerializer):
training = UserTrainingSerializer(many=True) training = UserTrainingSerializer(many=True)
member = MemberSerializer() member = MemberSerializer()
transactions = TransactionSerializer(many=True) transactions = serializers.SerializerMethodField()
class Meta: class Meta:
model = User model = User
fields = ['id', 'username', 'member', 'transactions', 'cards', 'training', 'is_staff'] fields = ['id', 'username', 'member', 'transactions', 'cards', 'training', 'is_staff']
depth = 1 depth = 1
def get_transactions(self, obj):
queryset = models.Transaction.objects.filter(user=obj)
queryset = queryset.exclude(category='Memberships:Fake Months')
queryset = queryset.order_by('-id', '-date')
serializer = TransactionSerializer(data=queryset, many=True)
serializer.is_valid()
return serializer.data
def request_from_protospace(request): def request_from_protospace(request):
whitelist = ['24.66.110.96', '205.233.15.76', '205.233.15.69'] whitelist = ['24.66.110.96', '205.233.15.76', '205.233.15.69']

View File

@ -48,8 +48,8 @@ def add_months(date, num_months):
def fake_missing_membership_months(member): def fake_missing_membership_months(member):
''' '''
Return a transaction adding fake months on importing the member so the Add fake months on importing the member so the length of their membership
length of their membership resolves to their imported expiry date resolves to their imported expiry date
''' '''
start_date = member.current_start_date start_date = member.current_start_date
expire_date = member.expire_date expire_date = member.expire_date
@ -57,22 +57,25 @@ def fake_missing_membership_months(member):
missing_months = num_months_spanned(expire_date, start_date) missing_months = num_months_spanned(expire_date, start_date)
user = member.user if member.user else None user = member.user if member.user else None
memo = '{} mth membership dues accounting old portal import, {} to {}'.format( tx = False
str(missing_months), start_date, expire_date for i in range(missing_months):
) memo = '{} / {} month membership dues accounting old portal import, {} to {} - hidden'.format(
str(i+1), str(missing_months), start_date, expire_date
)
tx = models.Transaction.objects.create( tx = models.Transaction.objects.create(
amount=0, amount=0,
user=user, user=user,
memo=memo, memo=memo,
member_id=member.id, member_id=member.id,
reference_number='', reference_number='',
info_source='System', info_source='System',
payment_method='N/A', payment_method='N/A',
category='Membership', category='Memberships:Fake Months',
account_type='Clearing', account_type='Clearing',
number_of_membership_months=missing_months, number_of_membership_months=1,
) date=add_months(start_date, i),
)
return tx return tx
@ -88,7 +91,7 @@ def tally_membership_months(member, fake_date=None):
txs = models.Transaction.objects.filter(member_id=member.id) txs = models.Transaction.objects.filter(member_id=member.id)
total_months_agg = txs.aggregate(Sum('number_of_membership_months')) total_months_agg = txs.aggregate(Sum('number_of_membership_months'))
total_months = total_months_agg['number_of_membership_months__sum'] total_months = total_months_agg['number_of_membership_months__sum'] or 0
expire_date = add_months(start_date, total_months) expire_date = add_months(start_date, total_months)
status, former = calc_member_status(expire_date, fake_date) status, former = calc_member_status(expire_date, fake_date)

View File

@ -144,13 +144,16 @@ for m in members:
tx = utils.fake_missing_membership_months(m) tx = utils.fake_missing_membership_months(m)
utils.tally_membership_months(m, import_date) utils.tally_membership_months(m, import_date)
print(m.first_name, m.last_name, tx.memo) if tx:
print(m.first_name, m.last_name, tx.memo)
if old_status != m.status or old_expire != m.expire_date: if old_status != m.status or old_expire != m.expire_date:
print('Expire / status mismatch member:', m.__dict__) print('Expire / status mismatch member:', m.__dict__)
print('New status:', m.status) print('New status:', m.status)
print('Old status:', old_status) print('Old status:', old_status)
print('New expire:', m.expire_date)
print('Old expire:', old_expire) print('Old expire:', old_expire)
print('')
bad_count += 1 bad_count += 1
print('Import mismatch count:', bad_count) print('Import mismatch count:', bad_count)

View File

@ -1,7 +1,7 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { BrowserRouter as Router, Switch, Route, Link, useParams, useHistory } from 'react-router-dom'; import { BrowserRouter as Router, Switch, Route, Link, useParams, useHistory } from 'react-router-dom';
import './light.css'; import './light.css';
import { Button, Container, Checkbox, Divider, Dropdown, Form, Grid, Header, Icon, Image, Menu, Message, Segment, Table } from 'semantic-ui-react'; import { Button, Container, Checkbox, Dimmer, Divider, Dropdown, Form, Grid, Header, Icon, Image, Menu, Message, Segment, Table } from 'semantic-ui-react';
import moment from 'moment'; import moment from 'moment';
import { BasicTable, staticUrl, requester } from './utils.js'; import { BasicTable, staticUrl, requester } from './utils.js';
import { TransactionList, TransactionEditor } from './Transactions.js'; import { TransactionList, TransactionEditor } from './Transactions.js';
@ -170,6 +170,7 @@ function AdminCardDetail(props) {
export function AdminMemberCards(props) { export function AdminMemberCards(props) {
const { token, result, refreshResult } = props; const { token, result, refreshResult } = props;
const cards = result.cards; const cards = result.cards;
const [dimmed, setDimmed] = useState(result.member.paused_date && cards.length);
const [input, setInput] = useState({ active_status: 'card_active' }); const [input, setInput] = useState({ active_status: 'card_active' });
const [error, setError] = useState(false); const [error, setError] = useState(false);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
@ -247,13 +248,25 @@ export function AdminMemberCards(props) {
<Header size='small'>Current Cards</Header> <Header size='small'>Current Cards</Header>
{cards.length ? <Dimmer.Dimmable dimmed={dimmed}>
cards.map(x => {cards.length ?
<AdminCardDetail key={x.id} card={x} {...props} /> cards.map(x =>
) <AdminCardDetail key={x.id} card={x} {...props} />
: )
<p>None</p> :
} <p>None</p>
}
<Dimmer active={dimmed}>
<p>
Member paused, {cards.length} card{cards.length === 1 ? '' : 's'} ignored anyway.
</p>
<p>
<Button size='tiny' onClick={() => setDimmed(false)}>Close</Button>
</p>
</Dimmer>
</Dimmer.Dimmable>
</div> </div>
); );
}; };
@ -320,11 +333,6 @@ export function AdminMemberForm(props) {
{...makeProps('vetted_date')} {...makeProps('vetted_date')}
/> />
<Form.Input
label='Expire Date'
{...makeProps('expire_date')}
/>
<Form.Input <Form.Input
label='Membership Fee' label='Membership Fee'
{...makeProps('monthly_fees')} {...makeProps('monthly_fees')}
@ -387,6 +395,15 @@ export function AdminMemberInfo(props) {
<Table.Cell>{member.status}</Table.Cell> <Table.Cell>{member.status}</Table.Cell>
</Table.Row> </Table.Row>
<Table.Row>
<Table.Cell>Expire Date:</Table.Cell>
<Table.Cell>{member.expire_date}</Table.Cell>
</Table.Row>
{member.paused_date && <Table.Row>
<Table.Cell>Paused Date:</Table.Cell>
<Table.Cell>{member.paused_date}</Table.Cell>
</Table.Row>}
<Table.Row> <Table.Row>
<Table.Cell>Phone:</Table.Cell> <Table.Cell>Phone:</Table.Cell>
<Table.Cell>{member.phone}</Table.Cell> <Table.Cell>{member.phone}</Table.Cell>

View File

@ -10,7 +10,7 @@ function MemberInfo(props) {
const user = props.user; const user = props.user;
const member = user.member; const member = user.member;
const lastTrans = user.transactions && user.transactions.slice(-3).slice().reverse(); const lastTrans = user.transactions && user.transactions.slice(0,3);
const lastCard = user.cards && user.cards.sort((a, b) => a.last_seen_at < b.last_seen_at)[0]; const lastCard = user.cards && user.cards.sort((a, b) => a.last_seen_at < b.last_seen_at)[0];
return ( return (