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',
'application_date',
'vetted_date',
'paused_date',
'monthly_fees',
'photo_large',
'photo_medium',
@ -170,6 +171,8 @@ class AdminMemberSerializer(MemberSerializer):
read_only_fields = [
'id',
'status',
'expire_date',
'paused_date',
'photo_large',
'photo_medium',
'photo_small',
@ -214,7 +217,7 @@ class AdminSearchSerializer(serializers.Serializer):
queryset = obj.user.transactions
else:
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.is_valid()
return serializer.data
@ -318,13 +321,21 @@ class UserTrainingSerializer(serializers.ModelSerializer):
class UserSerializer(serializers.ModelSerializer):
training = UserTrainingSerializer(many=True)
member = MemberSerializer()
transactions = TransactionSerializer(many=True)
transactions = serializers.SerializerMethodField()
class Meta:
model = User
fields = ['id', 'username', 'member', 'transactions', 'cards', 'training', 'is_staff']
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):
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):
'''
Return a transaction adding fake months on importing the member so the
length of their membership resolves to their imported expiry date
Add fake months on importing the member so the length of their membership
resolves to their imported expiry date
'''
start_date = member.current_start_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)
user = member.user if member.user else None
memo = '{} mth membership dues accounting old portal import, {} to {}'.format(
str(missing_months), start_date, expire_date
)
tx = False
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(
amount=0,
user=user,
memo=memo,
member_id=member.id,
reference_number='',
info_source='System',
payment_method='N/A',
category='Membership',
account_type='Clearing',
number_of_membership_months=missing_months,
)
tx = models.Transaction.objects.create(
amount=0,
user=user,
memo=memo,
member_id=member.id,
reference_number='',
info_source='System',
payment_method='N/A',
category='Memberships:Fake Months',
account_type='Clearing',
number_of_membership_months=1,
date=add_months(start_date, i),
)
return tx
@ -88,7 +91,7 @@ def tally_membership_months(member, fake_date=None):
txs = models.Transaction.objects.filter(member_id=member.id)
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)
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)
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:
print('Expire / status mismatch member:', m.__dict__)
print('New status:', m.status)
print('Old status:', old_status)
print('New expire:', m.expire_date)
print('Old expire:', old_expire)
print('')
bad_count += 1
print('Import mismatch count:', bad_count)

View File

@ -1,7 +1,7 @@
import React, { useState, useEffect } from 'react';
import { BrowserRouter as Router, Switch, Route, Link, useParams, useHistory } from 'react-router-dom';
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 { BasicTable, staticUrl, requester } from './utils.js';
import { TransactionList, TransactionEditor } from './Transactions.js';
@ -170,6 +170,7 @@ function AdminCardDetail(props) {
export function AdminMemberCards(props) {
const { token, result, refreshResult } = props;
const cards = result.cards;
const [dimmed, setDimmed] = useState(result.member.paused_date && cards.length);
const [input, setInput] = useState({ active_status: 'card_active' });
const [error, setError] = useState(false);
const [loading, setLoading] = useState(false);
@ -247,13 +248,25 @@ export function AdminMemberCards(props) {
<Header size='small'>Current Cards</Header>
{cards.length ?
cards.map(x =>
<AdminCardDetail key={x.id} card={x} {...props} />
)
:
<p>None</p>
}
<Dimmer.Dimmable dimmed={dimmed}>
{cards.length ?
cards.map(x =>
<AdminCardDetail key={x.id} card={x} {...props} />
)
:
<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>
);
};
@ -320,11 +333,6 @@ export function AdminMemberForm(props) {
{...makeProps('vetted_date')}
/>
<Form.Input
label='Expire Date'
{...makeProps('expire_date')}
/>
<Form.Input
label='Membership Fee'
{...makeProps('monthly_fees')}
@ -387,6 +395,15 @@ export function AdminMemberInfo(props) {
<Table.Cell>{member.status}</Table.Cell>
</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.Cell>Phone:</Table.Cell>
<Table.Cell>{member.phone}</Table.Cell>

View File

@ -10,7 +10,7 @@ function MemberInfo(props) {
const user = props.user;
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];
return (