Make expire and paused date read-only, add fake months individually
This commit is contained in:
parent
8ca8970092
commit
45965b29b2
|
@ -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']
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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 (
|
||||||
|
|
Loading…
Reference in New Issue
Block a user