Display protocoin amounts, improve transaction validation
This commit is contained in:
parent
81c9bd9c9b
commit
1c225da510
|
@ -3,6 +3,7 @@ logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
from django.contrib.auth.models import User, Group
|
from django.contrib.auth.models import User, Group
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
|
from django.db.models import Max, F, Count, Q, Sum
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.exceptions import ValidationError
|
from rest_framework.exceptions import ValidationError
|
||||||
|
@ -77,13 +78,21 @@ class TransactionSerializer(serializers.ModelSerializer):
|
||||||
'paypal_payer_id',
|
'paypal_payer_id',
|
||||||
]
|
]
|
||||||
|
|
||||||
def create(self, validated_data):
|
def validate_transaction(self, validated_data):
|
||||||
if not self.initial_data.get('member_id', None):
|
if not self.initial_data.get('member_id', None):
|
||||||
raise ValidationError(dict(member_id='This field is required.'))
|
raise ValidationError(dict(member_id='This field is required.'))
|
||||||
|
|
||||||
member = get_object_or_404(models.Member, id=self.initial_data['member_id'])
|
member = get_object_or_404(models.Member, id=self.initial_data['member_id'])
|
||||||
validated_data['user'] = member.user
|
validated_data['user'] = member.user
|
||||||
|
|
||||||
|
if validated_data['account_type'] == 'Protocoin':
|
||||||
|
validated_data['amount'] = 0
|
||||||
|
else:
|
||||||
|
validated_data['protocoin'] = 0
|
||||||
|
|
||||||
|
if validated_data['category'] != 'Membership':
|
||||||
|
validated_data['number_of_membership_months'] = 0
|
||||||
|
|
||||||
if validated_data['account_type'] == 'Protocoin' and validated_data['category'] == 'Exchange':
|
if validated_data['account_type'] == 'Protocoin' and validated_data['category'] == 'Exchange':
|
||||||
raise ValidationError(dict(category='Can\'t purchase Protocoin with Protocoin.'))
|
raise ValidationError(dict(category='Can\'t purchase Protocoin with Protocoin.'))
|
||||||
|
|
||||||
|
@ -92,10 +101,29 @@ class TransactionSerializer(serializers.ModelSerializer):
|
||||||
raise ValidationError(dict(category='Can\'t purchase 0 Protocoin.'))
|
raise ValidationError(dict(category='Can\'t purchase 0 Protocoin.'))
|
||||||
validated_data['protocoin'] = validated_data['amount']
|
validated_data['protocoin'] = validated_data['amount']
|
||||||
|
|
||||||
|
if validated_data['account_type'] == 'Protocoin':
|
||||||
|
if validated_data['protocoin'] == 0:
|
||||||
|
raise ValidationError(dict(account_type='Can\'t have a 0.00 protocoin transaction.'))
|
||||||
|
|
||||||
if validated_data['account_type'] not in ['Clearing', 'Protocoin']:
|
if validated_data['account_type'] not in ['Clearing', 'Protocoin']:
|
||||||
if validated_data['amount'] == 0:
|
if validated_data['amount'] == 0:
|
||||||
raise ValidationError(dict(account_type='Can\'t have a $0.00 {} transaction. Do you want "Membership Adjustment"?'.format(validated_data['account_type'])))
|
raise ValidationError(dict(account_type='Can\'t have a $0.00 {} transaction. Do you want "Membership Adjustment"?'.format(validated_data['account_type'])))
|
||||||
|
|
||||||
|
if validated_data['protocoin'] < 0:
|
||||||
|
current_protocoin = member.user.transactions.aggregate(Sum('protocoin'))['protocoin__sum']
|
||||||
|
new_protocoin = current_protocoin + validated_data['protocoin']
|
||||||
|
if new_protocoin < 0:
|
||||||
|
raise ValidationError(dict(protocoin='Insufficient funds. Member only has {} protocoin.'.format(current_protocoin)))
|
||||||
|
|
||||||
|
if validated_data['account_type'] in ['Interac', 'Dream Pmt', 'Square Pmt', 'PayPal']:
|
||||||
|
if not validated_data.get('reference_number', None):
|
||||||
|
raise ValidationError(dict(reference_number='This field is required.'))
|
||||||
|
|
||||||
|
return validated_data
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
validated_data = self.validate_transaction(validated_data)
|
||||||
|
|
||||||
if validated_data['account_type'] == 'PayPal':
|
if validated_data['account_type'] == 'PayPal':
|
||||||
msg = 'Manual PayPal transaction added:\n' + str(validated_data)
|
msg = 'Manual PayPal transaction added:\n' + str(validated_data)
|
||||||
utils.alert_tanner(msg)
|
utils.alert_tanner(msg)
|
||||||
|
@ -104,18 +132,10 @@ class TransactionSerializer(serializers.ModelSerializer):
|
||||||
msg = 'Manual Protocoin transaction added:\n' + str(validated_data)
|
msg = 'Manual Protocoin transaction added:\n' + str(validated_data)
|
||||||
utils.alert_tanner(msg)
|
utils.alert_tanner(msg)
|
||||||
|
|
||||||
if validated_data['account_type'] in ['Interac', 'Dream Pmt', 'Square Pmt', 'PayPal']:
|
|
||||||
if not validated_data.get('reference_number', None):
|
|
||||||
raise ValidationError(dict(reference_number='This field is required.'))
|
|
||||||
|
|
||||||
return super().create(validated_data)
|
return super().create(validated_data)
|
||||||
|
|
||||||
def update(self, instance, validated_data):
|
def update(self, instance, validated_data):
|
||||||
if not self.initial_data.get('member_id', None):
|
validated_data = self.validate_transaction(validated_data)
|
||||||
raise ValidationError(dict(member_id='This field is required.'))
|
|
||||||
|
|
||||||
member = get_object_or_404(models.Member, id=self.initial_data['member_id'])
|
|
||||||
validated_data['user'] = member.user
|
|
||||||
return super().update(instance, validated_data)
|
return super().update(instance, validated_data)
|
||||||
|
|
||||||
def get_member_id(self, obj):
|
def get_member_id(self, obj):
|
||||||
|
@ -183,6 +203,7 @@ class MemberSerializer(serializers.ModelSerializer):
|
||||||
crop = serializers.CharField(write_only=True, required=False)
|
crop = serializers.CharField(write_only=True, required=False)
|
||||||
email = fields.UserEmailField(serializers.EmailField)
|
email = fields.UserEmailField(serializers.EmailField)
|
||||||
phone = serializers.CharField()
|
phone = serializers.CharField()
|
||||||
|
protocoin = serializers.SerializerMethodField()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.Member
|
model = models.Member
|
||||||
|
@ -221,6 +242,11 @@ class MemberSerializer(serializers.ModelSerializer):
|
||||||
'mediawiki_username',
|
'mediawiki_username',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def get_protocoin(self, obj):
|
||||||
|
transactions = obj.user.transactions
|
||||||
|
total = transactions.aggregate(Sum('protocoin'))['protocoin__sum']
|
||||||
|
return total
|
||||||
|
|
||||||
def update(self, instance, validated_data):
|
def update(self, instance, validated_data):
|
||||||
instance.user.email = validated_data.get('email', instance.user.email)
|
instance.user.email = validated_data.get('email', instance.user.email)
|
||||||
instance.user.save()
|
instance.user.save()
|
||||||
|
|
|
@ -539,6 +539,11 @@ export function AdminMemberInfo(props) {
|
||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
</Table.Row>
|
</Table.Row>
|
||||||
|
|
||||||
|
<Table.Row>
|
||||||
|
<Table.Cell>Protocoin:</Table.Cell>
|
||||||
|
<Table.Cell>₱ {member.protocoin.toFixed(2)}</Table.Cell>
|
||||||
|
</Table.Row>
|
||||||
|
|
||||||
<Table.Row>
|
<Table.Row>
|
||||||
<Table.Cell>Application Date:</Table.Cell>
|
<Table.Cell>Application Date:</Table.Cell>
|
||||||
<Table.Cell>{member.application_date}</Table.Cell>
|
<Table.Cell>{member.application_date}</Table.Cell>
|
||||||
|
|
|
@ -48,6 +48,10 @@ function MemberInfo(props) {
|
||||||
{member.status || 'Unknown'}
|
{member.status || 'Unknown'}
|
||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
</Table.Row>
|
</Table.Row>
|
||||||
|
<Table.Row>
|
||||||
|
<Table.Cell>Protocoin:</Table.Cell>
|
||||||
|
<Table.Cell>₱ {member.protocoin.toFixed(2)}</Table.Cell>
|
||||||
|
</Table.Row>
|
||||||
<Table.Row>
|
<Table.Row>
|
||||||
<Table.Cell>Expiry:</Table.Cell>
|
<Table.Cell>Expiry:</Table.Cell>
|
||||||
<Table.Cell>{member.expire_date ? moment(member.expire_date).format('ll') : 'Unknown'}</Table.Cell>
|
<Table.Cell>{member.expire_date ? moment(member.expire_date).format('ll') : 'Unknown'}</Table.Cell>
|
||||||
|
@ -126,7 +130,7 @@ function MemberInfo(props) {
|
||||||
<Link to={'/transactions/'+x.id}>{moment(x.date).format('ll')}</Link>
|
<Link to={'/transactions/'+x.id}>{moment(x.date).format('ll')}</Link>
|
||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
<Table.Cell>{x.account_type}</Table.Cell>
|
<Table.Cell>{x.account_type}</Table.Cell>
|
||||||
<Table.Cell>${x.amount}</Table.Cell>
|
<Table.Cell>{x.protocoin !== '0.00' ? '₱ ' + x.protocoin : '$ ' + x.amount}</Table.Cell>
|
||||||
</Table.Row>
|
</Table.Row>
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
|
|
|
@ -159,7 +159,6 @@ export function TransactionEditor(props) {
|
||||||
{...makeProps('memo')}
|
{...makeProps('memo')}
|
||||||
/>
|
/>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -304,7 +303,7 @@ export function TransactionList(props) {
|
||||||
x.member_name
|
x.member_name
|
||||||
}
|
}
|
||||||
</Table.Cell>}
|
</Table.Cell>}
|
||||||
<Table.Cell>${x.amount}</Table.Cell>
|
<Table.Cell style={{ minWidth: '8rem' }}>{x.protocoin !== '0.00' ? '₱ ' + x.protocoin : '$ ' + x.amount}</Table.Cell>
|
||||||
<Table.Cell>{x.account_type}</Table.Cell>
|
<Table.Cell>{x.account_type}</Table.Cell>
|
||||||
{!noCategory && <Table.Cell>{x.category}</Table.Cell>}
|
{!noCategory && <Table.Cell>{x.category}</Table.Cell>}
|
||||||
<Table.Cell>{x.memo || x.report_memo}</Table.Cell>
|
<Table.Cell>{x.memo || x.report_memo}</Table.Cell>
|
||||||
|
@ -361,8 +360,12 @@ class TransactionTable extends React.Component {
|
||||||
</Table.Row>
|
</Table.Row>
|
||||||
<Table.Row>
|
<Table.Row>
|
||||||
<Table.Cell>Amount:</Table.Cell>
|
<Table.Cell>Amount:</Table.Cell>
|
||||||
<Table.Cell>${transaction.amount}</Table.Cell>
|
<Table.Cell>$ {transaction.amount}</Table.Cell>
|
||||||
</Table.Row>
|
</Table.Row>
|
||||||
|
{transaction.protocoin !== '0.00' && <Table.Row>
|
||||||
|
<Table.Cell>Protocoin:</Table.Cell>
|
||||||
|
<Table.Cell>₱ {transaction.protocoin}</Table.Cell>
|
||||||
|
</Table.Row>}
|
||||||
<Table.Row>
|
<Table.Row>
|
||||||
<Table.Cell>Category:</Table.Cell>
|
<Table.Cell>Category:</Table.Cell>
|
||||||
<Table.Cell>{transaction.category}</Table.Cell>
|
<Table.Cell>{transaction.category}</Table.Cell>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user